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([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])
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]
SUNWprivate_1.1 {
global:
# CACAO
- vm_createjvm;
+ VM_create;
vm_run;
# JNI
Doxyfile
doxygen:
- doxygen
+ doxygen $(srcdir)/Doxyfile
clean-local:
-rm -rf html latex
+++ /dev/null
-dnl m4/cacaoh.m4
-dnl
-dnl Copyright (C) 2007, 2008
-dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-dnl
-dnl This file is part of CACAO.
-dnl
-dnl This program is free software; you can redistribute it and/or
-dnl modify it under the terms of the GNU General Public License as
-dnl published by the Free Software Foundation; either version 2, or (at
-dnl your option) any later version.
-dnl
-dnl This program is distributed in the hope that it will be useful, but
-dnl WITHOUT ANY WARRANTY; without even the implied warranty of
-dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-dnl General Public License for more details.
-dnl
-dnl You should have received a copy of the GNU General Public License
-dnl along with this program; if not, write to the Free Software
-dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-dnl 02110-1301, USA.
-
-
-dnl check which cacaoh to use
-
-AC_DEFUN([AC_CHECK_WITH_CACAOH],[
-AC_MSG_CHECKING(which cacaoh to use (for crosscompilation))
-AC_ARG_WITH([cacaoh],
- [AS_HELP_STRING(--with-cacaoh,which cacaoh to use [[default=$(top_builddir)/src/cacaoh/cacaoh]])],
- [CACAOH="${withval}"],
- [CACAOH=["\$(top_builddir)/src/cacaoh/cacaoh"]])
-AC_MSG_RESULT(${CACAOH})
-AC_SUBST(CACAOH)
-])
AC_MSG_RESULT(${JAVA_RUNTIME_LIBRARY_CLASSES})
AC_DEFINE_UNQUOTED([JAVA_RUNTIME_LIBRARY_CLASSES], "${JAVA_RUNTIME_LIBRARY_CLASSES}", [Java runtime library classes])
AC_SUBST(JAVA_RUNTIME_LIBRARY_CLASSES)
+])
+
+
+dnl where are Java core library classes located at compilation time
+
+AC_DEFUN([AC_CHECK_WITH_BUILD_JAVA_RUNTIME_LIBRARY_CLASSES],[
+AC_MSG_CHECKING(where Java core library classes are located at compile time)
+AC_ARG_WITH([build-java-runtime-library-classes],
+ [AS_HELP_STRING(--with-build-java-runtime-library-classes=<path>,path to Java core library classes (includes the name of the file and may be flat) [[default=${JAVA_RUNTIME_LIBRARY_CLASSES}]])],
+ [BUILD_JAVA_RUNTIME_LIBRARY_CLASSES=${withval}],
+ [BUILD_JAVA_RUNTIME_LIBRARY_CLASSES=${JAVA_RUNTIME_LIBRARY_CLASSES}])
+AC_MSG_RESULT(${BUILD_JAVA_RUNTIME_LIBRARY_CLASSES})
+AC_DEFINE_UNQUOTED([BUILD_JAVA_RUNTIME_LIBRARY_CLASSES], "${BUILD_JAVA_RUNTIME_LIBRARY_CLASSES}", [Java core library classes at compile time])
+AC_SUBST(BUILD_JAVA_RUNTIME_LIBRARY_CLASSES)
dnl define BOOTCLASSPATH for Makefiles
case "${WITH_JAVA_RUNTIME_LIBRARY}" in
cldc1.1 | gnuclasspath)
- BOOTCLASSPATH="\$(top_builddir)/src/classes/classes:\$(JAVA_RUNTIME_LIBRARY_CLASSES)"
+ BOOTCLASSPATH="\$(top_builddir)/src/classes/classes:${BUILD_JAVA_RUNTIME_LIBRARY_CLASSES}"
;;
*)
- BOOTCLASSPATH="\$(JAVA_RUNTIME_LIBRARY_CLASSES)"
+ BOOTCLASSPATH="${BUILD_JAVA_RUNTIME_LIBRARY_CLASSES}"
;;
esac
AC_SUBST(BOOTCLASSPATH)
--- /dev/null
+dnl m4/opagent.m4
+dnl
+dnl Copyright (C) 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+dnl
+dnl This file is part of CACAO.
+dnl
+dnl This program is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU General Public License as
+dnl published by the Free Software Foundation; either version 2, or (at
+dnl your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+
+dnl check if opagent library should be used
+
+AC_DEFUN([AC_CHECK_ENABLE_OPAGENT],[
+AC_ARG_WITH([opagent-includedir],
+ [AS_HELP_STRING(--with-opagent-includedir=<path>,location of opagent header files [[default=/usr/include]])],
+ [OPAGENT_CFLAGS=-I"${withval}"],
+ [])
+AC_SUBST(OPAGENT_CFLAGS)
+
+AC_ARG_WITH([opagent-libdir],
+ [AS_HELP_STRING(--with-opagent-libdir=<path>,location of opagent library [[default=/usr/lib/oprofile]])],
+ [OPAGENT_LDFLAGS=-L"${withval}"],
+ [OPAGENT_LDFLAGS=-L/usr/lib/oprofile])
+AC_SUBST(OPAGENT_LDFLAGS)
+
+AC_MSG_CHECKING(whether Oprofile opagent support code should be compiled)
+AC_ARG_ENABLE([opagent],
+ [AS_HELP_STRING(--enable-opagent,enable opagent library support [[default=disabled]])],
+ [case "${enableval}" in
+ yes) ENABLE_OPAGENT=yes;;
+ *) ENABLE_OPAGENT=no;;
+ esac],
+ [ENABLE_OPAGENT=no])
+AC_MSG_RESULT(${ENABLE_OPAGENT})
+
+if test x"${ENABLE_OPAGENT}" = "xyes"; then
+ CFLAGS="$CFLAGS $OPAGENT_CFLAGS"
+ CPPFLAGS="$CPPFLAGS $OPAGENT_CFLAGS"
+ LDFLAGS="$LDFLAGS $OPAGENT_LDFLAGS"
+ AC_CHECK_HEADERS([opagent.h],, [AC_MSG_ERROR(cannot find opagent.h)])
+ AC_CHECK_LIB(opagent, op_open_agent,, [AC_MSG_ERROR(cannot find libopagent)])
+ AC_DEFINE([ENABLE_OPAGENT], 1, [use opagent])
+fi
+AM_CONDITIONAL([ENABLE_OPAGENT], [test x"${ENABLE_OPAGENT}" = "xyes"])
+])
+
DIST_SUBDIRS = \
cacao \
- cacaoh \
classes \
fdlibm \
mm \
scripts \
threads \
toolbox \
- vm \
- vmcore
+ vm
# DON'T CHANGE THIS ORDER!!!
SUBDIRS = \
- toolbox \
- vmcore \
- cacaoh \
classes \
- native \
fdlibm \
+ toolbox \
mm \
- threads \
vm \
+ threads \
+ native \
cacao \
scripts
libjvm.la
libjvm_la_LDFLAGS = \
- -version-info 1:0:0
+ -avoid-version
if WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
+if WITH_GNU_LD
libjvm_la_LDFLAGS += \
-Xlinker --version-script=$(top_srcdir)/contrib/mapfile-vers-product
+else
+# This is for the Solaris LD.
+libjvm_la_LDFLAGS += \
+ -Xlinker -M$(top_srcdir)/contrib/mapfile-vers-product
+endif
endif
cacao_LDFLAGS += \
$(top_builddir)/src/threads/libthreads.la \
$(top_builddir)/src/toolbox/libtoolbox.la \
$(top_builddir)/src/vm/libvm.la \
- $(top_builddir)/src/vmcore/libvmcore.la \
$(GC_LIB)
bin_PROGRAMS = \
cacao
cacao_SOURCES = \
- cacao.c
+ cacao.cpp
cacao_LDADD = \
$(CACAO_LIBS)
+++ /dev/null
-/* src/cacao/cacao.c - contains main() of cacao
-
- 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>
-
-#if defined(ENABLE_JRE_LAYOUT)
-# include <errno.h>
-# include <libgen.h>
-# include <unistd.h>
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/jvmti.h"
-# include "native/jvmti/cacaodbg.h"
-# include "threads/mutex.h"
-#endif
-
-#include "vmcore/system.h"
-
-#include "vm/vm.h"
-
-
-/* Defines. *******************************************************************/
-
-#define LIBJVM_NAME NATIVE_LIBRARY_PREFIX"jvm"NATIVE_LIBRARY_SUFFIX
-
-
-/* forward declarations *******************************************************/
-
-static JavaVMInitArgs *cacao_options_prepare(int argc, char **argv);
-
-
-/* main ************************************************************************
-
- The main program.
-
-*******************************************************************************/
-
-int main(int argc, char **argv)
-{
-#if defined(ENABLE_LIBJVM)
- char* path;
-
-# if defined(ENABLE_JRE_LAYOUT)
- int len;
-# endif
-#endif
-
-#if defined(ENABLE_LIBJVM)
- /* Variables for JNI_CreateJavaVM dlopen call. */
- void* libjvm_handle;
- void* libjvm_vm_createjvm;
- void* libjvm_vm_run;
- const char* lterror;
-
- bool (*vm_createjvm)(JavaVM **, void **, void *);
- void (*vm_run)(JavaVM *, JavaVMInitArgs *);
-#endif
-
- JavaVM *vm; /* denotes a Java VM */
- JNIEnv *env;
- JavaVMInitArgs *vm_args;
-
- /* prepare the options */
-
- vm_args = cacao_options_prepare(argc, argv);
-
- /* load and initialize a Java VM, return a JNI interface pointer in env */
-
-#if defined(ENABLE_LIBJVM)
-# if defined(ENABLE_JRE_LAYOUT)
- /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
-
- path = malloc(sizeof(char) * 4096);
-
- if (readlink("/proc/self/exe", path, 4095) == -1) {
- fprintf(stderr, "main: readlink failed: %s\n", strerror(errno));
- abort();
- }
-
- /* get the path of the current executable */
-
- path = dirname(path);
- len = strlen(path) + strlen("/../lib/"LIBJVM_NAME) + strlen("0");
-
- if (len > 4096) {
- fprintf(stderr, "main: libjvm name to long for buffer\n");
- abort();
- }
-
- /* concatinate the library name */
-
- strcat(path, "/../lib/"LIBJVM_NAME);
-# else
- path = CACAO_LIBDIR"/"LIBJVM_NAME;
-# endif
-
- /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
- If not found, try the absolute path. */
-
- libjvm_handle = system_dlopen(LIBJVM_NAME, RTLD_LAZY);
-
- if (libjvm_handle == NULL) {
- /* save the error message */
-
- lterror = strdup(system_dlerror());
-
- libjvm_handle = system_dlopen(path, RTLD_LAZY);
-
- if (libjvm_handle == NULL) {
- /* print the first error message too */
-
- fprintf(stderr, "main: system_dlopen failed: %s\n", lterror);
-
- /* and now the current one */
-
- fprintf(stderr, "main: system_dlopen failed: %s\n",
- system_dlerror());
- abort();
- }
-
- /* free the error string */
-
- free((void *) lterror);
- }
-
- libjvm_vm_createjvm = system_dlsym(libjvm_handle, "vm_createjvm");
-
- if (libjvm_vm_createjvm == NULL) {
- fprintf(stderr, "main: lt_dlsym failed: %s\n", system_dlerror());
- abort();
- }
-
- vm_createjvm =
- (bool (*)(JavaVM **, void **, void *)) (ptrint) libjvm_vm_createjvm;
-#endif
-
- /* create the Java VM */
-
- (void) vm_createjvm(&vm, (void *) &env, vm_args);
-
-#if defined(ENABLE_JVMTI)
- mutex_init(&dbgcomlock);
- if (jvmti) jvmti_set_phase(JVMTI_PHASE_START);
-#endif
-
-#if defined(ENABLE_LIBJVM)
- libjvm_vm_run = system_dlsym(libjvm_handle, "vm_run");
-
- if (libjvm_vm_run == NULL) {
- fprintf(stderr, "main: system_dlsym failed: %s\n", system_dlerror());
- abort();
- }
-
- vm_run = (void (*)(JavaVM *, JavaVMInitArgs *)) (ptrint) libjvm_vm_run;
-#endif
-
- /* run the VM */
-
- vm_run(vm, vm_args);
-
- /* keep compiler happy */
-
- return 0;
-}
-
-
-/* cacao_options_prepare *******************************************************
-
- Prepare the JavaVMInitArgs.
-
-*******************************************************************************/
-
-static JavaVMInitArgs *cacao_options_prepare(int argc, char **argv)
-{
- JavaVMInitArgs *vm_args;
- s4 i;
-
- vm_args = malloc(sizeof(JavaVMInitArgs));
-
- vm_args->version = JNI_VERSION_1_2;
- vm_args->nOptions = argc - 1;
- vm_args->options = malloc(sizeof(JavaVMOption) * argc);
- vm_args->ignoreUnrecognized = JNI_FALSE;
-
- for (i = 1; i < argc; i++)
- vm_args->options[i - 1].optionString = argv[i];
-
- return vm_args;
-}
-
-
-/*
- * 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/cacao/cacao.cpp - contains main() of cacao
+
+ 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>
+
+#if defined(ENABLE_JRE_LAYOUT)
+# include <errno.h>
+# include <libgen.h>
+# include <unistd.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "vm/types.h"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JVMTI)
+# include "native/jvmti/jvmti.h"
+# include "native/jvmti/cacaodbg.h"
+#endif
+
+#include "vm/os.hpp"
+#include "vm/vm.hpp"
+
+
+/* Defines. *******************************************************************/
+
+#define LIBJVM_NAME NATIVE_LIBRARY_PREFIX"jvm"NATIVE_LIBRARY_SUFFIX
+
+
+/* forward declarations *******************************************************/
+
+static JavaVMInitArgs* prepare_options(int argc, char** argv);
+
+
+/* main ************************************************************************
+
+ The main program.
+
+*******************************************************************************/
+
+int main(int argc, char **argv)
+{
+#if defined(ENABLE_LIBJVM)
+ char* path;
+
+# if defined(ENABLE_JRE_LAYOUT)
+ int len;
+# endif
+#endif
+
+#if defined(ENABLE_LIBJVM)
+ /* Variables for JNI_CreateJavaVM dlopen call. */
+ void* libjvm_handle;
+ void* libjvm_VM_create;
+ void* libjvm_vm_run;
+ const char* lterror;
+
+ bool (*VM_create)(JavaVM **, void **, void *);
+ void (*vm_run)(JavaVM *, JavaVMInitArgs *);
+#endif
+
+ JavaVM *vm; /* denotes a Java VM */
+ JNIEnv *env;
+ JavaVMInitArgs *vm_args;
+
+ /* prepare the options */
+
+ vm_args = prepare_options(argc, argv);
+
+ /* load and initialize a Java VM, return a JNI interface pointer in env */
+
+#if defined(ENABLE_LIBJVM)
+# if defined(ENABLE_JRE_LAYOUT)
+ /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
+
+ path = (char*) os::malloc(sizeof(char) * 4096);
+
+ if (readlink("/proc/self/exe", path, 4095) == -1) {
+ fprintf(stderr, "main: readlink failed: %s\n", strerror(errno));
+ os::abort();
+ }
+
+ /* get the path of the current executable */
+
+ path = os::dirname(path);
+ len = os::strlen(path) + os::strlen("/../lib/"LIBJVM_NAME) + os::strlen("0");
+
+ if (len > 4096) {
+ fprintf(stderr, "main: libjvm name to long for buffer\n");
+ os::abort();
+ }
+
+ /* concatinate the library name */
+
+ strcat(path, "/../lib/"LIBJVM_NAME);
+# else
+ path = (char*) CACAO_LIBDIR"/"LIBJVM_NAME;
+# endif
+
+ /* First try to open where dlopen searches, e.g. LD_LIBRARY_PATH.
+ If not found, try the absolute path. */
+
+ libjvm_handle = os::dlopen(LIBJVM_NAME, RTLD_NOW);
+
+ if (libjvm_handle == NULL) {
+ /* save the error message */
+
+ lterror = strdup(os::dlerror());
+
+ libjvm_handle = os::dlopen(path, RTLD_NOW);
+
+ if (libjvm_handle == NULL) {
+ /* print the first error message too */
+
+ fprintf(stderr, "main: os::dlopen failed: %s\n", lterror);
+
+ /* and now the current one */
+
+ fprintf(stderr, "main: os::dlopen failed: %s\n", os::dlerror());
+ os::abort();
+ }
+
+ /* free the error string */
+
+ free((void *) lterror);
+ }
+
+ libjvm_VM_create = os::dlsym(libjvm_handle, "VM_create");
+
+ if (libjvm_VM_create == NULL) {
+ fprintf(stderr, "main: lt_dlsym failed: %s\n", os::dlerror());
+ os::abort();
+ }
+
+ VM_create =
+ (bool (*)(JavaVM **, void **, void *)) (ptrint) libjvm_VM_create;
+#endif
+
+ /* create the Java VM */
+
+ (void) VM_create(&vm, (void**) &env, vm_args);
+
+#if defined(ENABLE_JVMTI)
+# error This should be a JVMTI function.
+ Mutex_init(&dbgcomlock);
+ if (jvmti) jvmti_set_phase(JVMTI_PHASE_START);
+#endif
+
+#if defined(ENABLE_LIBJVM)
+ libjvm_vm_run = os::dlsym(libjvm_handle, "vm_run");
+
+ if (libjvm_vm_run == NULL) {
+ fprintf(stderr, "main: os::dlsym failed: %s\n", os::dlerror());
+ os::abort();
+ }
+
+ vm_run = (void (*)(JavaVM *, JavaVMInitArgs *)) (ptrint) libjvm_vm_run;
+#endif
+
+ /* run the VM */
+
+ vm_run(vm, vm_args);
+
+ /* keep compiler happy */
+
+ return 0;
+}
+
+
+/**
+ * Prepare the JavaVMInitArgs structure.
+ */
+static JavaVMInitArgs* prepare_options(int argc, char** argv)
+{
+ JavaVMInitArgs* vm_args;
+
+ vm_args = (JavaVMInitArgs*) malloc(sizeof(JavaVMInitArgs));
+
+ vm_args->version = JNI_VERSION_1_2;
+ vm_args->nOptions = argc - 1;
+ vm_args->options = (JavaVMOption*) malloc(sizeof(JavaVMOption) * argc);
+ vm_args->ignoreUnrecognized = JNI_FALSE;
+
+ for (int i = 1; i < argc; i++)
+ vm_args->options[i - 1].optionString = argv[i];
+
+ return vm_args;
+}
+
+
+/*
+ * 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/cacaoh/Makefile.am
-##
-## 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.
-
-
-AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
-
-if ENABLE_RT_TIMING
-cacaoh_LDFLAGS = -lrt
-endif
-
-noinst_LTLIBRARIES = \
- libcacaoh.la
-
-libcacaoh_la_SOURCES = \
- dummy.c \
- headers.c \
- headers.h
-
-libcacaoh_la_LIBADD = \
- $(top_builddir)/src/toolbox/libtoolbox.la \
- $(top_builddir)/src/vmcore/libvmcore.la
-
-noinst_PROGRAMS = \
- cacaoh
-
-cacaoh_SOURCES = \
- cacaoh.c
-
-cacaoh_LDADD = \
- libcacaoh.la
-
-cacaoh_DEPENDENCIES = \
- $(cacaoh_LDADD)
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
+++ /dev/null
-/* src/cacaoh/cacaoh.c - main for header generation (cacaoh)
-
- 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "cacaoh/headers.h"
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
-
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/classcache.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vmcore/suck.h"
-
-
-/* define cacaoh options ******************************************************/
-
-enum {
- OPT_HELP,
- OPT_VERSION,
- OPT_VERBOSE,
- OPT_DIRECTORY,
- OPT_CLASSPATH,
- OPT_BOOTCLASSPATH,
-
- DUMMY
-};
-
-
-opt_struct opts[] = {
- { "help", false, OPT_HELP },
- { "version", false, OPT_VERSION },
- { "verbose", false, OPT_VERBOSE },
- { "d", true, OPT_DIRECTORY },
- { "classpath", true, OPT_CLASSPATH },
- { "bootclasspath", true, OPT_BOOTCLASSPATH },
- { NULL, false, 0 }
-};
-
-
-/* usage ***********************************************************************
-
- Obviously prints usage information of cacaoh.
-
-*******************************************************************************/
-
-void usage(void)
-{
- printf("Usage: cacaoh [options] <classes>\n"
- "\n"
- "Options:\n"
- " -help Print this message\n"
- " -classpath <path> \n"
- " -bootclasspath <path> \n"
- " -d <dir> Output directory\n"
- " -version Print version information\n"
- " -verbose Enable verbose output\n");
-
- /* exit with error code */
-
- exit(1);
-}
-
-
-/* version *********************************************************************
-
- Prints cacaoh version information.
-
-*******************************************************************************/
-
-static void version(void)
-{
- printf("cacaoh version "VERSION"\n");
- printf("Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,\n");
- printf("C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,\n");
- printf("E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,\n");
- printf("J. Wenninger, Institut f. Computersprachen - TU Wien\n\n");
-
- printf("This program is free software; you can redistribute it and/or\n");
- printf("modify it under the terms of the GNU General Public License as\n");
- printf("published by the Free Software Foundation; either version 2, or (at\n");
- printf("your option) any later version.\n\n");
-
- printf("This program is distributed in the hope that it will be useful, but\n");
- printf("WITHOUT ANY WARRANTY; without even the implied warranty of\n");
- printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n");
- printf("General Public License for more details.\n");
-
- exit(0);
-}
-
-
-/* forward declarations *******************************************************/
-
-static JavaVMInitArgs *cacaoh_options_prepare(int argc, char **argv);
-
-
-/* main ************************************************************************
-
- Main program.
-
-*******************************************************************************/
-
-int main(int argc, char **argv)
-{
- JavaVMInitArgs *vm_args;
- s4 i, j;
- s4 opt;
- classinfo *c;
- char *opt_directory;
-
- /********** internal (only used by main) *****************************/
-
- char *bootclasspath;
- char *classpath;
- char *cp;
- s4 cplen;
-
- if (argc < 2)
- usage();
-
- /* set the bootclasspath */
-
- cp = getenv("BOOTCLASSPATH");
-
- if (cp) {
- bootclasspath = MNEW(char, strlen(cp) + strlen("0"));
- strcpy(bootclasspath, cp);
- }
- else {
- cplen =
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- strlen(CACAO_VM_ZIP) +
- strlen(":") +
-#endif
- strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
- strlen("0");
-
- bootclasspath = MNEW(char, cplen);
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- strcat(bootclasspath, CACAO_VM_ZIP);
- strcat(bootclasspath, ":");
-#endif
- strcat(bootclasspath, JAVA_RUNTIME_LIBRARY_CLASSES);
- }
-
-
- /* set the classpath */
-
- cp = getenv("CLASSPATH");
-
- if (cp != NULL) {
- classpath = MNEW(char, strlen(cp) + strlen("0"));
- strcat(classpath, cp);
- }
- else {
- classpath = MNEW(char, strlen(".") + strlen("0"));
- strcpy(classpath, ".");
- }
-
-
- /* initialize options with default values */
-
- opt_verbose = false;
- opt_directory = NULL;
-
-
- /* parse the options ******************************************************/
-
- vm_args = cacaoh_options_prepare(argc, argv);
-
- while ((opt = options_get(opts, vm_args)) != OPT_DONE) {
- switch (opt) {
- case OPT_IGNORE:
- break;
-
- case OPT_HELP:
- usage();
- break;
-
- case OPT_CLASSPATH:
- /* forget old classpath and set the argument as new classpath */
- MFREE(classpath, char, strlen(classpath));
-
- classpath = MNEW(char, strlen(opt_arg) + strlen("0"));
- strcpy(classpath, opt_arg);
- break;
-
- case OPT_BOOTCLASSPATH:
- /* Forget default bootclasspath and set the argument as
- new boot classpath. */
- MFREE(bootclasspath, char, strlen(bootclasspath));
-
- bootclasspath = MNEW(char, strlen(opt_arg) + strlen("0"));
- strcpy(bootclasspath, opt_arg);
- break;
-
- case OPT_DIRECTORY:
- opt_directory = MNEW(char, strlen(opt_arg) + strlen("0"));
- strcpy(opt_directory, opt_arg);
- break;
-
- case OPT_VERSION:
- version();
- break;
-
- case OPT_VERBOSE:
- opt_verbose = true;
- loadverbose = true;
- break;
-
- default:
- usage();
- }
- }
-
- /**************************** Program start **************************/
-
- if (opt_verbose) {
- log_init(NULL);
- log_println("Java - header-generator started");
- }
-
- utf8_init();
-
- /* initialize the classcache hashtable stuff: lock, hashtable
- (must be done _after_ threads_preinit) */
-
- if (!classcache_init())
- vm_abort("classcache_init failed\n");
-
- /* initialize the loader with bootclasspath (must be done _after_
- thread_preinit) */
-
- if (!suck_init())
- vm_abort("suck_init failed\n");
-
- suck_add(bootclasspath);
-
- /* Also add the normal classpath, so the bootstrap class loader
- can find the files. */
-
- suck_add(classpath);
-
- /* AFTER: classcache_init */
-
- loader_preinit();
- loader_init();
-
-
- /* load Java classes ******************************************************/
-
- for (i = opt_index; i < vm_args->nOptions; i++) {
- cp = vm_args->options[i].optionString;
-
- /* convert classname */
-
- for (j = strlen(cp) - 1; j >= 0; j--) {
- switch (cp[j]) {
- case '.':
- cp[j] = '/';
- break;
- case '_':
- cp[j] = '$';
- break;
- }
- }
-
- /* exceptions are catched with new_exception call */
-
- if (!(c = load_class_bootstrap(utf_new_char(cp))))
- vm_abort("java.lang.NoClassDefFoundError: %s\n", cp);
-
- if (!link_class(c))
- vm_abort("java.lang.LinkageError: %s\n", cp);
-
- headerfile_generate(c, opt_directory);
- }
-
- /************************ Release all resources **********************/
-
- loader_close();
-
- if (opt_verbose) {
- log_println("Java - header-generator stopped");
-#if defined(ENABLE_STATISTICS)
- statistics_print_memory_usage();
-#endif
- }
-
- return 0;
-}
-
-
-/* cacaoh_options_prepare ******************************************************
-
- Prepare the JavaVMInitArgs.
-
-*******************************************************************************/
-
-static JavaVMInitArgs *cacaoh_options_prepare(int argc, char **argv)
-{
- JavaVMInitArgs *vm_args;
- s4 i;
-
- vm_args = NEW(JavaVMInitArgs);
-
- vm_args->nOptions = argc - 1;
- vm_args->options = MNEW(JavaVMOption, argc);
-
- for (i = 1; i < argc; i++)
- vm_args->options[i - 1].optionString = argv[i];
-
- return vm_args;
-}
-
-
-/*
- * 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/cacaoh/dummy.c - dummy functions for cacaoh
-
- 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.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/primitive.h"
-#include "vm/vm.h"
-
-#include "vm/jit/code.h"
-
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/field.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/utf8.h"
-#include "vmcore/system.h"
-
-
-/* global variables ***********************************************************/
-
-bool vm_initializing = true;
-char *_Jv_bootclasspath;
-
-
-java_handle_t *javastring_new_slash_to_dot(utf *u)
-{
- vm_abort("javastring_new_slash_to_dot");
-
- return NULL;
-}
-
-
-/* access *********************************************************************/
-
-bool access_is_accessible_class(classinfo *referer, classinfo *cls)
-{
- return true;
-}
-
-bool access_is_accessible_member(classinfo *referer, classinfo *declarer,
- int32_t memberflags)
-{
- vm_abort("access_is_accessible_member");
-
- return true;
-}
-
-
-/* array **********************************************************************/
-
-java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index)
-{
- java_handle_t *value;
- int32_t size;
-
- if (a == NULL) {
- log_println("array_objectarray_element_get(a=%p, index=%d): NullPointerException", a, index);
- return NULL;
- }
-
- size = LLNI_array_size(a);
-
- if ((index < 0) || (index > size)) {
- log_println("array_objectarray_element_get(a=%p, index=%d): ArrayIndexOutOfBoundsException", a, index);
- return NULL;
- }
-
- value = LLNI_WRAP(LLNI_array_direct(a, index));
-
- return value;
-}
-
-void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value)
-{
- int32_t size;
-
- if (a == NULL) {
- log_println("array_objectarray_element_set(a=%p, index=%d): NullPointerException", a, index);
- return;
- }
-
- size = LLNI_array_size(a);
-
- if ((index < 0) || (index > size)) {
- log_println("array_objectarray_element_set(a=%p, index=%d): ArrayIndexOutOfBoundsException", a, index);
- return;
- }
-
- LLNI_array_direct(a, index) = LLNI_UNWRAP(value);
-}
-
-int32_t array_length_get(java_handle_t *a)
-{
- if (a == NULL) {
- log_println("array_length_get(a=%p): NullPointerException", a);
- return 0;
- }
-
- return LLNI_array_size(a);
-}
-
-
-/* asm ************************************************************************/
-
-void asm_abstractmethoderror(void)
-{
- abort();
-}
-
-void intrp_asm_abstractmethoderror(void)
-{
- abort();
-}
-
-
-/* builtin ********************************************************************/
-
-java_handle_t *builtin_clone(void *env, java_handle_t *o)
-{
- vm_abort("builtin_clone: Not implemented.");
- return NULL;
-}
-
-bool builtin_isanysubclass(classinfo *sub, classinfo *super)
-{
- vm_abort("builtin_isanysubclass: Not implemented.");
- return 0;
-}
-
-bool builtin_instanceof(java_handle_t *o, classinfo *class)
-{
- vm_abort("builtin_instanceof: Not implemented.");
- return 0;
-}
-
-java_handle_t *builtin_new(classinfo *c)
-{
- vm_abort("builtin_new: Not implemented.");
- return NULL;
-}
-
-java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
-{
- java_objectarray_t *oa = (java_objectarray_t*) mem_alloc(
- sizeof(java_array_t) + size * sizeof(java_object_t*));
- java_handle_objectarray_t *h = (java_handle_objectarray_t*) LLNI_WRAP(
- (java_object_t*) oa);
-
- if (h != NULL) {
- LLNI_array_size(h) = size;
- }
-
- return h;
-}
-
-java_handle_bytearray_t *builtin_newarray_byte(int32_t size)
-{
- java_bytearray_t *ba = (java_bytearray_t*) mem_alloc(
- sizeof(java_array_t) + size * sizeof(int8_t));
- java_handle_bytearray_t *h = (java_handle_bytearray_t*) LLNI_WRAP(
- (java_object_t*) ba);
-
- if (h != NULL) {
- LLNI_array_size(h) = size;
- }
-
- return h;
-}
-
-
-/* code ***********************************************************************/
-
-void code_free_code_of_method(methodinfo *m)
-{
-}
-
-
-methodinfo *code_get_methodinfo_for_pv(void *pv)
-{
- return NULL;
-}
-
-
-/* codegen ********************************************************************/
-
-u1 *codegen_generate_stub_compiler(methodinfo *m)
-{
- return NULL;
-}
-
-codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
-{
- return NULL;
-}
-
-#if defined(ENABLE_INTRP)
-u1 *intrp_createcompilerstub(methodinfo *m)
-{
- return NULL;
-}
-#endif
-
-void removecompilerstub(u1 *stub)
-{
-}
-
-void removenativestub(u1 *stub)
-{
-}
-
-
-/* exceptions *****************************************************************/
-
-void exceptions_clear_exception(void)
-{
-}
-
-void exceptions_print_current_exception(void)
-{
- abort();
-}
-
-void exceptions_throw_abstractmethoderror(void)
-{
- fprintf(stderr, "java.lang.AbstractMethodError\n");
-
- abort();
-}
-
-void exceptions_throw_classcircularityerror(classinfo *c)
-{
- fprintf(stderr, "java.lang.ClassCircularityError: ");
-
- utf_display_printable_ascii(c->name);
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
-{
- va_list ap;
-
- fprintf(stderr, "java.lang.ClassFormatError: ");
-
- utf_display_printable_ascii(c->name);
- fprintf(stderr, ": ");
-
- va_start(ap, message);
- vfprintf(stderr, message, ap);
- va_end(ap);
-
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
-{
- fprintf(stderr, "java.lang.IncompatibleClassChangeError: ");
-
- if (c != NULL)
- utf_fprint_printable_ascii_classname(stderr, c->name);
-
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_internalerror(const char *message, ...)
-{
- va_list ap;
-
- fprintf(stderr, "java.lang.InternalError: ");
-
- va_start(ap, message);
- vfprintf(stderr, message, ap);
- va_end(ap);
-
- abort();
-}
-
-void exceptions_throw_linkageerror(const char *message, classinfo *c)
-{
- fprintf(stderr, "java.lang.LinkageError: %s", message);
-
- if (c != NULL)
- utf_fprint_printable_ascii_classname(stderr, c->name);
-
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_noclassdeffounderror(utf *name)
-{
- fprintf(stderr, "java.lang.NoClassDefFoundError: ");
- utf_fprint_printable_ascii(stderr, name);
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
-{
- fprintf(stderr, "java.lang.NoClassDefFoundError: ");
- utf_fprint_printable_ascii(stderr, c->name);
- fprintf(stderr, " (wrong name: ");
- utf_fprint_printable_ascii(stderr, name);
- fprintf(stderr, ")\n");
-
- abort();
-}
-
-void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
-{
- fprintf(stderr, "java.lang.VerifyError: ");
- utf_fprint_printable_ascii(stderr, m->name);
- fprintf(stderr, ": %s", message);
-
- abort();
-}
-
-void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
-{
- fprintf(stderr, "java.lang.NoSuchFieldError: ");
- utf_fprint_printable_ascii(stderr, c->name);
- fprintf(stderr, ".");
- utf_fprint_printable_ascii(stderr, name);
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
-{
- fprintf(stderr, "java.lang.NoSuchMethodError: ");
- utf_fprint_printable_ascii(stderr, c->name);
- fprintf(stderr, ".");
- utf_fprint_printable_ascii(stderr, name);
- utf_fprint_printable_ascii(stderr, desc);
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
-{
- fprintf(stderr, "java.lang.UnsupportedClassVersionError: " );
- utf_display_printable_ascii(c->name);
- fprintf(stderr, " (Unsupported major.minor version %d.%d)\n", ma, mi);
-
- abort();
-}
-
-void exceptions_throw_classnotfoundexception(utf *name)
-{
- fprintf(stderr, "java.lang.ClassNotFoundException: ");
- utf_fprint_printable_ascii(stderr, name);
- fputc('\n', stderr);
-
- abort();
-}
-
-void exceptions_throw_nullpointerexception(void)
-{
- fprintf(stderr, "java.lang.NullPointerException\n");
-
- abort();
-}
-
-
-/* finalizer ******************************************************************/
-
-void finalizer_notify(void)
-{
- vm_abort("finalizer_notify");
-}
-
-void finalizer_run(void *o, void *p)
-{
- vm_abort("finalizer_run");
-}
-
-
-/* gc *************************************************************************/
-
-void gc_reference_register(java_object_t **ref, int32_t reftype)
-{
- vm_abort("gc_reference_register");
-}
-
-int64_t gc_get_heap_size(void)
-{
- return 0;
-}
-
-int64_t gc_get_free_bytes(void)
-{
- return 0;
-}
-
-int64_t gc_get_total_bytes(void)
-{
- return 0;
-}
-
-int64_t gc_get_max_heap_size(void)
-{
- return 0;
-}
-
-
-/* heap ***********************************************************************/
-
-void *heap_alloc_uncollectable(size_t bytelength)
-{
- return calloc(bytelength, 1);
-}
-
-s4 heap_get_hashcode(java_object_t *o)
-{
- return 0;
-}
-
-
-/* instruction ****************************************************************/
-
-methoddesc *instruction_call_site(const instruction *iptr)
-{
- return NULL;
-}
-
-
-/* jit ************************************************************************/
-
-icmdtable_entry_t icmd_table[256] = {};
-
-void jit_invalidate_code(methodinfo *m)
-{
- vm_abort("jit_invalidate_code");
-}
-
-
-/* llni ***********************************************************************/
-
-void llni_critical_start()
-{
-}
-
-void llni_critical_end()
-{
-}
-
-
-/* localref *******************************************************************/
-
-java_handle_t *localref_add(java_object_t *o)
-{
-#if defined(ENABLE_HANDLES)
- java_handle_t *h = (java_handle_t*) mem_alloc(sizeof(java_handle_t));
-
- h->heap_object = o;
-
- return h;
-#else
- return (java_handle_t*) o;
-#endif
-}
-
-
-/* lock ***********************************************************************/
-
-void lock_init_object_lock(java_object_t *o)
-{
-}
-
-bool lock_monitor_enter(java_handle_t *o)
-{
- return true;
-}
-
-bool lock_monitor_exit(java_handle_t *o)
-{
- return true;
-}
-
-
-/* md *************************************************************************/
-
-void md_param_alloc(methoddesc *md)
-{
-}
-
-void md_param_alloc_native(methoddesc *md)
-{
-}
-
-
-/* memory *********************************************************************/
-
-void *mem_alloc(int32_t size)
-{
- /* real implementation in src/mm/memory.c clears memory */
-
- return calloc(size, 1);
-}
-
-void *mem_realloc(void *src, int32_t len1, int32_t len2)
-{
- return realloc(src, len2);
-}
-
-void mem_free(void *m, int32_t size)
-{
- free(m);
-}
-
-void *dumpmemory_get(size_t size)
-{
- return malloc(size);
-}
-
-int32_t dumpmemory_marker(void)
-{
- return 0;
-}
-
-void dumpmemory_release(int32_t size)
-{
-}
-
-
-/* package ********************************************************************/
-
-/* void Package_add(java_handle_t *packagename) */
-void Package_add(utf *packagename)
-{
- /* Do nothing. */
-}
-
-
-/* primitive ******************************************************************/
-
-classinfo *primitive_arrayclass_get_by_type(int type)
-{
- return NULL;
-}
-
-classinfo *primitive_class_get_by_type(int type)
-{
- abort();
- return NULL;
-}
-
-classinfo *primitive_class_get_by_char(char ch)
-{
- abort();
- return NULL;
-}
-
-
-/* properties *****************************************************************/
-
-void properties_add(char *key, char *value)
-{
-}
-
-char *properties_get(char *key)
-{
- return NULL;
-}
-
-
-/* reflect ********************************************************************/
-
-java_handle_t *reflect_constructor_new(fieldinfo *f)
-{
- vm_abort("reflect_constructor_new: Not implemented.");
- return NULL;
-}
-
-java_handle_t *reflect_field_new(fieldinfo *f)
-{
- vm_abort("reflect_field_new: Not implemented.");
- return NULL;
-}
-
-java_handle_t *reflect_method_new(methodinfo *m)
-{
- vm_abort("reflect_method_new: Not implemented.");
- return NULL;
-}
-
-
-/* resolve ********************************************************************/
-
-void resolve_handle_pending_exception(bool throwError)
-{
- vm_abort("resolve_handle_pending_exception: Not implemented.");
-}
-
-bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
-{
- abort();
-
- return false;
-}
-
-/* stupid resolving implementation used by resolve_classref_or_classinfo_eager */
-/* This function does eager resolving without any access checks. */
-
-static classinfo * dummy_resolve_class_from_name(classinfo *referer,
- utf *classname,
- bool checkaccess)
-{
- classinfo *cls = NULL;
- char *utf_ptr;
- int len;
-
- assert(referer);
- assert(classname);
-
- /* lookup if this class has already been loaded */
-
- cls = classcache_lookup(referer->classloader, classname);
-
- if (!cls) {
- /* resolve array types */
-
- if (classname->text[0] == '[') {
- utf_ptr = classname->text + 1;
- len = classname->blength - 1;
-
- /* classname is an array type name */
-
- switch (*utf_ptr) {
- case 'L':
- utf_ptr++;
- len -= 2;
- /* FALLTHROUGH */
- case '[':
- /* the component type is a reference type */
- /* resolve the component type */
- if ((cls = dummy_resolve_class_from_name(referer,
- utf_new(utf_ptr,len),
- checkaccess)) == NULL)
- return NULL; /* exception */
-
- /* create the array class */
- cls = class_array_of(cls,false);
- if (!cls)
- return NULL; /* exception */
- }
- }
-
- /* load the class */
- if (!cls) {
- if (!(cls = load_class_from_classloader(classname,
- referer->classloader)))
- return false; /* exception */
- }
- }
-
- /* the class is now loaded */
- assert(cls);
- assert(cls->state & CLASS_LOADED);
-
- return cls;
-}
-
-
-classinfo * resolve_classref_or_classinfo_eager(classref_or_classinfo cls,
- bool checkaccess)
-{
- classinfo *c;
-
- assert(cls.any);
-
- if (IS_CLASSREF(cls)) {
- /* we must resolve this reference */
-
- if ((c = dummy_resolve_class_from_name(cls.ref->referer, cls.ref->name,
- checkaccess)) == NULL)
- return NULL;
- }
- else {
- /* cls has already been resolved */
- c = cls.cls;
- }
-
- assert(c);
- assert(c->state & CLASS_LOADED);
-
- /* succeeded */
- return c;
-}
-
-
-/* stacktrace *****************************************************************/
-
-java_handle_objectarray_t *stacktrace_getClassContext()
-{
- return NULL;
-}
-
-
-/* threads ********************************************************************/
-
-#if defined(HAVE___THREAD)
-__thread threadobject *thread_current;
-#else
-#include <pthread.h>
-pthread_key_t thread_current_key;
-#endif
-
-intptr_t threads_get_current_tid(void)
-{
- return 0;
-}
-
-void threads_cast_stopworld(void)
-{
-}
-
-void threads_cast_startworld(void)
-{
-}
-
-
-/* vm *************************************************************************/
-
-void vm_printconfig(void)
-{
-}
-
-void vm_abort(const char *text, ...)
-{
- va_list ap;
-
- va_start(ap, text);
- vfprintf(stderr, text, ap);
- va_end(ap);
-
- system_abort();
-}
-
-void vm_abort_errno(const char *text, ...)
-{
- va_list ap;
-
- va_start(ap, text);
- vm_abort_errnum(errno, text, ap);
- va_end(ap);
-}
-
-void vm_abort_errnum(int errnum, const char *text, ...)
-{
- va_list ap;
-
- log_start();
-
- va_start(ap, text);
- log_vprint(text, ap);
- va_end(ap);
-
- log_print(": %s", system_strerror(errnum));
- log_finish();
-
- system_abort();
-}
-
-java_handle_t *vm_call_method(methodinfo *m, java_handle_t *o, ...)
-{
- return NULL;
-}
-
-
-/* XXX */
-
-void stringtable_update(void)
-{
- log_println("stringtable_update: REMOVE ME!");
-}
-
-java_object_t *literalstring_new(utf *u)
-{
- log_println("literalstring_new: REMOVE ME!");
-
- return NULL;
-}
-
-
-void print_dynamic_super_statistics(void)
-{
-}
-
-
-#if defined(ENABLE_VMLOG)
-void vmlog_cacao_set_prefix(const char *arg)
-{
-}
-
-void vmlog_cacao_set_stringprefix(const char *arg)
-{
-}
-
-void vmlog_cacao_set_ignoreprefix(const char *arg)
-{
-}
-#endif
-
-
-/*
- * 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/cacaoh/headers.c - functions for header generation
-
- 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 <ctype.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(ENABLE_THREADS)
-# if defined(__DARWIN__)
-# include <signal.h>
-# endif
-# include <ucontext.h>
-#endif
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#include "toolbox/chain.h"
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
-
-/************************ global variables **********************/
-
-#define ACC_NATIVELY_OVERLOADED 0x10000000
-
-#if defined(ENABLE_HANDLES)
-# define HEAP_PREFIX "heap_"
-#else
-# define HEAP_PREFIX ""
-#endif
-
-chain *ident_chain; /* chain with method and field names in current class */
-FILE *file = NULL;
-static uint32_t outputsize;
-static bool dopadding;
-
-
-static void printIDpart(int c)
-{
- if ((c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= '0' && c <= '9') ||
- (c == '_'))
- putc(c, file);
- else
- putc('_', file);
-}
-
-
-void printID(utf *u)
-{
- char *utf_ptr = u->text;
- int i;
-
- for (i = 0; i < utf_get_number_of_u2s(u); i++)
- printIDpart(utf_nextu2(&utf_ptr));
-}
-
-
-static void addoutputsize(int len)
-{
- uint32_t newsize;
- int32_t i;
-
- if (!dopadding)
- return;
-
- newsize = MEMORY_ALIGN(outputsize, len);
-
- for (i = outputsize; i < newsize; i++)
- fprintf(file, " uint8_t pad%d\n", (int) i);
-
- outputsize = newsize;
-}
-
-
-void printOverloadPart(utf *desc)
-{
- char *utf_ptr=desc->text;
- uint16_t c;
-
- fprintf(file, "__");
-
- while ((c = utf_nextu2(&utf_ptr)) != ')') {
- switch (c) {
- case 'I':
- case 'S':
- case 'B':
- case 'C':
- case 'Z':
- case 'J':
- case 'F':
- case 'D':
- fprintf(file, "%c", (char) c);
- break;
- case '[':
- fprintf(file, "_3");
- break;
- case 'L':
- putc('L', file);
- while ((c = utf_nextu2(&utf_ptr)) != ';')
- printIDpart(c);
- fprintf(file, "_2");
- break;
- case '(':
- break;
- default:
- log_text("invalid method descriptor");
- assert(0);
- }
- }
-}
-
-static char *printtype(char *utf_ptr, char *prefix, char *infix)
-{
- uint16_t c;
-
- switch (utf_nextu2(&utf_ptr)) {
- case 'V':
- fprintf(file, "void");
- break;
- case 'I':
- case 'S':
- case 'B':
- case 'C':
- case 'Z':
- addoutputsize(4);
- fprintf(file, "int32_t");
- break;
- case 'J':
- addoutputsize(8);
- fprintf(file, "int64_t");
- break;
- case 'F':
- addoutputsize(4);
- fprintf(file, "float");
- break;
- case 'D':
- addoutputsize(8);
- fprintf(file, "double");
- break;
- case '[':
- addoutputsize ( sizeof(java_array_t*) );
- switch (utf_nextu2(&utf_ptr)) {
- case 'I': fprintf (file, "java%s_intarray_t*", infix); break;
- case 'J': fprintf (file, "java%s_longarray_t*", infix); break;
- case 'Z': fprintf (file, "java%s_booleanarray_t*", infix); break;
- case 'B': fprintf (file, "java%s_bytearray_t*", infix); break;
- case 'S': fprintf (file, "java%s_shortarray_t*", infix); break;
- case 'C': fprintf (file, "java%s_chararray_t*", infix); break;
- case 'F': fprintf (file, "java%s_floatarray_t*", infix); break;
- case 'D': fprintf (file, "java%s_doublearray_t*", infix); break;
-
- case '[': fprintf(file, "java%s_objectarray_t*", infix);
- while ((c = utf_nextu2(&utf_ptr)) == '[');
- if (c == 'L')
- while (utf_nextu2(&utf_ptr) != ';');
- break;
-
- case 'L': fprintf(file, "java%s_objectarray_t*", infix);
- while (utf_nextu2(&utf_ptr) != ';');
- break;
- default:
- log_text("invalid type descriptor");
- assert(0);
- }
- break;
-
- case 'L':
- addoutputsize ( sizeof(java_object_t*));
- fprintf (file, "struct %s", prefix);
- while ( (c = utf_nextu2(&utf_ptr)) != ';' ) printIDpart (c);
- fprintf (file, "*");
- break;
-
- default:
- log_text("Unknown type in field descriptor");
- assert(0);
- }
-
- return utf_ptr;
-}
-
-
-/***** determine the number of entries of a utf string in the ident chain *****/
-
-static int searchidentchain_utf(utf *ident)
-{
- utf *u = chain_first(ident_chain); /* first element of list */
- int count = 0;
-
- while (u) {
- if (u==ident) count++; /* string found */
- u = chain_next(ident_chain); /* next element in list */
- }
-
- return count;
-}
-
-
-/************** print structure for direct access to objects ******************/
-
-static void printfields(classinfo *c)
-{
- int32_t i;
- fieldinfo *f;
- int ident_count;
-
- if (!c) {
- addoutputsize(sizeof(java_object_t));
- fprintf(file, " java_object_t header;\n");
- return;
- }
-
- printfields(c->super);
-
- for (i = 0; i < c->fieldscount; i++) {
- f = &(c->fields[i]);
-
- if (!(f->flags & ACC_STATIC)) {
- fprintf(file, " ");
- printtype(f->descriptor->text, HEAP_PREFIX, "");
- fprintf(file, " ");
- utf_fprint_printable_ascii(file, f->name);
-
- /* rename multiple fieldnames */
- if ((ident_count = searchidentchain_utf(f->name)))
- fprintf(file, "%d", ident_count - 1);
- chain_addlast(ident_chain, f->name);
-
- fprintf(file, ";\n");
- }
- }
-}
-
-
-/***************** store prototype for native method in file ******************/
-
-void printmethod(methodinfo *m)
-{
- char *utf_ptr;
- int32_t paramnum = 1;
-
- /* search for return-type in descriptor */
- utf_ptr = m->descriptor->text;
- while (utf_nextu2(&utf_ptr) != ')');
-
- /* create remarks */
- fprintf(file, "\n/*\n * Class: ");
- utf_fprint_printable_ascii(file, m->clazz->name);
- fprintf(file, "\n * Method: ");
- utf_fprint_printable_ascii(file, m->name);
- fprintf(file, "\n * Signature: ");
- utf_fprint_printable_ascii(file, m->descriptor);
- fprintf(file, "\n */\n");
-
- /* create prototype */
- fprintf(file, "JNIEXPORT ");
- printtype(utf_ptr, "", "_handle");
- fprintf(file, " JNICALL Java_");
- printID(m->clazz->name);
-
- chain_addlast(ident_chain, m->name);
-
- fprintf(file, "_");
- printID(m->name);
-
- /* ATTENTION: We use a dummy flag here. */
-
- if (m->flags & ACC_NATIVELY_OVERLOADED)
- printOverloadPart(m->descriptor);
-
- fprintf(file, "(JNIEnv *env");
-
- utf_ptr = m->descriptor->text + 1;
-
- if (!(m->flags & ACC_STATIC)) {
- fprintf(file, ", struct ");
- printID(m->clazz->name);
- fprintf(file, "* _this");
-
- } else {
- fprintf(file, ", jclass clazz");
- }
-
- if ((*utf_ptr) != ')') fprintf(file, ", ");
-
- while ((*utf_ptr) != ')') {
- utf_ptr = printtype(utf_ptr, "", "_handle");
- fprintf(file, " par%d", paramnum++);
- if ((*utf_ptr)!=')') fprintf(file, ", ");
- }
-
- fprintf(file, ");\n\n");
-}
-
-
-/******* remove package-name in fully-qualified classname *********************/
-
-void gen_header_filename(char *buffer, utf *u)
-{
- int32_t i;
-
- for (i = 0; i < utf_get_number_of_u2s(u); i++) {
- if ((u->text[i] == '/') || (u->text[i] == '$')) {
- buffer[i] = '_'; /* convert '$' and '/' to '_' */
-
- } else {
- buffer[i] = u->text[i];
- }
- }
- buffer[utf_get_number_of_u2s(u)] = '\0';
-}
-
-
-/* create headerfile for classes and store native methods in chain ************/
-
-void headerfile_generate(classinfo *c, char *opt_directory)
-{
- char header_filename[1024] = "";
- char classname[1024];
- char uclassname[1024];
- int32_t i;
- methodinfo *m;
- int32_t j;
- methodinfo *m2;
- bool nativelyoverloaded;
-
- /* prevent compiler warnings */
-
- nativelyoverloaded = false;
-
- /* open headerfile for class */
- gen_header_filename(classname, c->name);
-
- /* create chain for renaming fields */
- ident_chain = chain_new();
-
- if (opt_directory) {
- sprintf(header_filename, "%s/%s.h", opt_directory, classname);
-
- } else {
- sprintf(header_filename, "%s.h", classname);
- }
-
- file = fopen(header_filename, "w");
- if (!file) {
- log_text("Can not open file to store header information");
- assert(0);
- }
-
- fprintf(file, "/* This file is machine generated, don't edit it! */\n\n");
-
- /* convert to uppercase */
- for (i = 0; classname[i]; i++) {
- uclassname[i] = toupper(classname[i]);
- }
- uclassname[i] = '\0';
-
- fprintf(file, "#ifndef _%s_H\n#define _%s_H\n\n", uclassname, uclassname);
-
- /* create structure for direct access to objects */
- fprintf(file, "/* Structure information for class: ");
- utf_fprint_printable_ascii(file, c->name);
- fprintf(file, " */\n\n");
- fprintf(file, "typedef struct %s", HEAP_PREFIX);
- printID(c->name);
- fprintf(file, " {\n");
- outputsize = 0;
- dopadding = true;
-
- printfields(c);
-
- fprintf(file, "} %s", HEAP_PREFIX);
- printID(c->name);
- fprintf(file, ";\n\n");
-
-#if defined(ENABLE_HANDLES)
- /* create structure for indirection cell */
- fprintf(file, "typedef struct ");
- printID(c->name);
- fprintf(file, " {\n");
- fprintf(file, " %s", HEAP_PREFIX);
- printID(c->name);
- fprintf(file, " *heap_object;\n");
- fprintf(file, "} ");
- printID(c->name);
- fprintf(file, ";\n\n");
-#endif
-
- /* create chain for renaming overloaded methods */
- chain_free(ident_chain);
- ident_chain = chain_new();
-
- /* create method-prototypes */
-
- /* find overloaded methods */
-
- for (i = 0; i < c->methodscount; i++) {
- m = &(c->methods[i]);
-
- if (!(m->flags & ACC_NATIVE))
- continue;
-
- /* We use a dummy flag here. */
-
- if (!(m->flags & ACC_NATIVELY_OVERLOADED)) {
- nativelyoverloaded = false;
-
- for (j = i + 1; j < c->methodscount; j++) {
- m2 = &(c->methods[j]);
-
- if (!(m2->flags & ACC_NATIVE))
- continue;
-
- if (m->name == m2->name) {
- m2->flags |= ACC_NATIVELY_OVERLOADED;
- nativelyoverloaded = true;
- }
- }
- }
-
- if (nativelyoverloaded == true)
- m->flags |= ACC_NATIVELY_OVERLOADED;
- }
-
- for (i = 0; i < c->methodscount; i++) {
- m = &(c->methods[i]);
-
- if (m->flags & ACC_NATIVE)
- printmethod(m);
- }
-
- chain_free(ident_chain);
-
- fprintf(file, "#endif\n\n");
-
- fclose(file);
-}
-
-
-/******** print classname, '$' used to seperate inner-class name ***********/
-
-void print_classname(classinfo *clazz)
-{
- utf *u = clazz->name;
- char *endpos = u->text + u->blength;
- char *utf_ptr = u->text;
- uint16_t c;
-
- while (utf_ptr < endpos) {
- if ((c = utf_nextu2(&utf_ptr)) == '_')
- putc('$', file);
- else
- putc(c, file);
- }
-}
-
-
-/*
- * 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/cacaoh/headers.h - export functions for header generation
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _HEADERS_H
-#define _HEADERS_H
-
-#include "config.h"
-
-#include "toolbox/chain.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/utf8.h"
-
-
-/* export variables ***********************************************************/
-
-extern chain *nativemethod_chain;
-extern chain *nativeclass_chain;
-extern chain *ident_chain;
-extern FILE *file;
-
-
-/* function prototypes ********************************************************/
-
-void printID(utf *u);
-void printOverloadPart(utf *desc);
-void printmethod(methodinfo *m);
-void gen_header_filename(char *buffer, utf *u);
-void headerfile_generate(classinfo *c, char *opt_directory);
-void print_classname(classinfo *clazz);
-
-#endif /* _HEADERS_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:
- */
* @throws InterruptedException if the Thread is (or was) interrupted;
* it's <i>interrupted status</i> will be cleared
*/
- static void sleep(long ms, int ns) throws InterruptedException
- {
- // Note: JDK treats a zero length sleep is like Thread.yield(),
- // without checking the interrupted status of the thread.
- // It's unclear if this is a bug in the implementation or the spec.
- // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203
- if (ms == 0 && ns == 0)
- {
- if (Thread.interrupted())
- throw new InterruptedException();
- return;
- }
+// static void sleep(long ms, int ns) throws InterruptedException
+// {
+// // Note: JDK treats a zero length sleep is like Thread.yield(),
+// // without checking the interrupted status of the thread.
+// // It's unclear if this is a bug in the implementation or the spec.
+// // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203
+// if (ms == 0 && ns == 0)
+// {
+// if (Thread.interrupted())
+// throw new InterruptedException();
+// return;
+// }
- // Compute end time, but don't overflow
- long now = System.currentTimeMillis();
- long end = now + ms;
- if (end < now)
- end = Long.MAX_VALUE;
+// // Compute end time, but don't overflow
+// long now = System.currentTimeMillis();
+// long end = now + ms;
+// if (end < now)
+// end = Long.MAX_VALUE;
- // A VM is allowed to return from wait() without notify() having been
- // called, so we loop to handle possible spurious wakeups.
- VMThread vt = Thread.currentThread().vmThread;
- synchronized (vt)
- {
- while (true)
- {
- vt.wait(ms, ns);
- now = System.currentTimeMillis();
- if (now >= end)
- break;
- ms = end - now;
- ns = 0;
- }
- }
- }
+// // A VM is allowed to return from wait() without notify() having been
+// // called, so we loop to handle possible spurious wakeups.
+// VMThread vt = Thread.currentThread().vmThread;
+// synchronized (vt)
+// {
+// while (true)
+// {
+// vt.wait(ms, ns);
+// now = System.currentTimeMillis();
+// if (now >= end)
+// break;
+// ms = end - now;
+// ns = 0;
+// }
+// }
+// }
+ static native void sleep(long ms, int ns) throws InterruptedException;
/**
* Determine whether the current Thread has been interrupted, and clear
* Parses the annotations described by the passed byte array,
* but returns Annotation[] so I don't have to do this in C.
*
- * @author Mathias Panzenböck
+ * @author Mathias Panzenboeck
*
* @param rawAnnotations are the unparsed annotations
* @param constPool is the constant pool of the declaring class
/**
* Parses parameter annotations.
*
- * @author Mathias Panzenböck
+ * @author Mathias Panzenboeck
*
* @param parameterAnnotations are the unparsed parameter annotations
* @param constPool is the constant pool of the declaring class
* This method is basically copied from OpenJDKs
* java.lang.reflect.Method.getAnnotationDefault()
*
- * @author Mathias Panzenböck
+ * @author Mathias Panzenboeck
*
* @param method represents the method for which the annotation default value has to be parsed
* @param annotationDefault is the unparsed annotation default value
* sun.misc.SharedSecrets.getJavaLangAccess().setAnnotationType() so
* this class can be used with gnu classpath.
*
- * @author Mathias Panzenböck
+ * @author Mathias Panzenboeck
*/
private static Map<Class, AnnotationType> annotationTypes =
new HashMap<Class, AnnotationType>();
if DISABLE_GC
GC_FILE = \
- nogc.c
+ gc-none.cpp
endif
if ENABLE_GC_BOEHM
boehm-gc
GC_FILE = \
- boehm.c
+ gc-boehm.cpp
GC_LIB = \
$(top_builddir)/src/mm/boehm-gc/libgc.la
dumpmemory.c \
dumpmemory.h \
$(GC_FILE) \
- gc-common.h \
+ gc.hpp \
memory.c \
memory.h
libmm_la_LIBADD = \
$(GC_LIB)
+if ENABLE_TLH
+libmm_la_SOURCES += \
+ tlh.h \
+ tlh.c
+endif
## Local variables:
## mode: Makefile
## Process this file with automake to produce Makefile.in.
+ACLOCAL_AMFLAGS = -I m4
+
DISTCLEANFILES = \
atomic_ops.c \
atomic_ops_sysdeps.S \
*/
GC_API void GC_init(void);
-/* Added for cacao */
-int GC_signum1();
-int GC_signum2();
-/* cacao END */
-
/*
* general purpose allocation routines, with roughly malloc calling conv.
* The atomic versions promise that no relevant pointers are contained
# define SEQUENT
# define mach_type_known
# endif
-# if defined(sun) && (defined(i386) || defined(__i386__))
+# if (defined(sun) || defined(__sun)) && (defined(i386) || defined(__i386__))
# define I386
# define SOLARIS
# define mach_type_known
# endif
-# if defined(sun) && defined(__amd64)
+# if (defined(sun) || defined(__sun)) && defined(__amd64)
# define X86_64
# define SOLARIS
# define mach_type_known
return n_live_threads;
}
-void lock_stopworld(int);
-void unlock_stopworld();
-
void GC_stop_world()
{
int i;
}
}
-/* Added for cacao */
-int GC_signum1()
-{
- return SIG_SUSPEND;
-}
-
-int GC_signum2()
-{
- return SIG_THR_RESTART;
-}
-/* cacao END */
-
#endif
+++ /dev/null
-/* src/mm/boehm.c - interface for boehm gc
-
- 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>
-
-#if defined(ENABLE_THREADS) && defined(__LINUX__)
-#define GC_LINUX_THREADS
-#endif
-#if defined(ENABLE_THREADS) && defined(__IRIX__)
-#define GC_IRIX_THREADS
-#endif
-#if defined(ENABLE_THREADS) && defined(__DARWIN__)
-#define GC_DARWIN_THREADS
-#endif
-
-#include "boehm-gc/include/gc.h"
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/finalizer.h"
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-
-
-/* global variables ***********************************************************/
-
-static bool in_gc_out_of_memory = false; /* is GC out of memory? */
-
-
-/* prototype static functions *************************************************/
-
-static void gc_ignore_warnings(char *msg, GC_word arg);
-
-
-/* gc_init *********************************************************************
-
- Initializes the boehm garbage collector.
-
-*******************************************************************************/
-
-void gc_init(size_t heapmaxsize, size_t heapstartsize)
-{
- size_t heapcurrentsize;
-
- TRACESUBSYSTEMINITIALIZATION("gc_init");
-
- /* just to be sure (should be set to 1 by JAVA_FINALIZATION macro) */
-
- GC_java_finalization = 1;
-
- /* Ignore pointers that do not point to the start of an object. */
-
- GC_all_interior_pointers = 0;
-
- /* suppress warnings */
-
- GC_set_warn_proc(gc_ignore_warnings);
-
- /* install a GC notifier */
-
- GC_finalize_on_demand = 1;
- GC_finalizer_notifier = finalizer_notify;
-
- /* define OOM function */
-
- GC_oom_fn = gc_out_of_memory;
-
- GC_INIT();
-
- /* set the maximal heap size */
-
- GC_set_max_heap_size(heapmaxsize);
-
- /* set the initial heap size */
-
- heapcurrentsize = GC_get_heap_size();
-
- if (heapstartsize > heapcurrentsize)
- GC_expand_hp(heapstartsize - heapcurrentsize);
-}
-
-
-static void gc_ignore_warnings(char *msg, GC_word arg)
-{
-}
-
-
-void *heap_alloc_uncollectable(size_t size)
-{
- void *p;
-
- p = GC_MALLOC_UNCOLLECTABLE(size);
-
- /* clear allocated memory region */
-
- MSET(p, 0, uint8_t, size);
-
- return p;
-}
-
-
-/* heap_alloc ******************************************************************
-
- Allocates memory on the Java heap.
-
-*******************************************************************************/
-
-void *heap_alloc(size_t size, int references, methodinfo *finalizer, bool collect)
-{
- void *p;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_end;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- /* We can't use a bool here for references, as it's passed as a
- bitmask in builtin_new. Thus we check for != 0. */
-
- if (references != 0)
- p = GC_MALLOC(size);
- else
- p = GC_MALLOC_ATOMIC(size);
-
- if (p == NULL)
- return NULL;
-
- if (finalizer != NULL)
- GC_REGISTER_FINALIZER_NO_ORDER(p, finalizer_run, 0, 0, 0);
-
- /* clear allocated memory region */
-
- MSET(p, 0, uint8_t, size);
-
- RT_TIMING_GET_TIME(time_end);
- RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_GC_ALLOC);
-
- return p;
-}
-
-
-void heap_free(void *p)
-{
- GC_FREE(p);
-}
-
-void gc_call(void)
-{
- if (opt_verbosegc)
- dolog("Garbage Collection: previous/now = %d / %d ",
- 0, 0);
-
- GC_gcollect();
-}
-
-
-int64_t gc_get_heap_size(void)
-{
- return GC_get_heap_size();
-}
-
-
-int64_t gc_get_free_bytes(void)
-{
- return GC_get_free_bytes();
-}
-
-
-/* gc_get_total_bytes **********************************************************
-
- Returns the number of total bytes currently used on the Java heap.
-
-*******************************************************************************/
-
-int64_t gc_get_total_bytes(void)
-{
- return GC_get_total_bytes();
-}
-
-
-int64_t gc_get_max_heap_size(void)
-{
- return GC_get_max_heap_size();
-}
-
-
-void gc_invoke_finalizers(void)
-{
- GC_invoke_finalizers();
-}
-
-
-void gc_finalize_all(void)
-{
- GC_finalize_all();
-}
-
-
-/* gc_out_of_memory ************************************************************
-
- This function is called when boehm detects that it is OOM.
-
-*******************************************************************************/
-
-void *gc_out_of_memory(size_t bytes_requested)
-{
- /* if this happens, we are REALLY out of memory */
-
- if (in_gc_out_of_memory) {
- /* this is all we can do... */
- vm_abort("gc_out_of_memory: out of memory");
- }
-
- in_gc_out_of_memory = true;
-
- /* try to release some memory */
-
- gc_call();
-
- /* now instantiate the exception */
-
- exceptions_throw_outofmemoryerror();
-
- in_gc_out_of_memory = false;
-
- return NULL;
-}
-
-
-/*
- * 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:
- */
/* mm/cacao-gc/final.c - GC module for finalization and weak references
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* mm/cacao-gc/final.h - GC header for finalization and weak references
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#ifndef _FINAL_H
#define _FINAL_H
+#include "config.h"
#include "vm/types.h"
#include "toolbox/list.h"
-#include "vmcore/method.h"
+#include "vm/method.h"
/* Global Variables ***********************************************************/
#include "vm/types.h"
#include "threads/lock-common.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "compact.h"
#include "copy.h"
#include "rootset.h"
#include "mm/memory.h"
#include "toolbox/logging.h"
+
#include "vm/finalizer.h"
-#include "vm/vm.h"
-#include "vmcore/rt-timing.h"
+#include "vm/rt-timing.h"
+#include "vm/vm.hpp"
/* Global Variables ***********************************************************/
#include "config.h"
#include "vm/types.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/list.h"
#include "vm/jit/replace.h"
#if !defined(NDEBUG) && defined(GC_DEBUGGING)
# include <assert.h>
-# include "vmcore/options.h"
+# include "vm/options.h"
# define GC_LOG(code) if (opt_verbosegc) { code; }
# define GC_ASSERT(assertion) assert(assertion)
#else
/* mm/cacao-gc/heap.c - GC module for heap management
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/java_lang_String.h"
#include "native/llni.h"
#include "toolbox/logging.h"
+
#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
+#include "vm/options.h"
+#include "vm/rt-timing.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
/* Global Variables ***********************************************************/
#include "rootset.h"
#include "mm/memory.h"
#include "toolbox/logging.h"
+
#include "vm/global.h"
-#include "vm/vm.h"
-#include "vmcore/linker.h"
+#include "vm/linker.h"
+#include "vm/vm.hpp"
/* Helper Macros **************************************************************/
#include "mm/memory.h"
#include "threads/threadlist.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/logging.h"
#include "vm/global.h"
#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
rootset_t *rootset_create(void)
#include "config.h"
#include "vm/types.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
+
+#include "vm/method.h"
#include "vm/jit/replace.h"
-#include "vmcore/method.h"
/* Structures *****************************************************************/
#include <sys/mman.h> /* REMOVEME */
#include "threads/lock-common.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "mm/codememory.h"
#include "mm/memory.h"
-#include "vmcore/options.h"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/system.h"
-
-#include "vm/global.h"
-
/* global code memory variables ***********************************************/
/* Get the pagesize of this architecture. */
- pagesize = system_getpagesize();
+ pagesize = os_getpagesize();
}
/* allocate the memory */
- p = system_mmap_anonymous(NULL, code_memory_size,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE);
+ p = os_mmap_anonymous(NULL, code_memory_size,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE);
/* set global code memory pointer */
#include "config.h"
#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <sys/types.h>
void *codememory_get(size_t size);
void codememory_release(void *p, size_t size);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _CODEMEMORY_H */
#include "mm/dumpmemory.h"
#include "mm/memory.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
-#include "vmcore/options.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/system.h"
-
-#include "vm/vm.h"
+#include "vm/vm.hpp"
/*******************************************************************************
/* clear the memory */
- (void) system_memset(p, MEMORY_CLEAR_BYTE, da->size);
+ (void) os_memset(p, MEMORY_CLEAR_BYTE, da->size);
}
#endif /* defined(ENABLE_MEMCHECK) */
dst = dumpmemory_get(len2);
- (void) system_memcpy(dst, src, len1);
+ (void) os_memcpy(dst, src, len1);
#if defined(ENABLE_MEMCHECK)
/* destroy the source */
- (void) system_memset(src, MEMORY_CLEAR_BYTE, len1);
+ (void) os_memset(src, MEMORY_CLEAR_BYTE, len1);
#endif
return dst;
/* invalidate the freed memory */
- (void) system_memset(da->mem, MEMORY_CLEAR_BYTE, da->size);
+ (void) os_memset(da->mem, MEMORY_CLEAR_BYTE, da->size);
FREE(da, dump_allocation_t);
/* Release the dump memory and the dumpinfo structure. */
- system_free(tmp->dumpmem);
- system_free(tmp);
+ os_free(tmp->dumpmem);
+ os_free(tmp);
}
#endif /* defined(DISABLE_DUMP) */
#ifndef _DUMPMEMORY_H
#define _DUMPMEMORY_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* forward typedefs ***********************************************************/
typedef struct dumpblock_t dumpblock_t;
#define DNEW(type) ((type *) dumpmemory_get(sizeof(type)))
#define DMNEW(type,num) ((type *) dumpmemory_get(sizeof(type) * (num)))
-#define DMREALLOC(ptr,type,num1,num2) dumpmemory_realloc((ptr), sizeof(type) * (num1), \
- sizeof(type) * (num2))
+#define DMREALLOC(ptr,type,num1,num2) ((type*) dumpmemory_realloc((ptr), sizeof(type) * (num1), \
+ sizeof(type) * (num2)))
/* function prototypes ********************************************************/
int32_t dumpmemory_marker(void);
void dumpmemory_release(int32_t size);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _DUMPMEMORY_H */
--- /dev/null
+/* src/mm/gc-boehm.cpp - interface for boehm gc
+
+ 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>
+
+#if defined(ENABLE_THREADS) && defined(__LINUX__)
+#define GC_LINUX_THREADS
+#endif
+#if defined(ENABLE_THREADS) && defined(__IRIX__)
+#define GC_IRIX_THREADS
+#endif
+#if defined(ENABLE_THREADS) && defined(__DARWIN__)
+#define GC_DARWIN_THREADS
+#endif
+
+#include "boehm-gc/include/gc.h"
+#include "mm/gc.hpp"
+#include "mm/memory.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/finalizer.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/rt-timing.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+
+/* global variables ***********************************************************/
+
+static bool in_gc_out_of_memory = false; /* is GC out of memory? */
+
+
+/* prototype static functions *************************************************/
+
+static void gc_ignore_warnings(char *msg, GC_word arg);
+
+
+/* gc_init *********************************************************************
+
+ Initializes the boehm garbage collector.
+
+*******************************************************************************/
+
+void gc_init(size_t heapmaxsize, size_t heapstartsize)
+{
+ size_t heapcurrentsize;
+
+ TRACESUBSYSTEMINITIALIZATION("gc_init");
+
+ /* just to be sure (should be set to 1 by JAVA_FINALIZATION macro) */
+
+ GC_java_finalization = 1;
+
+ /* Ignore pointers that do not point to the start of an object. */
+
+ GC_all_interior_pointers = 0;
+
+ /* suppress warnings */
+
+ GC_set_warn_proc(gc_ignore_warnings);
+
+ /* install a GC notifier */
+
+ GC_finalize_on_demand = 1;
+ GC_finalizer_notifier = finalizer_notify;
+
+ /* define OOM function */
+
+ GC_oom_fn = gc_out_of_memory;
+
+ GC_INIT();
+
+ /* set the maximal heap size */
+
+ GC_set_max_heap_size(heapmaxsize);
+
+ /* set the initial heap size */
+
+ heapcurrentsize = GC_get_heap_size();
+
+ if (heapstartsize > heapcurrentsize)
+ GC_expand_hp(heapstartsize - heapcurrentsize);
+}
+
+
+static void gc_ignore_warnings(char *msg, GC_word arg)
+{
+}
+
+
+void *heap_alloc_uncollectable(size_t size)
+{
+ void *p;
+
+ p = GC_MALLOC_UNCOLLECTABLE(size);
+
+ /* clear allocated memory region */
+
+ MSET(p, 0, uint8_t, size);
+
+ return p;
+}
+
+
+/* heap_alloc ******************************************************************
+
+ Allocates memory on the Java heap.
+
+*******************************************************************************/
+
+void *heap_alloc(size_t size, int references, methodinfo *finalizer, bool collect)
+{
+ void *p;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_end;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ /* We can't use a bool here for references, as it's passed as a
+ bitmask in builtin_new. Thus we check for != 0. */
+
+ if (references != 0)
+ p = GC_MALLOC(size);
+ else
+ p = GC_MALLOC_ATOMIC(size);
+
+ if (p == NULL)
+ return NULL;
+
+ if (finalizer != NULL)
+ GC_REGISTER_FINALIZER_NO_ORDER(p, finalizer_run, 0, 0, 0);
+
+ /* clear allocated memory region */
+
+ MSET(p, 0, uint8_t, size);
+
+ RT_TIMING_GET_TIME(time_end);
+ RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_GC_ALLOC);
+
+ return p;
+}
+
+
+void heap_free(void *p)
+{
+ GC_FREE(p);
+}
+
+void gc_call(void)
+{
+ if (opt_verbosegc)
+ dolog("Garbage Collection: previous/now = %d / %d ",
+ 0, 0);
+
+ GC_gcollect();
+}
+
+
+int64_t gc_get_heap_size(void)
+{
+ return GC_get_heap_size();
+}
+
+
+int64_t gc_get_free_bytes(void)
+{
+ return GC_get_free_bytes();
+}
+
+
+/* gc_get_total_bytes **********************************************************
+
+ Returns the number of total bytes currently used on the Java heap.
+
+*******************************************************************************/
+
+int64_t gc_get_total_bytes(void)
+{
+ return GC_get_total_bytes();
+}
+
+
+int64_t gc_get_max_heap_size(void)
+{
+ return GC_get_max_heap_size();
+}
+
+
+void gc_invoke_finalizers(void)
+{
+ GC_invoke_finalizers();
+}
+
+
+void gc_finalize_all(void)
+{
+ GC_finalize_all();
+}
+
+
+/* gc_out_of_memory ************************************************************
+
+ This function is called when boehm detects that it is OOM.
+
+*******************************************************************************/
+
+void *gc_out_of_memory(size_t bytes_requested)
+{
+ /* if this happens, we are REALLY out of memory */
+
+ if (in_gc_out_of_memory) {
+ /* this is all we can do... */
+ vm_abort("gc_out_of_memory: out of memory");
+ }
+
+ in_gc_out_of_memory = true;
+
+ /* try to release some memory */
+
+ gc_call();
+
+ /* now instantiate the exception */
+
+ exceptions_throw_outofmemoryerror();
+
+ in_gc_out_of_memory = false;
+
+ return NULL;
+}
+
+
+/*
+ * 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/mm/gc-common.h - gc independant interface for heap managment
-
- 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 _GC_COMMON_H
-#define _GC_COMMON_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/global.h"
-
-#include "vmcore/method.h"
-
-
-/* reference types ************************************************************/
-
-enum {
- GC_REFTYPE_THREADOBJECT,
- GC_REFTYPE_CLASSLOADER,
- GC_REFTYPE_JNI_GLOBALREF,
- GC_REFTYPE_FINALIZER,
- GC_REFTYPE_LOCALREF,
- GC_REFTYPE_STACK,
- GC_REFTYPE_CLASSREF,
- GC_REFTYPE_LOCKRECORD
-};
-
-
-/* function prototypes ********************************************************/
-
-void gc_init(size_t heapmaxsize, size_t heapstartsize);
-
-void* heap_alloc_uncollectable(size_t size);
-void* heap_alloc(size_t size, int references, methodinfo *finalizer, bool collect);
-void heap_free(void *p);
-
-#if defined(ENABLE_GC_CACAO)
-void heap_init_objectheader(java_object_t *o, uint32_t size);
-int32_t heap_get_hashcode(java_object_t *o);
-
-void gc_reference_register(java_object_t **ref, int32_t reftype);
-void gc_reference_unregister(java_object_t **ref);
-
-void gc_weakreference_register(java_object_t **ref, int32_t reftype);
-void gc_weakreference_unregister(java_object_t **ref);
-#endif
-
-void gc_call(void);
-int64_t gc_get_heap_size(void);
-int64_t gc_get_free_bytes(void);
-int64_t gc_get_total_bytes(void);
-int64_t gc_get_max_heap_size(void);
-void gc_invoke_finalizers(void);
-void gc_finalize_all(void);
-void* gc_out_of_memory(size_t bytes_requested);
-
-
-/* inlined functions **********************************************************/
-
-static inline int32_t heap_hashcode(java_object_t *obj)
-{
-#if defined(ENABLE_GC_CACAO)
- return heap_get_hashcode(obj);
-#else
- return (int32_t)(intptr_t) obj;
-#endif
-}
-
-#endif /* _GC_COMMON_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/mm/gc-none.cpp - allocates memory through malloc (no GC)
+
+ 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 <stdlib.h>
+
+#if defined(HAVE_SYS_MMAN_H)
+# include <sys/mman.h>
+#endif
+
+#include "vm/types.h"
+
+#include "boehm-gc/include/gc.h"
+
+#include "mm/gc.hpp"
+#include "mm/memory.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+
+/* global stuff ***************************************************************/
+
+#define MMAP_HEAPADDRESS 0x10000000 /* try to map the heap to this addr. */
+#define ALIGNSIZE 8
+
+static void *mmapptr = NULL;
+static int mmapsize = 0;
+static void *mmaptop = NULL;
+
+
+void* heap_alloc(size_t size, int references, methodinfo *finalizer, bool collect)
+{
+ void *m;
+
+ mmapptr = (void *) MEMORY_ALIGN((ptrint) mmapptr, ALIGNSIZE);
+
+ m = mmapptr;
+ mmapptr = (void *) ((ptrint) mmapptr + size);
+
+ if (mmapptr > mmaptop)
+ vm_abort("heap_alloc: out of memory");
+
+ MSET(m, 0, u1, size);
+
+ return m;
+}
+
+
+void* heap_alloc_uncollectable(size_t size)
+{
+ return heap_alloc(size, false, NULL, false);
+}
+
+
+void heap_free(void* p)
+{
+ /* nop */
+}
+
+
+
+void gc_init(size_t heapmaxsize, size_t heapstartsize)
+{
+ heapmaxsize = MEMORY_ALIGN(heapmaxsize, ALIGNSIZE);
+
+#if defined(HAVE_MMAP)
+ mmapptr = mmap((void *) MMAP_HEAPADDRESS,
+ (size_t) heapmaxsize,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE |
+# if defined(MAP_ANONYMOUS)
+ MAP_ANONYMOUS,
+# elif defined(MAP_ANON)
+ MAP_ANON,
+# else
+ 0,
+# endif
+ -1,
+ (off_t) 0);
+
+ if (mmapptr == MAP_FAILED)
+ vm_abort("gc_init: out of memory");
+#else
+ mmapptr = malloc(heapmaxsize);
+
+ if (mmapptr == NULL)
+ vm_abort("gc_init: out of memory");
+#endif
+
+ mmapsize = heapmaxsize;
+ mmaptop = (void *) ((ptrint) mmapptr + mmapsize);
+}
+
+
+void gc_call(void)
+{
+ log_text("GC call: nothing done...");
+ /* nop */
+}
+
+
+s8 gc_get_heap_size(void)
+{
+ return 0;
+}
+
+
+s8 gc_get_free_bytes(void)
+{
+ return 0;
+}
+
+
+s8 gc_get_total_bytes(void)
+{
+ return 0;
+}
+
+
+s8 gc_get_max_heap_size(void)
+{
+ return 0;
+}
+
+
+void gc_invoke_finalizers(void)
+{
+ /* nop */
+}
+
+
+void gc_finalize_all(void)
+{
+ /* nop */
+}
+
+
+/*
+ * 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/mm/gc.hpp - gc independant interface for heap managment
+
+ 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 _GC_HPP
+#define _GC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/global.h"
+#include "vm/method.h"
+
+
+/* reference types ************************************************************/
+
+enum {
+ GC_REFTYPE_THREADOBJECT,
+ GC_REFTYPE_CLASSLOADER,
+ GC_REFTYPE_JNI_GLOBALREF,
+ GC_REFTYPE_FINALIZER,
+ GC_REFTYPE_LOCALREF,
+ GC_REFTYPE_STACK,
+ GC_REFTYPE_CLASSREF,
+ GC_REFTYPE_LOCKRECORD
+};
+
+
+/* function prototypes ********************************************************/
+
+void gc_init(size_t heapmaxsize, size_t heapstartsize);
+
+void* heap_alloc_uncollectable(size_t size);
+void* heap_alloc(size_t size, int references, methodinfo *finalizer, bool collect);
+void heap_free(void *p);
+
+#if defined(ENABLE_GC_CACAO)
+void heap_init_objectheader(java_object_t *o, uint32_t size);
+int32_t heap_get_hashcode(java_object_t *o);
+
+void gc_reference_register(java_object_t **ref, int32_t reftype);
+void gc_reference_unregister(java_object_t **ref);
+
+void gc_weakreference_register(java_object_t **ref, int32_t reftype);
+void gc_weakreference_unregister(java_object_t **ref);
+#endif
+
+void gc_call(void);
+int64_t gc_get_heap_size(void);
+int64_t gc_get_free_bytes(void);
+int64_t gc_get_total_bytes(void);
+int64_t gc_get_max_heap_size(void);
+void gc_invoke_finalizers(void);
+void gc_finalize_all(void);
+void* gc_out_of_memory(size_t bytes_requested);
+
+
+/* inlined functions **********************************************************/
+
+static inline int32_t heap_hashcode(java_object_t *obj)
+{
+#if defined(ENABLE_GC_CACAO)
+ return heap_get_hashcode(obj);
+#else
+ return (int32_t)(intptr_t) obj;
+#endif
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GC_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:
+ */
#include "config.h"
#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
+#include <stdint.h>
#if defined(__DARWIN__)
/* If we compile with -ansi on darwin, <sys/types.h> is not
#include "native/native.h"
#include "threads/lock-common.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "vm/exceptions.h"
#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
-#include "vmcore/options.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/system.h"
-
/* memory_mprotect *************************************************************
void memory_mprotect(void *addr, size_t len, int prot)
{
- if (system_mprotect(addr, len, prot) != 0)
- vm_abort("memory_mprotect: system_mprotect failed: %s",
- strerror(errno));
+ if (os_mprotect(addr, len, prot) != 0)
+ vm_abort_errno("memory_mprotect: os_mprotect failed");
}
{
/* always allocate memory zeroed out */
- void *p = calloc(size, 1);
+ void *p = os_calloc(size, 1);
if (p == NULL)
vm_abort("memory_checked_alloc: calloc failed: out of memory");
#if defined(ENABLE_MEMCHECK)
if (len2 < len1)
- memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2);
+ os_memset((u1*)dst + len2, MEMORY_CLEAR_BYTE, len1 - len2);
#endif
dst = realloc(src, len2);
#if defined(ENABLE_MEMCHECK)
if (len2 > len1)
- memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1);
+ os_memset((u1*)dst + len1, MEMORY_CLEAR_BYTE, len2 - len1);
#endif
return dst;
#if defined(ENABLE_MEMCHECK)
/* destroy the contents */
- memset(m, MEMORY_CLEAR_BYTE, size);
+ os_memset(m, MEMORY_CLEAR_BYTE, size);
#endif
- free(m);
+ os_free(m);
}
/* internal includes **********************************************************/
-#include "mm/gc-common.h"
+#include "mm/gc.hpp"
/*
+++ /dev/null
-/* src/mm/nogc.c - allocates memory through malloc (no GC)
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 <stdlib.h>
-
-#if defined(HAVE_SYS_MMAN_H)
-# include <sys/mman.h>
-#endif
-
-#include "vm/types.h"
-
-#include "boehm-gc/include/gc.h"
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
-
-/* global stuff ***************************************************************/
-
-#define MMAP_HEAPADDRESS 0x10000000 /* try to map the heap to this addr. */
-#define ALIGNSIZE 8
-
-static void *mmapptr = NULL;
-static int mmapsize = 0;
-static void *mmaptop = NULL;
-
-
-void *heap_alloc(u4 size, u4 references, methodinfo *finalizer, bool collect)
-{
- void *m;
-
- mmapptr = (void *) MEMORY_ALIGN((ptrint) mmapptr, ALIGNSIZE);
-
- m = mmapptr;
- mmapptr = (void *) ((ptrint) mmapptr + size);
-
- if (mmapptr > mmaptop)
- vm_abort("heap_alloc: out of memory");
-
- MSET(m, 0, u1, size);
-
- return m;
-}
-
-
-void *heap_alloc_uncollectable(u4 size)
-{
- return heap_alloc(size, false, NULL, false);
-}
-
-
-void heap_free(void *p)
-{
- /* nop */
-}
-
-
-
-void gc_init(u4 heapmaxsize, u4 heapstartsize)
-{
- heapmaxsize = MEMORY_ALIGN(heapmaxsize, ALIGNSIZE);
-
-#if defined(HAVE_MMAP)
- mmapptr = mmap((void *) MMAP_HEAPADDRESS,
- (size_t) heapmaxsize,
- PROT_READ | PROT_WRITE,
- MAP_PRIVATE |
-# if defined(MAP_ANONYMOUS)
- MAP_ANONYMOUS,
-# elif defined(MAP_ANON)
- MAP_ANON,
-# else
- 0,
-# endif
- -1,
- (off_t) 0);
-
- if (mmapptr == MAP_FAILED)
- vm_abort("gc_init: out of memory");
-#else
- mmapptr = malloc(heapmaxsize);
-
- if (mmapptr == NULL)
- vm_abort("gc_init: out of memory");
-#endif
-
- mmapsize = heapmaxsize;
- mmaptop = (void *) ((ptrint) mmapptr + mmapsize);
-}
-
-
-void gc_call(void)
-{
- log_text("GC call: nothing done...");
- /* nop */
-}
-
-
-s8 gc_get_heap_size(void)
-{
- return 0;
-}
-
-
-s8 gc_get_free_bytes(void)
-{
- return 0;
-}
-
-
-s8 gc_get_total_bytes(void)
-{
- return 0;
-}
-
-
-s8 gc_get_max_heap_size(void)
-{
- return 0;
-}
-
-
-void gc_invoke_finalizers(void)
-{
- /* nop */
-}
-
-
-void gc_finalize_all(void)
-{
- /* nop */
-}
-
-
-/*
- * 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/mm/tlh.c
+
+ Copyright (C) 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine 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 "mm/memory.h"
+#include "mm/tlh.h"
+
+#include "vm/global.h"
+
+#include <assert.h>
+#include <sys/mman.h>
+
+static const int TLH_MAX_SIZE = (20 * 1024 * 1024);
+
+static inline bool tlh_avail(tlh_t *tlh, unsigned n) {
+ /*
+ --- --- --- ---
+ ^ end
+ ^ top
+ ^ top + 2
+ */
+ return (tlh->top + n) <= tlh->end;
+}
+
+void tlh_init(tlh_t *tlh) {
+
+ void *heap = mmap(
+ NULL,
+ TLH_MAX_SIZE,
+ PROT_READ|PROT_WRITE,
+ MAP_ANONYMOUS|MAP_PRIVATE,
+ -1,
+ 0
+ );
+
+ if (heap == MAP_FAILED) {
+ /* The top pointer points to end, so all allocations will fail. */
+ tlh->start = NULL;
+ tlh->end = NULL;
+ tlh->top = NULL;
+ tlh->base = NULL;
+ } else {
+ tlh->start = (uint8_t *)heap;
+ tlh->top = tlh->start;
+ tlh->base = tlh->start;
+ tlh->end = tlh->start + TLH_MAX_SIZE;
+ }
+
+ tlh->overflows = 0;
+}
+
+void tlh_destroy(tlh_t *tlh) {
+ int res = munmap(tlh->start, TLH_MAX_SIZE);
+ if (res == -1) {
+ /* TODO */
+ assert(0);
+ }
+ tlh->start = NULL;
+ tlh->end = NULL;
+ tlh->top = NULL;
+ tlh->base = NULL;
+}
+
+void tlh_add_frame(tlh_t *tlh) {
+ if (tlh_avail(tlh, SIZEOF_VOID_P)) {
+ *(uint8_t **)tlh->top = tlh->base;
+ tlh->base = tlh->top;
+ tlh->top += SIZEOF_VOID_P;
+ } else {
+ tlh->overflows += 1;
+ }
+}
+
+void tlh_remove_frame(tlh_t *tlh) {
+ if (tlh->overflows > 0) {
+ tlh->overflows -= 1;
+ } else {
+ tlh->top = tlh->base;
+ tlh->base = *(uint8_t **)tlh->top;
+ }
+}
+
+void *tlh_alloc(tlh_t *tlh, size_t size) {
+ void *ret;
+ if (tlh_avail(tlh, size)) {
+ ret = tlh->top;
+ tlh->top += size;
+ MZERO(ret, char, size);
+ } else {
+ ret = NULL;
+ }
+ return ret;
+}
+
+/*
+ * 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/mm/tlh.h
+
+ Copyright (C) 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine 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 _MM_TLH_H
+#define _MM_TLH_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+typedef struct {
+ uint8_t *start;
+ uint8_t *end;
+ uint8_t *top;
+ uint8_t *base;
+ unsigned overflows;
+} tlh_t;
+
+void tlh_init(tlh_t *tlh);
+
+void tlh_destroy(tlh_t *tlh);
+
+void tlh_add_frame(tlh_t *tlh);
+
+void tlh_remove_frame(tlh_t *tlh);
+
+void *tlh_alloc(tlh_t *tlh, size_t size);
+
+#endif
+
+/*
+ * 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:
+ */
## src/native/Makefile.am
##
-## Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
##
## This file is part of CACAO.
##
LIBS =
SUBDIRS = \
- include \
vm
if ENABLE_JVMTI
if ENABLE_JNI
JNI_SOURCES = \
- jni.c \
+ jni.cpp \
jni.h \
localref.c \
localref.h
## 02110-1301, USA.
-JAVAH = $(CACAOH)
-JAVAHCMD = $(JAVAH) -bootclasspath $(BOOTCLASSPATH)
+JAVAH = javah
+JAVAHCMD = $(JAVAH) -jni -bootclasspath $(BOOTCLASSPATH)
-COMMON_HEADER_FILES = \
- java_lang_Class.h \
- java_lang_Object.h \
- java_lang_String.h \
- java_lang_Thread.h \
- java_lang_Throwable.h \
- \
- java_io_InputStream.h \
- java_io_PrintStream.h \
- \
- java_lang_Boolean.h \
- java_lang_Byte.h \
- java_lang_Character.h \
- java_lang_Double.h \
- java_lang_Float.h \
- java_lang_Integer.h \
- java_lang_Long.h \
- java_lang_Short.h \
- java_util_Vector.h
-
-JAVASE_HEADER_FILES = \
- java_lang_ClassLoader.h \
- java_lang_Cloneable.h \
- java_lang_ThreadGroup.h \
- java_util_Properties.h \
- \
- java_io_File.h \
- java_lang_Process.h \
- java_lang_StackTraceElement.h \
- java_lang_reflect_Constructor.h \
- java_lang_reflect_Field.h \
- java_lang_reflect_Method.h \
- java_nio_Buffer.h \
- java_security_ProtectionDomain.h \
- java_util_HashMap.h \
- java_util_Map.h \
- java_util_concurrent_atomic_AtomicLong.h \
- sun_misc_Unsafe.h
-
-if WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH
-JAVASE_HEADER_FILES += \
- java_lang_VMThread.h \
- java_lang_VMThrowable.h \
- \
- gnu_classpath_Pointer.h \
- gnu_classpath_Pointer32.h \
- gnu_classpath_Pointer64.h \
- gnu_java_lang_VMCPStringBuilder.h \
- java_lang_VMObject.h \
- java_lang_reflect_VMConstructor.h \
- java_lang_reflect_VMField.h \
- java_lang_reflect_VMMethod.h \
- java_nio_DirectByteBufferImpl.h
-
-if ENABLE_ANNOTATIONS
-JAVASE_HEADER_FILES += \
- sun_reflect_ConstantPool.h
-endif
-endif
-
-if WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
-JAVASE_HEADER_FILES += \
- java_lang_AssertionStatusDirectives.h \
- java_nio_ByteBuffer.h \
- sun_reflect_ConstantPool.h
-endif
-
-JAVAME_CLDC1_1_HEADER_FILES = \
+if WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1
+IMPLEMENTED_VM_CLASSES_HEADER_FILES = \
com_sun_cldc_io_ResourceInputStream.h \
com_sun_cldc_io_j2me_socket_Protocol.h \
com_sun_cldchi_io_ConsoleOutputStream.h \
com_sun_cldchi_jvm_FileDescriptor.h \
com_sun_cldchi_jvm_JVM.h \
+ java_lang_Class.h \
java_lang_Math.h \
java_lang_Runtime.h \
java_lang_System.h
-
-JVMTI_HEADER_FILES = \
- gnu_classpath_jdwp_VMFrame.h \
- gnu_classpath_jdwp_VMMethod.h \
- gnu_classpath_jdwp_VMVirtualMachine.h \
- gnu_classpath_jdwp_event_EventRequest.h \
- gnu_classpath_jdwp_util_VariableTable.h
+endif
if WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH
-ADDITIONAL_IMPLEMENTED_VM_CLASSES_HEADER_FILES = \
+IMPLEMENTED_VM_CLASSES_HEADER_FILES = \
gnu_classpath_VMStackWalker.h \
gnu_classpath_VMSystemProperties.h \
+ gnu_java_lang_VMCPStringBuilder.h \
gnu_java_lang_management_VMClassLoadingMXBeanImpl.h \
gnu_java_lang_management_VMMemoryMXBeanImpl.h \
gnu_java_lang_management_VMRuntimeMXBeanImpl.h \
gnu_java_lang_management_VMThreadMXBeanImpl.h \
java_lang_VMClass.h \
java_lang_VMClassLoader.h \
+ java_lang_VMObject.h \
java_lang_VMRuntime.h \
java_lang_VMString.h \
java_lang_VMSystem.h \
- java_lang_management_MemoryUsage.h \
- java_lang_management_ThreadInfo.h \
+ java_lang_VMThread.h \
+ java_lang_VMThrowable.h \
java_lang_management_VMManagementFactory.h \
+ java_lang_reflect_VMConstructor.h \
+ java_lang_reflect_VMField.h \
+ java_lang_reflect_VMMethod.h \
java_lang_reflect_VMProxy.h \
- java_security_VMAccessController.h
-endif
-
-CLEANFILES = \
- *.h
-
-DO_HEADER_FILES = \
- $(COMMON_HEADER_FILES)
+ java_security_VMAccessController.h \
+ java_util_concurrent_atomic_AtomicLong.h \
+ sun_misc_Unsafe.h
-if ENABLE_JAVASE
-DO_HEADER_FILES += \
- $(JAVASE_HEADER_FILES) \
- $(ADDITIONAL_IMPLEMENTED_VM_CLASSES_HEADER_FILES)
+if ENABLE_ANNOTATIONS
+IMPLEMENTED_VM_CLASSES_HEADER_FILES += \
+ sun_reflect_ConstantPool.h
+endif
endif
-if ENABLE_JAVAME_CLDC1_1
-DO_HEADER_FILES += \
- $(JAVAME_CLDC1_1_HEADER_FILES)
+if WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
+IMPLEMENTED_VM_CLASSES_HEADER_FILES = \
+ sun_misc_Unsafe.h
endif
if ENABLE_JVMTI
-DO_HEADER_FILES += \
- $(GEN_JVMTI_HEADER_FILES)
+JVMTI_HEADER_FILES = \
+ gnu_classpath_jdwp_VMFrame.h \
+ gnu_classpath_jdwp_VMMethod.h \
+ gnu_classpath_jdwp_VMVirtualMachine.h \
+ gnu_classpath_jdwp_event_EventRequest.h \
+ gnu_classpath_jdwp_util_VariableTable.h
endif
+CLEANFILES = \
+ *.h
+
+DO_HEADER_FILES = \
+ $(IMPLEMENTED_VM_CLASSES_HEADER_FILES)
+
if WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH
if ENABLE_ZLIB
VM_ZIP = $(top_builddir)/src/classes/vm.zip
+++ /dev/null
-/* src/native/jni.c - implementation of the Java Native Interface 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 <stdint.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/gnu_classpath_Pointer.h"
-
-# if SIZEOF_VOID_P == 8
-# include "native/include/gnu_classpath_Pointer64.h"
-# else
-# include "native/include/gnu_classpath_Pointer32.h"
-# endif
-# endif
-#endif
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Throwable.h"
-
-#if defined(ENABLE_JAVASE)
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-# endif
-
-/* java_lang_ClassLoader is used in java_lang_Class and vice versa, so
- we pre-define it here to prevent a compiler warning for Sun
- configurations. */
-
-struct java_lang_ClassLoader;
-
-# include "native/include/java_lang_Class.h"
-# include "native/include/java_lang_ClassLoader.h"
-
-# include "native/include/java_lang_reflect_Constructor.h"
-# include "native/include/java_lang_reflect_Field.h"
-# include "native/include/java_lang_reflect_Method.h"
-
-# include "native/include/java_nio_Buffer.h"
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_reflect_VMConstructor.h"
-# include "native/include/java_lang_reflect_VMField.h"
-# include "native/include/java_lang_reflect_VMMethod.h"
-
-# include "native/include/java_nio_DirectByteBufferImpl.h"
-# endif
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-# include "native/include/java_lang_Class.h"
-#endif
-
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
-#if defined(ENABLE_JAVASE)
-# include "native/vm/reflect.h"
-#endif
-
-#include "threads/lock-common.h"
-#include "threads/thread.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-#include "vm/primitive.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/argument.h"
-#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-
-# define TRACEJNICALLS(x) \
- do { \
- if (opt_TraceJNICalls) { \
- log_println x; \
- } \
- } while (0)
-
-# define TRACEJNICALLSENTER(x) \
- do { \
- if (opt_TraceJNICalls) { \
- log_start(); \
- log_print x; \
- } \
- } while (0)
-
-# define TRACEJNICALLSEXIT(x) \
- do { \
- if (opt_TraceJNICalls) { \
- log_print x; \
- log_finish(); \
- } \
- } while (0)
-
-#else
-
-# define TRACEJNICALLS(x)
-# define TRACEJNICALLSENTER(x)
-# define TRACEJNICALLSEXIT(x)
-
-#endif
-
-
-/* global variables ***********************************************************/
-
-/* global reference table *****************************************************/
-
-/* hashsize must be power of 2 */
-
-#define HASHTABLE_GLOBAL_REF_SIZE 64 /* initial size of globalref-hash */
-
-static hashtable *hashtable_global_ref; /* hashtable for globalrefs */
-
-
-/* direct buffer stuff ********************************************************/
-
-#if defined(ENABLE_JAVASE)
-static classinfo *class_java_nio_Buffer;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-static classinfo *class_java_nio_DirectByteBufferImpl;
-static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
-
-# if SIZEOF_VOID_P == 8
-static classinfo *class_gnu_classpath_Pointer64;
-# else
-static classinfo *class_gnu_classpath_Pointer32;
-# endif
-
-static methodinfo *dbbirw_init;
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-static classinfo *class_sun_nio_ch_DirectBuffer;
-static classinfo *class_java_nio_DirectByteBuffer;
-
-static methodinfo *dbb_init;
-
-# endif
-#endif
-
-
-/* some forward declarations **************************************************/
-
-jobject jni_NewLocalRef(JNIEnv *env, jobject ref);
-
-
-/* jni_init ********************************************************************
-
- Initialize the JNI subsystem.
-
-*******************************************************************************/
-
-bool jni_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("jni_init");
-
- /* create global ref hashtable */
-
- hashtable_global_ref = NEW(hashtable);
-
- hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
-
-
-#if defined(ENABLE_JAVASE)
- /* Direct buffer stuff. */
-
- if (!(class_java_nio_Buffer =
- load_class_bootstrap(utf_new_char("java/nio/Buffer"))) ||
- !link_class(class_java_nio_Buffer))
- return false;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- if (!(class_java_nio_DirectByteBufferImpl =
- load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
- !link_class(class_java_nio_DirectByteBufferImpl))
- return false;
-
- if (!(class_java_nio_DirectByteBufferImpl_ReadWrite =
- load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) ||
- !link_class(class_java_nio_DirectByteBufferImpl_ReadWrite))
- return false;
-
- if (!(dbbirw_init =
- class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite,
- utf_init,
- utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
- return false;
-
-# if SIZEOF_VOID_P == 8
- if (!(class_gnu_classpath_Pointer64 =
- load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
- !link_class(class_gnu_classpath_Pointer64))
- return false;
-# else
- if (!(class_gnu_classpath_Pointer32 =
- load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
- !link_class(class_gnu_classpath_Pointer32))
- return false;
-# endif
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- if (!(class_sun_nio_ch_DirectBuffer =
- load_class_bootstrap(utf_new_char("sun/nio/ch/DirectBuffer"))))
- vm_abort("jni_init: loading sun/nio/ch/DirectBuffer failed");
-
- if (!link_class(class_sun_nio_ch_DirectBuffer))
- vm_abort("jni_init: linking sun/nio/ch/DirectBuffer failed");
-
- if (!(class_java_nio_DirectByteBuffer =
- load_class_bootstrap(utf_new_char("java/nio/DirectByteBuffer"))))
- vm_abort("jni_init: loading java/nio/DirectByteBuffer failed");
-
- if (!link_class(class_java_nio_DirectByteBuffer))
- vm_abort("jni_init: linking java/nio/DirectByteBuffer failed");
-
- if (!(dbb_init =
- class_resolvemethod(class_java_nio_DirectByteBuffer,
- utf_init,
- utf_new_char("(JI)V"))))
- vm_abort("jni_init: resolving java/nio/DirectByteBuffer.init(JI)V failed");
-
-# endif
-
-#endif /* defined(ENABLE_JAVASE) */
-
- return true;
-}
-
-
-/* jni_version_check ***********************************************************
-
- Check if the given JNI version is supported.
-
- IN:
- version....JNI version to check
-
- RETURN VALUE:
- true.......supported
- false......not supported
-
-*******************************************************************************/
-
-bool jni_version_check(int version)
-{
- switch (version) {
- case JNI_VERSION_1_1:
- case JNI_VERSION_1_2:
- case JNI_VERSION_1_4:
- case JNI_VERSION_1_6:
- return true;
- default:
- return false;
- }
-}
-
-
-/* _Jv_jni_CallObjectMethod ****************************************************
-
- Internal function to call Java Object methods.
-
-*******************************************************************************/
-
-static java_handle_t *_Jv_jni_CallObjectMethod(java_handle_t *o,
- vftbl_t *vftbl,
- methodinfo *m, va_list ap)
-{
- methodinfo *resm;
- java_handle_t *ro;
-
- STATISTICS(jniinvokation());
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- ro = vm_call_method_valist(resm, o, ap);
-
- return ro;
-}
-
-
-/* _Jv_jni_CallObjectMethodA ***************************************************
-
- Internal function to call Java Object methods.
-
-*******************************************************************************/
-
-static java_handle_t *_Jv_jni_CallObjectMethodA(java_handle_t *o,
- vftbl_t *vftbl,
- methodinfo *m,
- const jvalue *args)
-{
- methodinfo *resm;
- java_handle_t *ro;
-
- STATISTICS(jniinvokation());
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- ro = vm_call_method_jvalue(resm, o, args);
-
- return ro;
-}
-
-
-/* _Jv_jni_CallIntMethod *******************************************************
-
- Internal function to call Java integer class methods (boolean,
- byte, char, short, int).
-
-*******************************************************************************/
-
-static jint _Jv_jni_CallIntMethod(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, va_list ap)
-{
- methodinfo *resm;
- jint i;
-
- STATISTICS(jniinvokation());
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- i = vm_call_method_int_valist(resm, o, ap);
-
- return i;
-}
-
-
-/* _Jv_jni_CallIntMethodA ******************************************************
-
- Internal function to call Java integer class methods (boolean,
- byte, char, short, int).
-
-*******************************************************************************/
-
-static jint _Jv_jni_CallIntMethodA(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, const jvalue *args)
-{
- methodinfo *resm;
- jint i;
-
- STATISTICS(jniinvokation());
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- i = vm_call_method_int_jvalue(resm, o, args);
-
- return i;
-}
-
-
-/* _Jv_jni_CallLongMethod ******************************************************
-
- Internal function to call Java long methods.
-
-*******************************************************************************/
-
-static jlong _Jv_jni_CallLongMethod(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, va_list ap)
-{
- methodinfo *resm;
- jlong l;
-
- STATISTICS(jniinvokation());
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- l = vm_call_method_long_valist(resm, o, ap);
-
- return l;
-}
-
-
-/* _Jv_jni_CallLongMethodA *****************************************************
-
- Internal function to call Java long methods.
-
-*******************************************************************************/
-
-static jlong _Jv_jni_CallLongMethodA(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, const jvalue *args)
-{
- methodinfo *resm;
- jlong l;
-
- STATISTICS(jniinvokation());
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
- }
- else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- l = vm_call_method_long_jvalue(resm, o, args);
-
- return l;
-}
-
-
-/* _Jv_jni_CallFloatMethod *****************************************************
-
- Internal function to call Java float methods.
-
-*******************************************************************************/
-
-static jfloat _Jv_jni_CallFloatMethod(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, va_list ap)
-{
- methodinfo *resm;
- jfloat f;
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- f = vm_call_method_float_valist(resm, o, ap);
-
- return f;
-}
-
-
-/* _Jv_jni_CallFloatMethodA ****************************************************
-
- Internal function to call Java float methods.
-
-*******************************************************************************/
-
-static jfloat _Jv_jni_CallFloatMethodA(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, const jvalue *args)
-{
- methodinfo *resm;
- jfloat f;
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
- }
- else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- f = vm_call_method_float_jvalue(resm, o, args);
-
- return f;
-}
-
-
-/* _Jv_jni_CallDoubleMethod ****************************************************
-
- Internal function to call Java double methods.
-
-*******************************************************************************/
-
-static jdouble _Jv_jni_CallDoubleMethod(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, va_list ap)
-{
- methodinfo *resm;
- jdouble d;
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- d = vm_call_method_double_valist(resm, o, ap);
-
- return d;
-}
-
-
-/* _Jv_jni_CallDoubleMethodA ***************************************************
-
- Internal function to call Java double methods.
-
-*******************************************************************************/
-
-static jdouble _Jv_jni_CallDoubleMethodA(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, const jvalue *args)
-{
- methodinfo *resm;
- jdouble d;
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
- }
- else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- d = vm_call_method_double_jvalue(resm, o, args);
-
- return d;
-}
-
-
-/* _Jv_jni_CallVoidMethod ******************************************************
-
- Internal function to call Java void methods.
-
-*******************************************************************************/
-
-static void _Jv_jni_CallVoidMethod(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, va_list ap)
-{
- methodinfo *resm;
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- (void) vm_call_method_valist(resm, o, ap);
-}
-
-
-/* _Jv_jni_CallVoidMethodA *****************************************************
-
- Internal function to call Java void methods.
-
-*******************************************************************************/
-
-static void _Jv_jni_CallVoidMethodA(java_handle_t *o, vftbl_t *vftbl,
- methodinfo *m, const jvalue *args)
-{
- methodinfo *resm;
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- /* Class initialization is done by the JIT compiler. This is ok
- since a static method always belongs to the declaring class. */
-
- if (m->flags & ACC_STATIC) {
- /* For static methods we reset the object. */
-
- if (o != NULL)
- o = NULL;
-
- /* for convenience */
-
- resm = m;
-
- } else {
- /* For instance methods we make a virtual function table lookup. */
-
- resm = method_vftbl_lookup(vftbl, m);
- }
-
- STATISTICS(jnicallXmethodnvokation());
-
- (void) vm_call_method_jvalue(resm, o, args);
-}
-
-
-/* GetVersion ******************************************************************
-
- Returns the major version number in the higher 16 bits and the
- minor version number in the lower 16 bits.
-
-*******************************************************************************/
-
-jint _Jv_JNI_GetVersion(JNIEnv *env)
-{
- TRACEJNICALLS(("_Jv_JNI_GetVersion(env=%p)", env));
-
- /* We support JNI 1.6. */
-
- return JNI_VERSION_1_6;
-}
-
-
-/* Class Operations ***********************************************************/
-
-/* DefineClass *****************************************************************
-
- Loads a class from a buffer of raw class data. The buffer
- containing the raw class data is not referenced by the VM after the
- DefineClass call returns, and it may be discarded if desired.
-
-*******************************************************************************/
-
-jclass _Jv_JNI_DefineClass(JNIEnv *env, const char *name, jobject loader,
- const jbyte *buf, jsize bufLen)
-{
-#if defined(ENABLE_JAVASE)
- utf *u;
- classloader_t *cl;
- classinfo *c;
- java_lang_Class *co;
-
- TRACEJNICALLS(("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen));
-
- u = utf_new_char(name);
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- c = class_define(u, cl, bufLen, (uint8_t *) buf, NULL);
-
- co = LLNI_classinfo_wrap(c);
-
- return (jclass) jni_NewLocalRef(env, (jobject) co);
-#else
- vm_abort("_Jv_JNI_DefineClass: not implemented in this configuration");
-
- /* keep compiler happy */
-
- return 0;
-#endif
-}
-
-
-/* FindClass *******************************************************************
-
- This function loads a locally-defined class. It searches the
- directories and zip files specified by the CLASSPATH environment
- variable for the class with the specified name.
-
-*******************************************************************************/
-
-jclass jni_FindClass(JNIEnv *env, const char *name)
-{
-#if defined(ENABLE_JAVASE)
-
- utf *u;
- classinfo *cc;
- classinfo *c;
- java_lang_Class *co;
-
- TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
-
- /* FIXME If name is NULL we have a problem here. */
-
- u = utf_new_char_classname((char *) name);
-
- if ((u == NULL) /*|| (int)strlen(name) > symbolOopDesc::max_length() */) {
- exceptions_throw_noclassdeffounderror(u);
- return NULL;
- }
-
- /* Check stacktrace for classloader, if one found use it,
- otherwise use the system classloader. */
-
- /* Quote from the JNI documentation:
-
- In the Java 2 Platform, FindClass locates the class loader
- associated with the current native method. If the native code
- belongs to a system class, no class loader will be
- involved. Otherwise, the proper class loader will be invoked to
- load and link the named class. When FindClass is called through
- the Invocation Interface, there is no current native method or
- its associated class loader. In that case, the result of
- ClassLoader.getBaseClassLoader is used." */
-
- cc = stacktrace_get_current_class();
-
- if (cc == NULL)
- c = load_class_from_sysloader(u);
- else
- c = load_class_from_classloader(u, cc->classloader);
-
- if (c == NULL) {
- resolve_handle_pending_exception(true);
- return NULL;
- }
-
- if (!link_class(c))
- return NULL;
-
- co = LLNI_classinfo_wrap(c);
-
- return (jclass) jni_NewLocalRef(env, (jobject) co);
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- utf *u;
- classinfo *c;
-
- TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
-
- u = utf_new_char_classname((char *) name);
- c = load_class_bootstrap(u);
-
- if (c == NULL) {
- resolve_handle_pending_exception(true);
- return NULL;
- }
-
- if (!link_class(c))
- return NULL;
-
- return (jclass) jni_NewLocalRef(env, (jobject) c);
-
-#else
- vm_abort("jni_FindClass: not implemented in this configuration");
-
- /* keep compiler happy */
-
- return NULL;
-#endif
-}
-
-
-/* GetSuperclass ***************************************************************
-
- If clazz represents any class other than the class Object, then
- this function returns the object that represents the superclass of
- the class specified by clazz.
-
-*******************************************************************************/
-
-jclass _Jv_JNI_GetSuperclass(JNIEnv *env, jclass sub)
-{
- classinfo *c;
- classinfo *super;
- java_lang_Class *co;
-
- TRACEJNICALLS(("_Jv_JNI_GetSuperclass(env=%p, sub=%p)", env, sub));
-
- c = LLNI_classinfo_unwrap(sub);
-
- if (c == NULL)
- return NULL;
-
- super = class_get_superclass(c);
-
- co = LLNI_classinfo_wrap(super);
-
- return (jclass) jni_NewLocalRef(env, (jobject) co);
-}
-
-
-/* IsAssignableFrom ************************************************************
-
- Determines whether an object of sub can be safely cast to sup.
-
-*******************************************************************************/
-
-jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
-{
- classinfo *to;
- classinfo *from;
-
- TRACEJNICALLS(("_Jv_JNI_IsAssignableFrom(env=%p, sub=%p, sup=%p)", env, sub, sup));
-
- to = (classinfo *) sup;
- from = (classinfo *) sub;
-
- return class_is_assignable_from(to, from);
-}
-
-
-/* Throw ***********************************************************************
-
- Causes a java.lang.Throwable object to be thrown.
-
-*******************************************************************************/
-
-jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
-{
- java_handle_t *o;
-
- STATISTICS(jniinvokation());
-
- o = (java_handle_t *) obj;
-
- exceptions_set_exception(o);
-
- return JNI_OK;
-}
-
-
-/* ThrowNew ********************************************************************
-
- Constructs an exception object from the specified class with the
- message specified by message and causes that exception to be
- thrown.
-
-*******************************************************************************/
-
-jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
-{
- classinfo *c;
- java_handle_t *o;
- java_handle_t *s;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
- if (msg == NULL)
- msg = "";
- s = javastring_new_from_utf_string(msg);
-
- /* instantiate exception object */
-
- o = native_new_and_init_string(c, s);
-
- if (o == NULL)
- return -1;
-
- exceptions_set_exception(o);
-
- return 0;
-}
-
-
-/* ExceptionOccurred ***********************************************************
-
- Determines if an exception is being thrown. The exception stays
- being thrown until either the native code calls ExceptionClear(),
- or the Java code handles the exception.
-
-*******************************************************************************/
-
-jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
-{
- java_handle_t *o;
-
- TRACEJNICALLS(("_Jv_JNI_ExceptionOccurred(env=%p)", env));
-
- o = exceptions_get_exception();
-
- return jni_NewLocalRef(env, (jthrowable) o);
-}
-
-
-/* ExceptionDescribe ***********************************************************
-
- Prints an exception and a backtrace of the stack to a system
- error-reporting channel, such as stderr. This is a convenience
- routine provided for debugging.
-
-*******************************************************************************/
-
-void jni_ExceptionDescribe(JNIEnv *env)
-{
- TRACEJNICALLS(("jni_ExceptionDescribe(env=%p)", env));
-
- exceptions_print_stacktrace();
-}
-
-
-/* ExceptionClear **************************************************************
-
- Clears any exception that is currently being thrown. If no
- exception is currently being thrown, this routine has no effect.
-
-*******************************************************************************/
-
-void jni_ExceptionClear(JNIEnv *env)
-{
- TRACEJNICALLS(("jni_ExceptionClear(env=%p)", env));
-
- exceptions_clear_exception();
-}
-
-
-/* FatalError ******************************************************************
-
- Raises a fatal error and does not expect the VM to recover. This
- function does not return.
-
-*******************************************************************************/
-
-void _Jv_JNI_FatalError(JNIEnv *env, const char *msg)
-{
- STATISTICS(jniinvokation());
-
- /* this seems to be the best way */
-
- vm_abort("JNI Fatal error: %s", msg);
-}
-
-
-/* PushLocalFrame **************************************************************
-
- Creates a new local reference frame, in which at least a given
- number of local references can be created.
-
-*******************************************************************************/
-
-jint jni_PushLocalFrame(JNIEnv* env, jint capacity)
-{
- TRACEJNICALLS(("jni_PushLocalFrame(env=%p, capacity=%d)", env, capacity));
-
- if (capacity <= 0)
- return -1;
-
- /* add new local reference frame to current table */
-
- if (!localref_frame_push(capacity))
- return -1;
-
- return 0;
-}
-
-
-/* PopLocalFrame ***************************************************************
-
- Pops off the current local reference frame, frees all the local
- references, and returns a local reference in the previous local
- reference frame for the given result object.
-
-*******************************************************************************/
-
-jobject jni_PopLocalFrame(JNIEnv* env, jobject result)
-{
- TRACEJNICALLS(("jni_PopLocalFrame(env=%p, result=%p)", env, result));
-
- /* release all current local frames */
-
- localref_frame_pop_all();
-
- /* add local reference and return the value */
-
- return jni_NewLocalRef(env, result);
-}
-
-
-/* DeleteLocalRef **************************************************************
-
- Deletes the local reference pointed to by localRef.
-
-*******************************************************************************/
-
-void jni_DeleteLocalRef(JNIEnv *env, jobject localRef)
-{
- java_handle_t *o;
-
- TRACEJNICALLS(("jni_DeleteLocalRef(env=%p, ref=%p)", env, localRef));
-
- o = (java_handle_t *) localRef;
-
- if (o == NULL)
- return;
-
- /* delete the reference */
-
- localref_del(o);
-}
-
-
-/* IsSameObject ****************************************************************
-
- Tests whether two references refer to the same Java object.
-
-*******************************************************************************/
-
-jboolean _Jv_JNI_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
-{
- java_handle_t *o1;
- java_handle_t *o2;
- jboolean result;
-
- STATISTICS(jniinvokation());
-
- o1 = (java_handle_t *) ref1;
- o2 = (java_handle_t *) ref2;
-
- LLNI_CRITICAL_START;
-
- if (LLNI_UNWRAP(o1) == LLNI_UNWRAP(o2))
- result = JNI_TRUE;
- else
- result = JNI_FALSE;
-
- LLNI_CRITICAL_END;
-
- return result;
-}
-
-
-/* NewLocalRef *****************************************************************
-
- Creates a new local reference that refers to the same object as ref.
-
-*******************************************************************************/
-
-jobject jni_NewLocalRef(JNIEnv *env, jobject ref)
-{
- java_handle_t *o;
- java_handle_t *localref;
-
- TRACEJNICALLS(("jni_NewLocalRef(env=%p, ref=%p)", env, ref));
-
- o = (java_handle_t *) ref;
-
- if (o == NULL)
- return NULL;
-
- /* insert the reference */
-
- localref = localref_add(LLNI_DIRECT(o));
-
- return (jobject) localref;
-}
-
-
-/* EnsureLocalCapacity *********************************************************
-
- Ensures that at least a given number of local references can be
- created in the current thread
-
-*******************************************************************************/
-
-jint jni_EnsureLocalCapacity(JNIEnv* env, jint capacity)
-{
- localref_table *lrt;
-
- TRACEJNICALLS(("jni_EnsureLocalCapacity(env=%p, capacity=%d)", env, capacity));
-
- /* get local reference table (thread specific) */
-
- lrt = LOCALREFTABLE;
-
- /* check if capacity elements are available in the local references table */
-
- if ((lrt->used + capacity) > lrt->capacity)
- return jni_PushLocalFrame(env, capacity);
-
- return 0;
-}
-
-
-/* AllocObject *****************************************************************
-
- Allocates a new Java object without invoking any of the
- constructors for the object. Returns a reference to the object.
-
-*******************************************************************************/
-
-jobject _Jv_JNI_AllocObject(JNIEnv *env, jclass clazz)
-{
- classinfo *c;
- java_handle_t *o;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
-
- if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
- exceptions_throw_instantiationexception(c);
- return NULL;
- }
-
- o = builtin_new(c);
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-/* NewObject *******************************************************************
-
- Programmers place all arguments that are to be passed to the
- constructor immediately following the methodID
- argument. NewObject() accepts these arguments and passes them to
- the Java method that the programmer wishes to invoke.
-
-*******************************************************************************/
-
-jobject jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
- va_list ap;
-
- TRACEJNICALLSENTER(("jni_NewObject(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
-
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* call constructor */
-
- va_start(ap, methodID);
- _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
- va_end(ap);
-
- TRACEJNICALLSEXIT(("->%p", o));
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-/* NewObjectV ******************************************************************
-
- Programmers place all arguments that are to be passed to the
- constructor in an args argument of type va_list that immediately
- follows the methodID argument. NewObjectV() accepts these
- arguments, and, in turn, passes them to the Java method that the
- programmer wishes to invoke.
-
-*******************************************************************************/
-
-jobject _Jv_JNI_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
- va_list args)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* call constructor */
-
- _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-/* NewObjectA *****************************************************************
-
- Programmers place all arguments that are to be passed to the
- constructor in an args array of jvalues that immediately follows
- the methodID argument. NewObjectA() accepts the arguments in this
- array, and, in turn, passes them to the Java method that the
- programmer wishes to invoke.
-
-*******************************************************************************/
-
-jobject _Jv_JNI_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
- const jvalue *args)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* call constructor */
-
- _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-/* GetObjectClass **************************************************************
-
- Returns the class of an object.
-
-*******************************************************************************/
-
-jclass _Jv_JNI_GetObjectClass(JNIEnv *env, jobject obj)
-{
- java_handle_t *o;
- classinfo *c;
- java_lang_Class *co;
-
- STATISTICS(jniinvokation());
-
- o = (java_handle_t *) obj;
-
- if ((o == NULL) || (LLNI_vftbl_direct(o) == NULL))
- return NULL;
-
- LLNI_class_get(o, c);
-
- co = LLNI_classinfo_wrap(c);
-
- return (jclass) jni_NewLocalRef(env, (jobject) co);
-}
-
-
-/* IsInstanceOf ****************************************************************
-
- Tests whether an object is an instance of a class.
-
-*******************************************************************************/
-
-jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
-{
- classinfo *c;
- java_handle_t *h;
-
- TRACEJNICALLS(("_Jv_JNI_IsInstanceOf(env=%p, obj=%p, clazz=%p)", env, obj, clazz));
-
- /* XXX Is this correct? */
- c = LLNI_classinfo_unwrap(clazz);
- h = (java_handle_t *) obj;
-
- return class_is_instance(c, h);
-}
-
-
-/* Reflection Support *********************************************************/
-
-/* FromReflectedMethod *********************************************************
-
- Converts java.lang.reflect.Method or java.lang.reflect.Constructor
- object to a method ID.
-
-*******************************************************************************/
-
-jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
-{
-#if defined(ENABLE_JAVASE)
- java_handle_t *o;
- java_lang_reflect_Method *rm;
- java_lang_reflect_Constructor *rc;
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_reflect_VMMethod *rvmm;
- java_lang_reflect_VMConstructor *rvmc;
-#endif
-
- TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
-
- o = (java_handle_t *) method;
-
- if (o == NULL)
- return NULL;
-
- if (o->vftbl->clazz == class_java_lang_reflect_Constructor) {
- rc = (java_lang_reflect_Constructor *) method;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- LLNI_field_get_ref(rc, cons , rvmc);
- LLNI_field_get_cls(rvmc, clazz, c);
- LLNI_field_get_val(rvmc, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- LLNI_field_get_cls(rc, clazz, c);
- LLNI_field_get_val(rc, slot , slot);
-
-#else
-# error unknown configuration
-#endif
- }
- else {
- assert(o->vftbl->clazz == class_java_lang_reflect_Method);
-
- rm = (java_lang_reflect_Method *) method;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- LLNI_field_get_ref(rm, m , rvmm);
- LLNI_field_get_cls(rvmm, clazz, c);
- LLNI_field_get_val(rvmm, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- LLNI_field_get_cls(rm, clazz, c);
- LLNI_field_get_val(rm, slot , slot);
-
-#else
-# error unknown configuration
-#endif
- }
-
- m = &(c->methods[slot]);
-
- return (jmethodID) m;
-#else
- vm_abort("jni_FromReflectedMethod: Not implemented in this configuration.");
-
- /* Keep compiler happy. */
-
- return NULL;
-#endif
-}
-
-
-/* FromReflectedField **********************************************************
-
- Converts a java.lang.reflect.Field to a field ID.
-
-*******************************************************************************/
-
-jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
-{
-#if defined(ENABLE_JAVASE)
- java_lang_reflect_Field *rf;
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_reflect_VMField *rvmf;
-#endif
-
- TRACEJNICALLS(("jni_FromReflectedField(env=%p, field=%p)", env, field));
-
- rf = (java_lang_reflect_Field *) field;
-
- if (rf == NULL)
- return NULL;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- LLNI_field_get_ref(rf, f, rvmf);
- LLNI_field_get_cls(rvmf, clazz, c);
- LLNI_field_get_val(rvmf, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- LLNI_field_get_cls(rf, clazz, c);
- LLNI_field_get_val(rf, slot , slot);
-
-#else
-# error unknown configuration
-#endif
-
- f = &(c->fields[slot]);
-
- return (jfieldID) f;
-#else
- vm_abort("jni_FromReflectedField: Not implemented in this configuration.");
-
- /* Keep compiler happy. */
-
- return NULL;
-#endif
-}
-
-
-/* ToReflectedMethod ***********************************************************
-
- Converts a method ID derived from cls to an instance of the
- java.lang.reflect.Method class or to an instance of the
- java.lang.reflect.Constructor class.
-
-*******************************************************************************/
-
-jobject _Jv_JNI_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID,
- jboolean isStatic)
-{
-#if defined(ENABLE_JAVASE)
- methodinfo *m;
- java_lang_reflect_Constructor *rc;
- java_lang_reflect_Method *rm;
-
- TRACEJNICALLS(("_Jv_JNI_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
-
- m = (methodinfo *) methodID;
-
- /* HotSpot does the same assert. */
-
- assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
-
- if (m->name == utf_init) {
- rc = reflect_constructor_new(m);
-
- return (jobject) rc;
- }
- else {
- rm = reflect_method_new(m);
-
- return (jobject) rm;
- }
-#else
- vm_abort("_Jv_JNI_ToReflectedMethod: not implemented in this configuration");
-
- /* keep compiler happy */
-
- return NULL;
-#endif
-}
-
-
-/* ToReflectedField ************************************************************
-
- Converts a field ID derived from cls to an instance of the
- java.lang.reflect.Field class.
-
-*******************************************************************************/
-
-jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
- jboolean isStatic)
-{
- STATISTICS(jniinvokation());
-
- log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* Calling Instance Methods ***************************************************/
-
-/* GetMethodID *****************************************************************
-
- Returns the method ID for an instance (nonstatic) method of a class
- or interface. The method may be defined in one of the clazz's
- superclasses and inherited by clazz. The method is determined by
- its name and signature.
-
- GetMethodID() causes an uninitialized class to be initialized.
-
-*******************************************************************************/
-
-jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
- const char *sig)
-{
- classinfo *c;
- utf *uname;
- utf *udesc;
- methodinfo *m;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
-
- if (c == NULL)
- return NULL;
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return NULL;
-
- /* try to get the method of the class or one of it's superclasses */
-
- uname = utf_new_char((char *) name);
- udesc = utf_new_char((char *) sig);
-
- m = class_resolvemethod(c, uname, udesc);
-
- if ((m == NULL) || (m->flags & ACC_STATIC)) {
- exceptions_throw_nosuchmethoderror(c, uname, udesc);
-
- return NULL;
- }
-
- return (jmethodID) m;
-}
-
-
-/* JNI-functions for calling instance methods *********************************/
-
-#define JNI_CALL_VIRTUAL_METHOD(name, type, intern) \
-type _Jv_JNI_Call##name##Method(JNIEnv *env, jobject obj, \
- jmethodID methodID, ...) \
-{ \
- java_handle_t *o; \
- methodinfo *m; \
- va_list ap; \
- type ret; \
- \
- o = (java_handle_t *) obj; \
- m = (methodinfo *) methodID; \
- \
- va_start(ap, methodID); \
- ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, ap); \
- va_end(ap); \
- \
- return ret; \
-}
-
-JNI_CALL_VIRTUAL_METHOD(Boolean, jboolean, Int)
-JNI_CALL_VIRTUAL_METHOD(Byte, jbyte, Int)
-JNI_CALL_VIRTUAL_METHOD(Char, jchar, Int)
-JNI_CALL_VIRTUAL_METHOD(Short, jshort, Int)
-JNI_CALL_VIRTUAL_METHOD(Int, jint, Int)
-JNI_CALL_VIRTUAL_METHOD(Long, jlong, Long)
-JNI_CALL_VIRTUAL_METHOD(Float, jfloat, Float)
-JNI_CALL_VIRTUAL_METHOD(Double, jdouble, Double)
-
-
-#define JNI_CALL_VIRTUAL_METHOD_V(name, type, intern) \
-type _Jv_JNI_Call##name##MethodV(JNIEnv *env, jobject obj, \
- jmethodID methodID, va_list args) \
-{ \
- java_handle_t *o; \
- methodinfo *m; \
- type ret; \
- \
- o = (java_handle_t *) obj; \
- m = (methodinfo *) methodID; \
- \
- ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, args); \
- \
- return ret; \
-}
-
-JNI_CALL_VIRTUAL_METHOD_V(Boolean, jboolean, Int)
-JNI_CALL_VIRTUAL_METHOD_V(Byte, jbyte, Int)
-JNI_CALL_VIRTUAL_METHOD_V(Char, jchar, Int)
-JNI_CALL_VIRTUAL_METHOD_V(Short, jshort, Int)
-JNI_CALL_VIRTUAL_METHOD_V(Int, jint, Int)
-JNI_CALL_VIRTUAL_METHOD_V(Long, jlong, Long)
-JNI_CALL_VIRTUAL_METHOD_V(Float, jfloat, Float)
-JNI_CALL_VIRTUAL_METHOD_V(Double, jdouble, Double)
-
-
-#define JNI_CALL_VIRTUAL_METHOD_A(name, type, intern) \
-type _Jv_JNI_Call##name##MethodA(JNIEnv *env, jobject obj, \
- jmethodID methodID, \
- const jvalue *args) \
-{ \
- java_handle_t *o; \
- methodinfo *m; \
- type ret; \
- \
- o = (java_handle_t *) obj; \
- m = (methodinfo *) methodID; \
- \
- ret = _Jv_jni_Call##intern##MethodA(o, LLNI_vftbl_direct(o), m, args); \
- \
- return ret; \
-}
-
-JNI_CALL_VIRTUAL_METHOD_A(Boolean, jboolean, Int)
-JNI_CALL_VIRTUAL_METHOD_A(Byte, jbyte, Int)
-JNI_CALL_VIRTUAL_METHOD_A(Char, jchar, Int)
-JNI_CALL_VIRTUAL_METHOD_A(Short, jshort, Int)
-JNI_CALL_VIRTUAL_METHOD_A(Int, jint, Int)
-JNI_CALL_VIRTUAL_METHOD_A(Long, jlong, Long)
-JNI_CALL_VIRTUAL_METHOD_A(Float, jfloat, Float)
-JNI_CALL_VIRTUAL_METHOD_A(Double, jdouble, Double)
-
-
-jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
- ...)
-{
- java_handle_t *o;
- methodinfo *m;
- java_handle_t *ret;
- va_list ap;
-
- o = (java_handle_t *) obj;
- m = (methodinfo *) methodID;
-
- va_start(ap, methodID);
- ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, ap);
- va_end(ap);
-
- return jni_NewLocalRef(env, (jobject) ret);
-}
-
-
-jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
- va_list args)
-{
- java_handle_t *o;
- methodinfo *m;
- java_handle_t *ret;
-
- o = (java_handle_t *) obj;
- m = (methodinfo *) methodID;
-
- ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, args);
-
- return jni_NewLocalRef(env, (jobject) ret);
-}
-
-
-jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
- const jvalue *args)
-{
- java_handle_t *o;
- methodinfo *m;
- java_handle_t *ret;
-
- o = (java_handle_t *) obj;
- m = (methodinfo *) methodID;
-
- ret = _Jv_jni_CallObjectMethodA(o, LLNI_vftbl_direct(o), m, args);
-
- return jni_NewLocalRef(env, (jobject) ret);
-}
-
-
-
-void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
-{
- java_handle_t *o;
- methodinfo *m;
- va_list ap;
-
- o = (java_handle_t *) obj;
- m = (methodinfo *) methodID;
-
- va_start(ap, methodID);
- _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
- va_end(ap);
-}
-
-
-void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
- va_list args)
-{
- java_handle_t *o;
- methodinfo *m;
-
- o = (java_handle_t *) obj;
- m = (methodinfo *) methodID;
-
- _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
-}
-
-
-void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
- const jvalue *args)
-{
- java_handle_t *o;
- methodinfo *m;
-
- o = (java_handle_t *) obj;
- m = (methodinfo *) methodID;
-
- _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
-}
-
-
-
-#define JNI_CALL_NONVIRTUAL_METHOD(name, type, intern) \
-type _Jv_JNI_CallNonvirtual##name##Method(JNIEnv *env, jobject obj, \
- jclass clazz, jmethodID methodID, \
- ...) \
-{ \
- java_handle_t *o; \
- classinfo *c; \
- methodinfo *m; \
- va_list ap; \
- type ret; \
- \
- o = (java_handle_t *) obj; \
- c = LLNI_classinfo_unwrap(clazz); \
- m = (methodinfo *) methodID; \
- \
- va_start(ap, methodID); \
- ret = _Jv_jni_Call##intern##Method(o, c->vftbl, m, ap); \
- va_end(ap); \
- \
- return ret; \
-}
-
-JNI_CALL_NONVIRTUAL_METHOD(Boolean, jboolean, Int)
-JNI_CALL_NONVIRTUAL_METHOD(Byte, jbyte, Int)
-JNI_CALL_NONVIRTUAL_METHOD(Char, jchar, Int)
-JNI_CALL_NONVIRTUAL_METHOD(Short, jshort, Int)
-JNI_CALL_NONVIRTUAL_METHOD(Int, jint, Int)
-JNI_CALL_NONVIRTUAL_METHOD(Long, jlong, Long)
-JNI_CALL_NONVIRTUAL_METHOD(Float, jfloat, Float)
-JNI_CALL_NONVIRTUAL_METHOD(Double, jdouble, Double)
-
-
-#define JNI_CALL_NONVIRTUAL_METHOD_V(name, type, intern) \
-type _Jv_JNI_CallNonvirtual##name##MethodV(JNIEnv *env, jobject obj, \
- jclass clazz, jmethodID methodID, \
- va_list args) \
-{ \
- java_handle_t *o; \
- classinfo *c; \
- methodinfo *m; \
- type ret; \
- \
- o = (java_handle_t *) obj; \
- c = LLNI_classinfo_unwrap(clazz); \
- m = (methodinfo *) methodID; \
- \
- ret = _Jv_jni_CallIntMethod(o, c->vftbl, m, args); \
- \
- return ret; \
-}
-
-JNI_CALL_NONVIRTUAL_METHOD_V(Boolean, jboolean, Int)
-JNI_CALL_NONVIRTUAL_METHOD_V(Byte, jbyte, Int)
-JNI_CALL_NONVIRTUAL_METHOD_V(Char, jchar, Int)
-JNI_CALL_NONVIRTUAL_METHOD_V(Short, jshort, Int)
-JNI_CALL_NONVIRTUAL_METHOD_V(Int, jint, Int)
-JNI_CALL_NONVIRTUAL_METHOD_V(Long, jlong, Long)
-JNI_CALL_NONVIRTUAL_METHOD_V(Float, jfloat, Float)
-JNI_CALL_NONVIRTUAL_METHOD_V(Double, jdouble, Double)
-
-
-#define JNI_CALL_NONVIRTUAL_METHOD_A(name, type, intern) \
-type _Jv_JNI_CallNonvirtual##name##MethodA(JNIEnv *env, jobject obj, \
- jclass clazz, jmethodID methodID, \
- const jvalue *args) \
-{ \
- log_text("JNI-Call: CallNonvirtual##name##MethodA: IMPLEMENT ME!"); \
- \
- return 0; \
-}
-
-JNI_CALL_NONVIRTUAL_METHOD_A(Boolean, jboolean, Int)
-JNI_CALL_NONVIRTUAL_METHOD_A(Byte, jbyte, Int)
-JNI_CALL_NONVIRTUAL_METHOD_A(Char, jchar, Int)
-JNI_CALL_NONVIRTUAL_METHOD_A(Short, jshort, Int)
-JNI_CALL_NONVIRTUAL_METHOD_A(Int, jint, Int)
-JNI_CALL_NONVIRTUAL_METHOD_A(Long, jlong, Long)
-JNI_CALL_NONVIRTUAL_METHOD_A(Float, jfloat, Float)
-JNI_CALL_NONVIRTUAL_METHOD_A(Double, jdouble, Double)
-
-jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
- jclass clazz, jmethodID methodID,
- ...)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
- java_handle_t *r;
- va_list ap;
-
- o = (java_handle_t *) obj;
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- va_start(ap, methodID);
- r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
- va_end(ap);
-
- return jni_NewLocalRef(env, (jobject) r);
-}
-
-
-jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
- jclass clazz, jmethodID methodID,
- va_list args)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
- java_handle_t *r;
-
- o = (java_handle_t *) obj;
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
-
- return jni_NewLocalRef(env, (jobject) r);
-}
-
-
-jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
- jclass clazz, jmethodID methodID,
- const jvalue *args)
-{
- log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
-
- return jni_NewLocalRef(env, NULL);
-}
-
-
-void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
- jmethodID methodID, ...)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
- va_list ap;
-
- o = (java_handle_t *) obj;
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- va_start(ap, methodID);
- _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
- va_end(ap);
-}
-
-
-void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
- jmethodID methodID, va_list args)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
-
- o = (java_handle_t *) obj;
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
-}
-
-
-void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
- jmethodID methodID, const jvalue * args)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
-
- o = (java_handle_t *) obj;
- c = LLNI_classinfo_unwrap(clazz);
- m = (methodinfo *) methodID;
-
- _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
-}
-
-
-/* Accessing Fields of Objects ************************************************/
-
-/* GetFieldID ******************************************************************
-
- Returns the field ID for an instance (nonstatic) field of a
- class. The field is specified by its name and signature. The
- Get<type>Field and Set<type>Field families of accessor functions
- use field IDs to retrieve object fields.
-
-*******************************************************************************/
-
-jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
- const char *sig)
-{
- classinfo *c;
- fieldinfo *f;
- utf *uname;
- utf *udesc;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
-
- /* XXX NPE check? */
-
- uname = utf_new_char((char *) name);
- udesc = utf_new_char((char *) sig);
-
- f = class_findfield(c, uname, udesc);
-
- if (f == NULL)
- exceptions_throw_nosuchfielderror(c, uname);
-
- return (jfieldID) f;
-}
-
-
-/* Get<type>Field Routines *****************************************************
-
- This family of accessor routines returns the value of an instance
- (nonstatic) field of an object. The field to access is specified by
- a field ID obtained by calling GetFieldID().
-
-*******************************************************************************/
-
-#define GET_FIELD(o,type,f) \
- *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset)))
-
-#define JNI_GET_FIELD(name, type, intern) \
-type _Jv_JNI_Get##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID) \
-{ \
- intern ret; \
- \
- TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "Field(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID)); \
- \
- LLNI_CRITICAL_START; \
- \
- ret = GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID); \
- \
- LLNI_CRITICAL_END; \
- \
- return (type) ret; \
-}
-
-JNI_GET_FIELD(Boolean, jboolean, s4)
-JNI_GET_FIELD(Byte, jbyte, s4)
-JNI_GET_FIELD(Char, jchar, s4)
-JNI_GET_FIELD(Short, jshort, s4)
-JNI_GET_FIELD(Int, jint, s4)
-JNI_GET_FIELD(Long, jlong, s8)
-JNI_GET_FIELD(Float, jfloat, float)
-JNI_GET_FIELD(Double, jdouble, double)
-
-
-jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
-{
- java_handle_t *o;
-
- TRACEJNICALLS(("_Jv_JNI_GetObjectField(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID));
-
- LLNI_CRITICAL_START;
-
- o = LLNI_WRAP(GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), java_object_t*, fieldID));
-
- LLNI_CRITICAL_END;
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-/* Set<type>Field Routines *****************************************************
-
- This family of accessor routines sets the value of an instance
- (nonstatic) field of an object. The field to access is specified by
- a field ID obtained by calling GetFieldID().
-
-*******************************************************************************/
-
-#define SET_FIELD(o,type,f,value) \
- *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
-
-#define JNI_SET_FIELD(name, type, intern) \
-void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID, \
- type value) \
-{ \
- TRACEJNICALLS(("_Jv_JNI_Set" STR(name) "Field(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value)); \
- \
- LLNI_CRITICAL_START; \
- \
- SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
- \
- LLNI_CRITICAL_START; \
-}
-
-JNI_SET_FIELD(Boolean, jboolean, s4)
-JNI_SET_FIELD(Byte, jbyte, s4)
-JNI_SET_FIELD(Char, jchar, s4)
-JNI_SET_FIELD(Short, jshort, s4)
-JNI_SET_FIELD(Int, jint, s4)
-JNI_SET_FIELD(Long, jlong, s8)
-JNI_SET_FIELD(Float, jfloat, float)
-JNI_SET_FIELD(Double, jdouble, double)
-
-
-void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
- jobject value)
-{
- TRACEJNICALLS(("_Jv_JNI_SetObjectField(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value));
-
- LLNI_CRITICAL_START;
-
- SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
-
- LLNI_CRITICAL_END;
-}
-
-
-/* Calling Static Methods *****************************************************/
-
-/* GetStaticMethodID ***********************************************************
-
- Returns the method ID for a static method of a class. The method is
- specified by its name and signature.
-
- GetStaticMethodID() causes an uninitialized class to be
- initialized.
-
-*******************************************************************************/
-
-jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
- const char *sig)
-{
- classinfo *c;
- utf *uname;
- utf *udesc;
- methodinfo *m;
-
- TRACEJNICALLS(("_Jv_JNI_GetStaticMethodID(env=%p, clazz=%p, name=%s, sig=%s)", env, clazz, name, sig));
-
- c = LLNI_classinfo_unwrap(clazz);
-
- if (c == NULL)
- return NULL;
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return NULL;
-
- /* try to get the static method of the class */
-
- uname = utf_new_char((char *) name);
- udesc = utf_new_char((char *) sig);
-
- m = class_resolvemethod(c, uname, udesc);
-
- if ((m == NULL) || !(m->flags & ACC_STATIC)) {
- exceptions_throw_nosuchmethoderror(c, uname, udesc);
-
- return NULL;
- }
-
- return (jmethodID) m;
-}
-
-
-#define JNI_CALL_STATIC_METHOD(name, type, intern) \
-type _Jv_JNI_CallStatic##name##Method(JNIEnv *env, jclass clazz, \
- jmethodID methodID, ...) \
-{ \
- methodinfo *m; \
- va_list ap; \
- type res; \
- \
- m = (methodinfo *) methodID; \
- \
- va_start(ap, methodID); \
- res = _Jv_jni_Call##intern##Method(NULL, NULL, m, ap); \
- va_end(ap); \
- \
- return res; \
-}
-
-JNI_CALL_STATIC_METHOD(Boolean, jboolean, Int)
-JNI_CALL_STATIC_METHOD(Byte, jbyte, Int)
-JNI_CALL_STATIC_METHOD(Char, jchar, Int)
-JNI_CALL_STATIC_METHOD(Short, jshort, Int)
-JNI_CALL_STATIC_METHOD(Int, jint, Int)
-JNI_CALL_STATIC_METHOD(Long, jlong, Long)
-JNI_CALL_STATIC_METHOD(Float, jfloat, Float)
-JNI_CALL_STATIC_METHOD(Double, jdouble, Double)
-
-
-#define JNI_CALL_STATIC_METHOD_V(name, type, intern) \
-type _Jv_JNI_CallStatic##name##MethodV(JNIEnv *env, jclass clazz, \
- jmethodID methodID, va_list args) \
-{ \
- methodinfo *m; \
- type res; \
- \
- m = (methodinfo *) methodID; \
- \
- res = _Jv_jni_Call##intern##Method(NULL, NULL, m, args); \
- \
- return res; \
-}
-
-JNI_CALL_STATIC_METHOD_V(Boolean, jboolean, Int)
-JNI_CALL_STATIC_METHOD_V(Byte, jbyte, Int)
-JNI_CALL_STATIC_METHOD_V(Char, jchar, Int)
-JNI_CALL_STATIC_METHOD_V(Short, jshort, Int)
-JNI_CALL_STATIC_METHOD_V(Int, jint, Int)
-JNI_CALL_STATIC_METHOD_V(Long, jlong, Long)
-JNI_CALL_STATIC_METHOD_V(Float, jfloat, Float)
-JNI_CALL_STATIC_METHOD_V(Double, jdouble, Double)
-
-
-#define JNI_CALL_STATIC_METHOD_A(name, type, intern) \
-type _Jv_JNI_CallStatic##name##MethodA(JNIEnv *env, jclass clazz, \
- jmethodID methodID, const jvalue *args) \
-{ \
- methodinfo *m; \
- type res; \
- \
- m = (methodinfo *) methodID; \
- \
- res = _Jv_jni_Call##intern##MethodA(NULL, NULL, m, args); \
- \
- return res; \
-}
-
-JNI_CALL_STATIC_METHOD_A(Boolean, jboolean, Int)
-JNI_CALL_STATIC_METHOD_A(Byte, jbyte, Int)
-JNI_CALL_STATIC_METHOD_A(Char, jchar, Int)
-JNI_CALL_STATIC_METHOD_A(Short, jshort, Int)
-JNI_CALL_STATIC_METHOD_A(Int, jint, Int)
-JNI_CALL_STATIC_METHOD_A(Long, jlong, Long)
-JNI_CALL_STATIC_METHOD_A(Float, jfloat, Float)
-JNI_CALL_STATIC_METHOD_A(Double, jdouble, Double)
-
-
-jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
- jmethodID methodID, ...)
-{
- methodinfo *m;
- java_handle_t *o;
- va_list ap;
-
- TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
-
- m = (methodinfo *) methodID;
-
- va_start(ap, methodID);
- o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
- va_end(ap);
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
- jmethodID methodID, va_list args)
-{
- methodinfo *m;
- java_handle_t *o;
-
- TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
-
- m = (methodinfo *) methodID;
-
- o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
- jmethodID methodID, const jvalue *args)
-{
- methodinfo *m;
- java_handle_t *o;
-
- TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
-
- m = (methodinfo *) methodID;
-
- o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
- jmethodID methodID, ...)
-{
- methodinfo *m;
- va_list ap;
-
- TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
-
- m = (methodinfo *) methodID;
-
- va_start(ap, methodID);
- _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
- va_end(ap);
-}
-
-
-void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
- jmethodID methodID, va_list args)
-{
- methodinfo *m;
-
- TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
-
- m = (methodinfo *) methodID;
-
- _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
-}
-
-
-void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
- jmethodID methodID, const jvalue * args)
-{
- methodinfo *m;
-
- TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
-
- m = (methodinfo *) methodID;
-
- _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
-}
-
-
-/* Accessing Static Fields ****************************************************/
-
-/* GetStaticFieldID ************************************************************
-
- Returns the field ID for a static field of a class. The field is
- specified by its name and signature. The GetStatic<type>Field and
- SetStatic<type>Field families of accessor functions use field IDs
- to retrieve static fields.
-
-*******************************************************************************/
-
-jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
- const char *sig)
-{
- classinfo *c;
- fieldinfo *f;
- utf *uname;
- utf *usig;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
-
- uname = utf_new_char((char *) name);
- usig = utf_new_char((char *) sig);
-
- f = class_findfield(c, uname, usig);
-
- if (f == NULL)
- exceptions_throw_nosuchfielderror(c, uname);
-
- return (jfieldID) f;
-}
-
-
-/* GetStatic<type>Field ********************************************************
-
- This family of accessor routines returns the value of a static
- field of an object.
-
-*******************************************************************************/
-
-#define JNI_GET_STATIC_FIELD(name, type, field) \
-type _Jv_JNI_GetStatic##name##Field(JNIEnv *env, jclass clazz, \
- jfieldID fieldID) \
-{ \
- classinfo *c; \
- fieldinfo *f; \
- \
- STATISTICS(jniinvokation()); \
- \
- c = LLNI_classinfo_unwrap(clazz); \
- f = (fieldinfo *) fieldID; \
- \
- if (!(c->state & CLASS_INITIALIZED)) \
- if (!initialize_class(c)) \
- return 0; \
- \
- return f->value->field; \
-}
-
-JNI_GET_STATIC_FIELD(Boolean, jboolean, i)
-JNI_GET_STATIC_FIELD(Byte, jbyte, i)
-JNI_GET_STATIC_FIELD(Char, jchar, i)
-JNI_GET_STATIC_FIELD(Short, jshort, i)
-JNI_GET_STATIC_FIELD(Int, jint, i)
-JNI_GET_STATIC_FIELD(Long, jlong, l)
-JNI_GET_STATIC_FIELD(Float, jfloat, f)
-JNI_GET_STATIC_FIELD(Double, jdouble, d)
-
-
-jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
- jfieldID fieldID)
-{
- classinfo *c;
- fieldinfo *f;
- java_handle_t *h;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
- f = (fieldinfo *) fieldID;
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return NULL;
-
- h = LLNI_WRAP(f->value->a);
-
- return jni_NewLocalRef(env, (jobject) h);
-}
-
-
-/* SetStatic<type>Field *******************************************************
-
- This family of accessor routines sets the value of a static field
- of an object.
-
-*******************************************************************************/
-
-#define JNI_SET_STATIC_FIELD(name, type, field) \
-void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
- jfieldID fieldID, \
- type value) \
-{ \
- classinfo *c; \
- fieldinfo *f; \
- \
- STATISTICS(jniinvokation()); \
- \
- c = LLNI_classinfo_unwrap(clazz); \
- f = (fieldinfo *) fieldID; \
- \
- if (!(c->state & CLASS_INITIALIZED)) \
- if (!initialize_class(c)) \
- return; \
- \
- f->value->field = value; \
-}
-
-JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
-JNI_SET_STATIC_FIELD(Byte, jbyte, i)
-JNI_SET_STATIC_FIELD(Char, jchar, i)
-JNI_SET_STATIC_FIELD(Short, jshort, i)
-JNI_SET_STATIC_FIELD(Int, jint, i)
-JNI_SET_STATIC_FIELD(Long, jlong, l)
-JNI_SET_STATIC_FIELD(Float, jfloat, f)
-JNI_SET_STATIC_FIELD(Double, jdouble, d)
-
-
-void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
- jobject value)
-{
- classinfo *c;
- fieldinfo *f;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
- f = (fieldinfo *) fieldID;
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return;
-
- f->value->a = LLNI_UNWRAP((java_handle_t *) value);
-}
-
-
-/* String Operations **********************************************************/
-
-/* NewString *******************************************************************
-
- Create new java.lang.String object from an array of Unicode
- characters.
-
-*******************************************************************************/
-
-jstring _Jv_JNI_NewString(JNIEnv *env, const jchar *buf, jsize len)
-{
- java_lang_String *s;
- java_handle_chararray_t *a;
- u4 i;
-
- STATISTICS(jniinvokation());
-
- s = (java_lang_String *) builtin_new(class_java_lang_String);
- a = builtin_newarray_char(len);
-
- /* javastring or characterarray could not be created */
- if ((a == NULL) || (s == NULL))
- return NULL;
-
- /* copy text */
- for (i = 0; i < len; i++)
- LLNI_array_direct(a, i) = buf[i];
-
- LLNI_field_set_ref(s, value , a);
- LLNI_field_set_val(s, offset, 0);
- LLNI_field_set_val(s, count , len);
-
- return (jstring) jni_NewLocalRef(env, (jobject) s);
-}
-
-
-static jchar emptyStringJ[]={0,0};
-
-/* GetStringLength *************************************************************
-
- Returns the length (the count of Unicode characters) of a Java
- string.
-
-*******************************************************************************/
-
-jsize _Jv_JNI_GetStringLength(JNIEnv *env, jstring str)
-{
- java_lang_String *s;
- jsize len;
-
- TRACEJNICALLS(("_Jv_JNI_GetStringLength(env=%p, str=%p)", env, str));
-
- s = (java_lang_String *) str;
-
- LLNI_field_get_val(s, count, len);
-
- return len;
-}
-
-
-/******************** convertes javastring to u2-array ****************************/
-
-u2 *javastring_tou2(jstring so)
-{
- java_lang_String *s;
- java_handle_chararray_t *a;
- u2 *stringbuffer;
- u4 i;
- int32_t count;
- int32_t offset;
-
- STATISTICS(jniinvokation());
-
- s = (java_lang_String *) so;
-
- if (!s)
- return NULL;
-
- LLNI_field_get_ref(s, value, a);
-
- if (!a)
- return NULL;
-
- LLNI_field_get_val(s, count, count);
- LLNI_field_get_val(s, offset, offset);
-
- /* allocate memory */
-
- stringbuffer = MNEW(u2, count + 1);
-
- /* copy text */
-
- for (i = 0; i < count; i++)
- stringbuffer[i] = LLNI_array_direct(a, offset + i);
-
- /* terminate string */
-
- stringbuffer[i] = '\0';
-
- return stringbuffer;
-}
-
-
-/* GetStringChars **************************************************************
-
- Returns a pointer to the array of Unicode characters of the
- string. This pointer is valid until ReleaseStringChars() is called.
-
-*******************************************************************************/
-
-const jchar *_Jv_JNI_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
-{
- jchar *jc;
-
- STATISTICS(jniinvokation());
-
- jc = javastring_tou2(str);
-
- if (jc) {
- if (isCopy)
- *isCopy = JNI_TRUE;
-
- return jc;
- }
-
- if (isCopy)
- *isCopy = JNI_TRUE;
-
- return emptyStringJ;
-}
-
-
-/* ReleaseStringChars **********************************************************
-
- Informs the VM that the native code no longer needs access to
- chars. The chars argument is a pointer obtained from string using
- GetStringChars().
-
-*******************************************************************************/
-
-void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
-{
- java_lang_String *s;
-
- STATISTICS(jniinvokation());
-
- if (chars == emptyStringJ)
- return;
-
- s = (java_lang_String *) str;
-
- MFREE(((jchar *) chars), jchar, LLNI_field_direct(s, count) + 1);
-}
-
-
-/* NewStringUTF ****************************************************************
-
- Constructs a new java.lang.String object from an array of UTF-8
- characters.
-
-*******************************************************************************/
-
-jstring _Jv_JNI_NewStringUTF(JNIEnv *env, const char *bytes)
-{
- java_lang_String *s;
-
- TRACEJNICALLS(("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes));
-
- s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
-
- return (jstring) jni_NewLocalRef(env, (jobject) s);
-}
-
-
-/****************** returns the utf8 length in bytes of a string *******************/
-
-jsize _Jv_JNI_GetStringUTFLength(JNIEnv *env, jstring string)
-{
- java_lang_String *s;
- s4 length;
-
- TRACEJNICALLS(("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string));
-
- s = (java_lang_String *) string;
-
- length = u2_utflength(LLNI_field_direct(s, value)->data, LLNI_field_direct(s, count));
-
- return length;
-}
-
-
-/* GetStringUTFChars ***********************************************************
-
- Returns a pointer to an array of UTF-8 characters of the
- string. This array is valid until it is released by
- ReleaseStringUTFChars().
-
-*******************************************************************************/
-
-const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
- jboolean *isCopy)
-{
- utf *u;
-
- STATISTICS(jniinvokation());
-
- if (string == NULL)
- return "";
-
- if (isCopy)
- *isCopy = JNI_TRUE;
-
- u = javastring_toutf((java_handle_t *) string, false);
-
- if (u != NULL)
- return u->text;
-
- return "";
-}
-
-
-/* ReleaseStringUTFChars *******************************************************
-
- Informs the VM that the native code no longer needs access to
- utf. The utf argument is a pointer derived from string using
- GetStringUTFChars().
-
-*******************************************************************************/
-
-void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
-{
- STATISTICS(jniinvokation());
-
- /* XXX we don't release utf chars right now, perhaps that should be done
- later. Since there is always one reference the garbage collector will
- never get them */
-}
-
-
-/* Array Operations ***********************************************************/
-
-/* GetArrayLength **************************************************************
-
- Returns the number of elements in the array.
-
-*******************************************************************************/
-
-jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
-{
- java_handle_t *a;
- jsize size;
-
- TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array));
-
- a = (java_handle_t *) array;
-
- size = LLNI_array_size(a);
-
- return size;
-}
-
-
-/* NewObjectArray **************************************************************
-
- Constructs a new array holding objects in class elementClass. All
- elements are initially set to initialElement.
-
-*******************************************************************************/
-
-jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
- jclass elementClass, jobject initialElement)
-{
- classinfo *c;
- java_handle_t *o;
- java_handle_objectarray_t *oa;
- s4 i;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(elementClass);
- o = (java_handle_t *) initialElement;
-
- if (length < 0) {
- exceptions_throw_negativearraysizeexception();
- return NULL;
- }
-
- oa = builtin_anewarray(length, c);
-
- if (oa == NULL)
- return NULL;
-
- /* set all elements to initialElement */
-
- for (i = 0; i < length; i++)
- array_objectarray_element_set(oa, i, o);
-
- return (jobjectArray) jni_NewLocalRef(env, (jobject) oa);
-}
-
-
-jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
- jsize index)
-{
- java_handle_objectarray_t *oa;
- java_handle_t *o;
-
- STATISTICS(jniinvokation());
-
- oa = (java_handle_objectarray_t *) array;
-
- if (index >= LLNI_array_size(oa)) {
- exceptions_throw_arrayindexoutofboundsexception();
- return NULL;
- }
-
- o = array_objectarray_element_get(oa, index);
-
- return jni_NewLocalRef(env, (jobject) o);
-}
-
-
-void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
- jsize index, jobject val)
-{
- java_handle_objectarray_t *oa;
- java_handle_t *o;
-
- STATISTICS(jniinvokation());
-
- oa = (java_handle_objectarray_t *) array;
- o = (java_handle_t *) val;
-
- if (index >= LLNI_array_size(oa)) {
- exceptions_throw_arrayindexoutofboundsexception();
- return;
- }
-
- /* check if the class of value is a subclass of the element class
- of the array */
-
- if (!builtin_canstore(oa, o))
- return;
-
- array_objectarray_element_set(oa, index, o);
-}
-
-
-#define JNI_NEW_ARRAY(name, type, intern) \
-type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len) \
-{ \
- java_handle_##intern##array_t *a; \
- \
- STATISTICS(jniinvokation()); \
- \
- if (len < 0) { \
- exceptions_throw_negativearraysizeexception(); \
- return NULL; \
- } \
- \
- a = builtin_newarray_##intern(len); \
- \
- return (type) jni_NewLocalRef(env, (jobject) a); \
-}
-
-JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
-JNI_NEW_ARRAY(Byte, jbyteArray, byte)
-JNI_NEW_ARRAY(Char, jcharArray, char)
-JNI_NEW_ARRAY(Short, jshortArray, short)
-JNI_NEW_ARRAY(Int, jintArray, int)
-JNI_NEW_ARRAY(Long, jlongArray, long)
-JNI_NEW_ARRAY(Float, jfloatArray, float)
-JNI_NEW_ARRAY(Double, jdoubleArray, double)
-
-
-/* Get<PrimitiveType>ArrayElements *********************************************
-
- A family of functions that returns the body of the primitive array.
-
-*******************************************************************************/
-
-#define JNI_GET_ARRAY_ELEMENTS(name, type, intern) \
-type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
- jboolean *isCopy) \
-{ \
- java_handle_##intern##array_t *a; \
- \
- TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \
- \
- a = (java_handle_##intern##array_t *) array; \
- \
- if (isCopy) \
- *isCopy = JNI_FALSE; \
- \
- return (type *) LLNI_array_data(a); \
-}
-
-JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
-JNI_GET_ARRAY_ELEMENTS(Byte, jbyte, byte)
-JNI_GET_ARRAY_ELEMENTS(Char, jchar, char)
-JNI_GET_ARRAY_ELEMENTS(Short, jshort, short)
-JNI_GET_ARRAY_ELEMENTS(Int, jint, int)
-JNI_GET_ARRAY_ELEMENTS(Long, jlong, long)
-JNI_GET_ARRAY_ELEMENTS(Float, jfloat, float)
-JNI_GET_ARRAY_ELEMENTS(Double, jdouble, double)
-
-
-/* Release<PrimitiveType>ArrayElements *****************************************
-
- A family of functions that informs the VM that the native code no
- longer needs access to elems. The elems argument is a pointer
- derived from array using the corresponding
- Get<PrimitiveType>ArrayElements() function. If necessary, this
- function copies back all changes made to elems to the original
- array.
-
-*******************************************************************************/
-
-#define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2) \
-void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array, \
- type *elems, jint mode) \
-{ \
- java_handle_##intern##array_t *a; \
- \
- STATISTICS(jniinvokation()); \
- \
- a = (java_handle_##intern##array_t *) array; \
- \
- if (elems != (type *) LLNI_array_data(a)) { \
- switch (mode) { \
- case JNI_COMMIT: \
- MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
- break; \
- case 0: \
- MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
- /* XXX TWISTI how should it be freed? */ \
- break; \
- case JNI_ABORT: \
- /* XXX TWISTI how should it be freed? */ \
- break; \
- } \
- } \
-}
-
-JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
-JNI_RELEASE_ARRAY_ELEMENTS(Byte, jbyte, byte, s1)
-JNI_RELEASE_ARRAY_ELEMENTS(Char, jchar, char, u2)
-JNI_RELEASE_ARRAY_ELEMENTS(Short, jshort, short, s2)
-JNI_RELEASE_ARRAY_ELEMENTS(Int, jint, int, s4)
-JNI_RELEASE_ARRAY_ELEMENTS(Long, jlong, long, s8)
-JNI_RELEASE_ARRAY_ELEMENTS(Float, jfloat, float, float)
-JNI_RELEASE_ARRAY_ELEMENTS(Double, jdouble, double, double)
-
-
-/* Get<PrimitiveType>ArrayRegion **********************************************
-
- A family of functions that copies a region of a primitive array
- into a buffer.
-
-*******************************************************************************/
-
-#define JNI_GET_ARRAY_REGION(name, type, intern, intern2) \
-void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array, \
- jsize start, jsize len, type *buf) \
-{ \
- java_handle_##intern##array_t *a; \
- \
- TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \
- \
- a = (java_handle_##intern##array_t *) array; \
- \
- if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
- exceptions_throw_arrayindexoutofboundsexception(); \
- else \
- MCOPY(buf, &LLNI_array_direct(a, start), intern2, len); \
-}
-
-JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
-JNI_GET_ARRAY_REGION(Byte, jbyte, byte, s1)
-JNI_GET_ARRAY_REGION(Char, jchar, char, u2)
-JNI_GET_ARRAY_REGION(Short, jshort, short, s2)
-JNI_GET_ARRAY_REGION(Int, jint, int, s4)
-JNI_GET_ARRAY_REGION(Long, jlong, long, s8)
-JNI_GET_ARRAY_REGION(Float, jfloat, float, float)
-JNI_GET_ARRAY_REGION(Double, jdouble, double, double)
-
-
-/* Set<PrimitiveType>ArrayRegion **********************************************
-
- A family of functions that copies back a region of a primitive
- array from a buffer.
-
-*******************************************************************************/
-
-#define JNI_SET_ARRAY_REGION(name, type, intern, intern2) \
-void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array, \
- jsize start, jsize len, const type *buf) \
-{ \
- java_handle_##intern##array_t *a; \
- \
- STATISTICS(jniinvokation()); \
- \
- a = (java_handle_##intern##array_t *) array; \
- \
- if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
- exceptions_throw_arrayindexoutofboundsexception(); \
- else \
- MCOPY(&LLNI_array_direct(a, start), buf, intern2, len); \
-}
-
-JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
-JNI_SET_ARRAY_REGION(Byte, jbyte, byte, s1)
-JNI_SET_ARRAY_REGION(Char, jchar, char, u2)
-JNI_SET_ARRAY_REGION(Short, jshort, short, s2)
-JNI_SET_ARRAY_REGION(Int, jint, int, s4)
-JNI_SET_ARRAY_REGION(Long, jlong, long, s8)
-JNI_SET_ARRAY_REGION(Float, jfloat, float, float)
-JNI_SET_ARRAY_REGION(Double, jdouble, double, double)
-
-
-/* Registering Native Methods *************************************************/
-
-/* RegisterNatives *************************************************************
-
- Registers native methods with the class specified by the clazz
- argument. The methods parameter specifies an array of
- JNINativeMethod structures that contain the names, signatures, and
- function pointers of the native methods. The nMethods parameter
- specifies the number of native methods in the array.
-
-*******************************************************************************/
-
-jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
- const JNINativeMethod *methods, jint nMethods)
-{
- classinfo *c;
-
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
-
- /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
- if (jvmti) jvmti_NativeMethodBind(method, address, new_address_ptr);
- */
-
- native_method_register(c->name, methods, nMethods);
-
- return 0;
-}
-
-
-/* UnregisterNatives ***********************************************************
-
- Unregisters native methods of a class. The class goes back to the
- state before it was linked or registered with its native method
- functions.
-
- This function should not be used in normal native code. Instead, it
- provides special programs a way to reload and relink native
- libraries.
-
-*******************************************************************************/
-
-jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
-{
- STATISTICS(jniinvokation());
-
- /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
-
- log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
-
- return 0;
-}
-
-
-/* Monitor Operations *********************************************************/
-
-/* MonitorEnter ****************************************************************
-
- Enters the monitor associated with the underlying Java object
- referred to by obj.
-
-*******************************************************************************/
-
-jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
-{
- STATISTICS(jniinvokation());
-
- if (obj == NULL) {
- exceptions_throw_nullpointerexception();
- return JNI_ERR;
- }
-
- LOCK_MONITOR_ENTER(obj);
-
- return JNI_OK;
-}
-
-
-/* MonitorExit *****************************************************************
-
- The current thread must be the owner of the monitor associated with
- the underlying Java object referred to by obj. The thread
- decrements the counter indicating the number of times it has
- entered this monitor. If the value of the counter becomes zero, the
- current thread releases the monitor.
-
-*******************************************************************************/
-
-jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
-{
- STATISTICS(jniinvokation());
-
- if (obj == NULL) {
- exceptions_throw_nullpointerexception();
- return JNI_ERR;
- }
-
- LOCK_MONITOR_EXIT(obj);
-
- return JNI_OK;
-}
-
-
-/* JavaVM Interface ***********************************************************/
-
-/* GetJavaVM *******************************************************************
-
- Returns the Java VM interface (used in the Invocation API)
- associated with the current thread. The result is placed at the
- location pointed to by the second argument, vm.
-
-*******************************************************************************/
-
-jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **vm)
-{
- STATISTICS(jniinvokation());
-
- *vm = (JavaVM *) _Jv_jvm;
-
- return 0;
-}
-
-
-/* GetStringRegion *************************************************************
-
- Copies len number of Unicode characters beginning at offset start
- to the given buffer buf.
-
- Throws StringIndexOutOfBoundsException on index overflow.
-
-*******************************************************************************/
-
-void _Jv_JNI_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len,
- jchar *buf)
-{
- java_lang_String *s;
- java_handle_chararray_t *ca;
-
- STATISTICS(jniinvokation());
-
- s = (java_lang_String *) str;
- LLNI_field_get_ref(s, value, ca);
-
- if ((start < 0) || (len < 0) || (start > LLNI_field_direct(s, count)) ||
- (start + len > LLNI_field_direct(s, count))) {
- exceptions_throw_stringindexoutofboundsexception();
- return;
- }
-
- MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
-}
-
-
-/* GetStringUTFRegion **********************************************************
-
- Translates len number of Unicode characters beginning at offset
- start into UTF-8 format and place the result in the given buffer
- buf.
-
- Throws StringIndexOutOfBoundsException on index overflow.
-
-*******************************************************************************/
-
-void _Jv_JNI_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
- jsize len, char *buf)
-{
- java_lang_String *s;
- java_handle_chararray_t *ca;
- s4 i;
- int32_t count;
- int32_t offset;
-
- TRACEJNICALLS(("_Jv_JNI_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
-
- s = (java_lang_String *) str;
- LLNI_field_get_ref(s, value, ca);
- LLNI_field_get_val(s, count, count);
- LLNI_field_get_val(s, offset, offset);
-
- if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
- exceptions_throw_stringindexoutofboundsexception();
- return;
- }
-
- for (i = 0; i < len; i++)
- buf[i] = LLNI_array_direct(ca, offset + start + i);
-
- buf[i] = '\0';
-}
-
-
-/* GetPrimitiveArrayCritical ***************************************************
-
- Obtain a direct pointer to array elements.
-
- ATTENTION: Critical section keeps open when this function returns!
- See ReleasePrimitiveArrayCritical.
-
-*******************************************************************************/
-
-void* jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
-{
- java_handle_t* h;
- java_array_t* a;
- arraydescriptor* ad;
- void* data;
-
- TRACEJNICALLS(("jni_GetPrimitiveArrayCritical(env=%p, array=%p, isCopy=%d)", env, array, isCopy));
-
- if (isCopy != NULL) {
- *isCopy = JNI_FALSE;
- }
-
- LLNI_CRITICAL_START;
-
- h = (java_handle_t*) array;
- a = (java_array_t*) LLNI_UNWRAP(h);
- ad = a->objheader.vftbl->arraydesc;
-
- /* Sanity check. */
-
- assert(ad != NULL);
-
- data = (void*) (((intptr_t) a) + ad->dataoffset);
-
- return data;
-}
-
-
-/* ReleasePrimitiveArrayCritical ***********************************************
-
- No specific documentation.
-
- ATTENTION: This function closes the critical section opened in
- GetPrimitiveArrayCritical!
-
-*******************************************************************************/
-
-void jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)
-{
- TRACEJNICALLS(("jni_ReleasePrimitiveArrayCritical(env=%p, array=%p, carray=%p, mode=%d)", env, array, carray, mode));
-
- LLNI_CRITICAL_END;
-}
-
-
-/* GetStringCritical ***********************************************************
-
- The semantics of these two functions are similar to the existing
- Get/ReleaseStringChars functions.
-
-*******************************************************************************/
-
-const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
- jboolean *isCopy)
-{
- STATISTICS(jniinvokation());
-
- return _Jv_JNI_GetStringChars(env, string, isCopy);
-}
-
-
-void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
- const jchar *cstring)
-{
- STATISTICS(jniinvokation());
-
- _Jv_JNI_ReleaseStringChars(env, string, cstring);
-}
-
-
-jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
-{
- TRACEJNICALLS(("_Jv_JNI_NewWeakGlobalRef(env=%p, obj=%p): IMPLEMENT ME!", env, obj));
-
- return obj;
-}
-
-
-void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
-{
- TRACEJNICALLS(("_Jv_JNI_DeleteWeakGlobalRef(env=%p, ref=%p): IMPLEMENT ME", env, ref));
-}
-
-
-/* NewGlobalRef ****************************************************************
-
- Creates a new global reference to the object referred to by the obj
- argument.
-
-*******************************************************************************/
-
-jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
-{
- hashtable_global_ref_entry *gre;
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
- java_handle_t *o;
-
- TRACEJNICALLS(("jni_NewGlobalRef(env=%p, obj=%p)", env, obj));
-
- o = (java_handle_t *) obj;
-
- LOCK_MONITOR_ENTER(hashtable_global_ref->header);
-
- LLNI_CRITICAL_START;
-
- /* normally addresses are aligned to 4, 8 or 16 bytes */
-
- key = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
- slot = key & (hashtable_global_ref->size - 1);
- gre = hashtable_global_ref->ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (gre) {
- if (gre->o == LLNI_DIRECT(o)) {
- /* global object found, increment the reference */
-
- gre->refs++;
-
- break;
- }
-
- gre = gre->hashlink; /* next element in external chain */
- }
-
- LLNI_CRITICAL_END;
-
- /* global ref not found, create a new one */
-
- if (gre == NULL) {
- gre = GCNEW_UNCOLLECTABLE(hashtable_global_ref_entry, 1);
-
-#if defined(ENABLE_GC_CACAO)
- /* register global ref with the GC */
-
- gc_reference_register(&(gre->o), GC_REFTYPE_JNI_GLOBALREF);
-#endif
-
- LLNI_CRITICAL_START;
-
- gre->o = LLNI_DIRECT(o);
- gre->refs = 1;
-
- LLNI_CRITICAL_END;
-
- /* insert entry into hashtable */
-
- gre->hashlink = hashtable_global_ref->ptr[slot];
-
- hashtable_global_ref->ptr[slot] = gre;
-
- /* update number of hashtable-entries */
-
- hashtable_global_ref->entries++;
- }
-
- LOCK_MONITOR_EXIT(hashtable_global_ref->header);
-
-#if defined(ENABLE_HANDLES)
- return gre;
-#else
- return obj;
-#endif
-}
-
-
-/* DeleteGlobalRef *************************************************************
-
- Deletes the global reference pointed to by globalRef.
-
-*******************************************************************************/
-
-void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
-{
- hashtable_global_ref_entry *gre;
- hashtable_global_ref_entry *prevgre;
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
- java_handle_t *o;
-
- TRACEJNICALLS(("jni_DeleteGlobalRef(env=%p, globalRef=%p)", env, globalRef));
-
- o = (java_handle_t *) globalRef;
-
- LOCK_MONITOR_ENTER(hashtable_global_ref->header);
-
- LLNI_CRITICAL_START;
-
- /* normally addresses are aligned to 4, 8 or 16 bytes */
-
- key = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
- slot = key & (hashtable_global_ref->size - 1);
- gre = hashtable_global_ref->ptr[slot];
-
- /* initialize prevgre */
-
- prevgre = NULL;
-
- /* search external hash chain for the entry */
-
- while (gre) {
- if (gre->o == LLNI_DIRECT(o)) {
- /* global object found, decrement the reference count */
-
- gre->refs--;
-
- /* if reference count is 0, remove the entry */
-
- if (gre->refs == 0) {
- /* special handling if it's the first in the chain */
-
- if (prevgre == NULL)
- hashtable_global_ref->ptr[slot] = gre->hashlink;
- else
- prevgre->hashlink = gre->hashlink;
-
-#if defined(ENABLE_GC_CACAO)
- /* unregister global ref with the GC */
-
- gc_reference_unregister(&(gre->o));
-#endif
-
- GCFREE(gre);
- }
-
- LLNI_CRITICAL_END;
-
- LOCK_MONITOR_EXIT(hashtable_global_ref->header);
-
- return;
- }
-
- prevgre = gre; /* save current pointer for removal */
- gre = gre->hashlink; /* next element in external chain */
- }
-
- log_println("jni_DeleteGlobalRef: Global reference not found.");
-
- LLNI_CRITICAL_END;
-
- LOCK_MONITOR_EXIT(hashtable_global_ref->header);
-}
-
-
-/* ExceptionCheck **************************************************************
-
- Returns JNI_TRUE when there is a pending exception; otherwise,
- returns JNI_FALSE.
-
-*******************************************************************************/
-
-jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
-{
- java_handle_t *o;
-
- STATISTICS(jniinvokation());
-
- o = exceptions_get_exception();
-
- return (o != NULL) ? JNI_TRUE : JNI_FALSE;
-}
-
-
-/* New JNI 1.4 functions ******************************************************/
-
-/* NewDirectByteBuffer *********************************************************
-
- Allocates and returns a direct java.nio.ByteBuffer referring to the
- block of memory starting at the memory address address and
- extending capacity bytes.
-
-*******************************************************************************/
-
-jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
-{
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_handle_t *nbuf;
-
-# if SIZEOF_VOID_P == 8
- gnu_classpath_Pointer64 *paddress;
-# else
- gnu_classpath_Pointer32 *paddress;
-# endif
-
- TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
-
- /* alocate a gnu.classpath.Pointer{32,64} object */
-
-# if SIZEOF_VOID_P == 8
- if (!(paddress = (gnu_classpath_Pointer64 *)
- builtin_new(class_gnu_classpath_Pointer64)))
-# else
- if (!(paddress = (gnu_classpath_Pointer32 *)
- builtin_new(class_gnu_classpath_Pointer32)))
-# endif
- return NULL;
-
- /* fill gnu.classpath.Pointer{32,64} with address */
-
- LLNI_field_set_val(paddress, data, (ptrint) address);
-
- /* create a java.nio.DirectByteBufferImpl$ReadWrite object */
-
- nbuf = (*env)->NewObject(env, class_java_nio_DirectByteBufferImpl_ReadWrite,
- (jmethodID) dbbirw_init, NULL, paddress,
- (jint) capacity, (jint) capacity, (jint) 0);
-
- /* add local reference and return the value */
-
- TRACEJNICALLSEXIT(("->%p", nbuf));
-
- return jni_NewLocalRef(env, nbuf);
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- jobject o;
- int64_t addr;
- int32_t cap;
-
- TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
-
- /* Be paranoid about address sign-extension. */
-
- addr = (int64_t) ((uintptr_t) address);
- cap = (int32_t) capacity;
-
- o = (*env)->NewObject(env, (jclass) class_java_nio_DirectByteBuffer,
- (jmethodID) dbb_init, addr, cap);
-
- /* Add local reference and return the value. */
-
- TRACEJNICALLSEXIT(("->%p", o));
-
- return jni_NewLocalRef(env, o);
-
-# else
-# error unknown classpath configuration
-# endif
-
-#else
- vm_abort("jni_NewDirectByteBuffer: Not implemented in this configuration.");
-
- /* keep compiler happy */
-
- return NULL;
-#endif
-}
-
-
-/* GetDirectBufferAddress ******************************************************
-
- Fetches and returns the starting address of the memory region
- referenced by the given direct java.nio.Buffer.
-
-*******************************************************************************/
-
-void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
-{
-#if defined(ENABLE_JAVASE)
- java_handle_t *h;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- java_nio_DirectByteBufferImpl *nbuf;
- gnu_classpath_Pointer *po;
-# if SIZEOF_VOID_P == 8
- gnu_classpath_Pointer64 *paddress;
- int64_t address;
-# else
- gnu_classpath_Pointer32 *paddress;
- int32_t address;
-# endif
- void *p;
-
- TRACEJNICALLS(("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
-
- /* Prevent compiler warning. */
-
- h = (java_handle_t *) buf;
-
- if ((h != NULL) && !builtin_instanceof(h, class_java_nio_Buffer))
- return NULL;
-
- nbuf = (java_nio_DirectByteBufferImpl *) buf;
-
- LLNI_field_get_ref(nbuf, address, po);
-
-# if SIZEOF_VOID_P == 8
- paddress = (gnu_classpath_Pointer64 *) po;
-# else
- paddress = (gnu_classpath_Pointer32 *) po;
-# endif
-
- if (paddress == NULL)
- return NULL;
-
- LLNI_field_get_val(paddress, data, address);
-
- p = (void *) (intptr_t) address;
-
- return p;
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- java_nio_Buffer *o;
- int64_t address;
- void *p;
-
- TRACEJNICALLS(("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
-
- /* Prevent compiler warning. */
-
- h = (java_handle_t *) buf;
-
- if ((h != NULL) && !builtin_instanceof(h, class_sun_nio_ch_DirectBuffer))
- return NULL;
-
- o = (java_nio_Buffer *) buf;
-
- LLNI_field_get_val(o, address, address);
-
- p = (void *) (intptr_t) address;
-
- return p;
-
-# else
-# error unknown classpath configuration
-# endif
-
-#else
-
- vm_abort("_Jv_JNI_GetDirectBufferAddress: not implemented in this configuration");
-
- /* keep compiler happy */
-
- return NULL;
-
-#endif
-}
-
-
-/* GetDirectBufferCapacity *****************************************************
-
- Fetches and returns the capacity in bytes of the memory region
- referenced by the given direct java.nio.Buffer.
-
-*******************************************************************************/
-
-jlong _Jv_JNI_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
-{
-#if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_handle_t *o;
- java_nio_Buffer *nbuf;
- jlong capacity;
-
- STATISTICS(jniinvokation());
-
- o = (java_handle_t *) buf;
-
- if (!builtin_instanceof(o, class_java_nio_DirectByteBufferImpl))
- return -1;
-
- nbuf = (java_nio_Buffer *) o;
-
- LLNI_field_get_val(nbuf, cap, capacity);
-
- return capacity;
-#else
- vm_abort("_Jv_JNI_GetDirectBufferCapacity: not implemented in this configuration");
-
- /* keep compiler happy */
-
- return 0;
-#endif
-}
-
-
-/* GetObjectRefType ************************************************************
-
- Returns the type of the object referred to by the obj argument. The
- argument obj can either be a local, global or weak global
- reference.
-
-*******************************************************************************/
-
-jobjectRefType jni_GetObjectRefType(JNIEnv *env, jobject obj)
-{
- log_println("jni_GetObjectRefType: IMPLEMENT ME!");
-
- return -1;
-}
-
-
-/* DestroyJavaVM ***************************************************************
-
- Unloads a Java VM and reclaims its resources. Only the main thread
- can unload the VM. The system waits until the main thread is only
- remaining user thread before it destroys the VM.
-
-*******************************************************************************/
-
-jint _Jv_JNI_DestroyJavaVM(JavaVM *vm)
-{
- int status;
-
- TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(vm=%p)", vm));
-
- if (vm_created == false)
- return JNI_ERR;
-
- status = vm_destroy(vm);
-
- return status;
-}
-
-
-/* AttachCurrentThread *********************************************************
-
- Attaches the current thread to a Java VM. Returns a JNI interface
- pointer in the JNIEnv argument.
-
- Trying to attach a thread that is already attached is a no-op.
-
- A native thread cannot be attached simultaneously to two Java VMs.
-
- When a thread is attached to the VM, the context class loader is
- the bootstrap loader.
-
-*******************************************************************************/
-
-static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
-{
-#if defined(ENABLE_THREADS)
- JavaVMAttachArgs *vm_aargs;
- bool result;
-
- /* If the current thread has already been attached, this operation
- is a no-op. */
-
- result = thread_current_is_attached();
-
- if (result == true) {
- *p_env = _Jv_env;
-
- return JNI_OK;
- }
-
- vm_aargs = (JavaVMAttachArgs *) thr_args;
-
- if (vm_aargs != NULL) {
- if ((vm_aargs->version != JNI_VERSION_1_2) &&
- (vm_aargs->version != JNI_VERSION_1_4))
- return JNI_EVERSION;
- }
-
- if (!thread_attach_current_external_thread(vm_aargs, false))
- return JNI_ERR;
-
- if (!localref_table_init())
- return JNI_ERR;
-#endif
-
- *p_env = _Jv_env;
-
- return JNI_OK;
-}
-
-
-jint jni_AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args)
-{
- int result;
-
- TRACEJNICALLS(("jni_AttachCurrentThread(vm=%p, p_env=%p, thr_args=%p)", vm, p_env, thr_args));
-
- if (vm_created == false)
- return JNI_ERR;
-
- result = jni_attach_current_thread(p_env, thr_args, false);
-
- return result;
-}
-
-
-/* DetachCurrentThread *********************************************************
-
- Detaches the current thread from a Java VM. All Java monitors held
- by this thread are released. All Java threads waiting for this
- thread to die are notified.
-
- In JDK 1.1, the main thread cannot be detached from the VM. It must
- call DestroyJavaVM to unload the entire VM.
-
- In the JDK, the main thread can be detached from the VM.
-
- The main thread, which is the thread that created the Java VM,
- cannot be detached from the VM. Instead, the main thread must call
- JNI_DestroyJavaVM() to unload the entire VM.
-
-*******************************************************************************/
-
-jint jni_DetachCurrentThread(JavaVM *vm)
-{
-#if defined(ENABLE_THREADS)
- bool result;
-
- TRACEJNICALLS(("jni_DetachCurrentThread(vm=%p)", vm));
-
- /* If the current thread has already been detached, this operation
- is a no-op. */
-
- result = thread_current_is_attached();
-
- if (result == false)
- return true;
-
- /* We need to pop all frames before we can destroy the table. */
-
- localref_frame_pop_all();
-
- if (!localref_table_destroy())
- return JNI_ERR;
-
- if (!thread_detach_current_external_thread())
- return JNI_ERR;
-#endif
-
- return JNI_OK;
-}
-
-
-/* GetEnv **********************************************************************
-
- If the current thread is not attached to the VM, sets *env to NULL,
- and returns JNI_EDETACHED. If the specified version is not
- supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
- sets *env to the appropriate interface, and returns JNI_OK.
-
-*******************************************************************************/
-
-jint jni_GetEnv(JavaVM *vm, void **env, jint version)
-{
- TRACEJNICALLS(("jni_GetEnv(vm=%p, env=%p, version=%d)", vm, env, version));
-
- if (vm_created == false) {
- *env = NULL;
- return JNI_EDETACHED;
- }
-
-#if defined(ENABLE_THREADS)
- if (thread_get_current() == NULL) {
- *env = NULL;
-
- return JNI_EDETACHED;
- }
-#endif
-
- /* Check the JNI version. */
-
- if (jni_version_check(version) == true) {
- *env = _Jv_env;
- return JNI_OK;
- }
-
-#if defined(ENABLE_JVMTI)
- if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE)
- == JVMTI_VERSION_INTERFACE_JVMTI) {
-
- *env = (void *) jvmti_new_environment();
-
- if (env != NULL)
- return JNI_OK;
- }
-#endif
-
- *env = NULL;
-
- return JNI_EVERSION;
-}
-
-
-/* AttachCurrentThreadAsDaemon *************************************************
-
- Same semantics as AttachCurrentThread, but the newly-created
- java.lang.Thread instance is a daemon.
-
- If the thread has already been attached via either
- AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
- simply sets the value pointed to by penv to the JNIEnv of the
- current thread. In this case neither AttachCurrentThread nor this
- routine have any effect on the daemon status of the thread.
-
-*******************************************************************************/
-
-jint jni_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)
-{
- int result;
-
- TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(vm=%p, penv=%p, args=%p)", vm, penv, args));
-
- if (vm_created == false)
- return JNI_ERR;
-
- result = jni_attach_current_thread(penv, args, true);
-
- return result;
-}
-
-
-/* JNI invocation table *******************************************************/
-
-const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
- NULL,
- NULL,
- NULL,
-
- _Jv_JNI_DestroyJavaVM,
- jni_AttachCurrentThread,
- jni_DetachCurrentThread,
- jni_GetEnv,
- jni_AttachCurrentThreadAsDaemon
-};
-
-
-/* JNI function table *********************************************************/
-
-struct JNINativeInterface_ _Jv_JNINativeInterface = {
- NULL,
- NULL,
- NULL,
- NULL,
- _Jv_JNI_GetVersion,
-
- _Jv_JNI_DefineClass,
- jni_FindClass,
- jni_FromReflectedMethod,
- jni_FromReflectedField,
- _Jv_JNI_ToReflectedMethod,
- _Jv_JNI_GetSuperclass,
- _Jv_JNI_IsAssignableFrom,
- _Jv_JNI_ToReflectedField,
-
- _Jv_JNI_Throw,
- _Jv_JNI_ThrowNew,
- _Jv_JNI_ExceptionOccurred,
- jni_ExceptionDescribe,
- jni_ExceptionClear,
- _Jv_JNI_FatalError,
- jni_PushLocalFrame,
- jni_PopLocalFrame,
-
- jni_NewGlobalRef,
- jni_DeleteGlobalRef,
- jni_DeleteLocalRef,
- _Jv_JNI_IsSameObject,
- jni_NewLocalRef,
- jni_EnsureLocalCapacity,
-
- _Jv_JNI_AllocObject,
- jni_NewObject,
- _Jv_JNI_NewObjectV,
- _Jv_JNI_NewObjectA,
-
- _Jv_JNI_GetObjectClass,
- _Jv_JNI_IsInstanceOf,
-
- _Jv_JNI_GetMethodID,
-
- _Jv_JNI_CallObjectMethod,
- _Jv_JNI_CallObjectMethodV,
- _Jv_JNI_CallObjectMethodA,
- _Jv_JNI_CallBooleanMethod,
- _Jv_JNI_CallBooleanMethodV,
- _Jv_JNI_CallBooleanMethodA,
- _Jv_JNI_CallByteMethod,
- _Jv_JNI_CallByteMethodV,
- _Jv_JNI_CallByteMethodA,
- _Jv_JNI_CallCharMethod,
- _Jv_JNI_CallCharMethodV,
- _Jv_JNI_CallCharMethodA,
- _Jv_JNI_CallShortMethod,
- _Jv_JNI_CallShortMethodV,
- _Jv_JNI_CallShortMethodA,
- _Jv_JNI_CallIntMethod,
- _Jv_JNI_CallIntMethodV,
- _Jv_JNI_CallIntMethodA,
- _Jv_JNI_CallLongMethod,
- _Jv_JNI_CallLongMethodV,
- _Jv_JNI_CallLongMethodA,
- _Jv_JNI_CallFloatMethod,
- _Jv_JNI_CallFloatMethodV,
- _Jv_JNI_CallFloatMethodA,
- _Jv_JNI_CallDoubleMethod,
- _Jv_JNI_CallDoubleMethodV,
- _Jv_JNI_CallDoubleMethodA,
- _Jv_JNI_CallVoidMethod,
- _Jv_JNI_CallVoidMethodV,
- _Jv_JNI_CallVoidMethodA,
-
- _Jv_JNI_CallNonvirtualObjectMethod,
- _Jv_JNI_CallNonvirtualObjectMethodV,
- _Jv_JNI_CallNonvirtualObjectMethodA,
- _Jv_JNI_CallNonvirtualBooleanMethod,
- _Jv_JNI_CallNonvirtualBooleanMethodV,
- _Jv_JNI_CallNonvirtualBooleanMethodA,
- _Jv_JNI_CallNonvirtualByteMethod,
- _Jv_JNI_CallNonvirtualByteMethodV,
- _Jv_JNI_CallNonvirtualByteMethodA,
- _Jv_JNI_CallNonvirtualCharMethod,
- _Jv_JNI_CallNonvirtualCharMethodV,
- _Jv_JNI_CallNonvirtualCharMethodA,
- _Jv_JNI_CallNonvirtualShortMethod,
- _Jv_JNI_CallNonvirtualShortMethodV,
- _Jv_JNI_CallNonvirtualShortMethodA,
- _Jv_JNI_CallNonvirtualIntMethod,
- _Jv_JNI_CallNonvirtualIntMethodV,
- _Jv_JNI_CallNonvirtualIntMethodA,
- _Jv_JNI_CallNonvirtualLongMethod,
- _Jv_JNI_CallNonvirtualLongMethodV,
- _Jv_JNI_CallNonvirtualLongMethodA,
- _Jv_JNI_CallNonvirtualFloatMethod,
- _Jv_JNI_CallNonvirtualFloatMethodV,
- _Jv_JNI_CallNonvirtualFloatMethodA,
- _Jv_JNI_CallNonvirtualDoubleMethod,
- _Jv_JNI_CallNonvirtualDoubleMethodV,
- _Jv_JNI_CallNonvirtualDoubleMethodA,
- _Jv_JNI_CallNonvirtualVoidMethod,
- _Jv_JNI_CallNonvirtualVoidMethodV,
- _Jv_JNI_CallNonvirtualVoidMethodA,
-
- _Jv_JNI_GetFieldID,
-
- _Jv_JNI_GetObjectField,
- _Jv_JNI_GetBooleanField,
- _Jv_JNI_GetByteField,
- _Jv_JNI_GetCharField,
- _Jv_JNI_GetShortField,
- _Jv_JNI_GetIntField,
- _Jv_JNI_GetLongField,
- _Jv_JNI_GetFloatField,
- _Jv_JNI_GetDoubleField,
- _Jv_JNI_SetObjectField,
- _Jv_JNI_SetBooleanField,
- _Jv_JNI_SetByteField,
- _Jv_JNI_SetCharField,
- _Jv_JNI_SetShortField,
- _Jv_JNI_SetIntField,
- _Jv_JNI_SetLongField,
- _Jv_JNI_SetFloatField,
- _Jv_JNI_SetDoubleField,
-
- _Jv_JNI_GetStaticMethodID,
-
- _Jv_JNI_CallStaticObjectMethod,
- _Jv_JNI_CallStaticObjectMethodV,
- _Jv_JNI_CallStaticObjectMethodA,
- _Jv_JNI_CallStaticBooleanMethod,
- _Jv_JNI_CallStaticBooleanMethodV,
- _Jv_JNI_CallStaticBooleanMethodA,
- _Jv_JNI_CallStaticByteMethod,
- _Jv_JNI_CallStaticByteMethodV,
- _Jv_JNI_CallStaticByteMethodA,
- _Jv_JNI_CallStaticCharMethod,
- _Jv_JNI_CallStaticCharMethodV,
- _Jv_JNI_CallStaticCharMethodA,
- _Jv_JNI_CallStaticShortMethod,
- _Jv_JNI_CallStaticShortMethodV,
- _Jv_JNI_CallStaticShortMethodA,
- _Jv_JNI_CallStaticIntMethod,
- _Jv_JNI_CallStaticIntMethodV,
- _Jv_JNI_CallStaticIntMethodA,
- _Jv_JNI_CallStaticLongMethod,
- _Jv_JNI_CallStaticLongMethodV,
- _Jv_JNI_CallStaticLongMethodA,
- _Jv_JNI_CallStaticFloatMethod,
- _Jv_JNI_CallStaticFloatMethodV,
- _Jv_JNI_CallStaticFloatMethodA,
- _Jv_JNI_CallStaticDoubleMethod,
- _Jv_JNI_CallStaticDoubleMethodV,
- _Jv_JNI_CallStaticDoubleMethodA,
- _Jv_JNI_CallStaticVoidMethod,
- _Jv_JNI_CallStaticVoidMethodV,
- _Jv_JNI_CallStaticVoidMethodA,
-
- _Jv_JNI_GetStaticFieldID,
-
- _Jv_JNI_GetStaticObjectField,
- _Jv_JNI_GetStaticBooleanField,
- _Jv_JNI_GetStaticByteField,
- _Jv_JNI_GetStaticCharField,
- _Jv_JNI_GetStaticShortField,
- _Jv_JNI_GetStaticIntField,
- _Jv_JNI_GetStaticLongField,
- _Jv_JNI_GetStaticFloatField,
- _Jv_JNI_GetStaticDoubleField,
- _Jv_JNI_SetStaticObjectField,
- _Jv_JNI_SetStaticBooleanField,
- _Jv_JNI_SetStaticByteField,
- _Jv_JNI_SetStaticCharField,
- _Jv_JNI_SetStaticShortField,
- _Jv_JNI_SetStaticIntField,
- _Jv_JNI_SetStaticLongField,
- _Jv_JNI_SetStaticFloatField,
- _Jv_JNI_SetStaticDoubleField,
-
- _Jv_JNI_NewString,
- _Jv_JNI_GetStringLength,
- _Jv_JNI_GetStringChars,
- _Jv_JNI_ReleaseStringChars,
-
- _Jv_JNI_NewStringUTF,
- _Jv_JNI_GetStringUTFLength,
- _Jv_JNI_GetStringUTFChars,
- _Jv_JNI_ReleaseStringUTFChars,
-
- _Jv_JNI_GetArrayLength,
-
- _Jv_JNI_NewObjectArray,
- _Jv_JNI_GetObjectArrayElement,
- _Jv_JNI_SetObjectArrayElement,
-
- _Jv_JNI_NewBooleanArray,
- _Jv_JNI_NewByteArray,
- _Jv_JNI_NewCharArray,
- _Jv_JNI_NewShortArray,
- _Jv_JNI_NewIntArray,
- _Jv_JNI_NewLongArray,
- _Jv_JNI_NewFloatArray,
- _Jv_JNI_NewDoubleArray,
-
- _Jv_JNI_GetBooleanArrayElements,
- _Jv_JNI_GetByteArrayElements,
- _Jv_JNI_GetCharArrayElements,
- _Jv_JNI_GetShortArrayElements,
- _Jv_JNI_GetIntArrayElements,
- _Jv_JNI_GetLongArrayElements,
- _Jv_JNI_GetFloatArrayElements,
- _Jv_JNI_GetDoubleArrayElements,
-
- _Jv_JNI_ReleaseBooleanArrayElements,
- _Jv_JNI_ReleaseByteArrayElements,
- _Jv_JNI_ReleaseCharArrayElements,
- _Jv_JNI_ReleaseShortArrayElements,
- _Jv_JNI_ReleaseIntArrayElements,
- _Jv_JNI_ReleaseLongArrayElements,
- _Jv_JNI_ReleaseFloatArrayElements,
- _Jv_JNI_ReleaseDoubleArrayElements,
-
- _Jv_JNI_GetBooleanArrayRegion,
- _Jv_JNI_GetByteArrayRegion,
- _Jv_JNI_GetCharArrayRegion,
- _Jv_JNI_GetShortArrayRegion,
- _Jv_JNI_GetIntArrayRegion,
- _Jv_JNI_GetLongArrayRegion,
- _Jv_JNI_GetFloatArrayRegion,
- _Jv_JNI_GetDoubleArrayRegion,
- _Jv_JNI_SetBooleanArrayRegion,
- _Jv_JNI_SetByteArrayRegion,
- _Jv_JNI_SetCharArrayRegion,
- _Jv_JNI_SetShortArrayRegion,
- _Jv_JNI_SetIntArrayRegion,
- _Jv_JNI_SetLongArrayRegion,
- _Jv_JNI_SetFloatArrayRegion,
- _Jv_JNI_SetDoubleArrayRegion,
-
- _Jv_JNI_RegisterNatives,
- _Jv_JNI_UnregisterNatives,
-
- _Jv_JNI_MonitorEnter,
- _Jv_JNI_MonitorExit,
-
- _Jv_JNI_GetJavaVM,
-
- /* New JNI 1.2 functions. */
-
- _Jv_JNI_GetStringRegion,
- _Jv_JNI_GetStringUTFRegion,
-
- jni_GetPrimitiveArrayCritical,
- jni_ReleasePrimitiveArrayCritical,
-
- _Jv_JNI_GetStringCritical,
- _Jv_JNI_ReleaseStringCritical,
-
- _Jv_JNI_NewWeakGlobalRef,
- _Jv_JNI_DeleteWeakGlobalRef,
-
- _Jv_JNI_ExceptionCheck,
-
- /* New JNI 1.4 functions. */
-
- jni_NewDirectByteBuffer,
- _Jv_JNI_GetDirectBufferAddress,
- _Jv_JNI_GetDirectBufferCapacity,
-
- /* New JNI 1.6 functions. */
-
- jni_GetObjectRefType
-};
-
-
-/* Invocation API Functions ***************************************************/
-
-/* JNI_GetDefaultJavaVMInitArgs ************************************************
-
- Returns a default configuration for the Java VM.
-
-*******************************************************************************/
-
-jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
-{
- JavaVMInitArgs *_vm_args;
-
- _vm_args = (JavaVMInitArgs *) vm_args;
-
- /* GNU classpath currently supports JNI 1.2 */
-
- switch (_vm_args->version) {
- case JNI_VERSION_1_1:
- _vm_args->version = JNI_VERSION_1_1;
- break;
-
- case JNI_VERSION_1_2:
- case JNI_VERSION_1_4:
- _vm_args->ignoreUnrecognized = JNI_FALSE;
- _vm_args->options = NULL;
- _vm_args->nOptions = 0;
- break;
-
- default:
- return -1;
- }
-
- return 0;
-}
-
-
-/* JNI_GetCreatedJavaVMs *******************************************************
-
- Returns all Java VMs that have been created. Pointers to VMs are written in
- the buffer vmBuf in the order they are created. At most bufLen number of
- entries will be written. The total number of created VMs is returned in
- *nVMs.
-
-*******************************************************************************/
-
-jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
-{
- TRACEJNICALLS(("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs));
-
- if (bufLen <= 0)
- return JNI_ERR;
-
- /* We currently only support 1 VM running. */
-
- vmBuf[0] = (JavaVM *) _Jv_jvm;
- *nVMs = 1;
-
- return JNI_OK;
-}
-
-
-/* JNI_CreateJavaVM ************************************************************
-
- Loads and initializes a Java VM. The current thread becomes the main thread.
- Sets the env argument to the JNI interface pointer of the main thread.
-
-*******************************************************************************/
-
-jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
-{
- TRACEJNICALLS(("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args));
-
- /* actually create the JVM */
-
- if (!vm_createjvm(p_vm, p_env, vm_args))
- return JNI_ERR;
-
- return JNI_OK;
-}
-
-
-/*
- * 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/native/jni.cpp - implementation of the Java Native Interface 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 <stdint.h>
+#include <string.h>
+
+#include "vm/types.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"
+
+#if defined(ENABLE_JVMTI)
+# include "native/jvmti/cacaodbg.h"
+#endif
+
+#include "threads/lock-common.h"
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/resolve.h"
+#include "vm/statistics.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/argument.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/stacktrace.hpp"
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+
+# define TRACEJNICALLS(x) \
+ do { \
+ if (opt_TraceJNICalls) { \
+ log_println x; \
+ } \
+ } while (0)
+
+# define TRACEJNICALLSENTER(x) \
+ do { \
+ if (opt_TraceJNICalls) { \
+ log_start(); \
+ log_print x; \
+ } \
+ } while (0)
+
+# define TRACEJNICALLSEXIT(x) \
+ do { \
+ if (opt_TraceJNICalls) { \
+ log_print x; \
+ log_finish(); \
+ } \
+ } while (0)
+
+#else
+
+# define TRACEJNICALLS(x)
+# define TRACEJNICALLSENTER(x)
+# define TRACEJNICALLSEXIT(x)
+
+#endif
+
+
+/* global variables ***********************************************************/
+
+/* global reference table *****************************************************/
+
+/* hashsize must be power of 2 */
+
+#define HASHTABLE_GLOBAL_REF_SIZE 64 /* initial size of globalref-hash */
+
+static hashtable *hashtable_global_ref; /* hashtable for globalrefs */
+
+
+/* direct buffer stuff ********************************************************/
+
+#if defined(ENABLE_JAVASE)
+static classinfo *class_java_nio_Buffer;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+static classinfo *class_java_nio_DirectByteBufferImpl;
+static classinfo *class_java_nio_DirectByteBufferImpl_ReadWrite;
+
+# if SIZEOF_VOID_P == 8
+static classinfo *class_gnu_classpath_Pointer64;
+# else
+static classinfo *class_gnu_classpath_Pointer32;
+# endif
+
+static methodinfo *dbbirw_init;
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+static classinfo *class_sun_nio_ch_DirectBuffer;
+static classinfo *class_java_nio_DirectByteBuffer;
+
+static methodinfo *dbb_init;
+
+# endif
+#endif
+
+
+/* some forward declarations **************************************************/
+
+extern "C" {
+jobject jni_NewLocalRef(JNIEnv *env, jobject ref);
+}
+
+
+/* jni_init ********************************************************************
+
+ Initialize the JNI subsystem.
+
+*******************************************************************************/
+
+bool jni_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("jni_init");
+
+ /* create global ref hashtable */
+
+ hashtable_global_ref = NEW(hashtable);
+
+ hashtable_create(hashtable_global_ref, HASHTABLE_GLOBAL_REF_SIZE);
+
+
+#if defined(ENABLE_JAVASE)
+ /* Direct buffer stuff. */
+
+ if (!(class_java_nio_Buffer =
+ load_class_bootstrap(utf_new_char("java/nio/Buffer"))) ||
+ !link_class(class_java_nio_Buffer))
+ return false;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ if (!(class_java_nio_DirectByteBufferImpl =
+ load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl"))) ||
+ !link_class(class_java_nio_DirectByteBufferImpl))
+ return false;
+
+ if (!(class_java_nio_DirectByteBufferImpl_ReadWrite =
+ load_class_bootstrap(utf_new_char("java/nio/DirectByteBufferImpl$ReadWrite"))) ||
+ !link_class(class_java_nio_DirectByteBufferImpl_ReadWrite))
+ return false;
+
+ if (!(dbbirw_init =
+ class_resolvemethod(class_java_nio_DirectByteBufferImpl_ReadWrite,
+ utf_init,
+ utf_new_char("(Ljava/lang/Object;Lgnu/classpath/Pointer;III)V"))))
+ return false;
+
+# if SIZEOF_VOID_P == 8
+ if (!(class_gnu_classpath_Pointer64 =
+ load_class_bootstrap(utf_new_char("gnu/classpath/Pointer64"))) ||
+ !link_class(class_gnu_classpath_Pointer64))
+ return false;
+# else
+ if (!(class_gnu_classpath_Pointer32 =
+ load_class_bootstrap(utf_new_char("gnu/classpath/Pointer32"))) ||
+ !link_class(class_gnu_classpath_Pointer32))
+ return false;
+# endif
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ if (!(class_sun_nio_ch_DirectBuffer =
+ load_class_bootstrap(utf_new_char("sun/nio/ch/DirectBuffer"))))
+ vm_abort("jni_init: loading sun/nio/ch/DirectBuffer failed");
+
+ if (!link_class(class_sun_nio_ch_DirectBuffer))
+ vm_abort("jni_init: linking sun/nio/ch/DirectBuffer failed");
+
+ if (!(class_java_nio_DirectByteBuffer =
+ load_class_bootstrap(utf_new_char("java/nio/DirectByteBuffer"))))
+ vm_abort("jni_init: loading java/nio/DirectByteBuffer failed");
+
+ if (!link_class(class_java_nio_DirectByteBuffer))
+ vm_abort("jni_init: linking java/nio/DirectByteBuffer failed");
+
+ if (!(dbb_init =
+ class_resolvemethod(class_java_nio_DirectByteBuffer,
+ utf_init,
+ utf_new_char("(JI)V"))))
+ vm_abort("jni_init: resolving java/nio/DirectByteBuffer.init(JI)V failed");
+
+# endif
+
+#endif /* defined(ENABLE_JAVASE) */
+
+ return true;
+}
+
+
+/* jni_version_check ***********************************************************
+
+ Check if the given JNI version is supported.
+
+ IN:
+ version....JNI version to check
+
+ RETURN VALUE:
+ true.......supported
+ false......not supported
+
+*******************************************************************************/
+
+bool jni_version_check(int version)
+{
+ switch (version) {
+ case JNI_VERSION_1_1:
+ case JNI_VERSION_1_2:
+ case JNI_VERSION_1_4:
+ case JNI_VERSION_1_6:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+/* _Jv_jni_CallObjectMethod ****************************************************
+
+ Internal function to call Java Object methods.
+
+*******************************************************************************/
+
+static java_handle_t *_Jv_jni_CallObjectMethod(java_handle_t *o,
+ vftbl_t *vftbl,
+ methodinfo *m, va_list ap)
+{
+ methodinfo *resm;
+ java_handle_t *ro;
+
+ STATISTICS(jniinvokation());
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ ro = vm_call_method_valist(resm, o, ap);
+
+ return ro;
+}
+
+
+/* _Jv_jni_CallObjectMethodA ***************************************************
+
+ Internal function to call Java Object methods.
+
+*******************************************************************************/
+
+static java_handle_t *_Jv_jni_CallObjectMethodA(java_handle_t *o,
+ vftbl_t *vftbl,
+ methodinfo *m,
+ const jvalue *args)
+{
+ methodinfo *resm;
+ java_handle_t *ro;
+
+ STATISTICS(jniinvokation());
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ ro = vm_call_method_jvalue(resm, o, args);
+
+ return ro;
+}
+
+
+/* _Jv_jni_CallIntMethod *******************************************************
+
+ Internal function to call Java integer class methods (boolean,
+ byte, char, short, int).
+
+*******************************************************************************/
+
+static jint _Jv_jni_CallIntMethod(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, va_list ap)
+{
+ methodinfo *resm;
+ jint i;
+
+ STATISTICS(jniinvokation());
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ i = vm_call_method_int_valist(resm, o, ap);
+
+ return i;
+}
+
+
+/* _Jv_jni_CallIntMethodA ******************************************************
+
+ Internal function to call Java integer class methods (boolean,
+ byte, char, short, int).
+
+*******************************************************************************/
+
+static jint _Jv_jni_CallIntMethodA(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, const jvalue *args)
+{
+ methodinfo *resm;
+ jint i;
+
+ STATISTICS(jniinvokation());
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ i = vm_call_method_int_jvalue(resm, o, args);
+
+ return i;
+}
+
+
+/* _Jv_jni_CallLongMethod ******************************************************
+
+ Internal function to call Java long methods.
+
+*******************************************************************************/
+
+static jlong _Jv_jni_CallLongMethod(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, va_list ap)
+{
+ methodinfo *resm;
+ jlong l;
+
+ STATISTICS(jniinvokation());
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ l = vm_call_method_long_valist(resm, o, ap);
+
+ return l;
+}
+
+
+/* _Jv_jni_CallLongMethodA *****************************************************
+
+ Internal function to call Java long methods.
+
+*******************************************************************************/
+
+static jlong _Jv_jni_CallLongMethodA(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, const jvalue *args)
+{
+ methodinfo *resm;
+ jlong l;
+
+ STATISTICS(jniinvokation());
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+ }
+ else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ l = vm_call_method_long_jvalue(resm, o, args);
+
+ return l;
+}
+
+
+/* _Jv_jni_CallFloatMethod *****************************************************
+
+ Internal function to call Java float methods.
+
+*******************************************************************************/
+
+static jfloat _Jv_jni_CallFloatMethod(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, va_list ap)
+{
+ methodinfo *resm;
+ jfloat f;
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ f = vm_call_method_float_valist(resm, o, ap);
+
+ return f;
+}
+
+
+/* _Jv_jni_CallFloatMethodA ****************************************************
+
+ Internal function to call Java float methods.
+
+*******************************************************************************/
+
+static jfloat _Jv_jni_CallFloatMethodA(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, const jvalue *args)
+{
+ methodinfo *resm;
+ jfloat f;
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+ }
+ else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ f = vm_call_method_float_jvalue(resm, o, args);
+
+ return f;
+}
+
+
+/* _Jv_jni_CallDoubleMethod ****************************************************
+
+ Internal function to call Java double methods.
+
+*******************************************************************************/
+
+static jdouble _Jv_jni_CallDoubleMethod(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, va_list ap)
+{
+ methodinfo *resm;
+ jdouble d;
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ d = vm_call_method_double_valist(resm, o, ap);
+
+ return d;
+}
+
+
+/* _Jv_jni_CallDoubleMethodA ***************************************************
+
+ Internal function to call Java double methods.
+
+*******************************************************************************/
+
+static jdouble _Jv_jni_CallDoubleMethodA(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, const jvalue *args)
+{
+ methodinfo *resm;
+ jdouble d;
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+ }
+ else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ d = vm_call_method_double_jvalue(resm, o, args);
+
+ return d;
+}
+
+
+/* _Jv_jni_CallVoidMethod ******************************************************
+
+ Internal function to call Java void methods.
+
+*******************************************************************************/
+
+static void _Jv_jni_CallVoidMethod(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, va_list ap)
+{
+ methodinfo *resm;
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ (void) vm_call_method_valist(resm, o, ap);
+}
+
+
+/* _Jv_jni_CallVoidMethodA *****************************************************
+
+ Internal function to call Java void methods.
+
+*******************************************************************************/
+
+static void _Jv_jni_CallVoidMethodA(java_handle_t *o, vftbl_t *vftbl,
+ methodinfo *m, const jvalue *args)
+{
+ methodinfo *resm;
+
+ if (m == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ /* Class initialization is done by the JIT compiler. This is ok
+ since a static method always belongs to the declaring class. */
+
+ if (m->flags & ACC_STATIC) {
+ /* For static methods we reset the object. */
+
+ if (o != NULL)
+ o = NULL;
+
+ /* for convenience */
+
+ resm = m;
+
+ } else {
+ /* For instance methods we make a virtual function table lookup. */
+
+ resm = method_vftbl_lookup(vftbl, m);
+ }
+
+ STATISTICS(jnicallXmethodnvokation());
+
+ (void) vm_call_method_jvalue(resm, o, args);
+}
+
+
+// JNI functions are exported as C functions.
+extern "C" {
+
+/* GetVersion ******************************************************************
+
+ Returns the major version number in the higher 16 bits and the
+ minor version number in the lower 16 bits.
+
+*******************************************************************************/
+
+jint _Jv_JNI_GetVersion(JNIEnv *env)
+{
+ TRACEJNICALLS(("_Jv_JNI_GetVersion(env=%p)", env));
+
+ /* We support JNI 1.6. */
+
+ return JNI_VERSION_1_6;
+}
+
+
+/* Class Operations ***********************************************************/
+
+/* DefineClass *****************************************************************
+
+ Loads a class from a buffer of raw class data. The buffer
+ containing the raw class data is not referenced by the VM after the
+ DefineClass call returns, and it may be discarded if desired.
+
+*******************************************************************************/
+
+jclass jni_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize bufLen)
+{
+#if defined(ENABLE_JAVASE)
+ utf *u;
+ classloader_t *cl;
+ classinfo *c;
+ java_handle_t* h;
+
+ TRACEJNICALLS(("jni_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen));
+
+ u = utf_new_char(name);
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ c = class_define(u, cl, bufLen, (uint8_t *) buf, NULL);
+
+ h = LLNI_classinfo_wrap(c);
+
+ return (jclass) jni_NewLocalRef(env, (jobject) h);
+#else
+ vm_abort("jni_DefineClass: Not implemented in this configuration");
+
+ // Keep compiler happy.
+
+ return 0;
+#endif
+}
+
+
+/* FindClass *******************************************************************
+
+ This function loads a locally-defined class. It searches the
+ directories and zip files specified by the CLASSPATH environment
+ variable for the class with the specified name.
+
+*******************************************************************************/
+
+jclass jni_FindClass(JNIEnv *env, const char *name)
+{
+#if defined(ENABLE_JAVASE)
+
+ utf* u;
+ classinfo* cc;
+ classinfo* c;
+ java_handle_t* h;
+
+ TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
+
+ /* FIXME If name is NULL we have a problem here. */
+
+ u = utf_new_char_classname((char *) name);
+
+ if ((u == NULL) /*|| (int)strlen(name) > symbolOopDesc::max_length() */) {
+ exceptions_throw_noclassdeffounderror(u);
+ return NULL;
+ }
+
+ /* Check stacktrace for classloader, if one found use it,
+ otherwise use the system classloader. */
+
+ /* Quote from the JNI documentation:
+
+ In the Java 2 Platform, FindClass locates the class loader
+ associated with the current native method. If the native code
+ belongs to a system class, no class loader will be
+ involved. Otherwise, the proper class loader will be invoked to
+ load and link the named class. When FindClass is called through
+ the Invocation Interface, there is no current native method or
+ its associated class loader. In that case, the result of
+ ClassLoader.getBaseClassLoader is used." */
+
+ cc = stacktrace_get_current_class();
+
+ if (cc == NULL)
+ c = load_class_from_sysloader(u);
+ else
+ c = load_class_from_classloader(u, cc->classloader);
+
+ if (c == NULL) {
+ resolve_handle_pending_exception(true);
+ return NULL;
+ }
+
+ if (!link_class(c))
+ return NULL;
+
+ h = LLNI_classinfo_wrap(c);
+
+ return (jclass) jni_NewLocalRef(env, (jobject) h);
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ utf *u;
+ classinfo *c;
+
+ TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
+
+ u = utf_new_char_classname((char *) name);
+ c = load_class_bootstrap(u);
+
+ if (c == NULL) {
+ resolve_handle_pending_exception(true);
+ return NULL;
+ }
+
+ if (!link_class(c))
+ return NULL;
+
+ return (jclass) jni_NewLocalRef(env, (jobject) c);
+
+#else
+ vm_abort("jni_FindClass: not implemented in this configuration");
+
+ /* keep compiler happy */
+
+ return NULL;
+#endif
+}
+
+
+/* GetSuperclass ***************************************************************
+
+ If clazz represents any class other than the class Object, then
+ this function returns the object that represents the superclass of
+ the class specified by clazz.
+
+*******************************************************************************/
+
+jclass jni_GetSuperclass(JNIEnv *env, jclass sub)
+{
+ classinfo* c;
+ classinfo* super;
+
+ TRACEJNICALLS(("jni_GetSuperclass(env=%p, sub=%p)", env, sub));
+
+ c = LLNI_classinfo_unwrap(sub);
+
+ if (c == NULL)
+ return NULL;
+
+ super = class_get_superclass(c);
+
+ java_handle_t* h = LLNI_classinfo_wrap(super);
+
+ return (jclass) jni_NewLocalRef(env, (jobject) h);
+}
+
+
+/* IsAssignableFrom ************************************************************
+
+ Determines whether an object of sub can be safely cast to sup.
+
+*******************************************************************************/
+
+jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
+{
+ classinfo *to;
+ classinfo *from;
+
+ TRACEJNICALLS(("_Jv_JNI_IsAssignableFrom(env=%p, sub=%p, sup=%p)", env, sub, sup));
+
+ to = (classinfo *) sup;
+ from = (classinfo *) sub;
+
+ return class_is_assignable_from(to, from);
+}
+
+
+/* Throw ***********************************************************************
+
+ Causes a java.lang.Throwable object to be thrown.
+
+*******************************************************************************/
+
+jint _Jv_JNI_Throw(JNIEnv *env, jthrowable obj)
+{
+ java_handle_t *o;
+
+ STATISTICS(jniinvokation());
+
+ o = (java_handle_t *) obj;
+
+ exceptions_set_exception(o);
+
+ return JNI_OK;
+}
+
+
+/* ThrowNew ********************************************************************
+
+ Constructs an exception object from the specified class with the
+ message specified by message and causes that exception to be
+ thrown.
+
+*******************************************************************************/
+
+jint _Jv_JNI_ThrowNew(JNIEnv* env, jclass clazz, const char *msg)
+{
+ classinfo *c;
+ java_handle_t *o;
+ java_handle_t *s;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+ if (msg == NULL)
+ msg = "";
+ s = javastring_new_from_utf_string(msg);
+
+ /* instantiate exception object */
+
+ o = native_new_and_init_string(c, s);
+
+ if (o == NULL)
+ return -1;
+
+ exceptions_set_exception(o);
+
+ return 0;
+}
+
+
+/* ExceptionOccurred ***********************************************************
+
+ Determines if an exception is being thrown. The exception stays
+ being thrown until either the native code calls ExceptionClear(),
+ or the Java code handles the exception.
+
+*******************************************************************************/
+
+jthrowable _Jv_JNI_ExceptionOccurred(JNIEnv *env)
+{
+ java_handle_t *o;
+
+ TRACEJNICALLS(("_Jv_JNI_ExceptionOccurred(env=%p)", env));
+
+ o = exceptions_get_exception();
+
+ return (jthrowable) jni_NewLocalRef(env, (jthrowable) o);
+}
+
+
+/* ExceptionDescribe ***********************************************************
+
+ Prints an exception and a backtrace of the stack to a system
+ error-reporting channel, such as stderr. This is a convenience
+ routine provided for debugging.
+
+*******************************************************************************/
+
+void jni_ExceptionDescribe(JNIEnv *env)
+{
+ TRACEJNICALLS(("jni_ExceptionDescribe(env=%p)", env));
+
+ exceptions_print_stacktrace();
+}
+
+
+/* ExceptionClear **************************************************************
+
+ Clears any exception that is currently being thrown. If no
+ exception is currently being thrown, this routine has no effect.
+
+*******************************************************************************/
+
+void jni_ExceptionClear(JNIEnv *env)
+{
+ TRACEJNICALLS(("jni_ExceptionClear(env=%p)", env));
+
+ exceptions_clear_exception();
+}
+
+
+/* FatalError ******************************************************************
+
+ Raises a fatal error and does not expect the VM to recover. This
+ function does not return.
+
+*******************************************************************************/
+
+void _Jv_JNI_FatalError(JNIEnv *env, const char *msg)
+{
+ STATISTICS(jniinvokation());
+
+ /* this seems to be the best way */
+
+ vm_abort("JNI Fatal error: %s", msg);
+}
+
+
+/* PushLocalFrame **************************************************************
+
+ Creates a new local reference frame, in which at least a given
+ number of local references can be created.
+
+*******************************************************************************/
+
+jint jni_PushLocalFrame(JNIEnv* env, jint capacity)
+{
+ TRACEJNICALLS(("jni_PushLocalFrame(env=%p, capacity=%d)", env, capacity));
+
+ if (capacity <= 0)
+ return -1;
+
+ /* add new local reference frame to current table */
+
+ if (!localref_frame_push(capacity))
+ return -1;
+
+ return 0;
+}
+
+
+/* PopLocalFrame ***************************************************************
+
+ Pops off the current local reference frame, frees all the local
+ references, and returns a local reference in the previous local
+ reference frame for the given result object.
+
+*******************************************************************************/
+
+jobject jni_PopLocalFrame(JNIEnv* env, jobject result)
+{
+ TRACEJNICALLS(("jni_PopLocalFrame(env=%p, result=%p)", env, result));
+
+ /* release all current local frames */
+
+ localref_frame_pop_all();
+
+ /* add local reference and return the value */
+
+ return jni_NewLocalRef(env, result);
+}
+
+
+/* DeleteLocalRef **************************************************************
+
+ Deletes the local reference pointed to by localRef.
+
+*******************************************************************************/
+
+void jni_DeleteLocalRef(JNIEnv *env, jobject localRef)
+{
+ java_handle_t *o;
+
+ TRACEJNICALLS(("jni_DeleteLocalRef(env=%p, ref=%p)", env, localRef));
+
+ o = (java_handle_t *) localRef;
+
+ if (o == NULL)
+ return;
+
+ /* delete the reference */
+
+ localref_del(o);
+}
+
+
+/* IsSameObject ****************************************************************
+
+ Tests whether two references refer to the same Java object.
+
+*******************************************************************************/
+
+jboolean _Jv_JNI_IsSameObject(JNIEnv *env, jobject ref1, jobject ref2)
+{
+ java_handle_t *o1;
+ java_handle_t *o2;
+ jboolean result;
+
+ STATISTICS(jniinvokation());
+
+ o1 = (java_handle_t *) ref1;
+ o2 = (java_handle_t *) ref2;
+
+ LLNI_CRITICAL_START;
+
+ if (LLNI_UNWRAP(o1) == LLNI_UNWRAP(o2))
+ result = JNI_TRUE;
+ else
+ result = JNI_FALSE;
+
+ LLNI_CRITICAL_END;
+
+ return result;
+}
+
+
+/* NewLocalRef *****************************************************************
+
+ Creates a new local reference that refers to the same object as ref.
+
+*******************************************************************************/
+
+jobject jni_NewLocalRef(JNIEnv *env, jobject ref)
+{
+ java_handle_t *o;
+ java_handle_t *localref;
+
+ TRACEJNICALLS(("jni_NewLocalRef(env=%p, ref=%p)", env, ref));
+
+ o = (java_handle_t *) ref;
+
+ if (o == NULL)
+ return NULL;
+
+ /* insert the reference */
+
+ localref = localref_add(LLNI_DIRECT(o));
+
+ return (jobject) localref;
+}
+
+
+/* EnsureLocalCapacity *********************************************************
+
+ Ensures that at least a given number of local references can be
+ created in the current thread
+
+*******************************************************************************/
+
+jint jni_EnsureLocalCapacity(JNIEnv* env, jint capacity)
+{
+ localref_table *lrt;
+
+ TRACEJNICALLS(("jni_EnsureLocalCapacity(env=%p, capacity=%d)", env, capacity));
+
+ /* get local reference table (thread specific) */
+
+ lrt = LOCALREFTABLE;
+
+ /* check if capacity elements are available in the local references table */
+
+ if ((lrt->used + capacity) > lrt->capacity)
+ return jni_PushLocalFrame(env, capacity);
+
+ return 0;
+}
+
+
+/* AllocObject *****************************************************************
+
+ Allocates a new Java object without invoking any of the
+ constructors for the object. Returns a reference to the object.
+
+*******************************************************************************/
+
+jobject _Jv_JNI_AllocObject(JNIEnv *env, jclass clazz)
+{
+ classinfo *c;
+ java_handle_t *o;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+
+ if ((c->flags & ACC_INTERFACE) || (c->flags & ACC_ABSTRACT)) {
+ exceptions_throw_instantiationexception(c);
+ return NULL;
+ }
+
+ o = builtin_new(c);
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+/* NewObject *******************************************************************
+
+ Programmers place all arguments that are to be passed to the
+ constructor immediately following the methodID
+ argument. NewObject() accepts these arguments and passes them to
+ the Java method that the programmer wishes to invoke.
+
+*******************************************************************************/
+
+jobject jni_NewObject(JNIEnv *env, jclass clazz, jmethodID methodID, ...)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+ va_list ap;
+
+ TRACEJNICALLSENTER(("jni_NewObject(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
+
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return NULL;
+
+ /* call constructor */
+
+ va_start(ap, methodID);
+ _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
+ va_end(ap);
+
+ TRACEJNICALLSEXIT(("->%p", o));
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+/* NewObjectV ******************************************************************
+
+ Programmers place all arguments that are to be passed to the
+ constructor in an args argument of type va_list that immediately
+ follows the methodID argument. NewObjectV() accepts these
+ arguments, and, in turn, passes them to the Java method that the
+ programmer wishes to invoke.
+
+*******************************************************************************/
+
+jobject _Jv_JNI_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
+ va_list args)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return NULL;
+
+ /* call constructor */
+
+ _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+/* NewObjectA *****************************************************************
+
+ Programmers place all arguments that are to be passed to the
+ constructor in an args array of jvalues that immediately follows
+ the methodID argument. NewObjectA() accepts the arguments in this
+ array, and, in turn, passes them to the Java method that the
+ programmer wishes to invoke.
+
+*******************************************************************************/
+
+jobject _Jv_JNI_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
+ const jvalue *args)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return NULL;
+
+ /* call constructor */
+
+ _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+/* GetObjectClass **************************************************************
+
+ Returns the class of an object.
+
+*******************************************************************************/
+
+jclass jni_GetObjectClass(JNIEnv *env, jobject obj)
+{
+ java_handle_t* o;
+ classinfo* c;
+
+ TRACEJNICALLS(("jni_GetObjectClass(env=%p, obj=%p)", env, obj));
+
+ o = (java_handle_t *) obj;
+
+ if ((o == NULL) || (LLNI_vftbl_direct(o) == NULL))
+ return NULL;
+
+ LLNI_class_get(o, c);
+
+ java_handle_t* h = LLNI_classinfo_wrap(c);
+
+ return (jclass) jni_NewLocalRef(env, (jobject) h);
+}
+
+
+/* IsInstanceOf ****************************************************************
+
+ Tests whether an object is an instance of a class.
+
+*******************************************************************************/
+
+jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
+{
+ classinfo *c;
+ java_handle_t *h;
+
+ TRACEJNICALLS(("_Jv_JNI_IsInstanceOf(env=%p, obj=%p, clazz=%p)", env, obj, clazz));
+
+ /* XXX Is this correct? */
+ c = LLNI_classinfo_unwrap(clazz);
+ h = (java_handle_t *) obj;
+
+ return class_is_instance(c, h);
+}
+
+
+/* Reflection Support *********************************************************/
+
+/* FromReflectedMethod *********************************************************
+
+ Converts java.lang.reflect.Method or java.lang.reflect.Constructor
+ object to a method ID.
+
+*******************************************************************************/
+
+jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
+{
+#if defined(ENABLE_JAVASE)
+ java_handle_t* o;
+ methodinfo* m;
+
+ TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
+
+ o = (java_handle_t *) method;
+
+ if (o == NULL)
+ return NULL;
+
+ // FIXME We can't access the object here directly.
+ if (o->vftbl->clazz == class_java_lang_reflect_Constructor) {
+ java_lang_reflect_Constructor rc(method);
+ m = rc.get_method();
+ }
+ else {
+ // FIXME We can't access the object here directly.
+ assert(o->vftbl->clazz == class_java_lang_reflect_Method);
+
+ java_lang_reflect_Method rm(method);
+ m = rm.get_method();
+ }
+
+ return (jmethodID) m;
+#else
+ vm_abort("jni_FromReflectedMethod: Not implemented in this configuration.");
+
+ // Keep compiler happy.
+ return NULL;
+#endif
+}
+
+
+/* FromReflectedField **********************************************************
+
+ Converts a java.lang.reflect.Field to a field ID.
+
+*******************************************************************************/
+
+jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
+{
+#if defined(ENABLE_JAVASE)
+
+ TRACEJNICALLS(("jni_FromReflectedField(env=%p, field=%p)", env, field));
+
+ java_lang_reflect_Field rf(field);
+
+ if (rf.is_null())
+ return NULL;
+
+ fieldinfo* f = rf.get_field();
+
+ return (jfieldID) f;
+#else
+ vm_abort("jni_FromReflectedField: Not implemented in this configuration.");
+
+ // Keep compiler happy.
+ return NULL;
+#endif
+}
+
+
+/* ToReflectedMethod ***********************************************************
+
+ Converts a method ID derived from cls to an instance of the
+ java.lang.reflect.Method class or to an instance of the
+ java.lang.reflect.Constructor class.
+
+*******************************************************************************/
+
+jobject jni_ToReflectedMethod(JNIEnv* env, jclass cls, jmethodID methodID, jboolean isStatic)
+{
+#if defined(ENABLE_JAVASE)
+ TRACEJNICALLS(("jni_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
+
+ methodinfo* m = (methodinfo *) methodID;
+
+ /* HotSpot does the same assert. */
+
+ assert(((m->flags & ACC_STATIC) != 0) == (isStatic != 0));
+
+ java_handle_t* h;
+
+ if (m->name == utf_init) {
+ h = java_lang_reflect_Constructor(m).get_handle();
+ }
+ else {
+ h = java_lang_reflect_Method(m).get_handle();
+ }
+
+ return (jobject) h;
+#else
+ vm_abort("jni_ToReflectedMethod: Not implemented in this configuration.");
+
+ /* keep compiler happy */
+
+ return NULL;
+#endif
+}
+
+
+/* ToReflectedField ************************************************************
+
+ Converts a field ID derived from cls to an instance of the
+ java.lang.reflect.Field class.
+
+*******************************************************************************/
+
+jobject _Jv_JNI_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
+ jboolean isStatic)
+{
+ STATISTICS(jniinvokation());
+
+ log_text("JNI-Call: ToReflectedField: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* Calling Instance Methods ***************************************************/
+
+/* GetMethodID *****************************************************************
+
+ Returns the method ID for an instance (nonstatic) method of a class
+ or interface. The method may be defined in one of the clazz's
+ superclasses and inherited by clazz. The method is determined by
+ its name and signature.
+
+ GetMethodID() causes an uninitialized class to be initialized.
+
+*******************************************************************************/
+
+jmethodID _Jv_JNI_GetMethodID(JNIEnv* env, jclass clazz, const char *name,
+ const char *sig)
+{
+ classinfo *c;
+ utf *uname;
+ utf *udesc;
+ methodinfo *m;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+
+ if (c == NULL)
+ return NULL;
+
+ if (!(c->state & CLASS_INITIALIZED))
+ if (!initialize_class(c))
+ return NULL;
+
+ /* try to get the method of the class or one of it's superclasses */
+
+ uname = utf_new_char((char *) name);
+ udesc = utf_new_char((char *) sig);
+
+ m = class_resolvemethod(c, uname, udesc);
+
+ if ((m == NULL) || (m->flags & ACC_STATIC)) {
+ exceptions_throw_nosuchmethoderror(c, uname, udesc);
+
+ return NULL;
+ }
+
+ return (jmethodID) m;
+}
+
+
+/* JNI-functions for calling instance methods *********************************/
+
+#define JNI_CALL_VIRTUAL_METHOD(name, type, intern) \
+type _Jv_JNI_Call##name##Method(JNIEnv *env, jobject obj, \
+ jmethodID methodID, ...) \
+{ \
+ java_handle_t *o; \
+ methodinfo *m; \
+ va_list ap; \
+ type ret; \
+ \
+ o = (java_handle_t *) obj; \
+ m = (methodinfo *) methodID; \
+ \
+ va_start(ap, methodID); \
+ ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, ap); \
+ va_end(ap); \
+ \
+ return ret; \
+}
+
+JNI_CALL_VIRTUAL_METHOD(Boolean, jboolean, Int)
+JNI_CALL_VIRTUAL_METHOD(Byte, jbyte, Int)
+JNI_CALL_VIRTUAL_METHOD(Char, jchar, Int)
+JNI_CALL_VIRTUAL_METHOD(Short, jshort, Int)
+JNI_CALL_VIRTUAL_METHOD(Int, jint, Int)
+JNI_CALL_VIRTUAL_METHOD(Long, jlong, Long)
+JNI_CALL_VIRTUAL_METHOD(Float, jfloat, Float)
+JNI_CALL_VIRTUAL_METHOD(Double, jdouble, Double)
+
+
+#define JNI_CALL_VIRTUAL_METHOD_V(name, type, intern) \
+type _Jv_JNI_Call##name##MethodV(JNIEnv *env, jobject obj, \
+ jmethodID methodID, va_list args) \
+{ \
+ java_handle_t *o; \
+ methodinfo *m; \
+ type ret; \
+ \
+ o = (java_handle_t *) obj; \
+ m = (methodinfo *) methodID; \
+ \
+ ret = _Jv_jni_Call##intern##Method(o, LLNI_vftbl_direct(o), m, args); \
+ \
+ return ret; \
+}
+
+JNI_CALL_VIRTUAL_METHOD_V(Boolean, jboolean, Int)
+JNI_CALL_VIRTUAL_METHOD_V(Byte, jbyte, Int)
+JNI_CALL_VIRTUAL_METHOD_V(Char, jchar, Int)
+JNI_CALL_VIRTUAL_METHOD_V(Short, jshort, Int)
+JNI_CALL_VIRTUAL_METHOD_V(Int, jint, Int)
+JNI_CALL_VIRTUAL_METHOD_V(Long, jlong, Long)
+JNI_CALL_VIRTUAL_METHOD_V(Float, jfloat, Float)
+JNI_CALL_VIRTUAL_METHOD_V(Double, jdouble, Double)
+
+
+#define JNI_CALL_VIRTUAL_METHOD_A(name, type, intern) \
+type _Jv_JNI_Call##name##MethodA(JNIEnv *env, jobject obj, \
+ jmethodID methodID, \
+ const jvalue *args) \
+{ \
+ java_handle_t *o; \
+ methodinfo *m; \
+ type ret; \
+ \
+ o = (java_handle_t *) obj; \
+ m = (methodinfo *) methodID; \
+ \
+ ret = _Jv_jni_Call##intern##MethodA(o, LLNI_vftbl_direct(o), m, args); \
+ \
+ return ret; \
+}
+
+JNI_CALL_VIRTUAL_METHOD_A(Boolean, jboolean, Int)
+JNI_CALL_VIRTUAL_METHOD_A(Byte, jbyte, Int)
+JNI_CALL_VIRTUAL_METHOD_A(Char, jchar, Int)
+JNI_CALL_VIRTUAL_METHOD_A(Short, jshort, Int)
+JNI_CALL_VIRTUAL_METHOD_A(Int, jint, Int)
+JNI_CALL_VIRTUAL_METHOD_A(Long, jlong, Long)
+JNI_CALL_VIRTUAL_METHOD_A(Float, jfloat, Float)
+JNI_CALL_VIRTUAL_METHOD_A(Double, jdouble, Double)
+
+
+jobject _Jv_JNI_CallObjectMethod(JNIEnv *env, jobject obj, jmethodID methodID,
+ ...)
+{
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *ret;
+ va_list ap;
+
+ o = (java_handle_t *) obj;
+ m = (methodinfo *) methodID;
+
+ va_start(ap, methodID);
+ ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, ap);
+ va_end(ap);
+
+ return jni_NewLocalRef(env, (jobject) ret);
+}
+
+
+jobject _Jv_JNI_CallObjectMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args)
+{
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *ret;
+
+ o = (java_handle_t *) obj;
+ m = (methodinfo *) methodID;
+
+ ret = _Jv_jni_CallObjectMethod(o, LLNI_vftbl_direct(o), m, args);
+
+ return jni_NewLocalRef(env, (jobject) ret);
+}
+
+
+jobject _Jv_JNI_CallObjectMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ const jvalue *args)
+{
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *ret;
+
+ o = (java_handle_t *) obj;
+ m = (methodinfo *) methodID;
+
+ ret = _Jv_jni_CallObjectMethodA(o, LLNI_vftbl_direct(o), m, args);
+
+ return jni_NewLocalRef(env, (jobject) ret);
+}
+
+
+
+void _Jv_JNI_CallVoidMethod(JNIEnv *env, jobject obj, jmethodID methodID, ...)
+{
+ java_handle_t *o;
+ methodinfo *m;
+ va_list ap;
+
+ o = (java_handle_t *) obj;
+ m = (methodinfo *) methodID;
+
+ va_start(ap, methodID);
+ _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, ap);
+ va_end(ap);
+}
+
+
+void _Jv_JNI_CallVoidMethodV(JNIEnv *env, jobject obj, jmethodID methodID,
+ va_list args)
+{
+ java_handle_t *o;
+ methodinfo *m;
+
+ o = (java_handle_t *) obj;
+ m = (methodinfo *) methodID;
+
+ _Jv_jni_CallVoidMethod(o, LLNI_vftbl_direct(o), m, args);
+}
+
+
+void _Jv_JNI_CallVoidMethodA(JNIEnv *env, jobject obj, jmethodID methodID,
+ const jvalue *args)
+{
+ java_handle_t *o;
+ methodinfo *m;
+
+ o = (java_handle_t *) obj;
+ m = (methodinfo *) methodID;
+
+ _Jv_jni_CallVoidMethodA(o, LLNI_vftbl_direct(o), m, args);
+}
+
+
+
+#define JNI_CALL_NONVIRTUAL_METHOD(name, type, intern) \
+type _Jv_JNI_CallNonvirtual##name##Method(JNIEnv *env, jobject obj, \
+ jclass clazz, jmethodID methodID, \
+ ...) \
+{ \
+ java_handle_t *o; \
+ classinfo *c; \
+ methodinfo *m; \
+ va_list ap; \
+ type ret; \
+ \
+ o = (java_handle_t *) obj; \
+ c = LLNI_classinfo_unwrap(clazz); \
+ m = (methodinfo *) methodID; \
+ \
+ va_start(ap, methodID); \
+ ret = _Jv_jni_Call##intern##Method(o, c->vftbl, m, ap); \
+ va_end(ap); \
+ \
+ return ret; \
+}
+
+JNI_CALL_NONVIRTUAL_METHOD(Boolean, jboolean, Int)
+JNI_CALL_NONVIRTUAL_METHOD(Byte, jbyte, Int)
+JNI_CALL_NONVIRTUAL_METHOD(Char, jchar, Int)
+JNI_CALL_NONVIRTUAL_METHOD(Short, jshort, Int)
+JNI_CALL_NONVIRTUAL_METHOD(Int, jint, Int)
+JNI_CALL_NONVIRTUAL_METHOD(Long, jlong, Long)
+JNI_CALL_NONVIRTUAL_METHOD(Float, jfloat, Float)
+JNI_CALL_NONVIRTUAL_METHOD(Double, jdouble, Double)
+
+
+#define JNI_CALL_NONVIRTUAL_METHOD_V(name, type, intern) \
+type _Jv_JNI_CallNonvirtual##name##MethodV(JNIEnv *env, jobject obj, \
+ jclass clazz, jmethodID methodID, \
+ va_list args) \
+{ \
+ java_handle_t *o; \
+ classinfo *c; \
+ methodinfo *m; \
+ type ret; \
+ \
+ o = (java_handle_t *) obj; \
+ c = LLNI_classinfo_unwrap(clazz); \
+ m = (methodinfo *) methodID; \
+ \
+ ret = _Jv_jni_CallIntMethod(o, c->vftbl, m, args); \
+ \
+ return ret; \
+}
+
+JNI_CALL_NONVIRTUAL_METHOD_V(Boolean, jboolean, Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Byte, jbyte, Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Char, jchar, Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Short, jshort, Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Int, jint, Int)
+JNI_CALL_NONVIRTUAL_METHOD_V(Long, jlong, Long)
+JNI_CALL_NONVIRTUAL_METHOD_V(Float, jfloat, Float)
+JNI_CALL_NONVIRTUAL_METHOD_V(Double, jdouble, Double)
+
+
+#define JNI_CALL_NONVIRTUAL_METHOD_A(name, type, intern) \
+type _Jv_JNI_CallNonvirtual##name##MethodA(JNIEnv *env, jobject obj, \
+ jclass clazz, jmethodID methodID, \
+ const jvalue *args) \
+{ \
+ log_text("JNI-Call: CallNonvirtual##name##MethodA: IMPLEMENT ME!"); \
+ \
+ return 0; \
+}
+
+JNI_CALL_NONVIRTUAL_METHOD_A(Boolean, jboolean, Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Byte, jbyte, Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Char, jchar, Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Short, jshort, Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Int, jint, Int)
+JNI_CALL_NONVIRTUAL_METHOD_A(Long, jlong, Long)
+JNI_CALL_NONVIRTUAL_METHOD_A(Float, jfloat, Float)
+JNI_CALL_NONVIRTUAL_METHOD_A(Double, jdouble, Double)
+
+jobject _Jv_JNI_CallNonvirtualObjectMethod(JNIEnv *env, jobject obj,
+ jclass clazz, jmethodID methodID,
+ ...)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+ java_handle_t *r;
+ va_list ap;
+
+ o = (java_handle_t *) obj;
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ va_start(ap, methodID);
+ r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, ap);
+ va_end(ap);
+
+ return jni_NewLocalRef(env, (jobject) r);
+}
+
+
+jobject _Jv_JNI_CallNonvirtualObjectMethodV(JNIEnv *env, jobject obj,
+ jclass clazz, jmethodID methodID,
+ va_list args)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+ java_handle_t *r;
+
+ o = (java_handle_t *) obj;
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ r = _Jv_jni_CallObjectMethod(o, c->vftbl, m, args);
+
+ return jni_NewLocalRef(env, (jobject) r);
+}
+
+
+jobject _Jv_JNI_CallNonvirtualObjectMethodA(JNIEnv *env, jobject obj,
+ jclass clazz, jmethodID methodID,
+ const jvalue *args)
+{
+ log_text("JNI-Call: CallNonvirtualObjectMethodA: IMPLEMENT ME!");
+
+ return jni_NewLocalRef(env, NULL);
+}
+
+
+void _Jv_JNI_CallNonvirtualVoidMethod(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, ...)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+ va_list ap;
+
+ o = (java_handle_t *) obj;
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ va_start(ap, methodID);
+ _Jv_jni_CallVoidMethod(o, c->vftbl, m, ap);
+ va_end(ap);
+}
+
+
+void _Jv_JNI_CallNonvirtualVoidMethodV(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, va_list args)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+
+ o = (java_handle_t *) obj;
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ _Jv_jni_CallVoidMethod(o, c->vftbl, m, args);
+}
+
+
+void _Jv_JNI_CallNonvirtualVoidMethodA(JNIEnv *env, jobject obj, jclass clazz,
+ jmethodID methodID, const jvalue * args)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+
+ o = (java_handle_t *) obj;
+ c = LLNI_classinfo_unwrap(clazz);
+ m = (methodinfo *) methodID;
+
+ _Jv_jni_CallVoidMethodA(o, c->vftbl, m, args);
+}
+
+
+/* Accessing Fields of Objects ************************************************/
+
+/* GetFieldID ******************************************************************
+
+ Returns the field ID for an instance (nonstatic) field of a
+ class. The field is specified by its name and signature. The
+ Get<type>Field and Set<type>Field families of accessor functions
+ use field IDs to retrieve object fields.
+
+*******************************************************************************/
+
+jfieldID _Jv_JNI_GetFieldID(JNIEnv *env, jclass clazz, const char *name,
+ const char *sig)
+{
+ classinfo *c;
+ fieldinfo *f;
+ utf *uname;
+ utf *udesc;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+
+ /* XXX NPE check? */
+
+ uname = utf_new_char((char *) name);
+ udesc = utf_new_char((char *) sig);
+
+ f = class_findfield(c, uname, udesc);
+
+ if (f == NULL)
+ exceptions_throw_nosuchfielderror(c, uname);
+
+ return (jfieldID) f;
+}
+
+
+/* Get<type>Field Routines *****************************************************
+
+ This family of accessor routines returns the value of an instance
+ (nonstatic) field of an object. The field to access is specified by
+ a field ID obtained by calling GetFieldID().
+
+*******************************************************************************/
+
+#define GET_FIELD(o,type,f) \
+ *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset)))
+
+#define JNI_GET_FIELD(name, type, intern) \
+type _Jv_JNI_Get##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID) \
+{ \
+ intern ret; \
+ \
+ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "Field(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID)); \
+ \
+ LLNI_CRITICAL_START; \
+ \
+ ret = GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID); \
+ \
+ LLNI_CRITICAL_END; \
+ \
+ return (type) ret; \
+}
+
+JNI_GET_FIELD(Boolean, jboolean, s4)
+JNI_GET_FIELD(Byte, jbyte, s4)
+JNI_GET_FIELD(Char, jchar, s4)
+JNI_GET_FIELD(Short, jshort, s4)
+JNI_GET_FIELD(Int, jint, s4)
+JNI_GET_FIELD(Long, jlong, s8)
+JNI_GET_FIELD(Float, jfloat, float)
+JNI_GET_FIELD(Double, jdouble, double)
+
+
+jobject _Jv_JNI_GetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID)
+{
+ java_handle_t *o;
+
+ TRACEJNICALLS(("_Jv_JNI_GetObjectField(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID));
+
+ LLNI_CRITICAL_START;
+
+ o = LLNI_WRAP(GET_FIELD(LLNI_DIRECT((java_handle_t *) obj), java_object_t*, fieldID));
+
+ LLNI_CRITICAL_END;
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+/* Set<type>Field Routines *****************************************************
+
+ This family of accessor routines sets the value of an instance
+ (nonstatic) field of an object. The field to access is specified by
+ a field ID obtained by calling GetFieldID().
+
+*******************************************************************************/
+
+#define SET_FIELD(o,type,f,value) \
+ *((type *) (((intptr_t) (o)) + ((intptr_t) ((fieldinfo *) (f))->offset))) = (type) (value)
+
+#define JNI_SET_FIELD(name, type, intern) \
+void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID, \
+ type value) \
+{ \
+ TRACEJNICALLS(("_Jv_JNI_Set" STR(name) "Field(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value)); \
+ \
+ LLNI_CRITICAL_START; \
+ \
+ SET_FIELD(LLNI_DIRECT((java_handle_t *) obj), intern, fieldID, value); \
+ \
+ LLNI_CRITICAL_START; \
+}
+
+JNI_SET_FIELD(Boolean, jboolean, s4)
+JNI_SET_FIELD(Byte, jbyte, s4)
+JNI_SET_FIELD(Char, jchar, s4)
+JNI_SET_FIELD(Short, jshort, s4)
+JNI_SET_FIELD(Int, jint, s4)
+JNI_SET_FIELD(Long, jlong, s8)
+JNI_SET_FIELD(Float, jfloat, float)
+JNI_SET_FIELD(Double, jdouble, double)
+
+
+void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
+ jobject value)
+{
+ TRACEJNICALLS(("_Jv_JNI_SetObjectField(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value));
+
+ LLNI_CRITICAL_START;
+
+ SET_FIELD(obj, java_handle_t*, fieldID, LLNI_UNWRAP((java_handle_t*) value));
+
+ LLNI_CRITICAL_END;
+}
+
+
+/* Calling Static Methods *****************************************************/
+
+/* GetStaticMethodID ***********************************************************
+
+ Returns the method ID for a static method of a class. The method is
+ specified by its name and signature.
+
+ GetStaticMethodID() causes an uninitialized class to be
+ initialized.
+
+*******************************************************************************/
+
+jmethodID _Jv_JNI_GetStaticMethodID(JNIEnv *env, jclass clazz, const char *name,
+ const char *sig)
+{
+ classinfo *c;
+ utf *uname;
+ utf *udesc;
+ methodinfo *m;
+
+ TRACEJNICALLS(("_Jv_JNI_GetStaticMethodID(env=%p, clazz=%p, name=%s, sig=%s)", env, clazz, name, sig));
+
+ c = LLNI_classinfo_unwrap(clazz);
+
+ if (c == NULL)
+ return NULL;
+
+ if (!(c->state & CLASS_INITIALIZED))
+ if (!initialize_class(c))
+ return NULL;
+
+ /* try to get the static method of the class */
+
+ uname = utf_new_char((char *) name);
+ udesc = utf_new_char((char *) sig);
+
+ m = class_resolvemethod(c, uname, udesc);
+
+ if ((m == NULL) || !(m->flags & ACC_STATIC)) {
+ exceptions_throw_nosuchmethoderror(c, uname, udesc);
+
+ return NULL;
+ }
+
+ return (jmethodID) m;
+}
+
+
+#define JNI_CALL_STATIC_METHOD(name, type, intern) \
+type _Jv_JNI_CallStatic##name##Method(JNIEnv *env, jclass clazz, \
+ jmethodID methodID, ...) \
+{ \
+ methodinfo *m; \
+ va_list ap; \
+ type res; \
+ \
+ m = (methodinfo *) methodID; \
+ \
+ va_start(ap, methodID); \
+ res = _Jv_jni_Call##intern##Method(NULL, NULL, m, ap); \
+ va_end(ap); \
+ \
+ return res; \
+}
+
+JNI_CALL_STATIC_METHOD(Boolean, jboolean, Int)
+JNI_CALL_STATIC_METHOD(Byte, jbyte, Int)
+JNI_CALL_STATIC_METHOD(Char, jchar, Int)
+JNI_CALL_STATIC_METHOD(Short, jshort, Int)
+JNI_CALL_STATIC_METHOD(Int, jint, Int)
+JNI_CALL_STATIC_METHOD(Long, jlong, Long)
+JNI_CALL_STATIC_METHOD(Float, jfloat, Float)
+JNI_CALL_STATIC_METHOD(Double, jdouble, Double)
+
+
+#define JNI_CALL_STATIC_METHOD_V(name, type, intern) \
+type _Jv_JNI_CallStatic##name##MethodV(JNIEnv *env, jclass clazz, \
+ jmethodID methodID, va_list args) \
+{ \
+ methodinfo *m; \
+ type res; \
+ \
+ m = (methodinfo *) methodID; \
+ \
+ res = _Jv_jni_Call##intern##Method(NULL, NULL, m, args); \
+ \
+ return res; \
+}
+
+JNI_CALL_STATIC_METHOD_V(Boolean, jboolean, Int)
+JNI_CALL_STATIC_METHOD_V(Byte, jbyte, Int)
+JNI_CALL_STATIC_METHOD_V(Char, jchar, Int)
+JNI_CALL_STATIC_METHOD_V(Short, jshort, Int)
+JNI_CALL_STATIC_METHOD_V(Int, jint, Int)
+JNI_CALL_STATIC_METHOD_V(Long, jlong, Long)
+JNI_CALL_STATIC_METHOD_V(Float, jfloat, Float)
+JNI_CALL_STATIC_METHOD_V(Double, jdouble, Double)
+
+
+#define JNI_CALL_STATIC_METHOD_A(name, type, intern) \
+type _Jv_JNI_CallStatic##name##MethodA(JNIEnv *env, jclass clazz, \
+ jmethodID methodID, const jvalue *args) \
+{ \
+ methodinfo *m; \
+ type res; \
+ \
+ m = (methodinfo *) methodID; \
+ \
+ res = _Jv_jni_Call##intern##MethodA(NULL, NULL, m, args); \
+ \
+ return res; \
+}
+
+JNI_CALL_STATIC_METHOD_A(Boolean, jboolean, Int)
+JNI_CALL_STATIC_METHOD_A(Byte, jbyte, Int)
+JNI_CALL_STATIC_METHOD_A(Char, jchar, Int)
+JNI_CALL_STATIC_METHOD_A(Short, jshort, Int)
+JNI_CALL_STATIC_METHOD_A(Int, jint, Int)
+JNI_CALL_STATIC_METHOD_A(Long, jlong, Long)
+JNI_CALL_STATIC_METHOD_A(Float, jfloat, Float)
+JNI_CALL_STATIC_METHOD_A(Double, jdouble, Double)
+
+
+jobject _Jv_JNI_CallStaticObjectMethod(JNIEnv *env, jclass clazz,
+ jmethodID methodID, ...)
+{
+ methodinfo *m;
+ java_handle_t *o;
+ va_list ap;
+
+ TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
+
+ m = (methodinfo *) methodID;
+
+ va_start(ap, methodID);
+ o = _Jv_jni_CallObjectMethod(NULL, NULL, m, ap);
+ va_end(ap);
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+jobject _Jv_JNI_CallStaticObjectMethodV(JNIEnv *env, jclass clazz,
+ jmethodID methodID, va_list args)
+{
+ methodinfo *m;
+ java_handle_t *o;
+
+ TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
+ m = (methodinfo *) methodID;
+
+ o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+jobject _Jv_JNI_CallStaticObjectMethodA(JNIEnv *env, jclass clazz,
+ jmethodID methodID, const jvalue *args)
+{
+ methodinfo *m;
+ java_handle_t *o;
+
+ TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
+ m = (methodinfo *) methodID;
+
+ o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+void _Jv_JNI_CallStaticVoidMethod(JNIEnv *env, jclass clazz,
+ jmethodID methodID, ...)
+{
+ methodinfo *m;
+ va_list ap;
+
+ TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
+
+ m = (methodinfo *) methodID;
+
+ va_start(ap, methodID);
+ _Jv_jni_CallVoidMethod(NULL, NULL, m, ap);
+ va_end(ap);
+}
+
+
+void _Jv_JNI_CallStaticVoidMethodV(JNIEnv *env, jclass clazz,
+ jmethodID methodID, va_list args)
+{
+ methodinfo *m;
+
+ TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
+ m = (methodinfo *) methodID;
+
+ _Jv_jni_CallVoidMethod(NULL, NULL, m, args);
+}
+
+
+void _Jv_JNI_CallStaticVoidMethodA(JNIEnv *env, jclass clazz,
+ jmethodID methodID, const jvalue * args)
+{
+ methodinfo *m;
+
+ TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
+ m = (methodinfo *) methodID;
+
+ _Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
+}
+
+
+/* Accessing Static Fields ****************************************************/
+
+/* GetStaticFieldID ************************************************************
+
+ Returns the field ID for a static field of a class. The field is
+ specified by its name and signature. The GetStatic<type>Field and
+ SetStatic<type>Field families of accessor functions use field IDs
+ to retrieve static fields.
+
+*******************************************************************************/
+
+jfieldID _Jv_JNI_GetStaticFieldID(JNIEnv *env, jclass clazz, const char *name,
+ const char *sig)
+{
+ classinfo *c;
+ fieldinfo *f;
+ utf *uname;
+ utf *usig;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+
+ uname = utf_new_char((char *) name);
+ usig = utf_new_char((char *) sig);
+
+ f = class_findfield(c, uname, usig);
+
+ if (f == NULL)
+ exceptions_throw_nosuchfielderror(c, uname);
+
+ return (jfieldID) f;
+}
+
+
+/* GetStatic<type>Field ********************************************************
+
+ This family of accessor routines returns the value of a static
+ field of an object.
+
+*******************************************************************************/
+
+#define JNI_GET_STATIC_FIELD(name, type, field) \
+type _Jv_JNI_GetStatic##name##Field(JNIEnv *env, jclass clazz, \
+ jfieldID fieldID) \
+{ \
+ classinfo *c; \
+ fieldinfo *f; \
+ \
+ STATISTICS(jniinvokation()); \
+ \
+ c = LLNI_classinfo_unwrap(clazz); \
+ f = (fieldinfo *) fieldID; \
+ \
+ if (!(c->state & CLASS_INITIALIZED)) \
+ if (!initialize_class(c)) \
+ return 0; \
+ \
+ return f->value->field; \
+}
+
+JNI_GET_STATIC_FIELD(Boolean, jboolean, i)
+JNI_GET_STATIC_FIELD(Byte, jbyte, i)
+JNI_GET_STATIC_FIELD(Char, jchar, i)
+JNI_GET_STATIC_FIELD(Short, jshort, i)
+JNI_GET_STATIC_FIELD(Int, jint, i)
+JNI_GET_STATIC_FIELD(Long, jlong, l)
+JNI_GET_STATIC_FIELD(Float, jfloat, f)
+JNI_GET_STATIC_FIELD(Double, jdouble, d)
+
+
+jobject _Jv_JNI_GetStaticObjectField(JNIEnv *env, jclass clazz,
+ jfieldID fieldID)
+{
+ classinfo *c;
+ fieldinfo *f;
+ java_handle_t *h;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+ f = (fieldinfo *) fieldID;
+
+ if (!(c->state & CLASS_INITIALIZED))
+ if (!initialize_class(c))
+ return NULL;
+
+ h = (java_handle_t*) LLNI_WRAP(f->value->a);
+
+ return jni_NewLocalRef(env, (jobject) h);
+}
+
+
+/* SetStatic<type>Field *******************************************************
+
+ This family of accessor routines sets the value of a static field
+ of an object.
+
+*******************************************************************************/
+
+#define JNI_SET_STATIC_FIELD(name, type, field) \
+void _Jv_JNI_SetStatic##name##Field(JNIEnv *env, jclass clazz, \
+ jfieldID fieldID, \
+ type value) \
+{ \
+ classinfo *c; \
+ fieldinfo *f; \
+ \
+ STATISTICS(jniinvokation()); \
+ \
+ c = LLNI_classinfo_unwrap(clazz); \
+ f = (fieldinfo *) fieldID; \
+ \
+ if (!(c->state & CLASS_INITIALIZED)) \
+ if (!initialize_class(c)) \
+ return; \
+ \
+ f->value->field = value; \
+}
+
+JNI_SET_STATIC_FIELD(Boolean, jboolean, i)
+JNI_SET_STATIC_FIELD(Byte, jbyte, i)
+JNI_SET_STATIC_FIELD(Char, jchar, i)
+JNI_SET_STATIC_FIELD(Short, jshort, i)
+JNI_SET_STATIC_FIELD(Int, jint, i)
+JNI_SET_STATIC_FIELD(Long, jlong, l)
+JNI_SET_STATIC_FIELD(Float, jfloat, f)
+JNI_SET_STATIC_FIELD(Double, jdouble, d)
+
+
+void _Jv_JNI_SetStaticObjectField(JNIEnv *env, jclass clazz, jfieldID fieldID,
+ jobject value)
+{
+ classinfo *c;
+ fieldinfo *f;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+ f = (fieldinfo *) fieldID;
+
+ if (!(c->state & CLASS_INITIALIZED))
+ if (!initialize_class(c))
+ return;
+
+ f->value->a = LLNI_UNWRAP((java_handle_t *) value);
+}
+
+
+/* String Operations **********************************************************/
+
+/* NewString *******************************************************************
+
+ Create new java.lang.String object from an array of Unicode
+ characters.
+
+*******************************************************************************/
+
+jstring jni_NewString(JNIEnv *env, const jchar *buf, jsize len)
+{
+ TRACEJNICALLS(("jni_NewString(env=%p, buf=%p, len=%d)", env, buf, len));
+
+ java_handle_chararray_t* a = builtin_newarray_char(len);
+
+ if (a == NULL)
+ return NULL;
+
+ /* copy text */
+ for (jsize i = 0; i < len; i++)
+ LLNI_array_direct(a, i) = buf[i];
+
+ java_handle_t* h = builtin_new(class_java_lang_String);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_String s(h, a, len, 0);
+
+ return (jstring) jni_NewLocalRef(env, (jobject) s.get_handle());
+}
+
+
+static jchar emptyStringJ[]={0,0};
+
+/* GetStringLength *************************************************************
+
+ Returns the length (the count of Unicode characters) of a Java
+ string.
+
+*******************************************************************************/
+
+jsize jni_GetStringLength(JNIEnv *env, jstring str)
+{
+ TRACEJNICALLSENTER(("jni_GetStringLength(env=%p, str=%p)", env, str));
+
+ java_lang_String s(str);
+ jsize count = s.get_count();
+
+ TRACEJNICALLSEXIT(("->%d)", count));
+
+ return count;
+}
+
+
+/* GetStringChars **************************************************************
+
+ Returns a pointer to the array of Unicode characters of the
+ string. This pointer is valid until ReleaseStringChars() is called.
+
+*******************************************************************************/
+
+const jchar* jni_GetStringChars(JNIEnv *env, jstring str, jboolean *isCopy)
+{
+ u2 *stringbuffer;
+ int32_t i;
+
+ TRACEJNICALLS(("jni_GetStringChars(env=%p, str=%p, isCopy=%p)", env, str, isCopy));
+
+ if (str == NULL)
+ // FIXME This is really ugly.
+ return emptyStringJ;
+
+ java_lang_String s(str);
+
+ java_handle_chararray_t* ca = s.get_value();
+ int32_t count = s.get_count();
+ int32_t offset = s.get_offset();
+
+ if (ca == NULL)
+ return NULL;
+
+ /* allocate memory */
+
+ stringbuffer = MNEW(u2, count + 1);
+
+ /* copy text */
+
+ for (i = 0; i < count; i++)
+ stringbuffer[i] = LLNI_array_direct(ca, offset + i);
+
+ /* terminate string */
+
+ stringbuffer[i] = '\0';
+
+ if (isCopy)
+ *isCopy = JNI_TRUE;
+
+ return (jchar*) stringbuffer;
+}
+
+
+/* ReleaseStringChars **********************************************************
+
+ Informs the VM that the native code no longer needs access to
+ chars. The chars argument is a pointer obtained from string using
+ GetStringChars().
+
+*******************************************************************************/
+
+void _Jv_JNI_ReleaseStringChars(JNIEnv *env, jstring str, const jchar *chars)
+{
+ TRACEJNICALLS(("jni_ReleaseStringChars(env=%p, str=%p, chars=%p)", env, str, chars));
+
+ // FIXME
+ if (chars == emptyStringJ)
+ return;
+
+ java_lang_String s(str);
+ int32_t count = s.get_count();
+
+ MFREE(((jchar*) chars), jchar, count + 1);
+}
+
+
+/* NewStringUTF ****************************************************************
+
+ Constructs a new java.lang.String object from an array of UTF-8
+ characters.
+
+*******************************************************************************/
+
+jstring jni_NewStringUTF(JNIEnv *env, const char *bytes)
+{
+ TRACEJNICALLS(("jni_NewStringUTF(env=%p, bytes=%s)", env, bytes));
+
+ java_handle_t *h = javastring_safe_new_from_utf8(bytes);
+
+ return (jstring) jni_NewLocalRef(env, (jobject) h);
+}
+
+
+/****************** returns the utf8 length in bytes of a string *******************/
+
+jsize jni_GetStringUTFLength(JNIEnv *env, jstring string)
+{
+ TRACEJNICALLS(("jni_GetStringUTFLength(env=%p, string=%p)", env, string));
+
+ java_lang_String s(string);
+ java_handle_chararray_t* ca = s.get_value();
+ int32_t count = s.get_count();
+
+ // FIXME GC critical section!
+ int32_t length = u2_utflength(ca->data, count);
+
+ return length;
+}
+
+
+/* GetStringUTFChars ***********************************************************
+
+ Returns a pointer to an array of UTF-8 characters of the
+ string. This array is valid until it is released by
+ ReleaseStringUTFChars().
+
+*******************************************************************************/
+
+const char *_Jv_JNI_GetStringUTFChars(JNIEnv *env, jstring string,
+ jboolean *isCopy)
+{
+ utf *u;
+
+ STATISTICS(jniinvokation());
+
+ if (string == NULL)
+ return "";
+
+ if (isCopy)
+ *isCopy = JNI_TRUE;
+
+ u = javastring_toutf((java_handle_t *) string, false);
+
+ if (u != NULL)
+ return u->text;
+
+ return "";
+}
+
+
+/* ReleaseStringUTFChars *******************************************************
+
+ Informs the VM that the native code no longer needs access to
+ utf. The utf argument is a pointer derived from string using
+ GetStringUTFChars().
+
+*******************************************************************************/
+
+void _Jv_JNI_ReleaseStringUTFChars(JNIEnv *env, jstring string, const char *utf)
+{
+ STATISTICS(jniinvokation());
+
+ /* XXX we don't release utf chars right now, perhaps that should be done
+ later. Since there is always one reference the garbage collector will
+ never get them */
+}
+
+
+/* Array Operations ***********************************************************/
+
+/* GetArrayLength **************************************************************
+
+ Returns the number of elements in the array.
+
+*******************************************************************************/
+
+jsize _Jv_JNI_GetArrayLength(JNIEnv *env, jarray array)
+{
+ java_handle_t *a;
+ jsize size;
+
+ TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array));
+
+ a = (java_handle_t *) array;
+
+ size = LLNI_array_size(a);
+
+ return size;
+}
+
+
+/* NewObjectArray **************************************************************
+
+ Constructs a new array holding objects in class elementClass. All
+ elements are initially set to initialElement.
+
+*******************************************************************************/
+
+jobjectArray _Jv_JNI_NewObjectArray(JNIEnv *env, jsize length,
+ jclass elementClass, jobject initialElement)
+{
+ classinfo *c;
+ java_handle_t *o;
+ java_handle_objectarray_t *oa;
+ s4 i;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(elementClass);
+ o = (java_handle_t *) initialElement;
+
+ if (length < 0) {
+ exceptions_throw_negativearraysizeexception();
+ return NULL;
+ }
+
+ oa = builtin_anewarray(length, c);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* set all elements to initialElement */
+
+ for (i = 0; i < length; i++)
+ array_objectarray_element_set(oa, i, o);
+
+ return (jobjectArray) jni_NewLocalRef(env, (jobject) oa);
+}
+
+
+jobject _Jv_JNI_GetObjectArrayElement(JNIEnv *env, jobjectArray array,
+ jsize index)
+{
+ java_handle_objectarray_t *oa;
+ java_handle_t *o;
+
+ STATISTICS(jniinvokation());
+
+ oa = (java_handle_objectarray_t *) array;
+
+ if (index >= LLNI_array_size(oa)) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return NULL;
+ }
+
+ o = array_objectarray_element_get(oa, index);
+
+ return jni_NewLocalRef(env, (jobject) o);
+}
+
+
+void _Jv_JNI_SetObjectArrayElement(JNIEnv *env, jobjectArray array,
+ jsize index, jobject val)
+{
+ java_handle_objectarray_t *oa;
+ java_handle_t *o;
+
+ STATISTICS(jniinvokation());
+
+ oa = (java_handle_objectarray_t *) array;
+ o = (java_handle_t *) val;
+
+ if (index >= LLNI_array_size(oa)) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return;
+ }
+
+ /* check if the class of value is a subclass of the element class
+ of the array */
+
+ if (!builtin_canstore(oa, o))
+ return;
+
+ array_objectarray_element_set(oa, index, o);
+}
+
+
+#define JNI_NEW_ARRAY(name, type, intern) \
+type _Jv_JNI_New##name##Array(JNIEnv *env, jsize len) \
+{ \
+ java_handle_##intern##array_t *a; \
+ \
+ STATISTICS(jniinvokation()); \
+ \
+ if (len < 0) { \
+ exceptions_throw_negativearraysizeexception(); \
+ return NULL; \
+ } \
+ \
+ a = builtin_newarray_##intern(len); \
+ \
+ return (type) jni_NewLocalRef(env, (jobject) a); \
+}
+
+JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
+JNI_NEW_ARRAY(Byte, jbyteArray, byte)
+JNI_NEW_ARRAY(Char, jcharArray, char)
+JNI_NEW_ARRAY(Short, jshortArray, short)
+JNI_NEW_ARRAY(Int, jintArray, int)
+JNI_NEW_ARRAY(Long, jlongArray, long)
+JNI_NEW_ARRAY(Float, jfloatArray, float)
+JNI_NEW_ARRAY(Double, jdoubleArray, double)
+
+
+/* Get<PrimitiveType>ArrayElements *********************************************
+
+ A family of functions that returns the body of the primitive array.
+
+*******************************************************************************/
+
+#define JNI_GET_ARRAY_ELEMENTS(name, type, intern) \
+type *_Jv_JNI_Get##name##ArrayElements(JNIEnv *env, type##Array array, \
+ jboolean *isCopy) \
+{ \
+ java_handle_##intern##array_t *a; \
+ \
+ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \
+ \
+ a = (java_handle_##intern##array_t *) array; \
+ \
+ if (isCopy) \
+ *isCopy = JNI_FALSE; \
+ \
+ return (type *) LLNI_array_data(a); \
+}
+
+JNI_GET_ARRAY_ELEMENTS(Boolean, jboolean, boolean)
+JNI_GET_ARRAY_ELEMENTS(Byte, jbyte, byte)
+JNI_GET_ARRAY_ELEMENTS(Char, jchar, char)
+JNI_GET_ARRAY_ELEMENTS(Short, jshort, short)
+JNI_GET_ARRAY_ELEMENTS(Int, jint, int)
+JNI_GET_ARRAY_ELEMENTS(Long, jlong, long)
+JNI_GET_ARRAY_ELEMENTS(Float, jfloat, float)
+JNI_GET_ARRAY_ELEMENTS(Double, jdouble, double)
+
+
+/* Release<PrimitiveType>ArrayElements *****************************************
+
+ A family of functions that informs the VM that the native code no
+ longer needs access to elems. The elems argument is a pointer
+ derived from array using the corresponding
+ Get<PrimitiveType>ArrayElements() function. If necessary, this
+ function copies back all changes made to elems to the original
+ array.
+
+*******************************************************************************/
+
+#define JNI_RELEASE_ARRAY_ELEMENTS(name, type, intern, intern2) \
+void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array, \
+ type *elems, jint mode) \
+{ \
+ java_handle_##intern##array_t *a; \
+ \
+ STATISTICS(jniinvokation()); \
+ \
+ a = (java_handle_##intern##array_t *) array; \
+ \
+ if (elems != (type *) LLNI_array_data(a)) { \
+ switch (mode) { \
+ case JNI_COMMIT: \
+ MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
+ break; \
+ case 0: \
+ MCOPY(LLNI_array_data(a), elems, intern2, LLNI_array_size(a)); \
+ /* XXX TWISTI how should it be freed? */ \
+ break; \
+ case JNI_ABORT: \
+ /* XXX TWISTI how should it be freed? */ \
+ break; \
+ } \
+ } \
+}
+
+JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
+JNI_RELEASE_ARRAY_ELEMENTS(Byte, jbyte, byte, s1)
+JNI_RELEASE_ARRAY_ELEMENTS(Char, jchar, char, u2)
+JNI_RELEASE_ARRAY_ELEMENTS(Short, jshort, short, s2)
+JNI_RELEASE_ARRAY_ELEMENTS(Int, jint, int, s4)
+JNI_RELEASE_ARRAY_ELEMENTS(Long, jlong, long, s8)
+JNI_RELEASE_ARRAY_ELEMENTS(Float, jfloat, float, float)
+JNI_RELEASE_ARRAY_ELEMENTS(Double, jdouble, double, double)
+
+
+/* Get<PrimitiveType>ArrayRegion **********************************************
+
+ A family of functions that copies a region of a primitive array
+ into a buffer.
+
+*******************************************************************************/
+
+#define JNI_GET_ARRAY_REGION(name, type, intern, intern2) \
+void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array, \
+ jsize start, jsize len, type *buf) \
+{ \
+ java_handle_##intern##array_t *a; \
+ \
+ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \
+ \
+ a = (java_handle_##intern##array_t *) array; \
+ \
+ if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
+ exceptions_throw_arrayindexoutofboundsexception(); \
+ else \
+ MCOPY(buf, &LLNI_array_direct(a, start), intern2, len); \
+}
+
+JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
+JNI_GET_ARRAY_REGION(Byte, jbyte, byte, s1)
+JNI_GET_ARRAY_REGION(Char, jchar, char, u2)
+JNI_GET_ARRAY_REGION(Short, jshort, short, s2)
+JNI_GET_ARRAY_REGION(Int, jint, int, s4)
+JNI_GET_ARRAY_REGION(Long, jlong, long, s8)
+JNI_GET_ARRAY_REGION(Float, jfloat, float, float)
+JNI_GET_ARRAY_REGION(Double, jdouble, double, double)
+
+
+/* Set<PrimitiveType>ArrayRegion **********************************************
+
+ A family of functions that copies back a region of a primitive
+ array from a buffer.
+
+*******************************************************************************/
+
+#define JNI_SET_ARRAY_REGION(name, type, intern, intern2) \
+void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array, \
+ jsize start, jsize len, const type *buf) \
+{ \
+ java_handle_##intern##array_t *a; \
+ \
+ STATISTICS(jniinvokation()); \
+ \
+ a = (java_handle_##intern##array_t *) array; \
+ \
+ if ((start < 0) || (len < 0) || (start + len > LLNI_array_size(a))) \
+ exceptions_throw_arrayindexoutofboundsexception(); \
+ else \
+ MCOPY(&LLNI_array_direct(a, start), buf, intern2, len); \
+}
+
+JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
+JNI_SET_ARRAY_REGION(Byte, jbyte, byte, s1)
+JNI_SET_ARRAY_REGION(Char, jchar, char, u2)
+JNI_SET_ARRAY_REGION(Short, jshort, short, s2)
+JNI_SET_ARRAY_REGION(Int, jint, int, s4)
+JNI_SET_ARRAY_REGION(Long, jlong, long, s8)
+JNI_SET_ARRAY_REGION(Float, jfloat, float, float)
+JNI_SET_ARRAY_REGION(Double, jdouble, double, double)
+
+
+/* Registering Native Methods *************************************************/
+
+/* RegisterNatives *************************************************************
+
+ Registers native methods with the class specified by the clazz
+ argument. The methods parameter specifies an array of
+ JNINativeMethod structures that contain the names, signatures, and
+ function pointers of the native methods. The nMethods parameter
+ specifies the number of native methods in the array.
+
+*******************************************************************************/
+
+jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
+ const JNINativeMethod *methods, jint nMethods)
+{
+ classinfo *c;
+
+ STATISTICS(jniinvokation());
+
+ c = LLNI_classinfo_unwrap(clazz);
+
+ /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
+ if (jvmti) jvmti_NativeMethodBind(method, address, new_address_ptr);
+ */
+
+ native_method_register(c->name, methods, nMethods);
+
+ return 0;
+}
+
+
+/* UnregisterNatives ***********************************************************
+
+ Unregisters native methods of a class. The class goes back to the
+ state before it was linked or registered with its native method
+ functions.
+
+ This function should not be used in normal native code. Instead, it
+ provides special programs a way to reload and relink native
+ libraries.
+
+*******************************************************************************/
+
+jint _Jv_JNI_UnregisterNatives(JNIEnv *env, jclass clazz)
+{
+ STATISTICS(jniinvokation());
+
+ /* XXX TWISTI hmm, maybe we should not support that (like kaffe) */
+
+ log_text("JNI-Call: UnregisterNatives: IMPLEMENT ME!!!");
+
+ return 0;
+}
+
+
+/* Monitor Operations *********************************************************/
+
+/* MonitorEnter ****************************************************************
+
+ Enters the monitor associated with the underlying Java object
+ referred to by obj.
+
+*******************************************************************************/
+
+jint _Jv_JNI_MonitorEnter(JNIEnv *env, jobject obj)
+{
+ STATISTICS(jniinvokation());
+
+ if (obj == NULL) {
+ exceptions_throw_nullpointerexception();
+ return JNI_ERR;
+ }
+
+ LOCK_MONITOR_ENTER(obj);
+
+ return JNI_OK;
+}
+
+
+/* MonitorExit *****************************************************************
+
+ The current thread must be the owner of the monitor associated with
+ the underlying Java object referred to by obj. The thread
+ decrements the counter indicating the number of times it has
+ entered this monitor. If the value of the counter becomes zero, the
+ current thread releases the monitor.
+
+*******************************************************************************/
+
+jint _Jv_JNI_MonitorExit(JNIEnv *env, jobject obj)
+{
+ STATISTICS(jniinvokation());
+
+ if (obj == NULL) {
+ exceptions_throw_nullpointerexception();
+ return JNI_ERR;
+ }
+
+ LOCK_MONITOR_EXIT(obj);
+
+ return JNI_OK;
+}
+
+
+/* JavaVM Interface ***********************************************************/
+
+/* GetJavaVM *******************************************************************
+
+ Returns the Java VM interface (used in the Invocation API)
+ associated with the current thread. The result is placed at the
+ location pointed to by the second argument, vm.
+
+*******************************************************************************/
+
+jint _Jv_JNI_GetJavaVM(JNIEnv *env, JavaVM **javavm)
+{
+ STATISTICS(jniinvokation());
+
+ *javavm = vm->get_javavm();
+
+ return 0;
+}
+
+
+/* GetStringRegion *************************************************************
+
+ Copies len number of Unicode characters beginning at offset start
+ to the given buffer buf.
+
+ Throws StringIndexOutOfBoundsException on index overflow.
+
+*******************************************************************************/
+
+void jni_GetStringRegion(JNIEnv* env, jstring str, jsize start, jsize len, jchar *buf)
+{
+ java_lang_String s(str);
+ java_handle_chararray_t* ca = s.get_value();
+ int32_t count = s.get_count();
+
+ if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
+ exceptions_throw_stringindexoutofboundsexception();
+ return;
+ }
+
+ MCOPY(buf, &LLNI_array_direct(ca, start), u2, len);
+}
+
+
+/* GetStringUTFRegion **********************************************************
+
+ Translates len number of Unicode characters beginning at offset
+ start into UTF-8 format and place the result in the given buffer
+ buf.
+
+ Throws StringIndexOutOfBoundsException on index overflow.
+
+*******************************************************************************/
+
+void jni_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start, jsize len, char *buf)
+{
+ TRACEJNICALLS(("jni_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
+
+ java_lang_String s(str);
+ java_handle_chararray_t* ca = s.get_value();
+ int32_t count = s.get_count();
+ int32_t offset = s.get_offset();
+
+ if ((start < 0) || (len < 0) || (start > count) || (start + len > count)) {
+ exceptions_throw_stringindexoutofboundsexception();
+ return;
+ }
+
+ int32_t i;
+
+ for (i = 0; i < len; i++)
+ buf[i] = LLNI_array_direct(ca, offset + start + i);
+
+ buf[i] = '\0';
+}
+
+
+/* GetPrimitiveArrayCritical ***************************************************
+
+ Obtain a direct pointer to array elements.
+
+ ATTENTION: Critical section keeps open when this function returns!
+ See ReleasePrimitiveArrayCritical.
+
+*******************************************************************************/
+
+void* jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
+{
+ java_handle_t* h;
+ java_array_t* a;
+ arraydescriptor* ad;
+ void* data;
+
+ TRACEJNICALLS(("jni_GetPrimitiveArrayCritical(env=%p, array=%p, isCopy=%d)", env, array, isCopy));
+
+ if (isCopy != NULL) {
+ *isCopy = JNI_FALSE;
+ }
+
+ LLNI_CRITICAL_START;
+
+ h = (java_handle_t*) array;
+ a = (java_array_t*) LLNI_UNWRAP(h);
+ ad = a->objheader.vftbl->arraydesc;
+
+ /* Sanity check. */
+
+ assert(ad != NULL);
+
+ data = (void*) (((intptr_t) a) + ad->dataoffset);
+
+ return data;
+}
+
+
+/* ReleasePrimitiveArrayCritical ***********************************************
+
+ No specific documentation.
+
+ ATTENTION: This function closes the critical section opened in
+ GetPrimitiveArrayCritical!
+
+*******************************************************************************/
+
+void jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)
+{
+ TRACEJNICALLS(("jni_ReleasePrimitiveArrayCritical(env=%p, array=%p, carray=%p, mode=%d)", env, array, carray, mode));
+
+ LLNI_CRITICAL_END;
+}
+
+
+/* GetStringCritical ***********************************************************
+
+ The semantics of these two functions are similar to the existing
+ Get/ReleaseStringChars functions.
+
+*******************************************************************************/
+
+const jchar *_Jv_JNI_GetStringCritical(JNIEnv *env, jstring string,
+ jboolean *isCopy)
+{
+ STATISTICS(jniinvokation());
+
+ return jni_GetStringChars(env, string, isCopy);
+}
+
+
+void _Jv_JNI_ReleaseStringCritical(JNIEnv *env, jstring string,
+ const jchar *cstring)
+{
+ STATISTICS(jniinvokation());
+
+ _Jv_JNI_ReleaseStringChars(env, string, cstring);
+}
+
+
+jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
+{
+ TRACEJNICALLS(("_Jv_JNI_NewWeakGlobalRef(env=%p, obj=%p): IMPLEMENT ME!", env, obj));
+
+ return (jweak) obj;
+}
+
+
+void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
+{
+ TRACEJNICALLS(("_Jv_JNI_DeleteWeakGlobalRef(env=%p, ref=%p): IMPLEMENT ME", env, ref));
+}
+
+
+/* NewGlobalRef ****************************************************************
+
+ Creates a new global reference to the object referred to by the obj
+ argument.
+
+*******************************************************************************/
+
+jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
+{
+ hashtable_global_ref_entry *gre;
+ u4 key; /* hashkey */
+ u4 slot; /* slot in hashtable */
+ java_handle_t *o;
+
+ TRACEJNICALLS(("jni_NewGlobalRef(env=%p, obj=%p)", env, obj));
+
+ o = (java_handle_t *) obj;
+
+ LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+
+ LLNI_CRITICAL_START;
+
+ /* normally addresses are aligned to 4, 8 or 16 bytes */
+
+ key = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
+ slot = key & (hashtable_global_ref->size - 1);
+ gre = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
+
+ /* search external hash chain for the entry */
+
+ while (gre) {
+ if (gre->o == LLNI_DIRECT(o)) {
+ /* global object found, increment the reference */
+
+ gre->refs++;
+
+ break;
+ }
+
+ gre = gre->hashlink; /* next element in external chain */
+ }
+
+ LLNI_CRITICAL_END;
+
+ /* global ref not found, create a new one */
+
+ if (gre == NULL) {
+ gre = (hashtable_global_ref_entry*) heap_alloc_uncollectable(sizeof(hashtable_global_ref_entry));
+
+#if defined(ENABLE_GC_CACAO)
+ /* register global ref with the GC */
+
+ gc_reference_register(&(gre->o), GC_REFTYPE_JNI_GLOBALREF);
+#endif
+
+ LLNI_CRITICAL_START;
+
+ gre->o = LLNI_DIRECT(o);
+ gre->refs = 1;
+
+ LLNI_CRITICAL_END;
+
+ /* insert entry into hashtable */
+
+ gre->hashlink = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
+
+ hashtable_global_ref->ptr[slot] = gre;
+
+ /* update number of hashtable-entries */
+
+ hashtable_global_ref->entries++;
+ }
+
+ LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+
+#if defined(ENABLE_HANDLES)
+ return gre;
+#else
+ return obj;
+#endif
+}
+
+
+/* DeleteGlobalRef *************************************************************
+
+ Deletes the global reference pointed to by globalRef.
+
+*******************************************************************************/
+
+void jni_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
+{
+ hashtable_global_ref_entry *gre;
+ hashtable_global_ref_entry *prevgre;
+ u4 key; /* hashkey */
+ u4 slot; /* slot in hashtable */
+ java_handle_t *o;
+
+ TRACEJNICALLS(("jni_DeleteGlobalRef(env=%p, globalRef=%p)", env, globalRef));
+
+ o = (java_handle_t *) globalRef;
+
+ LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+
+ LLNI_CRITICAL_START;
+
+ /* normally addresses are aligned to 4, 8 or 16 bytes */
+
+ key = heap_hashcode(LLNI_DIRECT(o)) >> 4; /* align to 16-byte boundaries */
+ slot = key & (hashtable_global_ref->size - 1);
+ gre = (hashtable_global_ref_entry*) hashtable_global_ref->ptr[slot];
+
+ /* initialize prevgre */
+
+ prevgre = NULL;
+
+ /* search external hash chain for the entry */
+
+ while (gre) {
+ if (gre->o == LLNI_DIRECT(o)) {
+ /* global object found, decrement the reference count */
+
+ gre->refs--;
+
+ /* if reference count is 0, remove the entry */
+
+ if (gre->refs == 0) {
+ /* special handling if it's the first in the chain */
+
+ if (prevgre == NULL)
+ hashtable_global_ref->ptr[slot] = gre->hashlink;
+ else
+ prevgre->hashlink = gre->hashlink;
+
+#if defined(ENABLE_GC_CACAO)
+ /* unregister global ref with the GC */
+
+ gc_reference_unregister(&(gre->o));
+#endif
+
+ heap_free(gre);
+ }
+
+ LLNI_CRITICAL_END;
+
+ LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+
+ return;
+ }
+
+ prevgre = gre; /* save current pointer for removal */
+ gre = gre->hashlink; /* next element in external chain */
+ }
+
+ log_println("jni_DeleteGlobalRef: Global reference not found.");
+
+ LLNI_CRITICAL_END;
+
+ LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+}
+
+
+/* ExceptionCheck **************************************************************
+
+ Returns JNI_TRUE when there is a pending exception; otherwise,
+ returns JNI_FALSE.
+
+*******************************************************************************/
+
+jboolean _Jv_JNI_ExceptionCheck(JNIEnv *env)
+{
+ java_handle_t *o;
+
+ STATISTICS(jniinvokation());
+
+ o = exceptions_get_exception();
+
+ return (o != NULL) ? JNI_TRUE : JNI_FALSE;
+}
+
+
+/* New JNI 1.4 functions ******************************************************/
+
+/* NewDirectByteBuffer *********************************************************
+
+ Allocates and returns a direct java.nio.ByteBuffer referring to the
+ block of memory starting at the memory address address and
+ extending capacity bytes.
+
+*******************************************************************************/
+
+jobject jni_NewDirectByteBuffer(JNIEnv *env, void *address, jlong capacity)
+{
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
+
+ // Allocate a gnu.classpath.Pointer{32,64} object.
+
+# if SIZEOF_VOID_P == 8
+ java_handle_t* h = builtin_new(class_gnu_classpath_Pointer64);
+# else
+ java_handle_t* h = builtin_new(class_gnu_classpath_Pointer32);
+# endif
+
+ if (h == NULL)
+ return NULL;
+
+ gnu_classpath_Pointer p(h, address);
+
+ // Create a java.nio.DirectByteBufferImpl$ReadWrite object.
+
+ java_handle_t* nbuf =
+ (java_handle_t*) jni_NewObject(env, (jclass) class_java_nio_DirectByteBufferImpl_ReadWrite,
+ (jmethodID) dbbirw_init, NULL, p.get_handle(),
+ (jint) capacity, (jint) capacity, (jint) 0);
+
+ // Add a local reference and return the value.
+
+ TRACEJNICALLSEXIT(("->%p", nbuf));
+
+ return jni_NewLocalRef(env, (jobject) nbuf);
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ jobject o;
+ int64_t addr;
+ int32_t cap;
+
+ TRACEJNICALLSENTER(("jni_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld)", env, address, capacity));
+
+ /* Be paranoid about address sign-extension. */
+
+ addr = (int64_t) ((uintptr_t) address);
+ cap = (int32_t) capacity;
+
+ o = jni_NewObject(env, (jclass) class_java_nio_DirectByteBuffer,
+ (jmethodID) dbb_init, addr, cap);
+
+ /* Add local reference and return the value. */
+
+ TRACEJNICALLSEXIT(("->%p", o));
+
+ return jni_NewLocalRef(env, o);
+
+# else
+# error unknown classpath configuration
+# endif
+
+#else
+ vm_abort("jni_NewDirectByteBuffer: Not implemented in this configuration.");
+
+ /* keep compiler happy */
+
+ return NULL;
+#endif
+}
+
+
+/* GetDirectBufferAddress ******************************************************
+
+ Fetches and returns the starting address of the memory region
+ referenced by the given direct java.nio.Buffer.
+
+*******************************************************************************/
+
+void* jni_GetDirectBufferAddress(JNIEnv *env, jobject buf)
+{
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ TRACEJNICALLSENTER(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
+
+ /* Prevent compiler warning. */
+
+ java_handle_t* h = (java_handle_t *) buf;
+
+ if ((h != NULL) && !builtin_instanceof(h, class_java_nio_Buffer))
+ return NULL;
+
+ java_nio_DirectByteBufferImpl dbb(buf);
+ java_handle_t* address = dbb.get_address();
+
+ if (address == NULL) {
+ TRACEJNICALLSEXIT(("->%p", NULL));
+ return NULL;
+ }
+
+ gnu_classpath_Pointer p(address);
+ void* data = p.get_data();
+
+ TRACEJNICALLSEXIT(("->%p", data));
+
+ return data;
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ TRACEJNICALLS(("jni_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
+
+ java_nio_Buffer jnb(buf);
+
+ if (jnb.is_non_null() && !builtin_instanceof(jnb.get_handle(), class_sun_nio_ch_DirectBuffer))
+ return NULL;
+
+ void* address = jnb.get_address();
+
+ return address;
+
+# else
+# error unknown classpath configuration
+# endif
+
+#else
+
+ vm_abort("jni_GetDirectBufferAddress: Not implemented in this configuration.");
+
+ // Keep compiler happy.
+ return NULL;
+
+#endif
+}
+
+
+/* GetDirectBufferCapacity *****************************************************
+
+ Fetches and returns the capacity in bytes of the memory region
+ referenced by the given direct java.nio.Buffer.
+
+*******************************************************************************/
+
+jlong jni_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
+{
+#if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ TRACEJNICALLS(("jni_GetDirectBufferCapacity(env=%p, buf=%p)", env, buf));
+
+ java_handle_t* h = (java_handle_t *) buf;
+
+ if (!builtin_instanceof(h, class_java_nio_DirectByteBufferImpl))
+ return -1;
+
+ java_nio_Buffer b(h);
+ jlong capacity = b.get_cap();
+
+ return capacity;
+#else
+ vm_abort("jni_GetDirectBufferCapacity: not implemented in this configuration");
+
+ // Keep compiler happy.
+
+ return 0;
+#endif
+}
+
+
+/* GetObjectRefType ************************************************************
+
+ Returns the type of the object referred to by the obj argument. The
+ argument obj can either be a local, global or weak global
+ reference.
+
+*******************************************************************************/
+
+jobjectRefType jni_GetObjectRefType(JNIEnv *env, jobject obj)
+{
+ log_println("jni_GetObjectRefType: IMPLEMENT ME!");
+
+ return (jobjectRefType) NULL;
+}
+
+
+/* DestroyJavaVM ***************************************************************
+
+ Unloads a Java VM and reclaims its resources. Only the main thread
+ can unload the VM. The system waits until the main thread is only
+ remaining user thread before it destroys the VM.
+
+*******************************************************************************/
+
+jint _Jv_JNI_DestroyJavaVM(JavaVM *javavm)
+{
+ int status;
+
+ TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(javavm=%p)", javavm));
+
+ if (vm->is_created() == false)
+ return JNI_ERR;
+
+ status = vm_destroy(javavm);
+
+ return status;
+}
+
+
+/* AttachCurrentThread *********************************************************
+
+ Attaches the current thread to a Java VM. Returns a JNI interface
+ pointer in the JNIEnv argument.
+
+ Trying to attach a thread that is already attached is a no-op.
+
+ A native thread cannot be attached simultaneously to two Java VMs.
+
+ When a thread is attached to the VM, the context class loader is
+ the bootstrap loader.
+
+*******************************************************************************/
+
+static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
+{
+#if defined(ENABLE_THREADS)
+ JavaVMAttachArgs *vm_aargs;
+ bool result;
+
+ /* If the current thread has already been attached, this operation
+ is a no-op. */
+
+ result = thread_current_is_attached();
+
+ if (result == true) {
+ *p_env = vm->get_jnienv();
+ return JNI_OK;
+ }
+
+ vm_aargs = (JavaVMAttachArgs *) thr_args;
+
+ if (vm_aargs != NULL) {
+ if ((vm_aargs->version != JNI_VERSION_1_2) &&
+ (vm_aargs->version != JNI_VERSION_1_4))
+ return JNI_EVERSION;
+ }
+
+ if (!thread_attach_current_external_thread(vm_aargs, false))
+ return JNI_ERR;
+
+ if (!localref_table_init())
+ return JNI_ERR;
+#endif
+
+ *p_env = vm->get_jnienv();
+
+ return JNI_OK;
+}
+
+
+jint jni_AttachCurrentThread(JavaVM *javavm, void **p_env, void *thr_args)
+{
+ int result;
+
+ TRACEJNICALLS(("jni_AttachCurrentThread(javavm=%p, p_env=%p, thr_args=%p)", javavm, p_env, thr_args));
+
+ if (vm->is_created() == false)
+ return JNI_ERR;
+
+ result = jni_attach_current_thread(p_env, thr_args, false);
+
+ return result;
+}
+
+
+/* DetachCurrentThread *********************************************************
+
+ Detaches the current thread from a Java VM. All Java monitors held
+ by this thread are released. All Java threads waiting for this
+ thread to die are notified.
+
+ In JDK 1.1, the main thread cannot be detached from the VM. It must
+ call DestroyJavaVM to unload the entire VM.
+
+ In the JDK, the main thread can be detached from the VM.
+
+ The main thread, which is the thread that created the Java VM,
+ cannot be detached from the VM. Instead, the main thread must call
+ JNI_DestroyJavaVM() to unload the entire VM.
+
+*******************************************************************************/
+
+jint jni_DetachCurrentThread(JavaVM *vm)
+{
+#if defined(ENABLE_THREADS)
+ bool result;
+
+ TRACEJNICALLS(("jni_DetachCurrentThread(vm=%p)", vm));
+
+ /* If the current thread has already been detached, this operation
+ is a no-op. */
+
+ result = thread_current_is_attached();
+
+ if (result == false)
+ return true;
+
+ /* We need to pop all frames before we can destroy the table. */
+
+ localref_frame_pop_all();
+
+ if (!localref_table_destroy())
+ return JNI_ERR;
+
+ if (!thread_detach_current_external_thread())
+ return JNI_ERR;
+#endif
+
+ return JNI_OK;
+}
+
+
+/* GetEnv **********************************************************************
+
+ If the current thread is not attached to the VM, sets *env to NULL,
+ and returns JNI_EDETACHED. If the specified version is not
+ supported, sets *env to NULL, and returns JNI_EVERSION. Otherwise,
+ sets *env to the appropriate interface, and returns JNI_OK.
+
+*******************************************************************************/
+
+jint jni_GetEnv(JavaVM *javavm, void **env, jint version)
+{
+ TRACEJNICALLS(("jni_GetEnv(javavm=%p, env=%p, version=%d)", javavm, env, version));
+
+ if (vm->is_created() == false) {
+ *env = NULL;
+ return JNI_EDETACHED;
+ }
+
+#if defined(ENABLE_THREADS)
+ if (thread_get_current() == NULL) {
+ *env = NULL;
+
+ return JNI_EDETACHED;
+ }
+#endif
+
+ /* Check the JNI version. */
+
+ if (jni_version_check(version) == true) {
+ *env = vm->get_jnienv();
+ return JNI_OK;
+ }
+
+#if defined(ENABLE_JVMTI)
+ if ((version & JVMTI_VERSION_MASK_INTERFACE_TYPE)
+ == JVMTI_VERSION_INTERFACE_JVMTI) {
+
+ *env = (void *) jvmti_new_environment();
+
+ if (env != NULL)
+ return JNI_OK;
+ }
+#endif
+
+ *env = NULL;
+
+ return JNI_EVERSION;
+}
+
+
+/* AttachCurrentThreadAsDaemon *************************************************
+
+ Same semantics as AttachCurrentThread, but the newly-created
+ java.lang.Thread instance is a daemon.
+
+ If the thread has already been attached via either
+ AttachCurrentThread or AttachCurrentThreadAsDaemon, this routine
+ simply sets the value pointed to by penv to the JNIEnv of the
+ current thread. In this case neither AttachCurrentThread nor this
+ routine have any effect on the daemon status of the thread.
+
+*******************************************************************************/
+
+jint jni_AttachCurrentThreadAsDaemon(JavaVM *javavm, void **penv, void *args)
+{
+ int result;
+
+ TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(javavm=%p, penv=%p, args=%p)", javavm, penv, args));
+
+ if (vm->is_created() == false)
+ return JNI_ERR;
+
+ result = jni_attach_current_thread(penv, args, true);
+
+ return result;
+}
+
+
+/* JNI invocation table *******************************************************/
+
+const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface = {
+ NULL,
+ NULL,
+ NULL,
+
+ _Jv_JNI_DestroyJavaVM,
+ jni_AttachCurrentThread,
+ jni_DetachCurrentThread,
+ jni_GetEnv,
+ jni_AttachCurrentThreadAsDaemon
+};
+
+
+/* JNI function table *********************************************************/
+
+struct JNINativeInterface_ _Jv_JNINativeInterface = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ _Jv_JNI_GetVersion,
+
+ jni_DefineClass,
+ jni_FindClass,
+ jni_FromReflectedMethod,
+ jni_FromReflectedField,
+ jni_ToReflectedMethod,
+ jni_GetSuperclass,
+ _Jv_JNI_IsAssignableFrom,
+ _Jv_JNI_ToReflectedField,
+
+ _Jv_JNI_Throw,
+ _Jv_JNI_ThrowNew,
+ _Jv_JNI_ExceptionOccurred,
+ jni_ExceptionDescribe,
+ jni_ExceptionClear,
+ _Jv_JNI_FatalError,
+ jni_PushLocalFrame,
+ jni_PopLocalFrame,
+
+ jni_NewGlobalRef,
+ jni_DeleteGlobalRef,
+ jni_DeleteLocalRef,
+ _Jv_JNI_IsSameObject,
+ jni_NewLocalRef,
+ jni_EnsureLocalCapacity,
+
+ _Jv_JNI_AllocObject,
+ jni_NewObject,
+ _Jv_JNI_NewObjectV,
+ _Jv_JNI_NewObjectA,
+
+ jni_GetObjectClass,
+ _Jv_JNI_IsInstanceOf,
+
+ _Jv_JNI_GetMethodID,
+
+ _Jv_JNI_CallObjectMethod,
+ _Jv_JNI_CallObjectMethodV,
+ _Jv_JNI_CallObjectMethodA,
+ _Jv_JNI_CallBooleanMethod,
+ _Jv_JNI_CallBooleanMethodV,
+ _Jv_JNI_CallBooleanMethodA,
+ _Jv_JNI_CallByteMethod,
+ _Jv_JNI_CallByteMethodV,
+ _Jv_JNI_CallByteMethodA,
+ _Jv_JNI_CallCharMethod,
+ _Jv_JNI_CallCharMethodV,
+ _Jv_JNI_CallCharMethodA,
+ _Jv_JNI_CallShortMethod,
+ _Jv_JNI_CallShortMethodV,
+ _Jv_JNI_CallShortMethodA,
+ _Jv_JNI_CallIntMethod,
+ _Jv_JNI_CallIntMethodV,
+ _Jv_JNI_CallIntMethodA,
+ _Jv_JNI_CallLongMethod,
+ _Jv_JNI_CallLongMethodV,
+ _Jv_JNI_CallLongMethodA,
+ _Jv_JNI_CallFloatMethod,
+ _Jv_JNI_CallFloatMethodV,
+ _Jv_JNI_CallFloatMethodA,
+ _Jv_JNI_CallDoubleMethod,
+ _Jv_JNI_CallDoubleMethodV,
+ _Jv_JNI_CallDoubleMethodA,
+ _Jv_JNI_CallVoidMethod,
+ _Jv_JNI_CallVoidMethodV,
+ _Jv_JNI_CallVoidMethodA,
+
+ _Jv_JNI_CallNonvirtualObjectMethod,
+ _Jv_JNI_CallNonvirtualObjectMethodV,
+ _Jv_JNI_CallNonvirtualObjectMethodA,
+ _Jv_JNI_CallNonvirtualBooleanMethod,
+ _Jv_JNI_CallNonvirtualBooleanMethodV,
+ _Jv_JNI_CallNonvirtualBooleanMethodA,
+ _Jv_JNI_CallNonvirtualByteMethod,
+ _Jv_JNI_CallNonvirtualByteMethodV,
+ _Jv_JNI_CallNonvirtualByteMethodA,
+ _Jv_JNI_CallNonvirtualCharMethod,
+ _Jv_JNI_CallNonvirtualCharMethodV,
+ _Jv_JNI_CallNonvirtualCharMethodA,
+ _Jv_JNI_CallNonvirtualShortMethod,
+ _Jv_JNI_CallNonvirtualShortMethodV,
+ _Jv_JNI_CallNonvirtualShortMethodA,
+ _Jv_JNI_CallNonvirtualIntMethod,
+ _Jv_JNI_CallNonvirtualIntMethodV,
+ _Jv_JNI_CallNonvirtualIntMethodA,
+ _Jv_JNI_CallNonvirtualLongMethod,
+ _Jv_JNI_CallNonvirtualLongMethodV,
+ _Jv_JNI_CallNonvirtualLongMethodA,
+ _Jv_JNI_CallNonvirtualFloatMethod,
+ _Jv_JNI_CallNonvirtualFloatMethodV,
+ _Jv_JNI_CallNonvirtualFloatMethodA,
+ _Jv_JNI_CallNonvirtualDoubleMethod,
+ _Jv_JNI_CallNonvirtualDoubleMethodV,
+ _Jv_JNI_CallNonvirtualDoubleMethodA,
+ _Jv_JNI_CallNonvirtualVoidMethod,
+ _Jv_JNI_CallNonvirtualVoidMethodV,
+ _Jv_JNI_CallNonvirtualVoidMethodA,
+
+ _Jv_JNI_GetFieldID,
+
+ _Jv_JNI_GetObjectField,
+ _Jv_JNI_GetBooleanField,
+ _Jv_JNI_GetByteField,
+ _Jv_JNI_GetCharField,
+ _Jv_JNI_GetShortField,
+ _Jv_JNI_GetIntField,
+ _Jv_JNI_GetLongField,
+ _Jv_JNI_GetFloatField,
+ _Jv_JNI_GetDoubleField,
+ _Jv_JNI_SetObjectField,
+ _Jv_JNI_SetBooleanField,
+ _Jv_JNI_SetByteField,
+ _Jv_JNI_SetCharField,
+ _Jv_JNI_SetShortField,
+ _Jv_JNI_SetIntField,
+ _Jv_JNI_SetLongField,
+ _Jv_JNI_SetFloatField,
+ _Jv_JNI_SetDoubleField,
+
+ _Jv_JNI_GetStaticMethodID,
+
+ _Jv_JNI_CallStaticObjectMethod,
+ _Jv_JNI_CallStaticObjectMethodV,
+ _Jv_JNI_CallStaticObjectMethodA,
+ _Jv_JNI_CallStaticBooleanMethod,
+ _Jv_JNI_CallStaticBooleanMethodV,
+ _Jv_JNI_CallStaticBooleanMethodA,
+ _Jv_JNI_CallStaticByteMethod,
+ _Jv_JNI_CallStaticByteMethodV,
+ _Jv_JNI_CallStaticByteMethodA,
+ _Jv_JNI_CallStaticCharMethod,
+ _Jv_JNI_CallStaticCharMethodV,
+ _Jv_JNI_CallStaticCharMethodA,
+ _Jv_JNI_CallStaticShortMethod,
+ _Jv_JNI_CallStaticShortMethodV,
+ _Jv_JNI_CallStaticShortMethodA,
+ _Jv_JNI_CallStaticIntMethod,
+ _Jv_JNI_CallStaticIntMethodV,
+ _Jv_JNI_CallStaticIntMethodA,
+ _Jv_JNI_CallStaticLongMethod,
+ _Jv_JNI_CallStaticLongMethodV,
+ _Jv_JNI_CallStaticLongMethodA,
+ _Jv_JNI_CallStaticFloatMethod,
+ _Jv_JNI_CallStaticFloatMethodV,
+ _Jv_JNI_CallStaticFloatMethodA,
+ _Jv_JNI_CallStaticDoubleMethod,
+ _Jv_JNI_CallStaticDoubleMethodV,
+ _Jv_JNI_CallStaticDoubleMethodA,
+ _Jv_JNI_CallStaticVoidMethod,
+ _Jv_JNI_CallStaticVoidMethodV,
+ _Jv_JNI_CallStaticVoidMethodA,
+
+ _Jv_JNI_GetStaticFieldID,
+
+ _Jv_JNI_GetStaticObjectField,
+ _Jv_JNI_GetStaticBooleanField,
+ _Jv_JNI_GetStaticByteField,
+ _Jv_JNI_GetStaticCharField,
+ _Jv_JNI_GetStaticShortField,
+ _Jv_JNI_GetStaticIntField,
+ _Jv_JNI_GetStaticLongField,
+ _Jv_JNI_GetStaticFloatField,
+ _Jv_JNI_GetStaticDoubleField,
+ _Jv_JNI_SetStaticObjectField,
+ _Jv_JNI_SetStaticBooleanField,
+ _Jv_JNI_SetStaticByteField,
+ _Jv_JNI_SetStaticCharField,
+ _Jv_JNI_SetStaticShortField,
+ _Jv_JNI_SetStaticIntField,
+ _Jv_JNI_SetStaticLongField,
+ _Jv_JNI_SetStaticFloatField,
+ _Jv_JNI_SetStaticDoubleField,
+
+ jni_NewString,
+ jni_GetStringLength,
+ jni_GetStringChars,
+ _Jv_JNI_ReleaseStringChars,
+
+ jni_NewStringUTF,
+ jni_GetStringUTFLength,
+ _Jv_JNI_GetStringUTFChars,
+ _Jv_JNI_ReleaseStringUTFChars,
+
+ _Jv_JNI_GetArrayLength,
+
+ _Jv_JNI_NewObjectArray,
+ _Jv_JNI_GetObjectArrayElement,
+ _Jv_JNI_SetObjectArrayElement,
+
+ _Jv_JNI_NewBooleanArray,
+ _Jv_JNI_NewByteArray,
+ _Jv_JNI_NewCharArray,
+ _Jv_JNI_NewShortArray,
+ _Jv_JNI_NewIntArray,
+ _Jv_JNI_NewLongArray,
+ _Jv_JNI_NewFloatArray,
+ _Jv_JNI_NewDoubleArray,
+
+ _Jv_JNI_GetBooleanArrayElements,
+ _Jv_JNI_GetByteArrayElements,
+ _Jv_JNI_GetCharArrayElements,
+ _Jv_JNI_GetShortArrayElements,
+ _Jv_JNI_GetIntArrayElements,
+ _Jv_JNI_GetLongArrayElements,
+ _Jv_JNI_GetFloatArrayElements,
+ _Jv_JNI_GetDoubleArrayElements,
+
+ _Jv_JNI_ReleaseBooleanArrayElements,
+ _Jv_JNI_ReleaseByteArrayElements,
+ _Jv_JNI_ReleaseCharArrayElements,
+ _Jv_JNI_ReleaseShortArrayElements,
+ _Jv_JNI_ReleaseIntArrayElements,
+ _Jv_JNI_ReleaseLongArrayElements,
+ _Jv_JNI_ReleaseFloatArrayElements,
+ _Jv_JNI_ReleaseDoubleArrayElements,
+
+ _Jv_JNI_GetBooleanArrayRegion,
+ _Jv_JNI_GetByteArrayRegion,
+ _Jv_JNI_GetCharArrayRegion,
+ _Jv_JNI_GetShortArrayRegion,
+ _Jv_JNI_GetIntArrayRegion,
+ _Jv_JNI_GetLongArrayRegion,
+ _Jv_JNI_GetFloatArrayRegion,
+ _Jv_JNI_GetDoubleArrayRegion,
+ _Jv_JNI_SetBooleanArrayRegion,
+ _Jv_JNI_SetByteArrayRegion,
+ _Jv_JNI_SetCharArrayRegion,
+ _Jv_JNI_SetShortArrayRegion,
+ _Jv_JNI_SetIntArrayRegion,
+ _Jv_JNI_SetLongArrayRegion,
+ _Jv_JNI_SetFloatArrayRegion,
+ _Jv_JNI_SetDoubleArrayRegion,
+
+ _Jv_JNI_RegisterNatives,
+ _Jv_JNI_UnregisterNatives,
+
+ _Jv_JNI_MonitorEnter,
+ _Jv_JNI_MonitorExit,
+
+ _Jv_JNI_GetJavaVM,
+
+ /* New JNI 1.2 functions. */
+
+ jni_GetStringRegion,
+ jni_GetStringUTFRegion,
+
+ jni_GetPrimitiveArrayCritical,
+ jni_ReleasePrimitiveArrayCritical,
+
+ _Jv_JNI_GetStringCritical,
+ _Jv_JNI_ReleaseStringCritical,
+
+ _Jv_JNI_NewWeakGlobalRef,
+ _Jv_JNI_DeleteWeakGlobalRef,
+
+ _Jv_JNI_ExceptionCheck,
+
+ /* New JNI 1.4 functions. */
+
+ jni_NewDirectByteBuffer,
+ jni_GetDirectBufferAddress,
+ jni_GetDirectBufferCapacity,
+
+ /* New JNI 1.6 functions. */
+
+ jni_GetObjectRefType
+};
+
+
+/* Invocation API Functions ***************************************************/
+
+/* JNI_GetDefaultJavaVMInitArgs ************************************************
+
+ Returns a default configuration for the Java VM.
+
+*******************************************************************************/
+
+jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
+{
+ JavaVMInitArgs *_vm_args;
+
+ _vm_args = (JavaVMInitArgs *) vm_args;
+
+ /* GNU classpath currently supports JNI 1.2 */
+
+ switch (_vm_args->version) {
+ case JNI_VERSION_1_1:
+ _vm_args->version = JNI_VERSION_1_1;
+ break;
+
+ case JNI_VERSION_1_2:
+ case JNI_VERSION_1_4:
+ _vm_args->ignoreUnrecognized = JNI_FALSE;
+ _vm_args->options = NULL;
+ _vm_args->nOptions = 0;
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* JNI_GetCreatedJavaVMs *******************************************************
+
+ Returns all Java VMs that have been created. Pointers to VMs are written in
+ the buffer vmBuf in the order they are created. At most bufLen number of
+ entries will be written. The total number of created VMs is returned in
+ *nVMs.
+
+*******************************************************************************/
+
+jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
+{
+ TRACEJNICALLS(("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs));
+
+ if (bufLen <= 0)
+ return JNI_ERR;
+
+ // We currently only support 1 VM running.
+
+ vmBuf[0] = vm->get_javavm();
+ *nVMs = 1;
+
+ return JNI_OK;
+}
+
+
+/* JNI_CreateJavaVM ************************************************************
+
+ Loads and initializes a Java VM. The current thread becomes the main thread.
+ Sets the env argument to the JNI interface pointer of the main thread.
+
+*******************************************************************************/
+
+jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
+{
+ TRACEJNICALLS(("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args));
+
+ /* actually create the JVM */
+
+ if (!VM_create(p_vm, p_env, vm_args))
+ return JNI_ERR;
+
+ return JNI_OK;
+}
+
+} // extern "C"
+
+
+/*
+ * 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:
+ */
#ifndef _JNI_H
#define _JNI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
#include "vm/types.h"
#include "vm/global.h"
-
-#include "vmcore/method.h"
+#include "vm/method.h"
+#if 0
/* _Jv_JNIEnv *****************************************************************/
#ifndef __cplusplus
};
#endif
+#endif
/* CACAO related stuff ********************************************************/
bool jni_init(void);
bool jni_version_check(int version);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _JNI_H */
#include "native/jvmti/jvmti.h"
#include "native/jvmti/cacaodbg.h"
#include "native/jvmti/dbg.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/loader.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/builtin.h"
#include "vm/jit/asmpart.h"
-#include "vm/stringlocal.h"
+#include "vm/string.hpp"
#include "toolbox/logging.h"
#include "threads/mutex.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include <sys/types.h>
#include <unistd.h>
#define _CACAODBG_H
#include "threads/mutex.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "native/jvmti/jvmti.h"
#include "native/include/java_lang_String.h"
#include <ltdl.h>
#include "native/native.h"
#include "native/jvmti/cacaodbg.h"
#include "native/jvmti/jvmti.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/global.h"
#include "vm/loader.h"
#include "vm/builtin.h"
#include "vm/jit/asmpart.h"
#include "vm/class.h"
#include "vm/classcache.h"
-#include "mm/gc-common.h"
+#include "mm/gc.hpp"
#include "toolbox/logging.h"
#include "vm/options.h"
-#include "vm/stringlocal.h"
+#include "vm/string.hpp"
#include "mm/memory.h"
#include "threads/mutex.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "threads/lock-common.h"
-#include "vm/exceptions.h"
-#include "native/include/java_util_Vector.h"
+#include "vm/exceptions.hpp"
#include "native/include/java_io_PrintStream.h"
#include "native/include/java_io_InputStream.h"
#include "native/include/java_lang_Cloneable.h"
#include <assert.h>
-#include "threads/thread.h"
+#include "threads/thread.hpp"
/* LLNI critical sections ******************************************************
#ifndef _LLNI_H
#define _LLNI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "config.h"
/* forward defines ************************************************************/
#include "native/localref.h"
-#include "threads/thread.h"
-
-
-/* LLNI macros *****************************************************************
-
- The following macros should be used whenever a Java Object is
- accessed in native code without the use of an JNI function.
-
- LLNI_field_set_val, LLNI_field_get_val:
- Deal with primitive values like integer and float values. Do
- not use these macros to access pointers or references!
-
- LLNI_field_set_ref, LLNI_field_get_ref:
- Deal with references to other objects.
-
- LLNI_field_set_cls, LLNI_field_get_cls:
- Deal with references to Java Classes which are internally
- represented by classinfo or java_lang_Class.
+#include "threads/thread.hpp"
-*******************************************************************************/
-
-#define LLNI_field_set_val(obj, field, value) \
- LLNI_field_direct(obj, field) = (value)
-
-#define LLNI_field_set_ref(obj, field, reference) \
- LLNI_field_direct(obj, field) = LLNI_UNWRAP(reference)
-
-#define LLNI_field_set_cls(obj, field, value) \
- LLNI_field_direct(obj, field) = (java_lang_Class *) (value)
-
-#define LLNI_field_get_val(obj, field, variable) \
- (variable) = LLNI_field_direct(obj, field)
-
-#define LLNI_field_get_ref(obj, field, variable) \
- (variable) = LLNI_WRAP(LLNI_field_direct(obj, field))
-
-#define LLNI_field_get_cls(obj, field, variable) \
- (variable) = (classinfo *) LLNI_field_direct(obj, field)
#define LLNI_class_get(obj, variable) \
(variable) = LLNI_field_direct((java_handle_t *) obj, vftbl->clazz)
*******************************************************************************/
#define LLNI_classinfo_wrap(classinfo) \
- ((java_lang_Class *) LLNI_WRAP(classinfo))
+ ((java_handle_t*) LLNI_WRAP(classinfo))
#define LLNI_classinfo_unwrap(clazz) \
((classinfo *) LLNI_UNWRAP((java_handle_t *) (clazz)))
void llni_critical_start_thread(threadobject *t);
void llni_critical_end_thread(threadobject *t);
+#ifdef __cplusplus
+}
+#endif
#endif /* _LLNI_H */
#include "native/localref.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "vm/vm.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#include "vm/jit/argument.h"
-#include "vmcore/options.h"
-
/* debug **********************************************************************/
/* src/native/localref.h - Management of local reference tables
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
typedef struct localref_table localref_table;
#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/types.h"
#include "vm/global.h"
-
-#include "vmcore/method.h"
+#include "vm/method.h"
/* localref_table **************************************************************
void localref_dump(void);
#endif
+#ifdef __cplusplus
+}
+#endif
#endif /* _LOCALREF_H */
#include "toolbox/logging.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/system.h"
-
#if defined(ENABLE_JVMTI)
#include "native/jvmti/cacaodbg.h"
#endif
ne = le->namelink;
while ((ne != NULL) && (f == NULL)) {
- f = (functionptr) (ptrint) system_dlsym(ne->handle, name->text);
+ f = (functionptr) (ptrint) os_dlsym(ne->handle, name->text);
if (f == NULL)
- f = (functionptr) (ptrint) system_dlsym(ne->handle, newname->text);
+ f = (functionptr) (ptrint) os_dlsym(ne->handle, newname->text);
ne = ne->hashlink;
}
/* try to open the library */
- handle = system_dlopen(filename->text, RTLD_LAZY);
+ handle = os_dlopen(filename->text, RTLD_LAZY);
if (handle == NULL) {
if (opt_verbosejni)
if (opt_verbose) {
log_start();
- log_print("native_library_open: system_dlopen failed: ");
+ log_print("native_library_open: os_dlopen failed: ");
log_print(dlerror());
log_finish();
}
/* Close the library. */
- result = system_dlclose(handle);
+ result = os_dlclose(handle);
if (result != 0) {
if (opt_verbose) {
log_start();
- log_print("native_library_close: system_dlclose failed: ");
+ log_print("native_library_close: os_dlclose failed: ");
log_print(dlerror());
log_finish();
}
# if defined(ENABLE_JNI)
/* Resolve JNI_OnLoad function. */
- onload = system_dlsym(handle, "JNI_OnLoad");
+ onload = os_dlsym(handle, "JNI_OnLoad");
if (onload != NULL) {
JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
loaded. */
if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
- system_dlclose(handle);
+ os_dlclose(handle);
return 0;
}
}
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "native/jni.h"
+#include "vm/class.h"
#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/system.h"
-#include "vmcore/utf8.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/os.hpp"
+#include "vm/utf8.h"
/* defines ********************************************************************/
java_handle_t *native_new_and_init(classinfo *c);
java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _NATIVE_H */
endif
if ENABLE_JAVASE
-REFLECT_SOURCES = \
- reflect.c \
- reflect.h
+REFLECTION_SOURCES = \
+ reflection.c \
+ reflection.h
SUN_MISC_UNSAFE_SOURCES = \
- sun_misc_Unsafe.c
+ sun_misc_Unsafe.cpp
endif
noinst_LTLIBRARIES = \
libnativevm_la_SOURCES = \
nativevm.c \
nativevm.h \
- $(REFLECT_SOURCES) \
+ $(REFLECTION_SOURCES) \
$(SUN_MISC_UNSAFE_SOURCES)
libnativevm_la_LIBADD = \
## src/native/vm/cldc1.1/Makefile.am
##
-## Copyright (C) 2006, 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) 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
##
## This file is part of CACAO.
##
libnativevmcore.la
libnativevmcore_la_SOURCES = \
- com_sun_cldc_io_ResourceInputStream.c \
- com_sun_cldc_io_j2me_socket_Protocol.c \
- com_sun_cldchi_io_ConsoleOutputStream.c \
- com_sun_cldchi_jvm_JVM.c \
- java_lang_Class.c \
- java_lang_Double.c \
- java_lang_Float.c \
- java_lang_Math.c \
- java_lang_Object.c \
- java_lang_Runtime.c \
- java_lang_String.c \
- java_lang_System.c \
- java_lang_Thread.c \
- java_lang_Throwable.c
+ com_sun_cldc_io_ResourceInputStream.cpp \
+ com_sun_cldc_io_j2me_socket_Protocol.cpp \
+ com_sun_cldchi_io_ConsoleOutputStream.cpp \
+ com_sun_cldchi_jvm_JVM.cpp \
+ java_lang_Class.cpp \
+ java_lang_Double.cpp \
+ java_lang_Float.cpp \
+ java_lang_Math.cpp \
+ java_lang_Object.cpp \
+ java_lang_Runtime.cpp \
+ java_lang_String.cpp \
+ java_lang_System.cpp \
+ java_lang_Thread.cpp \
+ java_lang_Throwable.cpp
## Local variables:
+++ /dev/null
-/* src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.c
-
- 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
-
- 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 <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <zlib.h>
-
-#include "config.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/com_sun_cldc_io_ResourceInputStream.h"
-#include "native/include/com_sun_cldchi_jvm_FileDescriptor.h"
-
-#include "vm/types.h"
-#include "vm/builtin.h"
-#include "vm/vm.h" /* REMOVE ME: temporarily */
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/zip.h"
-
-#include "threads/lock-common.h"
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "open", "(Ljava/lang/String;)Ljava/lang/Object;", (void *) (ptrint) &Java_com_sun_cldc_io_ResourceInputStream_open },
- { "bytesRemain", "(Ljava/lang/Object;)I", (void *) (ptrint) &Java_com_sun_cldc_io_ResourceInputStream_bytesRemain },
- { "readByte", "(Ljava/lang/Object;)I", (void *) (ptrint) &Java_com_sun_cldc_io_ResourceInputStream_readByte },
- { "readBytes", "(Ljava/lang/Object;[BII)I", (void *) (ptrint) &Java_com_sun_cldc_io_ResourceInputStream_readBytes },
- { "clone", "(Ljava/lang/Object;)Ljava/lang/Object;", (void *) (ptrint) &Java_com_sun_cldc_io_ResourceInputStream_clone },
-};
-
-/* _Jv_com_sun_cldc_io_ResourceInputStream_init ********************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_com_sun_cldc_io_ResourceInputStream_init(void)
-{
- utf *u;
-
- u = utf_new_char("com/sun/cldc/io/ResourceInputStream");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-static struct com_sun_cldchi_jvm_FileDescriptor* zip_read_resource(list_classpath_entry *lce, utf *name)
-{
- hashtable_zipfile_entry *htzfe;
- lfh lfh;
- u1 *indata;
- u1 *outdata;
- z_stream zs;
- int err;
-
- classinfo *ci;
- com_sun_cldchi_jvm_FileDescriptor *fileDescriptor = NULL;
-
- /* try to find the class in the current archive */
-
- htzfe = zip_find(lce, name);
-
- if (htzfe == NULL)
- return NULL;
-
- /* read stuff from local file header */
-
- lfh.filenamelength = SUCK_LE_U2(htzfe->data + LFH_FILE_NAME_LENGTH);
- lfh.extrafieldlength = SUCK_LE_U2(htzfe->data + LFH_EXTRA_FIELD_LENGTH);
-
- indata = htzfe->data +
- LFH_HEADER_SIZE +
- lfh.filenamelength +
- lfh.extrafieldlength;
-
- /* allocate buffer for uncompressed data */
-
- outdata = MNEW(u1, htzfe->uncompressedsize);
-
- /* how is the file stored? */
-
- switch (htzfe->compressionmethod) {
- case Z_DEFLATED:
- /* fill z_stream structure */
-
- zs.next_in = indata;
- zs.avail_in = htzfe->compressedsize;
- zs.next_out = outdata;
- zs.avail_out = htzfe->uncompressedsize;
-
- zs.zalloc = Z_NULL;
- zs.zfree = Z_NULL;
- zs.opaque = Z_NULL;
-
- /* initialize this inflate run */
-
- if (inflateInit2(&zs, -MAX_WBITS) != Z_OK)
- vm_abort("zip_get: inflateInit2 failed: %s", strerror(errno));
-
- /* decompress the file into buffer */
-
- err = inflate(&zs, Z_SYNC_FLUSH);
-
- if ((err != Z_STREAM_END) && (err != Z_OK))
- vm_abort("zip_get: inflate failed: %s", strerror(errno));
-
- /* finish this inflate run */
-
- if (inflateEnd(&zs) != Z_OK)
- vm_abort("zip_get: inflateEnd failed: %s", strerror(errno));
- break;
-
- case 0:
- /* uncompressed file, just copy the data */
- MCOPY(outdata, indata, u1, htzfe->compressedsize);
- break;
-
- default:
- vm_abort("zip_get: unknown compression method %d",
- htzfe->compressionmethod);
- }
-
- /* Create a file descriptor object */
- ci = load_class_bootstrap(utf_new_char("com/sun/cldchi/jvm/FileDescriptor"));
- fileDescriptor = (com_sun_cldchi_jvm_FileDescriptor *) native_new_and_init(ci);
- LLNI_field_set_val(fileDescriptor, pointer, (int)outdata);
- LLNI_field_set_val(fileDescriptor, length, htzfe->uncompressedsize);
- LLNI_field_set_val(fileDescriptor, position, 0);
- return fileDescriptor;
-
-}
-
-static struct com_sun_cldchi_jvm_FileDescriptor* file_read_resource(char *path)
-{
- int len;
- struct stat statBuffer;
- u1 *filep;
- com_sun_cldchi_jvm_FileDescriptor *fileDescriptor = NULL;
- classinfo *ci;
- int fd;
-
- fd = open(path, O_RDONLY);
-
- if (fd > 0) {
-
- if (fstat(fd, &statBuffer) != -1) {
- len = statBuffer.st_size;
- } else {
- return NULL;
- }
-
- /* Map file into the memory */
- filep = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
-
- /* Create a file descriptor object */
- ci = load_class_bootstrap(utf_new_char("com/sun/cldchi/jvm/FileDescriptor"));
- fileDescriptor = (com_sun_cldchi_jvm_FileDescriptor *) native_new_and_init(ci);
- LLNI_field_set_val(fileDescriptor, pointer, (int)filep);
- LLNI_field_set_val(fileDescriptor, length, len);
- LLNI_field_set_val(fileDescriptor, position, 0);
-
- return fileDescriptor;
-
- } else {
- return NULL;
- }
-
-}
-
-
-/*
- * Class: com/sun/cldc/io/ResourceInputStream
- * Method: open
- * Signature: (Ljava/lang/String;)Ljava/lang/Object;
- */
-JNIEXPORT struct java_lang_Object* JNICALL Java_com_sun_cldc_io_ResourceInputStream_open(JNIEnv *env, jclass clazz, java_lang_String *name)
-{
-
- list_classpath_entry *lce;
- char *filename;
- s4 filenamelen;
- char *path;
- utf *uname;
- com_sun_cldchi_jvm_FileDescriptor* descriptor;
-
- /* get the classname as char string (do it here for the warning at
- the end of the function) */
-
- uname = javastring_toutf((java_handle_t *)name, false);
- filenamelen = utf_bytes(uname) + strlen("0");
- filename = MNEW(char, filenamelen);
- utf_copy(filename, uname);
-
- /* walk through all classpath entries */
-
- for (lce = list_first(list_classpath_entries); lce != NULL;
- lce = list_next(list_classpath_entries, lce)) {
-
-#if defined(ENABLE_ZLIB)
- if (lce->type == CLASSPATH_ARCHIVE) {
-
- /* enter a monitor on zip/jar archives */
- LOCK_MONITOR_ENTER(lce);
-
- /* try to get the file in current archive */
- descriptor = zip_read_resource(lce, uname);
-
- /* leave the monitor */
- LOCK_MONITOR_EXIT(lce);
-
- if (descriptor != NULL) { /* file exists */
- break;
- }
-
- } else {
-#endif
-
- path = MNEW(char, lce->pathlen + filenamelen);
- strcpy(path, lce->path);
- strcat(path, filename);
-
- descriptor = file_read_resource(path);
-
- MFREE(path, char, lce->pathlen + filenamelen);
-
- if (descriptor != NULL) { /* file exists */
- break;
- }
-
-#if defined(ENABLE_ZLIB)
- }
-#endif
-
- }
-
- MFREE(filename, char, filenamelen);
-
- return (java_lang_Object*) descriptor;
-
-}
-
-
-/*
- * Class: com_sun_cldc_io_ResourceInputStream
- * Method: bytesRemain
- * Signature: (Ljava/lang/Object;)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_ResourceInputStream_bytesRemain(JNIEnv *env, jclass clazz, struct java_lang_Object* jobj) {
-
- com_sun_cldchi_jvm_FileDescriptor *fileDescriptor;
- int32_t length;
- int32_t position;
-
- fileDescriptor = (com_sun_cldchi_jvm_FileDescriptor *) jobj;
- LLNI_field_get_val(fileDescriptor, position, position);
- LLNI_field_get_val(fileDescriptor, length, length);
-
- return length - position;
-
-}
-
-/*
- * Class: com_sun_cldc_io_ResourceInputStream
- * Method: readByte
- * Signature: (Ljava/lang/Object;)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_ResourceInputStream_readByte(JNIEnv *env, jclass clazz, struct java_lang_Object* jobj) {
-
- com_sun_cldchi_jvm_FileDescriptor *fileDescriptor;
- u1 byte;
- int32_t length;
- int32_t position;
- int64_t filep;
-
- fileDescriptor = (com_sun_cldchi_jvm_FileDescriptor *) jobj;
- LLNI_field_get_val(fileDescriptor, position, position);
- LLNI_field_get_val(fileDescriptor, length, length);
- LLNI_field_get_val(fileDescriptor, pointer, filep);
-
- if (position < length) {
- byte = ((u1*)(int)filep)[position];
- position++;
- } else {
- return -1; /* EOF */
- }
-
- /* Update access position */
- LLNI_field_set_val(fileDescriptor, position, position);
-
- return (byte & 0xFF);
-
-}
-
-/*
- * Class: com_sun_cldc_io_ResourceInputStream
- * Method: readBytes
- * Signature: (Ljava/lang/Object;[BII)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_ResourceInputStream_readBytes(JNIEnv *env, jclass clazz, struct java_lang_Object* jobj, java_handle_bytearray_t* byteArray, s4 off, s4 len) {
-
- com_sun_cldchi_jvm_FileDescriptor *fileDescriptor;
- s4 readBytes = -1;
- int32_t fileLength;
- int32_t position;
- s4 available;
- int64_t filep;
- void *buf;
-
- /* get pointer to the buffer */
- buf = &(LLNI_array_direct(byteArray, off));
-
- fileDescriptor = (com_sun_cldchi_jvm_FileDescriptor *) jobj;
- LLNI_field_get_val(fileDescriptor, position, position);
- LLNI_field_get_val(fileDescriptor, length, fileLength);
- LLNI_field_get_val(fileDescriptor, pointer, filep);
-
- if (position < fileLength) {
- available = fileLength - position;
- if (available < len) {
- readBytes = available;
- } else {
- readBytes = len;
- }
- memcpy(buf, ((u1*)(int)filep) + position, readBytes * sizeof(u1));
- position += readBytes;
- } else {
- return -1; /* EOF */
- }
-
- /* Update access position */
- LLNI_field_set_val(fileDescriptor, position, position);
-
- return readBytes;
-}
-
-/*
- * Class: com_sun_cldc_io_ResourceInputStream
- * Method: clone
- * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
- */
-JNIEXPORT struct java_lang_Object* JNICALL Java_com_sun_cldc_io_ResourceInputStream_clone(JNIEnv *env, jclass clazz, struct java_lang_Object* jobj) {
-
- classinfo *ci;
- com_sun_cldchi_jvm_FileDescriptor *srcFileDescriptor;
- com_sun_cldchi_jvm_FileDescriptor *dstFileDescriptor;
- int32_t srcLength;
- int32_t srcPosition;
- int64_t srcFilePointer;
-
- srcFileDescriptor = (com_sun_cldchi_jvm_FileDescriptor *) jobj;
- LLNI_field_get_val(srcFileDescriptor, position, srcPosition);
- LLNI_field_get_val(srcFileDescriptor, length, srcLength);
- LLNI_field_get_val(srcFileDescriptor, pointer, srcFilePointer);
-
- ci = load_class_bootstrap(utf_new_char("com/sun/cldchi/jvm/FileDescriptor"));
- dstFileDescriptor = (com_sun_cldchi_jvm_FileDescriptor *) native_new_and_init(ci);
- LLNI_field_set_val(dstFileDescriptor, position, srcPosition);
- LLNI_field_set_val(dstFileDescriptor, length, srcLength);
- LLNI_field_set_val(dstFileDescriptor, pointer, srcFilePointer);
-
- return (java_lang_Object*) dstFileDescriptor;
-
-}
-
-
-/*
- * 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/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp
+
+ 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.
+
+*/
+
+
+#include "config.h"
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <zlib.h>
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/com_sun_cldc_io_ResourceInputStream.h"
+#endif
+
+#include "threads/lock-common.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/string.hpp"
+#include "vm/types.h"
+#include "vm/vm.hpp" /* REMOVE ME: temporarily */
+#include "vm/zip.h"
+
+
+static java_handle_t* zip_read_resource(list_classpath_entry *lce, utf *name)
+{
+ hashtable_zipfile_entry *htzfe;
+ lfh lfh;
+ u1 *indata;
+ u1 *outdata;
+ z_stream zs;
+ int err;
+
+ classinfo *ci;
+
+ /* try to find the class in the current archive */
+
+ htzfe = zip_find(lce, name);
+
+ if (htzfe == NULL)
+ return NULL;
+
+ /* read stuff from local file header */
+
+ lfh.filenamelength = SUCK_LE_U2(htzfe->data + LFH_FILE_NAME_LENGTH);
+ lfh.extrafieldlength = SUCK_LE_U2(htzfe->data + LFH_EXTRA_FIELD_LENGTH);
+
+ indata = htzfe->data +
+ LFH_HEADER_SIZE +
+ lfh.filenamelength +
+ lfh.extrafieldlength;
+
+ /* allocate buffer for uncompressed data */
+
+ outdata = MNEW(u1, htzfe->uncompressedsize);
+
+ /* how is the file stored? */
+
+ switch (htzfe->compressionmethod) {
+ case Z_DEFLATED:
+ /* fill z_stream structure */
+
+ zs.next_in = indata;
+ zs.avail_in = htzfe->compressedsize;
+ zs.next_out = outdata;
+ zs.avail_out = htzfe->uncompressedsize;
+
+ zs.zalloc = Z_NULL;
+ zs.zfree = Z_NULL;
+ zs.opaque = Z_NULL;
+
+ /* initialize this inflate run */
+
+ if (inflateInit2(&zs, -MAX_WBITS) != Z_OK)
+ vm_abort("zip_get: inflateInit2 failed: %s", strerror(errno));
+
+ /* decompress the file into buffer */
+
+ err = inflate(&zs, Z_SYNC_FLUSH);
+
+ if ((err != Z_STREAM_END) && (err != Z_OK))
+ vm_abort("zip_get: inflate failed: %s", strerror(errno));
+
+ /* finish this inflate run */
+
+ if (inflateEnd(&zs) != Z_OK)
+ vm_abort("zip_get: inflateEnd failed: %s", strerror(errno));
+ break;
+
+ case 0:
+ /* uncompressed file, just copy the data */
+ MCOPY(outdata, indata, u1, htzfe->compressedsize);
+ break;
+
+ default:
+ vm_abort("zip_get: unknown compression method %d",
+ htzfe->compressionmethod);
+ }
+
+ // Create a file descriptor object.
+ ci = load_class_bootstrap(utf_new_char("com/sun/cldchi/jvm/FileDescriptor"));
+ java_handle_t* h = native_new_and_init(ci);
+
+ if (h == NULL)
+ return NULL;
+
+ com_sun_cldchi_jvm_FileDescriptor fd(h, (int64_t) outdata, 0, htzfe->uncompressedsize);
+
+ return fd.get_handle();
+}
+
+
+static java_handle_t* file_read_resource(char *path)
+{
+ int len;
+ struct stat statBuffer;
+ u1 *filep;
+ classinfo *ci;
+ int fd;
+
+ fd = open(path, O_RDONLY);
+
+ if (fd > 0) {
+
+ if (fstat(fd, &statBuffer) != -1) {
+ len = statBuffer.st_size;
+ } else {
+ return NULL;
+ }
+
+ /* Map file into the memory */
+ filep = (u1*) mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ /* Create a file descriptor object */
+ ci = load_class_bootstrap(utf_new_char("com/sun/cldchi/jvm/FileDescriptor"));
+ java_handle_t* h = native_new_and_init(ci);
+
+ if (h == NULL)
+ return NULL;
+
+ com_sun_cldchi_jvm_FileDescriptor fd(h, (int64_t) filep, 0, len);
+
+ return fd.get_handle();
+ }
+ else {
+ return NULL;
+ }
+}
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: com/sun/cldc/io/ResourceInputStream
+ * Method: open
+ * Signature: (Ljava/lang/String;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_cldc_io_ResourceInputStream_open(JNIEnv *env, jclass clazz, jstring name)
+{
+ list_classpath_entry *lce;
+ char *filename;
+ s4 filenamelen;
+ char *path;
+ utf *uname;
+ java_handle_t* descriptor;
+
+ /* get the classname as char string (do it here for the warning at
+ the end of the function) */
+
+ uname = javastring_toutf((java_handle_t *)name, false);
+ filenamelen = utf_bytes(uname) + strlen("0");
+ filename = MNEW(char, filenamelen);
+ utf_copy(filename, uname);
+
+ /* walk through all classpath entries */
+
+ for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL;
+ lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
+
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+
+ /* enter a monitor on zip/jar archives */
+ LOCK_MONITOR_ENTER(lce);
+
+ /* try to get the file in current archive */
+ descriptor = zip_read_resource(lce, uname);
+
+ /* leave the monitor */
+ LOCK_MONITOR_EXIT(lce);
+
+ if (descriptor != NULL) { /* file exists */
+ break;
+ }
+
+ } else {
+#endif
+
+ path = MNEW(char, lce->pathlen + filenamelen);
+ strcpy(path, lce->path);
+ strcat(path, filename);
+
+ descriptor = file_read_resource(path);
+
+ MFREE(path, char, lce->pathlen + filenamelen);
+
+ if (descriptor != NULL) { /* file exists */
+ break;
+ }
+#if defined(ENABLE_ZLIB)
+ }
+#endif
+ }
+
+ MFREE(filename, char, filenamelen);
+
+ return (jobject) descriptor;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/ResourceInputStream
+ * Method: bytesRemain
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_ResourceInputStream_bytesRemain(JNIEnv *env, jclass clazz, jobject jobj)
+{
+ com_sun_cldchi_jvm_FileDescriptor fd(jobj);
+ int32_t length = fd.get_position();
+ int32_t position = fd.get_length();
+
+ return length - position;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/ResourceInputStream
+ * Method: readByte
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_ResourceInputStream_readByte(JNIEnv *env, jclass clazz, jobject jobj)
+{
+ com_sun_cldchi_jvm_FileDescriptor fd(jobj);
+
+ int64_t filep = fd.get_pointer();
+ int32_t position = fd.get_position();
+ int32_t length = fd.get_length();
+
+ uint8_t byte;
+
+ if (position < length) {
+ byte = ((uint8_t*) filep)[position];
+ position++;
+ }
+ else {
+ return -1; /* EOF */
+ }
+
+ // Update access position.
+ fd.set_position(position);
+
+ return (byte & 0xFF);
+}
+
+
+/*
+ * Class: com/sun/cldc/io/ResourceInputStream
+ * Method: readBytes
+ * Signature: (Ljava/lang/Object;[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_ResourceInputStream_readBytes(JNIEnv *env, jclass clazz, jobject jobj, jbyteArray byteArray, jint off, jint len)
+{
+ /* get pointer to the buffer */
+ // XXX Not GC safe.
+ void* buf = &(LLNI_array_direct((java_handle_bytearray_t*) byteArray, off));
+
+ com_sun_cldchi_jvm_FileDescriptor fd(jobj);
+
+ int64_t filep = fd.get_pointer();
+ int32_t position = fd.get_position();
+ int32_t fileLength = fd.get_length();
+
+ int32_t readBytes = -1;
+
+ if (position < fileLength) {
+ int32_t available = fileLength - position;
+
+ if (available < len) {
+ readBytes = available;
+ } else {
+ readBytes = len;
+ }
+
+ os::memcpy(buf, ((uint8_t*) filep) + position, readBytes * sizeof(uint8_t));
+ position += readBytes;
+ }
+ else {
+ return -1; /* EOF */
+ }
+
+ // Update access position.
+ fd.set_position(position);
+
+ return readBytes;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/ResourceInputStream
+ * Method: clone
+ * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_com_sun_cldc_io_ResourceInputStream_clone(JNIEnv *env, jclass clazz, jobject jobj)
+{
+ com_sun_cldchi_jvm_FileDescriptor fd(jobj);
+
+ classinfo* c = load_class_bootstrap(utf_new_char("com/sun/cldchi/jvm/FileDescriptor"));
+ java_handle_t* h = native_new_and_init(c);
+
+ if (h == NULL)
+ return NULL;
+
+ com_sun_cldchi_jvm_FileDescriptor clonefd(h, fd);
+
+ return (jobject) clonefd.get_handle();
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "open", (char*) "(Ljava/lang/String;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_com_sun_cldc_io_ResourceInputStream_open },
+ { (char*) "bytesRemain", (char*) "(Ljava/lang/Object;)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_ResourceInputStream_bytesRemain },
+ { (char*) "readByte", (char*) "(Ljava/lang/Object;)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_ResourceInputStream_readByte },
+ { (char*) "readBytes", (char*) "(Ljava/lang/Object;[BII)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_ResourceInputStream_readBytes },
+ { (char*) "clone", (char*) "(Ljava/lang/Object;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_com_sun_cldc_io_ResourceInputStream_clone },
+};
+
+
+/* _Jv_com_sun_cldc_io_ResourceInputStream_init ********************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_com_sun_cldc_io_ResourceInputStream_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("com/sun/cldc/io/ResourceInputStream");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.c
-
- 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
-
- 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 <errno.h>
-#include <netdb.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/com_sun_cldc_io_j2me_socket_Protocol.h"
-
-#include "vm/global.h"
-#include "vm/vm.h" /* REMOVE ME: temporarily */
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "open0", "([BII)I", (void *) (ptrint) &Java_com_sun_cldc_io_j2me_socket_Protocol_open0 },
- { "readBuf", "(I[BII)I", (void *) (ptrint) &Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf },
- { "readByte", "(I)I", (void *) (ptrint) &Java_com_sun_cldc_io_j2me_socket_Protocol_readByte },
- { "writeBuf", "(I[BII)I", (void *) (ptrint) &Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf },
- { "writeByte", "(II)I", (void *) (ptrint) &Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte },
- { "available0", "(I)I", (void *) (ptrint) &Java_com_sun_cldc_io_j2me_socket_Protocol_available0 },
- { "close0", "(I)V", (void *) (ptrint) &Java_com_sun_cldc_io_j2me_socket_Protocol_close0 },
-};
-
-
-/* _Jv_com_sun_cldc_io_j2me_socket_Protocol_init *******************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init(void)
-{
- utf *u;
-
- u = utf_new_char("com/sun/cldc/io/j2me/socket/Protocol");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: com/sun/cldc/io/j2me/socket/Protocol
- * Method: open0
- * Signature: ([BII)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_open0(JNIEnv *env, jclass clazz, java_handle_bytearray_t *hostname, s4 port, s4 mode)
-{
- struct hostent *phostent;
- struct sockaddr_in serv_addr;
- char *name;
- s4 sockfd;
- s4 result;
-
- /* The hostname byte-array is a NULL terminated C-string. */
-
- name = (char *) &(LLNI_array_data(hostname));
-
- /* get the host */
-
- phostent = gethostbyname(name);
-
- if (phostent == NULL)
- return -1;
-
- /* fill the sockaddr structure */
-
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(port);
-
- MCOPY(&serv_addr.sin_addr, phostent->h_addr, u1, phostent->h_length);
-
- /* create the socket */
-
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
-
- if (sockfd < 0)
- return -1;
-
- /* connect the socket */
-
- result = connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
-
- if (result < 0)
- return -1;
-
- return sockfd;
-}
-
-
-/*
- * Class: com/sun/cldc/io/j2me/socket/Protocol
- * Method: readBuf
- * Signature: (I[BII)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf(JNIEnv *env, jclass clazz, s4 handle, java_handle_bytearray_t *b, s4 off, s4 len)
-{
- void *buf;
- ssize_t result;
-
- /* get pointer to the buffer */
-
- buf = &(LLNI_array_direct(b, off));
-
- /* receive from the socket */
-
- result = recv(handle, buf, len, 0);
-
- if (result == 0) {
- /* the peer has performed an orderly shutdown */
-
- return -1;
- }
- else if (result < 0) {
- vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf: recv failed: %s", strerror(errno));
- }
-
- return result;
-}
-
-
-/*
- * Class: com/sun/cldc/io/j2me/socket/Protocol
- * Method: readByte
- * Signature: (I)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readByte(JNIEnv *env, jclass clazz, s4 handle) {
-
- char byte;
- ssize_t result;
-
- /* receive from the socket */
-
- result = recv(handle, &byte, 1, 0);
-
- if (result == 0) {
- /* the peer has performed an orderly shutdown */
-
- return -1;
- }
- else if (result < 0) {
- /* should throw an IOException */
-
- vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_readByte: recv failed: %s", strerror(errno));
- }
-
- return byte;
-}
-
-
-/*
- * Class: com/sun/cldc/io/j2me/socket/Protocol
- * Method: writeBuf
- * Signature: (I[BII)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf(JNIEnv *env, jclass clazz, s4 handle, java_handle_bytearray_t * b, s4 off, s4 len) {
-
- void *buf;
- ssize_t result;
-
- /* get pointer to the buffer */
-
- buf = &(LLNI_array_direct(b, off));
-
- /* send the given byte to the socket */
-
- result = send(handle, buf, len, 0);
-
- if (result < 0)
- /* should throw an IOException */
-
- vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf: send failed: %s", strerror(errno));
-
- return result;
-
-}
-
-
-/*
- * Class: com/sun/cldc/io/j2me/socket/Protocol
- * Method: writeByte
- * Signature: (II)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte(JNIEnv *env, jclass clazz, s4 handle, s4 b)
-{
- char byte;
- ssize_t result;
-
- byte = (char) b;
-
- /* send the given byte to the socket */
-
- result = send(handle, &byte, 1, 0);
-
- if (result < 0)
- vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte: send failed: %s", strerror(errno));
-
- return result;
-}
-
-
-/*
- * Class: com/sun/cldc/io/j2me/socket/Protocol
- * Method: available0
- * Signature: (I)I
- */
-JNIEXPORT s4 JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_available0(JNIEnv *env, jclass clazz, s4 handle)
-{
- /* NOTE: Sun doesn't have an implementation too */
-
- return 0;
-}
-
-
-/*
- * Class: com/sun/cldc/io/j2me/socket/Protocol
- * Method: close0
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_close0(JNIEnv *env, jclass clazz, s4 handle)
-{
- int result;
-
- /* close the file descriptor */
-
- result = close(handle);
-
- if (result < 0)
- vm_abort("Java_com_sun_cldc_io_j2me_socket_Protocol_close0: close failed: %s", strerror(errno));
-}
-
-
-/*
- * 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/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp
+
+ 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.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/com_sun_cldc_io_j2me_socket_Protocol.h"
+#endif
+
+#include "vm/global.h"
+#include "vm/vm.hpp" /* REMOVE ME: temporarily */
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: com/sun/cldc/io/j2me/socket/Protocol
+ * Method: open0
+ * Signature: ([BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_open0(JNIEnv *env, jclass clazz, jbyteArray hostname, jint port, jint mode)
+{
+ struct hostent *phostent;
+ struct sockaddr_in serv_addr;
+
+ // The hostname byte-array is a NULL terminated C-string.
+ // XXX Not GC safe.
+ char* name = (char*) &(LLNI_array_data((java_handle_bytearray_t*) hostname));
+
+ /* get the host */
+
+ phostent = gethostbyname(name);
+
+ if (phostent == NULL)
+ return -1;
+
+ /* fill the sockaddr structure */
+
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_port = htons(port);
+
+ MCOPY(&serv_addr.sin_addr, phostent->h_addr, u1, phostent->h_length);
+
+ /* create the socket */
+
+ int sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (sockfd < 0)
+ return -1;
+
+ /* connect the socket */
+
+ int result = connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr));
+
+ if (result < 0)
+ return -1;
+
+ return sockfd;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/j2me/socket/Protocol
+ * Method: readBuf
+ * Signature: (I[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf(JNIEnv *env, jclass clazz, jint handle, jbyteArray b, jint off, jint len)
+{
+ // Get pointer to the buffer.
+ // XXX Not GC safe.
+ void* buf = &(LLNI_array_direct((java_handle_bytearray_t*) b, off));
+
+ // Receive from the socket.
+ ssize_t result = recv(handle, buf, len, 0);
+
+ if (result == 0) {
+ // The peer has performed an orderly shutdown.
+ return -1;
+ }
+ else if (result < 0) {
+ vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf: recv failed");
+ }
+
+ return result;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/j2me/socket/Protocol
+ * Method: readByte
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readByte(JNIEnv *env, jclass clazz, jint handle)
+{
+ char byte;
+
+ // Receive from the socket.
+ ssize_t result = recv(handle, &byte, 1, 0);
+
+ if (result == 0) {
+ // The peer has performed an orderly shutdown.
+ return -1;
+ }
+ else if (result < 0) {
+ // TODO Should throw an IOException.
+ vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readByte: recv failed");
+ }
+
+ return byte;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/j2me/socket/Protocol
+ * Method: writeBuf
+ * Signature: (I[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf(JNIEnv *env, jclass clazz, jint handle, jbyteArray b, jint off, jint len)
+{
+ // Get pointer to the buffer.
+ // XXX Not GC safe.
+ void* buf = &(LLNI_array_direct((java_handle_bytearray_t*) b, off));
+
+ // Send the given byte to the socket.
+ ssize_t result = send(handle, buf, len, 0);
+
+ if (result < 0) {
+ // TODO Should throw an IOException.
+ vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf: send failed");
+ }
+
+ return result;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/j2me/socket/Protocol
+ * Method: writeByte
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte(JNIEnv *env, jclass clazz, jint handle, jint b)
+{
+ char byte = (char) b;
+
+ // Send the given byte to the socket.
+ ssize_t result = send(handle, &byte, 1, 0);
+
+ if (result < 0)
+ vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte: send failed");
+
+ return result;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/j2me/socket/Protocol
+ * Method: available0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_available0(JNIEnv *env, jclass clazz, jint handle)
+{
+ // NOTE: Sun doesn't have an implementation too.
+ return 0;
+}
+
+
+/*
+ * Class: com/sun/cldc/io/j2me/socket/Protocol
+ * Method: close0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_close0(JNIEnv *env, jclass clazz, jint handle)
+{
+ // Close the file descriptor.
+ int result = close(handle);
+
+ if (result < 0)
+ vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_close0: close failed");
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "open0", (char*) "([BII)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_open0 },
+ { (char*) "readBuf", (char*) "(I[BII)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf },
+ { (char*) "readByte", (char*) "(I)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_readByte },
+ { (char*) "writeBuf", (char*) "(I[BII)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf },
+ { (char*) "writeByte", (char*) "(II)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte },
+ { (char*) "available0", (char*) "(I)I", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_available0 },
+ { (char*) "close0", (char*) "(I)V", (void*) (uintptr_t) &Java_com_sun_cldc_io_j2me_socket_Protocol_close0 },
+};
+
+
+/* _Jv_com_sun_cldc_io_j2me_socket_Protocol_init *******************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("com/sun/cldc/io/j2me/socket/Protocol");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/com_sun_cldchi_io_ConsoleOutputStream.c
-
- Copyright (C) 2006, 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
-
- 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 <stdio.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/com_sun_cldchi_io_ConsoleOutputStream.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "write", "(I)V", (void *) (ptrint) &Java_com_sun_cldchi_io_ConsoleOutputStream_write },
-};
-
-
-/* _Jv_com_sun_cldchi_io_ConsoleOutputStream_init ******************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init(void)
-{
- utf *u;
-
- u = utf_new_char("com/sun/cldchi/io/ConsoleOutputStream");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: com/sun/cldchi/io/ConsoleOutputStream
- * Method: write
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_com_sun_cldchi_io_ConsoleOutputStream_write(JNIEnv *env, com_sun_cldchi_io_ConsoleOutputStream *this, s4 c)
-{
- (void) fputc(c, stdout);
-}
-
-
-/*
- * 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/native/vm/cldc1.1/com_sun_cldchi_io_ConsoleOutputStream.cpp
+
+ Copyright (C) 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 <stdio.h>
+
+#include "vm/types.h"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/com_sun_cldchi_io_ConsoleOutputStream.h"
+#endif
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: com/sun/cldchi/io/ConsoleOutputStream
+ * Method: write
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_cldchi_io_ConsoleOutputStream_write(JNIEnv *env, jobject _this, jint c)
+{
+ (void) fputc(c, stdout);
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "write", (char*) "(I)V", (void*) (uintptr_t) &Java_com_sun_cldchi_io_ConsoleOutputStream_write },
+};
+
+
+/* _Jv_com_sun_cldchi_io_ConsoleOutputStream_init ******************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("com/sun/cldchi/io/ConsoleOutputStream");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/com_sun_cldchi_jvm_JVM.c
-
- 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.
-
-*/
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h"
-
-#include "native/include/com_sun_cldchi_jvm_JVM.h"
-
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "loadLibrary", "(Ljava/lang/String;)V", (void *) (ptrint) &Java_com_sun_cldchi_jvm_JVM_loadLibrary },
-};
-
-
-/* _Jv_com_sun_cldchi_jvm_JVM_init *********************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_com_sun_cldchi_jvm_JVM_init(void)
-{
- utf *u;
-
- u = utf_new_char("com/sun/cldchi/jvm/JVM");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: com/sun/cldchi/jvm/JVM
- * Method: loadLibrary
- * Signature: (Ljava/lang/String;)V
- */
-JNIEXPORT void JNICALL Java_com_sun_cldchi_jvm_JVM_loadLibrary(JNIEnv *env, jclass clazz, java_lang_String *libName)
-{
- int result;
- utf *name;
-
- /* REMOVEME When we use Java-strings internally. */
-
- if (libName == NULL) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- name = javastring_toutf((java_handle_t *) libName, false);
-
- result = native_library_load(env, name, NULL);
-
- /* Check for error and throw an exception in case. */
-
- if (result == 0) {
- exceptions_throw_unsatisfiedlinkerror(name);
- }
-}
-
-
-/*
- * 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/native/vm/cldc1.1/com_sun_cldchi_jvm_JVM.cpp
+
+ 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.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/com_sun_cldchi_jvm_JVM.h"
+#endif
+
+#include "vm/exceptions.hpp"
+#include "vm/string.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: com/sun/cldchi/jvm/JVM
+ * Method: loadLibrary
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_sun_cldchi_jvm_JVM_loadLibrary(JNIEnv *env, jclass clazz, jstring libName)
+{
+ if (libName == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ /* REMOVEME When we use Java-strings internally. */
+
+ utf* name = javastring_toutf((java_handle_t *) libName, false);
+
+ int result = native_library_load(env, name, NULL);
+
+ /* Check for error and throw an exception in case. */
+
+ if (result == 0) {
+ exceptions_throw_unsatisfiedlinkerror(name);
+ }
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "loadLibrary", (char*) "(Ljava/lang/String;)V", (void*) (uintptr_t) &Java_com_sun_cldchi_jvm_JVM_loadLibrary },
+};
+
+
+/* _Jv_com_sun_cldchi_jvm_JVM_init *********************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_com_sun_cldchi_jvm_JVM_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("com/sun/cldchi/jvm/JVM");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Class.c
-
- Copyright (C) 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 "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h" /* required by j.l.C */
-#include "native/include/java_lang_Object.h"
-
-#include "native/include/java_lang_Class.h"
-
-#include "vm/exceptions.h"
-#include "vm/initialize.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "forName", "(Ljava/lang/String;)Ljava/lang/Class;",(void *) (ptrint) &Java_java_lang_Class_forName },
- { "newInstance", "()Ljava/lang/Object;", (void *) (ptrint) &Java_java_lang_Class_newInstance },
- { "isInstance", "(Ljava/lang/Object;)Z", (void *) (ptrint) &Java_java_lang_Class_isInstance },
- { "isAssignableFrom", "(Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_Class_isAssignableFrom },
- { "isInterface", "()Z", (void *) (ptrint) &Java_java_lang_Class_isInterface },
- { "isArray", "()Z", (void *) (ptrint) &Java_java_lang_Class_isArray },
- { "getName", "()Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_Class_getName },
-};
-
-/* _Jv_java_lang_Class_init ****************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Class_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Class");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: forName
- * Signature: (Ljava/lang/String;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_Class_forName(JNIEnv *env, jclass clazz, java_lang_String *name)
-{
- utf *ufile;
- utf *uname;
- classinfo *c;
- u2 *pos;
- s4 i;
-
- /* illegal argument */
-
- if (name == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* create utf string in which '.' is replaced by '/' */
-
- ufile = javastring_toutf((java_handle_t *) name, true);
- uname = javastring_toutf((java_handle_t *) name, false);
-
- /* name must not contain '/' (mauve test) */
-
- for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
- if (*pos == '/') {
- exceptions_throw_classnotfoundexception(uname);
- return NULL;
- }
- }
-
- /* try to load, ... */
-
- c = load_class_bootstrap(ufile);
-
- if (c == NULL)
- return NULL;
-
- /* link, ... */
-
- if (!link_class(c))
- return NULL;
-
- /* ...and initialize it. */
-
- if (!initialize_class(c))
- return NULL;
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: newInstance
- * Signature: ()Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_Class_newInstance(JNIEnv *env, java_lang_Class* this)
-{
- classinfo *c;
- java_handle_t *o;
-
- c = LLNI_classinfo_unwrap(this);
-
- o = native_new_and_init(c);
-
- return (java_lang_Object *) o;
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: isInstance
- * Signature: (Ljava/lang/Object;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_Class_isInstance(JNIEnv *env, java_lang_Class *this, java_lang_Object *obj)
-{
- classinfo *c;
- java_handle_t *h;
-
- c = LLNI_classinfo_unwrap(this);
- h = (java_handle_t *) obj;
-
- return class_is_instance(c, h);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: isAssignableFrom
- * Signature: (Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_Class_isAssignableFrom(JNIEnv *env, java_lang_Class *this, java_lang_Class *cls)
-{
- classinfo *to;
- classinfo *from;
-
- to = LLNI_classinfo_unwrap(this);
- from = LLNI_classinfo_unwrap(cls);
-
- if (from == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- return class_is_assignable_from(to, from);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: isInterface
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_Class_isInterface(JNIEnv *env, java_lang_Class *this)
-{
- classinfo *c;
-
- c = LLNI_classinfo_unwrap(this);
-
- return class_is_interface(c);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: isArray
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_Class_isArray(JNIEnv *env, java_lang_Class *this)
-{
- classinfo *c;
-
- c = LLNI_classinfo_unwrap(this);
-
- return class_is_array(c);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: getName
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_Class_getName(JNIEnv *env, java_lang_Class *this)
-{
- classinfo *c;
-
- c = LLNI_classinfo_unwrap(this);
-
- return (java_lang_String*) class_get_classname(c);
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_Class.cpp
+
+ Copyright (C) 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 "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Class.h"
+#endif
+
+#include "vm/exceptions.hpp"
+#include "vm/initialize.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Class
+ * Method: forName
+ * Signature: (Ljava/lang/String;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_Class_forName(JNIEnv *env, jclass clazz, jstring name)
+{
+ utf *ufile;
+ utf *uname;
+ classinfo *c;
+ char* pos;
+ int32_t i;
+
+ /* illegal argument */
+
+ if (name == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* create utf string in which '.' is replaced by '/' */
+
+ ufile = javastring_toutf((java_handle_t *) name, true);
+ uname = javastring_toutf((java_handle_t *) name, false);
+
+ /* name must not contain '/' (mauve test) */
+
+ // FIXME Move this check into a function.
+ for (i = 0, pos = uname->text; i < uname->blength; i++, pos++) {
+ if (*pos == '/') {
+ exceptions_throw_classnotfoundexception(uname);
+ return NULL;
+ }
+ }
+
+ /* try to load, ... */
+
+ c = load_class_bootstrap(ufile);
+
+ if (c == NULL)
+ return NULL;
+
+ /* link, ... */
+
+ if (!link_class(c))
+ return NULL;
+
+ /* ...and initialize it. */
+
+ if (!initialize_class(c))
+ return NULL;
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: java/lang/Class
+ * Method: newInstance
+ * Signature: ()Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_Class_newInstance(JNIEnv *env, jclass _this)
+{
+ classinfo *c;
+ java_handle_t *o;
+
+ c = LLNI_classinfo_unwrap(_this);
+
+ o = native_new_and_init(c);
+
+ return (jobject) o;
+}
+
+
+/*
+ * Class: java/lang/Class
+ * Method: isInstance
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Class_isInstance(JNIEnv *env, jclass _this, jobject obj)
+{
+ classinfo *c;
+ java_handle_t *h;
+
+ c = LLNI_classinfo_unwrap(_this);
+ h = (java_handle_t *) obj;
+
+ return class_is_instance(c, h);
+}
+
+
+/*
+ * Class: java/lang/Class
+ * Method: isAssignableFrom
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Class_isAssignableFrom(JNIEnv *env, jclass _this, jclass cls)
+{
+ classinfo *to;
+ classinfo *from;
+
+ to = LLNI_classinfo_unwrap(_this);
+ from = LLNI_classinfo_unwrap(cls);
+
+ if (from == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ return class_is_assignable_from(to, from);
+}
+
+
+/*
+ * Class: java/lang/Class
+ * Method: isInterface
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Class_isInterface(JNIEnv *env, jclass _this)
+{
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(_this);
+
+ return class_is_interface(c);
+}
+
+
+/*
+ * Class: java/lang/Class
+ * Method: isArray
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Class_isArray(JNIEnv *env, jclass _this)
+{
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(_this);
+
+ return class_is_array(c);
+}
+
+
+/*
+ * Class: java/lang/Class
+ * Method: getName
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_Class_getName(JNIEnv *env, jclass _this)
+{
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(_this);
+
+ return (jstring) class_get_classname(c);
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "forName", (char*) "(Ljava/lang/String;)Ljava/lang/Class;",(void*) (uintptr_t) &Java_java_lang_Class_forName },
+ { (char*) "newInstance", (char*) "()Ljava/lang/Object;", (void*) (uintptr_t) &Java_java_lang_Class_newInstance },
+ { (char*) "isInstance", (char*) "(Ljava/lang/Object;)Z", (void*) (uintptr_t) &Java_java_lang_Class_isInstance },
+ { (char*) "isAssignableFrom", (char*) "(Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_Class_isAssignableFrom },
+ { (char*) "isInterface", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_Class_isInterface },
+ { (char*) "isArray", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_Class_isArray },
+ { (char*) "getName", (char*) "()Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_Class_getName },
+};
+
+/* _Jv_java_lang_Class_init ****************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Class_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Class");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Double.c
-
- Copyright (C) 2006, 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
-
- 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 "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Double.h"
-
-#include "vm/builtin.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "doubleToLongBits", "(D)J", (void *) (ptrint) &Java_java_lang_Double_doubleToLongBits },
- { "longBitsToDouble", "(J)D", (void *) (ptrint) &Java_java_lang_Double_longBitsToDouble },
-};
-
-
-/* _Jv_java_lang_Double_init ***************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Double_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Double");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/Double
- * Method: doubleToLongBits
- * Signature: (D)J
- */
-JNIEXPORT s8 JNICALL Java_java_lang_Double_doubleToLongBits(JNIEnv *env, jclass clazz, double doubleValue)
-{
- jvalue val;
- s8 e, f;
- val.d = doubleValue;
-
-#if defined(__IEEE_BYTES_LITTLE_ENDIAN)
- /* On little endian ARM processors when using FPA, word order of
- doubles is still big endian. So take that into account here. When
- using VFP, word order of doubles follows byte order. */
-
-#define SWAP_DOUBLE(a) (((a) << 32) | (((a) >> 32) & 0x00000000ffffffff))
-
- val.j = SWAP_DOUBLE(val.j);
-#endif
-
- e = val.j & 0x7ff0000000000000LL;
- f = val.j & 0x000fffffffffffffLL;
-
- if (e == DBL_POSINF && f != 0L)
- val.j = DBL_NAN;
-
- return val.j;
-}
-
-
-/*
- * Class: java/lang/Double
- * Method: longBitsToDouble
- * Signature: (J)D
- */
-JNIEXPORT double JNICALL Java_java_lang_Double_longBitsToDouble(JNIEnv *env, jclass clazz, s8 longValue)
-{
- jvalue val;
- val.j = longValue;
-
-#if defined(__IEEE_BYTES_LITTLE_ENDIAN)
- val.j = SWAP_DOUBLE(val.j);
-#endif
-
- return val.d;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
--- /dev/null
+/* src/native/vm/cldc1.1/java_lang_Double.c
+
+ Copyright (C) 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 "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Double.h"
+#endif
+
+#include "vm/builtin.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Double
+ * Method: doubleToLongBits
+ * Signature: (D)J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_Double_doubleToLongBits(JNIEnv *env, jclass clazz, jdouble doubleValue)
+{
+ jvalue val;
+ s8 e, f;
+ val.d = doubleValue;
+
+#if defined(__IEEE_BYTES_LITTLE_ENDIAN)
+ /* On little endian ARM processors when using FPA, word order of
+ doubles is still big endian. So take that into account here. When
+ using VFP, word order of doubles follows byte order. */
+
+#define SWAP_DOUBLE(a) (((a) << 32) | (((a) >> 32) & 0x00000000ffffffff))
+
+ val.j = SWAP_DOUBLE(val.j);
+#endif
+
+ e = val.j & 0x7ff0000000000000LL;
+ f = val.j & 0x000fffffffffffffLL;
+
+ if (e == DBL_POSINF && f != 0L)
+ val.j = DBL_NAN;
+
+ return val.j;
+}
+
+
+/*
+ * Class: java/lang/Double
+ * Method: longBitsToDouble
+ * Signature: (J)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Double_longBitsToDouble(JNIEnv *env, jclass clazz, jlong longValue)
+{
+ jvalue val;
+ val.j = longValue;
+
+#if defined(__IEEE_BYTES_LITTLE_ENDIAN)
+ val.j = SWAP_DOUBLE(val.j);
+#endif
+
+ return val.d;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "doubleToLongBits", (char*) "(D)J", (void*) (uintptr_t) &Java_java_lang_Double_doubleToLongBits },
+ { (char*) "longBitsToDouble", (char*) "(J)D", (void*) (uintptr_t) &Java_java_lang_Double_longBitsToDouble },
+};
+
+
+/* _Jv_java_lang_Double_init ***************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Double_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Double");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Float.c
-
- Copyright (C) 2006, 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
-
- 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 "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Float.h"
-
-#include "vm/builtin.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "floatToIntBits", "(F)I", (void *) (ptrint) &Java_java_lang_Float_floatToIntBits },
-};
-
-
-/* _Jv_java_lang_Float_init ****************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Float_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Float");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-/*
- * Class: java/lang/Float
- * Method: floatToIntBits
- * Signature: (F)I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_Float_floatToIntBits(JNIEnv *env, jclass clazz, float value)
-{
- imm_union val;
- int e, f;
-
- val.f = value;
-
- e = val.i & 0x7f800000;
- f = val.i & 0x007fffff;
-
- if (e == FLT_POSINF && f != 0)
- return FLT_NAN;
-
- return val.i;
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_Float.cpp
+
+ Copyright (C) 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 "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Float.h"
+#endif
+
+#include "vm/builtin.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Float
+ * Method: floatToIntBits
+ * Signature: (F)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_Float_floatToIntBits(JNIEnv *env, jclass clazz, jfloat value)
+{
+ imm_union val;
+ int e, f;
+
+ val.f = value;
+
+ e = val.i & 0x7f800000;
+ f = val.i & 0x007fffff;
+
+ if (e == FLT_POSINF && f != 0)
+ return FLT_NAN;
+
+ return val.i;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "floatToIntBits", (char*) "(F)I", (void*) (uintptr_t) &Java_java_lang_Float_floatToIntBits },
+};
+
+
+/* _Jv_java_lang_Float_init ****************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Float_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Float");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Math.c
-
- Copyright (C) 2006, 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
-
- 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 "vm/types.h"
-
-#include "fdlibm/fdlibm.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Math.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "ceil", "(D)D", (void *) (ptrint) &Java_java_lang_Math_ceil },
- { "cos", "(D)D", (void *) (ptrint) &Java_java_lang_Math_cos },
- { "floor", "(D)D", (void *) (ptrint) &Java_java_lang_Math_floor },
- { "sin", "(D)D", (void *) (ptrint) &Java_java_lang_Math_sin },
- { "sqrt", "(D)D", (void *) (ptrint) &Java_java_lang_Math_sqrt },
- { "tan", "(D)D", (void *) (ptrint) &Java_java_lang_Math_tan },
-};
-
-
-/* _Jv_java_lang_Math_init *****************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Math_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Math");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/Math
- * Method: ceil
- * Signature: (D)D
- */
-JNIEXPORT double JNICALL Java_java_lang_Math_ceil(JNIEnv *env, jclass clazz, double a)
-{
- return ceil(a);
-}
-
-
-/*
- * Class: java/lang/Math
- * Method: cos
- * Signature: (D)D
- */
-JNIEXPORT double JNICALL Java_java_lang_Math_cos(JNIEnv *env, jclass clazz, double a)
-{
- return cos(a);
-}
-
-
-/*
- * Class: java/lang/Math
- * Method: floor
- * Signature: (D)D
- */
-JNIEXPORT double JNICALL Java_java_lang_Math_floor(JNIEnv *env, jclass clazz, double a)
-{
- return floor(a);
-}
-
-
-/*
- * Class: java/lang/Math
- * Method: sin
- * Signature: (D)D
- */
-JNIEXPORT double JNICALL Java_java_lang_Math_sin(JNIEnv *env, jclass clazz, double a)
-{
- return sin(a);
-}
-
-
-/*
- * Class: java/lang/Math
- * Method: sqrt
- * Signature: (D)D
- */
-JNIEXPORT double JNICALL Java_java_lang_Math_sqrt(JNIEnv *env, jclass clazz, double a)
-{
- return sqrt(a);
-}
-
-
-/*
- * Class: java/lang/Math
- * Method: tan
- * Signature: (D)D
- */
-JNIEXPORT double JNICALL Java_java_lang_Math_tan(JNIEnv *env, jclass clazz, double a)
-{
- return tan(a);
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_Math.cpp
+
+ Copyright (C) 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 "fdlibm/fdlibm.h"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Math.h"
+#endif
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Math
+ * Method: ceil
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Math_ceil(JNIEnv *env, jclass clazz, jdouble a)
+{
+ return ceil(a);
+}
+
+
+/*
+ * Class: java/lang/Math
+ * Method: cos
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Math_cos(JNIEnv *env, jclass clazz, jdouble a)
+{
+ return cos(a);
+}
+
+
+/*
+ * Class: java/lang/Math
+ * Method: floor
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Math_floor(JNIEnv *env, jclass clazz, jdouble a)
+{
+ return floor(a);
+}
+
+
+/*
+ * Class: java/lang/Math
+ * Method: sin
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Math_sin(JNIEnv *env, jclass clazz, jdouble a)
+{
+ return sin(a);
+}
+
+
+/*
+ * Class: java/lang/Math
+ * Method: sqrt
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Math_sqrt(JNIEnv *env, jclass clazz, jdouble a)
+{
+ return sqrt(a);
+}
+
+
+/*
+ * Class: java/lang/Math
+ * Method: tan
+ * Signature: (D)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_Math_tan(JNIEnv *env, jclass clazz, jdouble a)
+{
+ return tan(a);
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "ceil", (char*) "(D)D", (void*) (uintptr_t) &Java_java_lang_Math_ceil },
+ { (char*) "cos", (char*) "(D)D", (void*) (uintptr_t) &Java_java_lang_Math_cos },
+ { (char*) "floor", (char*) "(D)D", (void*) (uintptr_t) &Java_java_lang_Math_floor },
+ { (char*) "sin", (char*) "(D)D", (void*) (uintptr_t) &Java_java_lang_Math_sin },
+ { (char*) "sqrt", (char*) "(D)D", (void*) (uintptr_t) &Java_java_lang_Math_sqrt },
+ { (char*) "tan", (char*) "(D)D", (void*) (uintptr_t) &Java_java_lang_Math_tan },
+};
+
+
+/* _Jv_java_lang_Math_init *****************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Math_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Math");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Object.c
-
- Copyright (C) 2006, 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
-
- 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 <stdlib.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h" /* required by j.l.C */
-#include "native/include/java_lang_Class.h"
-
-#include "native/include/java_lang_Object.h"
-
-#include "threads/lock-common.h"
-
-#include "vm/exceptions.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getClass", "()Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_Object_getClass },
- { "hashCode", "()I", (void *) (ptrint) &Java_java_lang_Object_hashCode },
- { "notify", "()V", (void *) (ptrint) &Java_java_lang_Object_notify },
- { "notifyAll", "()V", (void *) (ptrint) &Java_java_lang_Object_notifyAll },
- { "wait", "(J)V", (void *) (ptrint) &Java_java_lang_Object_wait },
-};
-
-
-/* _Jv_java_lang_Object_init ***************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Object_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Object");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/Object
- * Method: getClass
- * Signature: ()Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_Object_getClass(JNIEnv *env, java_lang_Object *obj)
-{
- classinfo *c;
-
- if (obj == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- LLNI_class_get(obj, c);
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: java/lang/Object
- * Method: hashCode
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_Object_hashCode(JNIEnv *env, java_lang_Object *this)
-{
-#if defined(ENABLE_GC_CACAO)
- assert(0);
-#else
- return (int32_t) ((intptr_t) this);
-#endif
-}
-
-
-/*
- * Class: java/lang/Object
- * Method: notify
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Object_notify(JNIEnv *env, java_lang_Object *this)
-{
-#if defined(ENABLE_THREADS)
- lock_notify_object((java_handle_t *) this);
-#endif
-}
-
-
-/*
- * Class: java/lang/Object
- * Method: notifyAll
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Object_notifyAll(JNIEnv *env, java_lang_Object *this)
-{
-#if defined(ENABLE_THREADS)
- lock_notify_all_object((java_handle_t *) this);
-#endif
-}
-
-
-/*
- * Class: java/lang/Object
- * Method: wait
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_java_lang_Object_wait(JNIEnv *env, java_lang_Object *this, s8 timeout)
-{
-#if defined(ENABLE_JVMTI)
- /* Monitor Wait */
- if (jvmti) jvmti_MonitorWaiting(true, this, timeout);
-#endif
-
-#if defined(ENABLE_THREADS)
- lock_wait_for_object((java_handle_t *) this, timeout, 0);
-#endif
-
-#if defined(ENABLE_JVMTI)
- /* Monitor Waited */
- /* XXX: How do you know if wait timed out ?*/
- if (jvmti) jvmti_MonitorWaiting(false, this, 0);
-#endif
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_Object.c
+
+ Copyright (C) 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 <stdlib.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Object.h"
+#endif
+
+#include "threads/lock-common.h"
+
+#include "vm/exceptions.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Object
+ * Method: getClass
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_Object_getClass(JNIEnv *env, jobject obj)
+{
+ classinfo *c;
+
+ if (obj == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ LLNI_class_get(obj, c);
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: java/lang/Object
+ * Method: hashCode
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_Object_hashCode(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_GC_CACAO)
+ assert(0);
+#else
+ return (int32_t) ((uintptr_t) _this);
+#endif
+}
+
+
+/*
+ * Class: java/lang/Object
+ * Method: notify
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Object_notify(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ lock_notify_object((java_handle_t *) _this);
+#endif
+}
+
+
+/*
+ * Class: java/lang/Object
+ * Method: notifyAll
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Object_notifyAll(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ lock_notify_all_object((java_handle_t *) _this);
+#endif
+}
+
+
+/*
+ * Class: java/lang/Object
+ * Method: wait
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Object_wait(JNIEnv *env, jobject _this, jlong timeout)
+{
+#if defined(ENABLE_JVMTI)
+ /* Monitor Wait */
+ if (jvmti) jvmti_MonitorWaiting(true, _this, timeout);
+#endif
+
+#if defined(ENABLE_THREADS)
+ lock_wait_for_object((java_handle_t *) _this, timeout, 0);
+#endif
+
+#if defined(ENABLE_JVMTI)
+ /* Monitor Waited */
+ /* XXX: How do you know if wait timed out ?*/
+ if (jvmti) jvmti_MonitorWaiting(false, _this, 0);
+#endif
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getClass", (char*) "()Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_Object_getClass },
+ { (char*) "hashCode", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_Object_hashCode },
+ { (char*) "notify", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Object_notify },
+ { (char*) "notifyAll", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Object_notifyAll },
+ { (char*) "wait", (char*) "(J)V", (void*) (uintptr_t) &Java_java_lang_Object_wait },
+};
+
+
+/* _Jv_java_lang_Object_init ***************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Object_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Object");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Runtime.c
-
- Copyright (C) 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 "mm/gc-common.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Runtime.h"
-
-#include "vm/vm.h"
-
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "exitInternal", "(I)V", (void *) (intptr_t) &Java_java_lang_Runtime_exitInternal },
- { "freeMemory", "()J", (void *) (intptr_t) &Java_java_lang_Runtime_freeMemory },
- { "totalMemory", "()J", (void *) (intptr_t) &Java_java_lang_Runtime_totalMemory },
- { "gc", "()V", (void *) (intptr_t) &Java_java_lang_Runtime_gc },
-};
-
-
-/* _Jv_java_lang_Runtime_init **************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Runtime_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Runtime");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: exitInternal
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_java_lang_Runtime_exitInternal(JNIEnv *env, java_lang_Runtime *this, int32_t status)
-{
- vm_shutdown(status);
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: freeMemory
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_java_lang_Runtime_freeMemory(JNIEnv *env, java_lang_Runtime *this)
-{
- return gc_get_free_bytes();
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: totalMemory
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_java_lang_Runtime_totalMemory(JNIEnv *env, java_lang_Runtime *this)
-{
- return gc_get_heap_size();
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: gc
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Runtime_gc(JNIEnv *env, java_lang_Runtime *this)
-{
- gc_call();
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_Runtime.cpp
+
+ Copyright (C) 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 "mm/gc.hpp"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Runtime.h"
+#endif
+
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Runtime
+ * Method: exitInternal
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Runtime_exitInternal(JNIEnv *env, jobject _this, jint status)
+{
+ vm_shutdown(status);
+}
+
+
+/*
+ * Class: java/lang/Runtime
+ * Method: freeMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_Runtime_freeMemory(JNIEnv *env, jobject _this)
+{
+ return gc_get_free_bytes();
+}
+
+
+/*
+ * Class: java/lang/Runtime
+ * Method: totalMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_Runtime_totalMemory(JNIEnv *env, jobject _this)
+{
+ return gc_get_heap_size();
+}
+
+
+/*
+ * Class: java/lang/Runtime
+ * Method: gc
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Runtime_gc(JNIEnv *env, jobject _this)
+{
+ gc_call();
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "exitInternal", (char*) "(I)V", (void*) (uintptr_t) &Java_java_lang_Runtime_exitInternal },
+ { (char*) "freeMemory", (char*) "()J", (void*) (uintptr_t) &Java_java_lang_Runtime_freeMemory },
+ { (char*) "totalMemory", (char*) "()J", (void*) (uintptr_t) &Java_java_lang_Runtime_totalMemory },
+ { (char*) "gc", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Runtime_gc },
+};
+
+
+/* _Jv_java_lang_Runtime_init **************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Runtime_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Runtime");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_String.c
-
- Copyright (C) 2006, 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
-
- 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 <stdlib.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-
-#include "native/include/java_lang_String.h"
-
-#include "vm/stringlocal.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "hashCode", "()I", (void *) (ptrint) &Java_java_lang_String_hashCode },
- { "indexOf", "(I)I", (void *) (ptrint) &Java_java_lang_String_indexOf__I },
- { "indexOf", "(II)I", (void *) (ptrint) &Java_java_lang_String_indexOf__II },
- { "lastIndexOf", "(I)I", (void *) (ptrint) &Java_java_lang_String_lastIndexOf__I },
- { "lastIndexOf", "(II)I", (void *) (ptrint) &Java_java_lang_String_lastIndexOf__II },
-#if 0
- { "equals", "(Ljava/lang/Object;)Z;", (void *) (ptrint) &Java_java_lang_String_equals },
-#endif
- { "intern", "()Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_String_intern },
-};
-
-
-/* _Jv_java_lang_String_init ***************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_String_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/String");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/String
- * Method: hashCode
- * Signature: ()I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_String_hashCode(JNIEnv *env, java_lang_String *this)
-{
- java_handle_chararray_t *value;
- int32_t offset;
- int32_t count;
- s4 hash;
- s4 i;
-
- /* get values from Java object */
-
- LLNI_field_get_val(this, offset, offset);
- LLNI_field_get_val(this, count, count);
- LLNI_field_get_ref(this, value, value);
-
- hash = 0;
-
- for (i = 0; i < count; i++) {
- hash = (31 * hash) + LLNI_array_direct(value, offset + i);
- }
-
- return hash;
-}
-
-
-/*
- * Class: java/lang/String
- * Method: indexOf
- * Signature: (I)I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_String_indexOf__I(JNIEnv *env, java_lang_String *this, s4 ch)
-{
- java_handle_chararray_t *value;
- int32_t offset;
- int32_t count;
- s4 i;
-
- /* get values from Java object */
-
- LLNI_field_get_val(this, offset, offset);
- LLNI_field_get_val(this, count, count);
- LLNI_field_get_ref(this, value, value);
-
- for (i = 0; i < count; i++) {
- if (LLNI_array_direct(value, offset + i) == ch) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-/*
- * Class: java/lang/String
- * Method: indexOf
- * Signature: (II)I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_String_indexOf__II(JNIEnv *env, java_lang_String *this, s4 ch, s4 fromIndex)
-{
- java_handle_chararray_t *value;
- int32_t offset;
- int32_t count;
- s4 i;
-
- /* get values from Java object */
-
- LLNI_field_get_val(this, offset, offset);
- LLNI_field_get_val(this, count, count);
- LLNI_field_get_ref(this, value, value);
-
- if (fromIndex < 0) {
- fromIndex = 0;
- }
- else if (fromIndex >= count) {
- /* Note: fromIndex might be near -1>>>1. */
- return -1;
- }
-
- for (i = fromIndex ; i < count ; i++) {
- if (LLNI_array_direct(value, offset + i) == ch) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-/*
- * Class: java/lang/String
- * Method: lastIndexOf
- * Signature: (I)I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_String_lastIndexOf__I(JNIEnv *env, java_lang_String *this, s4 ch)
-{
- int32_t count;
-
- LLNI_field_get_val(this, count, count);
-
- return Java_java_lang_String_lastIndexOf__II(env, this, ch, count - 1);
-}
-
-
-/*
- * Class: java/lang/String
- * Method: lastIndexOf
- * Signature: (II)I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_String_lastIndexOf__II(JNIEnv *env, java_lang_String *this, s4 ch, s4 fromIndex)
-{
- java_handle_chararray_t *value;
- int32_t offset;
- int32_t count;
- s4 start;
- s4 i;
-
- /* get values from Java object */
-
- LLNI_field_get_val(this, offset, offset);
- LLNI_field_get_val(this, count, count);
- LLNI_field_get_ref(this, value, value);
-
- start = ((fromIndex >= count) ? count - 1 : fromIndex);
-
- for (i = start; i >= 0; i--) {
- if (LLNI_array_direct(value, offset + i) == ch) {
- return i;
- }
- }
-
- return -1;
-}
-
-
-#if 0
-/*
- * Class: java/lang/String
- * Method: equals
- * Signature: (Ljava/lang/Object;)Z;
- */
-JNIEXPORT s4 JNICALL Java_java_lang_String_equals(JNIEnv *env, java_lang_String* this, java_lang_Object *o)
-{
- java_lang_String* s;
- java_handle_chararray_t *value;
- int32_t offset;
- int32_t count;
- java_handle_chararray_t *dvalue;
- int32_t doffset;
- int32_t dcount;
- classinfo *c;
-
- LLNI_field_get_val(this, offset, offset);
- LLNI_field_get_val(this, count, count);
- LLNI_field_get_ref(this, value, value);
- LLNI_class_get(o, c);
-
- /* TODO: is this the correct implementation for short-circuiting on object identity? */
- if ((java_lang_Object*)this == o)
- return 1;
-
- if (c != class_java_lang_String)
- return 0;
-
- s = (java_lang_String *) o;
- LLNI_field_get_val(this, offset, doffset);
- LLNI_field_get_val(this, count, dcount);
- LLNI_field_get_ref(this, value, dvalue);
-
- if (count != dcount)
- return 0;
-
- return ( 0 == memcmp((void*)(LLNI_array_direct(value, offset)),
- (void*)(LLNI_array_direct(dvalue, doffset),
- count) );
-
-}
-#endif
-
-
-/*
- * Class: java/lang/String
- * Method: intern
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_String_intern(JNIEnv *env, java_lang_String *this)
-{
- if (this == NULL)
- return NULL;
-
- return (java_lang_String *) javastring_intern((java_handle_t *) this);
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_String.cpp
+
+ Copyright (C) 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 <stdlib.h>
+#include <string.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_String.h"
+#endif
+
+#include "vm/javaobjects.hpp"
+#include "vm/string.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/String
+ * Method: hashCode
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_String_hashCode(JNIEnv *env, jstring _this)
+{
+ java_lang_String jls(_this);
+
+ java_handle_chararray_t* value = jls.get_value();
+ int32_t offset = jls.get_offset();
+ int32_t count = jls.get_count();
+
+ int32_t hash = 0;
+
+ for (int32_t i = 0; i < count; i++) {
+ hash = (31 * hash) + LLNI_array_direct(value, offset + i);
+ }
+
+ return hash;
+}
+
+
+/*
+ * Class: java/lang/String
+ * Method: indexOf
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_String_indexOf__I(JNIEnv *env, jstring _this, jint ch)
+{
+ java_lang_String jls(_this);
+
+ java_handle_chararray_t* value = jls.get_value();
+ int32_t offset = jls.get_offset();
+ int32_t count = jls.get_count();
+
+ for (int32_t i = 0; i < count; i++) {
+ if (LLNI_array_direct(value, offset + i) == ch) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/*
+ * Class: java/lang/String
+ * Method: indexOf
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_String_indexOf__II(JNIEnv *env, jstring _this, jint ch, jint fromIndex)
+{
+ java_lang_String jls(_this);
+
+ java_handle_chararray_t* value = jls.get_value();
+ int32_t offset = jls.get_offset();
+ int32_t count = jls.get_count();
+
+ if (fromIndex < 0) {
+ fromIndex = 0;
+ }
+ else if (fromIndex >= count) {
+ // Note: fromIndex might be near -1>>>1.
+ return -1;
+ }
+
+ for (int32_t i = fromIndex ; i < count ; i++) {
+ if (LLNI_array_direct(value, offset + i) == ch) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/*
+ * Class: java/lang/String
+ * Method: lastIndexOf
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_String_lastIndexOf__II(JNIEnv *env, jstring _this, jint ch, jint fromIndex)
+{
+ java_lang_String jls(_this);
+
+ java_handle_chararray_t* value = jls.get_value();
+ int32_t offset = jls.get_offset();
+ int32_t count = jls.get_count();
+
+ int32_t start = ((fromIndex >= count) ? count - 1 : fromIndex);
+
+ for (int32_t i = start; i >= 0; i--) {
+ if (LLNI_array_direct(value, offset + i) == ch) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/*
+ * Class: java/lang/String
+ * Method: lastIndexOf
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_String_lastIndexOf__I(JNIEnv *env, jstring _this, jint ch)
+{
+ java_lang_String jls(_this);
+
+ return Java_java_lang_String_lastIndexOf__II(env, _this, ch, jls.get_count() - 1);
+}
+
+
+/*
+ * Class: java/lang/String
+ * Method: intern
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_String_intern(JNIEnv *env, jstring _this)
+{
+ java_lang_String jls(_this);
+
+ if (jls.is_null())
+ return NULL;
+
+ return (jstring) javastring_intern(jls.get_handle());
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "hashCode", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_String_hashCode },
+ { (char*) "indexOf", (char*) "(I)I", (void*) (uintptr_t) &Java_java_lang_String_indexOf__I },
+ { (char*) "indexOf", (char*) "(II)I", (void*) (uintptr_t) &Java_java_lang_String_indexOf__II },
+ { (char*) "lastIndexOf", (char*) "(II)I", (void*) (uintptr_t) &Java_java_lang_String_lastIndexOf__II },
+ { (char*) "lastIndexOf", (char*) "(I)I", (void*) (uintptr_t) &Java_java_lang_String_lastIndexOf__I },
+#if 0
+ { (char*) "equals", (char*) "(Ljava/lang/Object;)Z;", (void*) (uintptr_t) &Java_java_lang_String_equals },
+#endif
+ { (char*) "intern", (char*) "()Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_String_intern },
+};
+
+
+/* _Jv_java_lang_String_init ***************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_String_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/String");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_System.c
-
- Copyright (C) 2006, 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
-
- 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 <stdlib.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-
-#include "native/include/java_lang_System.h"
-
-#include "vm/builtin.h"
-#include "vm/properties.h"
-#include "vm/stringlocal.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", (void *) (ptrint) &Java_java_lang_System_arraycopy },
- { "getProperty0", "(Ljava/lang/String;)Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_System_getProperty0 },
-};
-
-
-/* _Jv_java_lang_System_init ***************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_System_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/System");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/System
- * Method: arraycopy
- * Signature: (Ljava/lang/Object;ILjava/lang/Object;II)V
- */
-JNIEXPORT void JNICALL Java_java_lang_System_arraycopy(JNIEnv *env, jclass clazz, java_lang_Object *src, s4 srcStart, java_lang_Object *dest, s4 destStart, s4 len)
-{
- builtin_arraycopy((java_handle_t *) src, srcStart,
- (java_handle_t *) dest, destStart, len);
-}
-
-
-/*
- * Class: java/lang/System
- * Method: getProperty0
- * Signature: (Ljava/lang/String;)Ljava/lang/String;
- */
-
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_System_getProperty0(JNIEnv *env, jclass clazz, java_lang_String *s)
-{
- java_handle_t *so;
- char* key;
- char* value;
- java_handle_t *result;
-
- so = (java_handle_t *) s;
-
- /* build an ASCII string out of the java/lang/String passed */
-
- key = javastring_tochar(so);
-
- /* get the property from the internal table */
-
- value = properties_get(key);
-
- /* release the memory allocated in javastring_tochar */
-
- MFREE(key, char, 0);
-
- if (value == NULL)
- return NULL;
-
- result = javastring_new_from_ascii(value);
-
- return (java_lang_String *) result;
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_System.cpp
+
+ Copyright (C) 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 <stdlib.h>
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_System.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/properties.h"
+#include "vm/string.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/System
+ * Method: arraycopy
+ * Signature: (Ljava/lang/Object;ILjava/lang/Object;II)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_System_arraycopy(JNIEnv *env, jclass clazz, jobject src, jint srcStart, jobject dest, jint destStart, jint len)
+{
+ builtin_arraycopy((java_handle_t *) src, srcStart,
+ (java_handle_t *) dest, destStart, len);
+}
+
+
+/*
+ * Class: java/lang/System
+ * Method: getProperty0
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+
+JNIEXPORT jstring JNICALL Java_java_lang_System_getProperty0(JNIEnv *env, jclass clazz, jstring s)
+{
+ java_handle_t *so;
+ char* key;
+ const char* value;
+ java_handle_t *result;
+
+ so = (java_handle_t *) s;
+
+ /* build an ASCII string out of the java/lang/String passed */
+
+ key = javastring_tochar(so);
+
+ /* get the property from the internal table */
+
+ value = properties_get(key);
+
+ /* release the memory allocated in javastring_tochar */
+
+ MFREE(key, char, 0);
+
+ if (value == NULL)
+ return NULL;
+
+ result = javastring_new_from_ascii(value);
+
+ return (jstring) result;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "arraycopy", (char*) "(Ljava/lang/Object;ILjava/lang/Object;II)V", (void*) (uintptr_t) &Java_java_lang_System_arraycopy },
+ { (char*) "getProperty0", (char*) "(Ljava/lang/String;)Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_System_getProperty0 },
+};
+
+
+/* _Jv_java_lang_System_init ***************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_System_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/System");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Thread.c
-
- Copyright (C) 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 "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Thread.h"
-
-#include "threads/thread.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "currentThread", "()Ljava/lang/Thread;", (void *) (ptrint) &Java_java_lang_Thread_currentThread },
- { "setPriority0", "(II)V", (void *) (ptrint) &Java_java_lang_Thread_setPriority0 },
- { "sleep", "(J)V", (void *) (ptrint) &Java_java_lang_Thread_sleep },
- { "start0", "()V", (void *) (ptrint) &Java_java_lang_Thread_start0 },
- { "isAlive", "()Z", (void *) (ptrint) &Java_java_lang_Thread_isAlive },
-#if 0
- { "activeCount", "()I", (void *) (ptrint) &Java_java_lang_Thread_activeCount },
- { "setPriority0", "(II)V", (void *) (ptrint) &Java_java_lang_Thread_setPriority0 },
- { "interrupt0", "()V", (void *) (ptrint) &Java_java_lang_Thread_interrupt0 },
- { "internalExit", "()V", (void *) (ptrint) &Java_java_lang_Thread_internalExit },
-#endif
- { "yield", "()V", (void *) (ptrint) &Java_java_lang_Thread_yield },
-};
-
-
-/* _Jv_java_lang_Thread_init ***************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Thread_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Thread");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: currentThread
- * Signature: ()Ljava/lang/Thread;
- */
-JNIEXPORT java_lang_Thread* JNICALL Java_java_lang_Thread_currentThread(JNIEnv *env, jclass clazz)
-{
- java_lang_Thread *to;
-
- to = (java_lang_Thread *) thread_get_current_object();
-
- return to;
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: setPriority0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_lang_Thread_setPriority0(JNIEnv *env, java_lang_Thread *this, s4 oldPriority, s4 newPriority)
-{
-#if defined(ENABLE_THREADS)
- threadobject *t;
-
- t = (threadobject *) this->vm_thread;
-
- /* The threadobject is null when a thread is created in Java. The
- priority is set later during startup. */
-
- if (t == NULL)
- return;
-
- threads_set_thread_priority(t->tid, newPriority);
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: sleep
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_java_lang_Thread_sleep(JNIEnv *env, jclass clazz, s8 millis)
-{
-#if defined(ENABLE_THREADS)
- threads_sleep(millis, 0);
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: start0
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Thread_start0(JNIEnv *env, java_lang_Thread *this)
-{
-#if defined(ENABLE_THREADS)
- threads_thread_start((java_handle_t *) this);
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: isAlive
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_Thread_isAlive(JNIEnv *env, java_lang_Thread *this)
-{
-#if defined(ENABLE_THREADS)
- threadobject *t;
- bool result;
-
- t = (threadobject *) this->vm_thread;
-
- if (t == NULL)
- return 0;
-
- result = threads_thread_is_alive(t);
-
- return result;
-#else
- /* If threads are disabled, the only thread running is alive. */
-
- return 1;
-#endif
-}
-
-
-#if 0
-/*
- * Class: java/lang/Thread
- * Method: activeCount
- * Signature: ()I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_Thread_activeCount(JNIEnv *env, jclass clazz)
-{
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: setPriority0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_lang_Thread_setPriority0(JNIEnv *env, struct java_lang_Thread* this, s4 par1, s4 par2)
-{
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: interrupt0
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Thread_interrupt0(JNIEnv *env, struct java_lang_Thread* this)
-{
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: internalExit
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Thread_internalExit(JNIEnv *env, struct java_lang_Thread* this)
-{
-}
-#endif
-
-
-/*
- * Class: java/lang/Thread
- * Method: yield
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Thread_yield(JNIEnv *env, jclass clazz)
-{
-#if defined(ENABLE_THREADS)
- threads_yield();
-#endif
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_Thread.cpp
+
+ Copyright (C) 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 "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Thread.h"
+#endif
+
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
+#include "vm/javaobjects.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Thread
+ * Method: currentThread
+ * Signature: ()Ljava/lang/Thread;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_Thread_currentThread(JNIEnv *env, jclass clazz)
+{
+ return (jobject) thread_get_current_object();
+}
+
+
+/*
+ * Class: java/lang/Thread
+ * Method: setPriority0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_setPriority0(JNIEnv *env, jobject _this, jint oldPriority, jint newPriority)
+{
+#if defined(ENABLE_THREADS)
+ java_lang_Thread jlt(_this);
+ threadobject* t = jlt.get_vm_thread();
+
+ // The threadobject is null when a thread is created in Java. The
+ // priority is set later during startup.
+ if (t == NULL)
+ return;
+
+ threads_set_thread_priority(t->tid, newPriority);
+#endif
+}
+
+
+/*
+ * Class: java/lang/Thread
+ * Method: sleep
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_sleep(JNIEnv *env, jclass clazz, jlong millis)
+{
+#if defined(ENABLE_THREADS)
+ threads_sleep(millis, 0);
+#endif
+}
+
+
+/*
+ * Class: java/lang/Thread
+ * Method: start0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_start0(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ java_lang_Thread jlt(_this);
+ threads_thread_start(jlt.get_handle());
+#endif
+}
+
+
+/*
+ * Class: java/lang/Thread
+ * Method: isAlive
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_Thread_isAlive(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ java_lang_Thread jlt(_this);
+ threadobject* t = jlt.get_vm_thread();
+
+ if (t == NULL)
+ return 0;
+
+ bool result = threads_thread_is_alive(t);
+
+ return result;
+#else
+ // If threads are disabled, the only thread running is alive.
+ return 1;
+#endif
+}
+
+
+#if 0
+/*
+ * Class: java/lang/Thread
+ * Method: activeCount
+ * Signature: ()I
+ */
+JNIEXPORT s4 JNICALL Java_java_lang_Thread_activeCount(JNIEnv *env, jclass clazz)
+{
+}
+
+
+/*
+ * Class: java/lang/Thread
+ * Method: interrupt0
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_interrupt0(JNIEnv *env, jobject _this)
+{
+}
+
+
+/*
+ * Class: java/lang/Thread
+ * Method: internalExit
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_internalExit(JNIEnv *env, jobject _this)
+{
+}
+#endif
+
+
+/*
+ * Class: java/lang/Thread
+ * Method: yield
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Thread_yield(JNIEnv *env, jclass clazz)
+{
+#if defined(ENABLE_THREADS)
+ threads_yield();
+#endif
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "currentThread", (char*) "()Ljava/lang/Thread;", (void*) (uintptr_t) &Java_java_lang_Thread_currentThread },
+ { (char*) "setPriority0", (char*) "(II)V", (void*) (uintptr_t) &Java_java_lang_Thread_setPriority0 },
+ { (char*) "sleep", (char*) "(J)V", (void*) (uintptr_t) &Java_java_lang_Thread_sleep },
+ { (char*) "start0", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_start0 },
+ { (char*) "isAlive", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_Thread_isAlive },
+#if 0
+ { (char*) "activeCount", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_Thread_activeCount },
+ { (char*) "setPriority0", (char*) "(II)V", (void*) (uintptr_t) &Java_java_lang_Thread_setPriority0 },
+ { (char*) "interrupt0", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_interrupt0 },
+ { (char*) "internalExit", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_internalExit },
+#endif
+ { (char*) "yield", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Thread_yield },
+};
+
+
+/* _Jv_java_lang_Thread_init ***************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Thread_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Thread");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/cldc1.1/java_lang_Throwable.c - java/lang/Throwable
-
- Copyright (C) 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 <stdint.h>
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Throwable.h"
-
-#include "vm/exceptions.h"
-#include "vm/jit/stacktrace.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "printStackTrace", "()V", (void *) (uintptr_t) &Java_java_lang_Throwable_printStackTrace },
- { "fillInStackTrace", "()V", (void *) (uintptr_t) &Java_java_lang_Throwable_fillInStackTrace },
-};
-
-
-/* _Jv_java_lang_Throwable_init ************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_Throwable_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/Throwable");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/Throwable
- * Method: printStackTrace
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Throwable_printStackTrace(JNIEnv *env, java_lang_Throwable *this)
-{
- java_handle_t *o;
-
- o = (java_handle_t *) this;
-
- exceptions_print_exception(o);
- stacktrace_print_exception(o);
-}
-
-
-/*
- * Class: java/lang/Throwable
- * Method: fillInStackTrace
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_Throwable_fillInStackTrace(JNIEnv *env, java_lang_Throwable *this)
-{
- java_handle_bytearray_t *ba;
-
- ba = stacktrace_get_current();
-
- if (ba == NULL)
- return;
-
- LLNI_field_set_ref(this, backtrace, (java_lang_Object *) ba);
-}
-
-
-/*
- * 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/native/vm/cldc1.1/java_lang_Throwable.cpp
+
+ Copyright (C) 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 <stdint.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_lang_Throwable.h"
+#endif
+
+#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
+
+#include "vm/jit/stacktrace.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/Throwable
+ * Method: printStackTrace
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Throwable_printStackTrace(JNIEnv *env, jobject _this)
+{
+ java_lang_Throwable jlt(_this);
+
+ exceptions_print_exception(jlt.get_handle());
+ stacktrace_print_exception(jlt.get_handle());
+}
+
+
+/*
+ * Class: java/lang/Throwable
+ * Method: fillInStackTrace
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_Throwable_fillInStackTrace(JNIEnv *env, jobject _this)
+{
+ java_handle_bytearray_t* ba = stacktrace_get_current();
+
+ if (ba == NULL)
+ return;
+
+ java_lang_Throwable jlt(_this);
+ jlt.set_backtrace(ba);
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "printStackTrace", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Throwable_printStackTrace },
+ { (char*) "fillInStackTrace", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_Throwable_fillInStackTrace },
+};
+
+
+/* _Jv_java_lang_Throwable_init ************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_Throwable_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/Throwable");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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:
+ */
-## src/native/vm/gnu/Makefile.am
+## src/native/vm/gnuclasspath/Makefile.am
##
## Copyright (C) 1996-2005, 2006, 2008
## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
if ENABLE_ANNOTATIONS
SUN_REFLECT_SOURCES = \
- sun_reflect_ConstantPool.c
+ sun_reflect_ConstantPool.cpp
endif
libnativevmcore_la_SOURCES = \
- gnu_classpath_VMStackWalker.c \
- gnu_classpath_VMSystemProperties.c \
- gnu_java_lang_VMCPStringBuilder.c \
- gnu_java_lang_management_VMClassLoadingMXBeanImpl.c \
- gnu_java_lang_management_VMMemoryMXBeanImpl.c \
- gnu_java_lang_management_VMRuntimeMXBeanImpl.c \
- gnu_java_lang_management_VMThreadMXBeanImpl.c \
- java_lang_VMClass.c \
- java_lang_VMClassLoader.c \
- java_lang_VMObject.c \
- java_lang_VMRuntime.c \
- java_lang_VMString.c \
- java_lang_VMSystem.c \
- java_lang_VMThread.c \
- java_lang_VMThrowable.c \
+ gnu_classpath_VMStackWalker.cpp \
+ gnu_classpath_VMSystemProperties.cpp \
+ gnu_java_lang_VMCPStringBuilder.cpp \
+ gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp \
+ gnu_java_lang_management_VMMemoryMXBeanImpl.cpp \
+ gnu_java_lang_management_VMRuntimeMXBeanImpl.cpp \
+ gnu_java_lang_management_VMThreadMXBeanImpl.cpp \
+ java_lang_VMClass.cpp \
+ java_lang_VMClassLoader.cpp \
+ java_lang_VMObject.cpp \
+ java_lang_VMRuntime.cpp \
+ java_lang_VMString.cpp \
+ java_lang_VMSystem.cpp \
+ java_lang_VMThread.cpp \
+ java_lang_VMThrowable.cpp \
java_lang_management_VMManagementFactory.c \
- java_lang_reflect_VMConstructor.c \
- java_lang_reflect_VMField.c \
- java_lang_reflect_VMMethod.c \
+ java_lang_reflect_VMConstructor.cpp \
+ java_lang_reflect_VMField.cpp \
+ java_lang_reflect_VMMethod.cpp \
java_lang_reflect_VMProxy.c \
- java_security_VMAccessController.c \
- java_util_concurrent_atomic_AtomicLong.c \
+ java_security_VMAccessController.cpp \
+ java_util_concurrent_atomic_AtomicLong.cpp \
$(SUN_REFLECT_SOURCES)
if ENABLE_JVMTI
+++ /dev/null
-/* src/native/vm/gnu/gnu_classpath_VMStackWalker.c
-
- 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 "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_ClassLoader.h"
-
-#include "native/include/gnu_classpath_VMStackWalker.h"
-
-#include "vm/global.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getClassContext", "()[Ljava/lang/Class;", (void *) (ptrint) &Java_gnu_classpath_VMStackWalker_getClassContext },
- { "getCallingClass", "()Ljava/lang/Class;", (void *) (ptrint) &Java_gnu_classpath_VMStackWalker_getCallingClass },
- { "getCallingClassLoader", "()Ljava/lang/ClassLoader;", (void *) (ptrint) &Java_gnu_classpath_VMStackWalker_getCallingClassLoader },
- { "firstNonNullClassLoader", "()Ljava/lang/ClassLoader;", (void *) (ptrint) &Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader },
-};
-
-
-/* _Jv_gnu_classpath_VMStackWalker_init ****************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_gnu_classpath_VMStackWalker_init(void)
-{
- utf *u;
-
- u = utf_new_char("gnu/classpath/VMStackWalker");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: gnu/classpath/VMStackWalker
- * Method: getClassContext
- * Signature: ()[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_gnu_classpath_VMStackWalker_getClassContext(JNIEnv *env, jclass clazz)
-{
- java_handle_objectarray_t *oa;
-
- oa = stacktrace_getClassContext();
-
- return oa;
-}
-
-
-/*
- * Class: gnu/classpath/VMStackWalker
- * Method: getCallingClass
- * Signature: ()Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_gnu_classpath_VMStackWalker_getCallingClass(JNIEnv *env, jclass clazz)
-{
- classinfo *c;
-
- c = stacktrace_get_caller_class(2);
-
- return (java_lang_Class *) c;
-}
-
-
-/*
- * Class: gnu/classpath/VMStackWalker
- * Method: getCallingClassLoader
- * Signature: ()Ljava/lang/ClassLoader;
- */
-JNIEXPORT java_lang_ClassLoader* JNICALL Java_gnu_classpath_VMStackWalker_getCallingClassLoader(JNIEnv *env, jclass clazz)
-{
- classinfo *c;
- classloader_t *cl;
-
- c = stacktrace_get_caller_class(2);
- cl = class_get_classloader(c);
-
- return (java_lang_ClassLoader *) cl;
-}
-
-
-/*
- * Class: gnu/classpath/VMStackWalker
- * Method: firstNonNullClassLoader
- * Signature: ()Ljava/lang/ClassLoader;
- */
-JNIEXPORT java_lang_ClassLoader* JNICALL Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader(JNIEnv *env, jclass clazz)
-{
- classloader_t *cl;
-
- cl = stacktrace_first_nonnull_classloader();
-
- return (java_lang_ClassLoader *) cl;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/gnu_classpath_VMStackWalker.cpp
+
+ 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 "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/gnu_classpath_VMStackWalker.h"
+#endif
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/utf8.h"
+
+#include "vm/jit/stacktrace.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: gnu/classpath/VMStackWalker
+ * Method: getClassContext
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_gnu_classpath_VMStackWalker_getClassContext(JNIEnv *env, jclass clazz)
+{
+ java_handle_objectarray_t *oa;
+
+ oa = stacktrace_getClassContext();
+
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: gnu/classpath/VMStackWalker
+ * Method: getCallingClass
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_gnu_classpath_VMStackWalker_getCallingClass(JNIEnv *env, jclass clazz)
+{
+ classinfo *c;
+
+ c = stacktrace_get_caller_class(2);
+
+ return (jclass) c;
+}
+
+
+/*
+ * Class: gnu/classpath/VMStackWalker
+ * Method: getCallingClassLoader
+ * Signature: ()Ljava/lang/ClassLoader;
+ */
+JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_getCallingClassLoader(JNIEnv *env, jclass clazz)
+{
+ classinfo *c;
+ classloader_t *cl;
+
+ c = stacktrace_get_caller_class(2);
+ cl = class_get_classloader(c);
+
+ return (jobject) cl;
+}
+
+
+/*
+ * Class: gnu/classpath/VMStackWalker
+ * Method: firstNonNullClassLoader
+ * Signature: ()Ljava/lang/ClassLoader;
+ */
+JNIEXPORT jobject JNICALL Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader(JNIEnv *env, jclass clazz)
+{
+ classloader_t *cl;
+
+ cl = stacktrace_first_nonnull_classloader();
+
+ return (jobject) cl;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getClassContext", (char*) "()[Ljava/lang/Class;", (void*) (uintptr_t) &Java_gnu_classpath_VMStackWalker_getClassContext },
+ { (char*) "getCallingClass", (char*) "()Ljava/lang/Class;", (void*) (uintptr_t) &Java_gnu_classpath_VMStackWalker_getCallingClass },
+ { (char*) "getCallingClassLoader", (char*) "()Ljava/lang/ClassLoader;", (void*) (uintptr_t) &Java_gnu_classpath_VMStackWalker_getCallingClassLoader },
+ { (char*) "firstNonNullClassLoader", (char*) "()Ljava/lang/ClassLoader;", (void*) (uintptr_t) &Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader },
+};
+
+
+/* _Jv_gnu_classpath_VMStackWalker_init ****************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_gnu_classpath_VMStackWalker_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/classpath/VMStackWalker");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/gnu_classpath_VMSystemProperties.c
-
- 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 <stdlib.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_util_Properties.h"
-
-#include "native/include/gnu_classpath_VMSystemProperties.h"
-
-#include "vm/exceptions.h"
-#include "vm/properties.h"
-#include "vm/vm.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "preInit", "(Ljava/util/Properties;)V", (void *) (ptrint) &Java_gnu_classpath_VMSystemProperties_preInit },
- { "postInit", "(Ljava/util/Properties;)V", (void *) (ptrint) &Java_gnu_classpath_VMSystemProperties_postInit },
-};
-
-
-/* _Jv_gnu_classpat_VMSystemProperties_init ************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_gnu_classpath_VMSystemProperties_init(void)
-{
- utf *u;
-
- u = utf_new_char("gnu/classpath/VMSystemProperties");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: gnu/classpath/VMSystemProperties
- * Method: preInit
- * Signature: (Ljava/util/Properties;)V
- */
-JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_preInit(JNIEnv *env, jclass clazz, java_util_Properties *properties)
-{
- java_handle_t *p;
-
- p = (java_handle_t *) properties;
-
- if (p == NULL) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- /* fill the java.util.Properties object */
-
- properties_system_add_all(p);
-}
-
-
-/*
- * Class: gnu/classpath/VMSystemProperties
- * Method: postInit
- * Signature: (Ljava/util/Properties;)V
- */
-JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_postInit(JNIEnv *env, jclass clazz, java_util_Properties *properties)
-{
- java_handle_t *p;
-#if defined(ENABLE_JRE_LAYOUT)
- char *java_home;
- char *path;
- s4 len;
-#endif
-
- p = (java_handle_t *) properties;
-
- if (p == NULL) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- /* post-set some properties */
-
-#if defined(ENABLE_JRE_LAYOUT)
- /* XXX when we do it that way, we can't set these properties on
- commandline */
-
- java_home = properties_get("java.home");
-
- properties_system_add(p, "gnu.classpath.home", java_home);
-
- len =
- strlen("file://") +
- strlen(java_home) +
- strlen("/lib") +
- strlen("0");
-
- path = MNEW(char, len);
-
- strcpy(path, "file://");
- strcat(path, java_home);
- strcat(path, "/lib");
-
- properties_system_add(p, "gnu.classpath.home.url", path);
-
- MFREE(path, char, len);
-#endif
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/gnu_classpath_VMSystemProperties.cpp
+
+ 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 <stdlib.h>
+#include <string.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/gnu_classpath_VMSystemProperties.h"
+#endif
+
+#include "vm/exceptions.hpp"
+#include "vm/properties.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: gnu/classpath/VMSystemProperties
+ * Method: preInit
+ * Signature: (Ljava/util/Properties;)V
+ */
+JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_preInit(JNIEnv *env, jclass clazz, jobject properties)
+{
+ java_handle_t *p;
+
+ p = (java_handle_t *) properties;
+
+ if (p == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ /* fill the java.util.Properties object */
+
+ properties_system_add_all(p);
+}
+
+
+/*
+ * Class: gnu/classpath/VMSystemProperties
+ * Method: postInit
+ * Signature: (Ljava/util/Properties;)V
+ */
+JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_postInit(JNIEnv *env, jclass clazz, jobject properties)
+{
+ java_handle_t *p;
+#if defined(ENABLE_JRE_LAYOUT)
+ const char *java_home;
+ char *path;
+ s4 len;
+#endif
+
+ p = (java_handle_t *) properties;
+
+ if (p == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ /* post-set some properties */
+
+#if defined(ENABLE_JRE_LAYOUT)
+ /* XXX when we do it that way, we can't set these properties on
+ commandline */
+
+ java_home = properties_get("java.home");
+
+ properties_system_add(p, "gnu.classpath.home", java_home);
+
+ len =
+ strlen("file://") +
+ strlen(java_home) +
+ strlen("/lib") +
+ strlen("0");
+
+ path = MNEW(char, len);
+
+ strcpy(path, "file://");
+ strcat(path, java_home);
+ strcat(path, "/lib");
+
+ properties_system_add(p, "gnu.classpath.home.url", path);
+
+ MFREE(path, char, len);
+#endif
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "preInit", (char*) "(Ljava/util/Properties;)V", (void*) (uintptr_t) &Java_gnu_classpath_VMSystemProperties_preInit },
+ { (char*) "postInit", (char*) "(Ljava/util/Properties;)V", (void*) (uintptr_t) &Java_gnu_classpath_VMSystemProperties_postInit },
+};
+
+
+/* _Jv_gnu_classpat_VMSystemProperties_init ************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_gnu_classpath_VMSystemProperties_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/classpath/VMSystemProperties");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_reflect_VMConstructor.c
-
- 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 "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h"
-
-#include "native/include/gnu_java_lang_VMCPStringBuilder.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "toString", "([CII)Ljava/lang/String;", (void *) (intptr_t) &Java_gnu_java_lang_VMCPStringBuilder_toString },
-};
-
-
-/* _Jv_gnu_java_lang_VMCPStringBuilder *****************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_gnu_java_lang_VMCPStringBuilder_init(void)
-{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/VMCPStringBuilder");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: gnu/java/lang/VMCPStringBuilder
- * Method: toString
- * Signature: ([CII)Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_gnu_java_lang_VMCPStringBuilder_toString(JNIEnv *env, jclass clazz, java_handle_chararray_t *value, int32_t startIndex, int32_t count)
-{
- int32_t length;
- java_handle_t *o;
- java_lang_String *s;
-
- /* This is a native version of
- java.lang.String.<init>([CIIZ)Ljava/lang/String; */
-
- if (startIndex < 0) {
-/* exceptions_throw_stringindexoutofboundsexception("offset: " + offset); */
- exceptions_throw_stringindexoutofboundsexception();
- return NULL;
- }
-
- if (count < 0) {
-/* exceptions_throw_stringindexoutofboundsexception("count: " + count); */
- exceptions_throw_stringindexoutofboundsexception();
- return NULL;
- }
-
- /* equivalent to: offset + count < 0 || offset + count > data.length */
-
- LLNI_CRITICAL_START;
- length = LLNI_array_size(value);
- LLNI_CRITICAL_END;
-
- if (length - startIndex < count) {
-/* exceptions_throw_stringindexoutofboundsexception("offset + count: " + (offset + count)); */
- exceptions_throw_stringindexoutofboundsexception();
- return NULL;
- }
-
- o = builtin_new(class_java_lang_String);
-
- if (o == NULL)
- return NULL;
-
- s = (java_lang_String *) o;
-
- LLNI_field_set_ref(s, value, value);
- LLNI_field_set_val(s, count, count);
- LLNI_field_set_val(s, offset, startIndex);
-
- return s;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/gnu_java_lang_VMCPStringBuilder.cpp
+
+ Copyright (C) 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 "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/gnu_java_lang_VMCPStringBuilder.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+
+
+/*
+ * Class: gnu/java/lang/VMCPStringBuilder
+ * Method: toString
+ * Signature: ([CII)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_gnu_java_lang_VMCPStringBuilder_toString(JNIEnv *env, jclass clazz, jcharArray value, jint startIndex, jint count)
+{
+ /* This is a native version of
+ java.lang.String.<init>([CIIZ)Ljava/lang/String; */
+
+ if (startIndex < 0) {
+/* exceptions_throw_stringindexoutofboundsexception("offset: " + offset); */
+ exceptions_throw_stringindexoutofboundsexception();
+ return NULL;
+ }
+
+ if (count < 0) {
+/* exceptions_throw_stringindexoutofboundsexception("count: " + count); */
+ exceptions_throw_stringindexoutofboundsexception();
+ return NULL;
+ }
+
+ /* equivalent to: offset + count < 0 || offset + count > data.length */
+
+ java_handle_chararray_t* ca = (java_handle_chararray_t*) value;
+
+ LLNI_CRITICAL_START;
+ int32_t length = LLNI_array_size(ca);
+ LLNI_CRITICAL_END;
+
+ if (length - startIndex < count) {
+/* exceptions_throw_stringindexoutofboundsexception("offset + count: " + (offset + count)); */
+ exceptions_throw_stringindexoutofboundsexception();
+ return NULL;
+ }
+
+ java_handle_t* h = builtin_new(class_java_lang_String);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_String s(h, ca, (int32_t) count, (int32_t) startIndex);
+
+ return (jstring) s.get_handle();
+}
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "toString", (char*) "([CII)Ljava/lang/String;", (void*) (uintptr_t) &Java_gnu_java_lang_VMCPStringBuilder_toString },
+};
+
+
+/* _Jv_gnu_java_lang_VMCPStringBuilder *****************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_gnu_java_lang_VMCPStringBuilder_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/java/lang/VMCPStringBuilder");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/gnu_java_lang_management_VMClassLoadingMXBeanImpl.c
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 "mm/gc-common.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/gnu_java_lang_management_VMClassLoadingMXBeanImpl.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/vm.h"
-
-#include "vmcore/classcache.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getLoadedClassCount", "()I", (void *) (intptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getLoadedClassCount },
- { "getUnloadedClassCount", "()J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount },
- { "isVerbose", "()Z", (void *) (intptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose },
- { "setVerbose", "(Z)V", (void *) (intptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose },
-};
-
-
-/* _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init ******************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init(void)
-{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/management/VMClassLoadingMXBeanImpl");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
- * Method: getLoadedClassCount
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getLoadedClassCount(JNIEnv *env, jclass clazz)
-{
- int32_t count;
-
- count = classcache_get_loaded_class_count();
-
- return count;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
- * Method: getUnloadedClassCount
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount(JNIEnv *env, jclass clazz)
-{
- log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
- * Method: isVerbose
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
-{
- return _Jv_jvm->Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
- * Method: setVerbose
- * Signature: (Z)V
- */
-JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, int32_t verbose)
-{
- _Jv_jvm->Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose = verbose;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp
+
+ 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 "mm/gc.hpp"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/gnu_java_lang_management_VMClassLoadingMXBeanImpl.h"
+#endif
+
+#include "toolbox/logging.h"
+
+#include "vm/classcache.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
+ * Method: getLoadedClassCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getLoadedClassCount(JNIEnv *env, jclass clazz)
+{
+ int32_t count;
+
+ count = classcache_get_loaded_class_count();
+
+ return count;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
+ * Method: getUnloadedClassCount
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount(JNIEnv *env, jclass clazz)
+{
+ log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
+ * Method: isVerbose
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
+{
+/* return _Jv_jvm->Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose; */
+#warning Move to C++
+ log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose: MOVE TO C++!");
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMClassLoadingMXBeanImpl
+ * Method: setVerbose
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, jboolean verbose)
+{
+/* _Jv_jvm->Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose = verbose; */
+#warning Move to C++
+ log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose: MOVE TO C++!");
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getLoadedClassCount", (char*) "()I", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getLoadedClassCount },
+ { (char*) "getUnloadedClassCount", (char*) "()J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount },
+ { (char*) "isVerbose", (char*) "()Z", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose },
+ { (char*) "setVerbose", (char*) "(Z)V", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose },
+};
+
+
+/* _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init ******************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/java/lang/management/VMClassLoadingMXBeanImpl");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/gnu_java_lang_management_VMMemoryMXBeanImpl.c
-
- 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 "mm/gc-common.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_management_MemoryUsage.h"
-
-#include "native/include/gnu_java_lang_management_VMMemoryMXBeanImpl.h"
-
-#include "vm/builtin.h"
-#include "vm/global.h"
-#include "vm/vm.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h" /* XXX only for load_class_bootstrap */
-#include "vmcore/options.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getHeapMemoryUsage", "()Ljava/lang/management/MemoryUsage;", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage },
- { "getNonHeapMemoryUsage", "()Ljava/lang/management/MemoryUsage;", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage },
- { "getObjectPendingFinalizationCount", "()I", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount },
- { "isVerbose", "()Z", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose },
- { "setVerbose", "(Z)V", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose },
-};
-
-
-/* _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init ************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init(void)
-{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/management/VMMemoryMXBeanImpl");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
- * Method: getHeapMemoryUsage
- * Signature: ()Ljava/lang/management/MemoryUsage;
- */
-JNIEXPORT java_lang_management_MemoryUsage* JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage(JNIEnv *env, jclass clazz)
-{
- classinfo *class_java_lang_management_MemoryUsage;
- java_handle_t *o;
- java_lang_management_MemoryUsage *mu;
- methodinfo *m;
- int64_t init;
- int64_t used;
- int64_t commited;
- int64_t maximum;
-
- /* get the class */
- /* XXX optimize me! sometime... */
-
- if (!(class_java_lang_management_MemoryUsage = load_class_bootstrap(utf_new_char("java/lang/management/MemoryUsage"))))
- return false;
-
- /* create the object */
-
- o = builtin_new(class_java_lang_management_MemoryUsage);
-
- if (o == NULL)
- return NULL;
-
- /* cast the object to a MemoryUsage object (for debugability) */
-
- mu = (java_lang_management_MemoryUsage *) o;
-
- /* find initializer */
-
- m = class_findmethod(class_java_lang_management_MemoryUsage,
- utf_init, utf_new_char("(JJJJ)V"));
-
- /* initializer not found */
-
- if (m == NULL)
- return NULL;
-
- /* get values from the VM */
- /* XXX if we ever support more than one VM, change this */
-
- init = opt_heapstartsize;
- used = gc_get_total_bytes();
- commited = gc_get_heap_size();
- maximum = gc_get_max_heap_size();
-
- /* call initializer */
-
- (void) vm_call_method(m, o, init, used, commited, maximum);
-
- return mu;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
- * Method: getNonHeapMemoryUsage
- * Signature: ()Ljava/lang/management/MemoryUsage;
- */
-JNIEXPORT java_lang_management_MemoryUsage* JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage(JNIEnv *env, jclass clazz)
-{
- log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
- * Method: getObjectPendingFinalizationCount
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount(JNIEnv *env, jclass clazz)
-{
- log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
- * Method: isVerbose
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
-{
- return _Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
- * Method: setVerbose
- * Signature: (Z)V
- */
-JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, int32_t verbose)
-{
- _Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose = verbose;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/gnu_java_lang_management_VMMemoryMXBeanImpl.cpp
+
+ 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 "mm/gc.hpp"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/gnu_java_lang_management_VMMemoryMXBeanImpl.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h" /* XXX only for load_class_bootstrap */
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
+ * Method: getHeapMemoryUsage
+ * Signature: ()Ljava/lang/management/MemoryUsage;
+ */
+JNIEXPORT jobject JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage(JNIEnv *env, jclass clazz)
+{
+ classinfo *class_java_lang_management_MemoryUsage;
+ java_handle_t *o;
+ methodinfo *m;
+ int64_t init;
+ int64_t used;
+ int64_t commited;
+ int64_t maximum;
+
+ /* get the class */
+ /* XXX optimize me! sometime... */
+
+ if (!(class_java_lang_management_MemoryUsage = load_class_bootstrap(utf_new_char("java/lang/management/MemoryUsage"))))
+ return false;
+
+ /* create the object */
+
+ o = builtin_new(class_java_lang_management_MemoryUsage);
+
+ if (o == NULL)
+ return NULL;
+
+ /* find initializer */
+
+ m = class_findmethod(class_java_lang_management_MemoryUsage,
+ utf_init, utf_new_char("(JJJJ)V"));
+
+ /* initializer not found */
+
+ if (m == NULL)
+ return NULL;
+
+ /* get values from the VM */
+ /* XXX if we ever support more than one VM, change this */
+
+ init = opt_heapstartsize;
+ used = gc_get_total_bytes();
+ commited = gc_get_heap_size();
+ maximum = gc_get_max_heap_size();
+
+ /* call initializer */
+
+ (void) vm_call_method(m, o, init, used, commited, maximum);
+
+ return (jobject) o;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
+ * Method: getNonHeapMemoryUsage
+ * Signature: ()Ljava/lang/management/MemoryUsage;
+ */
+JNIEXPORT jobject JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage(JNIEnv *env, jclass clazz)
+{
+ log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
+ * Method: getObjectPendingFinalizationCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount(JNIEnv *env, jclass clazz)
+{
+ log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
+ * Method: isVerbose
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
+{
+/* return _Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose; */
+#warning Move to C++
+ log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose: MOVE TO C++!");
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMMemoryMXBeanImpl
+ * Method: setVerbose
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, jboolean verbose)
+{
+/* _Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose = verbose; */
+#warning Move to C++
+ log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose: MOVE TO C++!");
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getHeapMemoryUsage", (char*) "()Ljava/lang/management/MemoryUsage;", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage },
+ { (char*) "getNonHeapMemoryUsage", (char*) "()Ljava/lang/management/MemoryUsage;", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage },
+ { (char*) "getObjectPendingFinalizationCount", (char*) "()I", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount },
+ { (char*) "isVerbose", (char*) "()Z", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose },
+ { (char*) "setVerbose", (char*) "(Z)V", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose },
+};
+
+
+/* _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init ************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/java/lang/management/VMMemoryMXBeanImpl");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/gnu_java_lang_management_VMRuntimeMXBeanImpl.c
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/gnu_java_lang_management_VMRuntimeMXBeanImpl.h"
-
-#include "vm/builtin.h"
-#include "vm/global.h"
-#include "vm/vm.h"
-
-#include "vmcore/class.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getInputArguments", "()[Ljava/lang/String;", (void *) (intptr_t) &Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments },
- { "getStartTime", "()J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime },
-};
-
-
-/* _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init ***********************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init(void)
-{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/management/VMRuntimeMXBeanImpl");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMRuntimeMXBeanImpl
- * Method: getInputArguments
- * Signature: ()[Ljava/lang/String;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments(JNIEnv *env, jclass clazz)
-{
- log_println("Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments: IMPLEMENT ME!");
-
- return builtin_anewarray(0, class_java_lang_String);
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMRuntimeMXBeanImpl
- * Method: getStartTime
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime(JNIEnv *env, jclass clazz)
-{
- return _Jv_jvm->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:
- */
--- /dev/null
+/* src/native/vm/gnuclasspath/gnu_java_lang_management_VMRuntimeMXBeanImpl.cpp
+
+ 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 "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/gnu_java_lang_management_VMRuntimeMXBeanImpl.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: gnu/java/lang/management/VMRuntimeMXBeanImpl
+ * Method: getInputArguments
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments(JNIEnv *env, jclass clazz)
+{
+ log_println("Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments: IMPLEMENT ME!");
+
+ return builtin_anewarray(0, class_java_lang_String);
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMRuntimeMXBeanImpl
+ * Method: getStartTime
+ * Signature: ()J
+ */
+JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime(JNIEnv *env, jclass clazz)
+{
+ return vm->get_starttime();
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getInputArguments", (char*) "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getInputArguments },
+ { (char*) "getStartTime", (char*) "()J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime },
+};
+
+
+/* _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init ***********************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/java/lang/management/VMRuntimeMXBeanImpl");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/gnu_java_lang_management_VMThreadMXBeanImpl.c
-
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- 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 "mm/gc-common.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Throwable.h"
-#include "native/include/java_lang_management_ThreadInfo.h"
-
-#include "native/include/gnu_java_lang_management_VMThreadMXBeanImpl.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/vm.h"
-
-#include "vmcore/classcache.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "findMonitorDeadlockedThreads", "()[J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_findMonitorDeadlockedThreads },
- { "getCurrentThreadCpuTime", "()J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadCpuTime },
- { "getCurrentThreadUserTime", "()J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadUserTime },
- { "getPeakThreadCount", "()I", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getPeakThreadCount },
- { "getThreadCpuTime", "(J)J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadCpuTime },
- { "getThreadInfoForId", "(JI)Ljava/lang/management/ThreadInfo;", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadInfoForId },
- { "getThreadUserTime", "(J)J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadUserTime },
- { "getTotalStartedThreadCount", "()J", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTotalStartedThreadCount },
- { "resetPeakThreadCount", "()V", (void *) (intptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount },
-};
-
-
-/* _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init ************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init(void)
-{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/management/VMThreadMXBeanImpl");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: findMonitorDeadlockedThreads
- * Signature: ()[J
- */
-JNIEXPORT java_handle_longarray_t* JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_findMonitorDeadlockedThreads(JNIEnv *env, jclass clazz)
-{
- log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_findMonitorDeadlockedThreads: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: getCurrentThreadCpuTime
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadCpuTime(JNIEnv *env, jclass clazz)
-{
- log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadCpuTime: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: getCurrentThreadUserTime
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadUserTime(JNIEnv *env, jclass clazz)
-{
- log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadUserTime: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: getPeakThreadCount
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getPeakThreadCount(JNIEnv *env, jclass clazz)
-{
- return _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: getThreadCpuTime
- * Signature: (J)J
- */
-JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadCpuTime(JNIEnv *env, jclass clazz, int64_t id)
-{
- log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadCpuTime: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: getThreadInfoForId
- * Signature: (JI)Ljava/lang/management/ThreadInfo;
- */
-JNIEXPORT java_lang_management_ThreadInfo* JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadInfoForId(JNIEnv *env, jclass clazz, int64_t id, int32_t maxDepth)
-{
- log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadInfoForId: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: getThreadUserTime
- * Signature: (J)J
- */
-JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadUserTime(JNIEnv *env, jclass clazz, int64_t par1)
-{
- log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadUserTime: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: getTotalStartedThreadCount
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTotalStartedThreadCount(JNIEnv *env, jclass clazz)
-{
- return _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount;
-}
-
-
-/*
- * Class: gnu/java/lang/management/VMThreadMXBeanImpl
- * Method: resetPeakThreadCount
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount(JNIEnv *env, jclass clazz)
-{
- _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
- _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp
+
+ Copyright (C) 1996-2005, 2006, 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 "mm/gc.hpp"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/gnu_java_lang_management_VMThreadMXBeanImpl.h"
+#endif
+
+#include "toolbox/logging.h"
+
+#include "vm/classcache.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: findMonitorDeadlockedThreads
+ * Signature: ()[J
+ */
+JNIEXPORT jlongArray JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_findMonitorDeadlockedThreads(JNIEnv *env, jclass clazz)
+{
+ log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_findMonitorDeadlockedThreads: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: getCurrentThreadCpuTime
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadCpuTime(JNIEnv *env, jclass clazz)
+{
+ log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadCpuTime: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: getCurrentThreadUserTime
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadUserTime(JNIEnv *env, jclass clazz)
+{
+ log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadUserTime: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: getPeakThreadCount
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getPeakThreadCount(JNIEnv *env, jclass clazz)
+{
+/* return _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount; */
+#warning Move to C++
+ log_println("Java_gnu_java_lang_management_ThreadMXBean_getPeakThreadCount: MOVE TO C++!");
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: getThreadCpuTime
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadCpuTime(JNIEnv *env, jclass clazz, jlong id)
+{
+ log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadCpuTime: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: getThreadInfoForId
+ * Signature: (JI)Ljava/lang/management/ThreadInfo;
+ */
+JNIEXPORT jobject JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadInfoForId(JNIEnv *env, jclass clazz, jlong id, jint maxDepth)
+{
+ log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadInfoForId: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: getThreadUserTime
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadUserTime(JNIEnv *env, jclass clazz, jlong par1)
+{
+ log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadUserTime: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: getTotalStartedThreadCount
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTotalStartedThreadCount(JNIEnv *env, jclass clazz)
+{
+/* return _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount; */
+#warning Move to C++
+ log_println("Java_gnu_java_lang_management_ThreadMXBean_getTotalStartedThreadCount: MOVE TO C++!");
+ return 0;
+}
+
+
+/*
+ * Class: gnu/java/lang/management/VMThreadMXBeanImpl
+ * Method: resetPeakThreadCount
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount(JNIEnv *env, jclass clazz)
+{
+/* _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
+/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
+#warning Move to C++
+ log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount: MOVE TO C++!");
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "findMonitorDeadlockedThreads", (char*) "()[J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_findMonitorDeadlockedThreads },
+ { (char*) "getCurrentThreadCpuTime", (char*) "()J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadCpuTime },
+ { (char*) "getCurrentThreadUserTime", (char*) "()J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurrentThreadUserTime },
+ { (char*) "getPeakThreadCount", (char*) "()I", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getPeakThreadCount },
+ { (char*) "getThreadCpuTime", (char*) "(J)J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadCpuTime },
+ { (char*) "getThreadInfoForId", (char*) "(JI)Ljava/lang/management/ThreadInfo;", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadInfoForId },
+ { (char*) "getThreadUserTime", (char*) "(J)J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThreadUserTime },
+ { (char*) "getTotalStartedThreadCount", (char*) "()J", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTotalStartedThreadCount },
+ { (char*) "resetPeakThreadCount", (char*) "()V", (void*) (uintptr_t) &Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount },
+};
+
+
+/* _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init ************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/java/lang/management/VMThreadMXBeanImpl");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnuclasspath/java_lang_VMClass.c
-
- Copyright (C) 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 "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_ClassLoader.h"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Throwable.h"
-#include "native/include/java_lang_reflect_Constructor.h"
-#include "native/include/java_lang_reflect_Method.h"
-
-#include "native/include/java_lang_VMClass.h"
-
-#include "vm/exceptions.h"
-#include "vm/initialize.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/class.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "native/include/sun_reflect_ConstantPool.h"
-
-#include "vm/vm.h"
-
-#include "vmcore/annotation.h"
-#endif
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "isInstance", "(Ljava/lang/Class;Ljava/lang/Object;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isInstance },
- { "isAssignableFrom", "(Ljava/lang/Class;Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isAssignableFrom },
- { "isInterface", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isInterface },
- { "isPrimitive", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isPrimitive },
- { "getName", "(Ljava/lang/Class;)Ljava/lang/String;", (void *) (uintptr_t) &Java_java_lang_VMClass_getName },
- { "getSuperclass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getSuperclass },
- { "getInterfaces", "(Ljava/lang/Class;)[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getInterfaces },
- { "getComponentType", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getComponentType },
- { "getModifiers", "(Ljava/lang/Class;Z)I", (void *) (uintptr_t) &Java_java_lang_VMClass_getModifiers },
- { "getDeclaringClass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaringClass },
- { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredClasses },
- { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredFields },
- { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredMethods },
- { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredConstructors },
- { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;", (void *) (uintptr_t) &Java_java_lang_VMClass_getClassLoader },
- { "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_forName },
- { "isArray", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isArray },
- { "throwException", "(Ljava/lang/Throwable;)V", (void *) (uintptr_t) &Java_java_lang_VMClass_throwException },
-#if defined(ENABLE_ANNOTATIONS)
- { "getDeclaredAnnotations", "(Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredAnnotations },
-#endif
- { "getEnclosingClass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getEnclosingClass },
- { "getEnclosingConstructor", "(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", (void *) (uintptr_t) &Java_java_lang_VMClass_getEnclosingConstructor },
- { "getEnclosingMethod", "(Ljava/lang/Class;)Ljava/lang/reflect/Method;", (void *) (uintptr_t) &Java_java_lang_VMClass_getEnclosingMethod },
- { "getClassSignature", "(Ljava/lang/Class;)Ljava/lang/String;", (void *) (uintptr_t) &Java_java_lang_VMClass_getClassSignature },
- { "isAnonymousClass", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isAnonymousClass },
- { "isLocalClass", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isLocalClass },
- { "isMemberClass", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isMemberClass },
-};
-
-
-/* _Jv_java_lang_VMClass_init **************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMClass_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMClass");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isInstance
- * Signature: (Ljava/lang/Class;Ljava/lang/Object;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Object *o)
-{
- classinfo *c;
- java_handle_t *h;
-
- c = LLNI_classinfo_unwrap(klass);
- h = (java_handle_t *) o;
-
- return class_is_instance(c, h);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isAssignableFrom
- * Signature: (Ljava/lang/Class;Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Class *c)
-{
- classinfo *to;
- classinfo *from;
-
- to = LLNI_classinfo_unwrap(klass);
- from = LLNI_classinfo_unwrap(c);
-
- if (from == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- return class_is_assignable_from(to, from);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isInterface
- * Signature: (Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
-
- c = LLNI_classinfo_unwrap(klass);
-
- return class_is_interface(c);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isPrimitive
- * Signature: (Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
-
- c = LLNI_classinfo_unwrap(klass);
-
- return class_is_primitive(c);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getName
- * Signature: (Ljava/lang/Class;)Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo* c;
-
- c = LLNI_classinfo_unwrap(klass);
-
- return (java_lang_String*) class_get_classname(c);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getSuperclass
- * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
- classinfo *super;
-
- c = LLNI_classinfo_unwrap(klass);
-
- super = class_get_superclass(c);
-
- return LLNI_classinfo_wrap(super);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getInterfaces
- * Signature: (Ljava/lang/Class;)[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getInterfaces(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- c = LLNI_classinfo_unwrap(klass);
-
- oa = class_get_interfaces(c);
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getComponentType
- * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getComponentType(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
- classinfo *component;
-
- c = LLNI_classinfo_unwrap(klass);
-
- component = class_get_componenttype(c);
-
- return LLNI_classinfo_wrap(component);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getModifiers
- * Signature: (Ljava/lang/Class;Z)I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_getModifiers(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t ignoreInnerClassesAttrib)
-{
- classinfo *c;
- int32_t flags;
-
- c = LLNI_classinfo_unwrap(klass);
-
- flags = class_get_modifiers(c, ignoreInnerClassesAttrib);
-
- return flags;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getDeclaringClass
- * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getDeclaringClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
- classinfo *dc;
-
- c = LLNI_classinfo_unwrap(klass);
-
- dc = class_get_declaringclass(c);
-
- return LLNI_classinfo_wrap(dc);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getDeclaredClasses
- * Signature: (Ljava/lang/Class;Z)[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- c = LLNI_classinfo_unwrap(klass);
-
- oa = class_get_declaredclasses(c, publicOnly);
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getDeclaredFields
- * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- c = LLNI_classinfo_unwrap(klass);
-
- oa = class_get_declaredfields(c, publicOnly);
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getDeclaredMethods
- * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- c = LLNI_classinfo_unwrap(klass);
-
- oa = class_get_declaredmethods(c, publicOnly);
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getDeclaredConstructors
- * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- c = LLNI_classinfo_unwrap(klass);
-
- oa = class_get_declaredconstructors(c, publicOnly);
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getClassLoader
- * Signature: (Ljava/lang/Class;)Ljava/lang/ClassLoader;
- */
-JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
- classloader_t *cl;
-
- c = LLNI_classinfo_unwrap(klass);
- cl = class_get_classloader(c);
-
- return (java_lang_ClassLoader *) cl;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: forName
- * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *name, int32_t initialize, java_lang_ClassLoader *loader)
-{
- classloader_t *cl;
- utf *ufile;
- utf *uname;
- classinfo *c;
- u2 *pos;
- int32_t i;
-
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- /* illegal argument */
-
- if (name == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* create utf string in which '.' is replaced by '/' */
-
- ufile = javastring_toutf((java_handle_t *) name, true);
- uname = javastring_toutf((java_handle_t *) name, false);
-
- /* name must not contain '/' (mauve test) */
-
- for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
- if (*pos == '/') {
- exceptions_throw_classnotfoundexception(uname);
- return NULL;
- }
- }
-
- /* try to load, ... */
-
- c = load_class_from_classloader(ufile, cl);
-
- if (c == NULL)
- return NULL;
-
- /* link, ... */
-
- if (!link_class(c))
- return NULL;
-
- /* ...and initialize it, if required */
-
- if (initialize)
- if (!initialize_class(c))
- return NULL;
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isArray
- * Signature: (Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
-
- c = LLNI_classinfo_unwrap(klass);
-
- return class_is_array(c);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: throwException
- * Signature: (Ljava/lang/Throwable;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(JNIEnv *env, jclass clazz, java_lang_Throwable *t)
-{
- java_handle_t *o;
-
- o = (java_handle_t *) t;
-
- exceptions_set_exception(o);
-}
-
-
-#if defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/VMClass
- * Method: getDeclaredAnnotations
- * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredAnnotations(JNIEnv *env, jclass clazz, java_lang_Class* klass)
-{
- classinfo *c = NULL; /* classinfo for the java.lang.Class object 'klass' */
- static methodinfo *m_parseAnnotationsIntoArray = NULL; /* parser method (cached, therefore static) */
- utf *utf_parseAnnotationsIntoArray = NULL; /* parser method name */
- utf *utf_desc = NULL; /* parser method descriptor (signature) */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- sun_reflect_ConstantPool *constantPool = NULL; /* constant pool of klass */
- java_lang_Object *constantPoolOop = (java_lang_Object*)klass; /* constantPoolOop field of */
- /* sun.reflect.ConstantPool */
-
- if (klass == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- c = LLNI_classinfo_unwrap(klass);
-
- /* get annotations: */
- annotations = class_get_annotations(c);
-
- constantPool =
- (sun_reflect_ConstantPool*)native_new_and_init(
- class_sun_reflect_ConstantPool);
-
- if (constantPool == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
-
- /* only resolve the parser method the first time */
- if (m_parseAnnotationsIntoArray == NULL) {
- utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
- utf_desc = utf_new_char(
- "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
- "[Ljava/lang/annotation/Annotation;");
-
- if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
- /* out of memory */
- return NULL;
- }
-
- m_parseAnnotationsIntoArray = class_resolveclassmethod(
- class_sun_reflect_annotation_AnnotationParser,
- utf_parseAnnotationsIntoArray,
- utf_desc,
- class_java_lang_Class,
- true);
-
- if (m_parseAnnotationsIntoArray == NULL) {
- /* method not found */
- return NULL;
- }
- }
-
- return (java_handle_objectarray_t*)vm_call_method(
- m_parseAnnotationsIntoArray, NULL,
- annotations, constantPool, klass);
-}
-#endif
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getEnclosingClass
- * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_getEnclosingClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo *c;
- classinfo *result;
-
- c = LLNI_classinfo_unwrap(klass);
-
- result = class_get_enclosingclass(c);
-
- return LLNI_classinfo_wrap(result);
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getEnclosingConstructor
- * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
- */
-JNIEXPORT java_lang_reflect_Constructor* JNICALL Java_java_lang_VMClass_getEnclosingConstructor(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo* c;
- java_handle_t* h;
-
- c = LLNI_classinfo_unwrap(klass);
- h = class_get_enclosingconstructor(c);
-
- return (java_lang_reflect_Constructor*) h;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getEnclosingMethod
- * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
- */
-JNIEXPORT java_lang_reflect_Method* JNICALL Java_java_lang_VMClass_getEnclosingMethod(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- classinfo* c;
- java_handle_t* h;
-
- c = LLNI_classinfo_unwrap(klass);
- h = class_get_enclosingmethod(c);
-
- return (java_lang_reflect_Method*) h;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: getClassSignature
- * Signature: (Ljava/lang/Class;)Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getClassSignature(JNIEnv *env, jclass clazz, java_lang_Class* klass)
-{
- classinfo *c;
- utf *u;
- java_handle_t *s;
-
- c = LLNI_classinfo_unwrap(klass);
-
- u = class_get_signature(c);
-
- if (u == NULL)
- return NULL;
-
- s = javastring_new(u);
-
- /* in error case s is NULL */
-
- return (java_lang_String *) s;
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isAnonymousClass
- * Signature: (Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isAnonymousClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- return class_is_anonymousclass(LLNI_classinfo_unwrap(klass));
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isLocalClass
- * Signature: (Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- return class_is_localclass(LLNI_classinfo_unwrap(klass));
-}
-
-
-/*
- * Class: java/lang/VMClass
- * Method: isMemberClass
- * Signature: (Ljava/lang/Class;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, java_lang_Class *klass)
-{
- return class_is_memberclass(LLNI_classinfo_unwrap(klass));
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMClass.cpp
+
+ Copyright (C) 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 "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMClass.h"
+#endif
+
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/string.hpp"
+
+#if defined(ENABLE_ANNOTATIONS)
+#include "vm/annotation.h"
+#include "vm/vm.hpp"
+#endif
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isInstance
+ * Signature: (Ljava/lang/Class;Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, jclass klass, jobject o)
+{
+ classinfo *c;
+ java_handle_t *h;
+
+ c = LLNI_classinfo_unwrap(klass);
+ h = (java_handle_t *) o;
+
+ return class_is_instance(c, h);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isAssignableFrom
+ * Signature: (Ljava/lang/Class;Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, jclass klass, jclass c)
+{
+ classinfo *to;
+ classinfo *from;
+
+ to = LLNI_classinfo_unwrap(klass);
+ from = LLNI_classinfo_unwrap(c);
+
+ if (from == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ return class_is_assignable_from(to, from);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isInterface
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ return class_is_interface(c);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isPrimitive
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isPrimitive(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ return class_is_primitive(c);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getName
+ * Signature: (Ljava/lang/Class;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo* c;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ return (jstring) class_get_classname(c);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getSuperclass
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getSuperclass(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+ classinfo *super;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ super = class_get_superclass(c);
+
+ return (jclass) LLNI_classinfo_wrap(super);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getInterfaces
+ * Signature: (Ljava/lang/Class;)[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClass_getInterfaces(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_interfaces(c);
+
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getComponentType
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getComponentType(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+ classinfo *component;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ component = class_get_componenttype(c);
+
+ return (jclass) LLNI_classinfo_wrap(component);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getModifiers
+ * Signature: (Ljava/lang/Class;Z)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMClass_getModifiers(JNIEnv *env, jclass clazz, jclass klass, jboolean ignoreInnerClassesAttrib)
+{
+ classinfo *c;
+ int32_t flags;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ flags = class_get_modifiers(c, ignoreInnerClassesAttrib);
+
+ return flags;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaringClass
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getDeclaringClass(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+ classinfo *dc;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ dc = class_get_declaringclass(c);
+
+ return (jclass) LLNI_classinfo_wrap(dc);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredClasses
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, jclass klass, jboolean publicOnly)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_declaredclasses(c, publicOnly);
+
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredFields
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, jclass klass, jboolean publicOnly)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_declaredfields(c, publicOnly);
+
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredMethods
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, jclass klass, jboolean publicOnly)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_declaredmethods(c, publicOnly);
+
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredConstructors
+ * Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, jclass klass, jboolean publicOnly)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_declaredconstructors(c, publicOnly);
+
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getClassLoader
+ * Signature: (Ljava/lang/Class;)Ljava/lang/ClassLoader;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+ classloader_t *cl;
+
+ c = LLNI_classinfo_unwrap(klass);
+ cl = class_get_classloader(c);
+
+ return (jobject) cl;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: forName
+ * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, jstring name, jboolean initialize, jobject loader)
+{
+ classloader_t *cl;
+ utf *ufile;
+ utf *uname;
+ classinfo *c;
+ char* pos;
+ int32_t i;
+
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ /* illegal argument */
+
+ if (name == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* create utf string in which '.' is replaced by '/' */
+
+ ufile = javastring_toutf((java_handle_t *) name, true);
+ uname = javastring_toutf((java_handle_t *) name, false);
+
+ /* name must not contain '/' (mauve test) */
+
+ // FIXME Move this check into a function.
+ for (i = 0, pos = uname->text; i < uname->blength; i++, pos++) {
+ if (*pos == '/') {
+ exceptions_throw_classnotfoundexception(uname);
+ return NULL;
+ }
+ }
+
+ /* try to load, ... */
+
+ c = load_class_from_classloader(ufile, cl);
+
+ if (c == NULL)
+ return NULL;
+
+ /* link, ... */
+
+ if (!link_class(c))
+ return NULL;
+
+ /* ...and initialize it, if required */
+
+ if (initialize)
+ if (!initialize_class(c))
+ return NULL;
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isArray
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isArray(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ return class_is_array(c);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: throwException
+ * Signature: (Ljava/lang/Throwable;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMClass_throwException(JNIEnv *env, jclass clazz, jobject t)
+{
+ java_handle_t *o;
+
+ o = (java_handle_t *) t;
+
+ exceptions_set_exception(o);
+}
+
+
+#if defined(ENABLE_ANNOTATIONS)
+/*
+ * Class: java/lang/VMClass
+ * Method: getDeclaredAnnotations
+ * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_VMClass_getDeclaredAnnotations(JNIEnv *env, jclass clazz, jclass klass)
+{
+ static methodinfo* m_parseAnnotationsIntoArray = NULL;
+
+ if (klass == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ classinfo* c = LLNI_classinfo_unwrap(klass);
+
+ /* get annotations: */
+ java_handle_bytearray_t* annotations = class_get_annotations(c);
+
+ java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
+
+ if (h == NULL)
+ return NULL;
+
+ sun_reflect_ConstantPool cp(h);
+ cp.set_constantPoolOop(klass);
+
+ /* only resolve the parser method the first time */
+ if (m_parseAnnotationsIntoArray == NULL) {
+ utf* utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
+ utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
+ "[Ljava/lang/annotation/Annotation;");
+
+ if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+
+ m_parseAnnotationsIntoArray = class_resolveclassmethod(
+ class_sun_reflect_annotation_AnnotationParser,
+ utf_parseAnnotationsIntoArray,
+ utf_desc,
+ class_java_lang_Class,
+ true);
+
+ if (m_parseAnnotationsIntoArray == NULL) {
+ /* method not found */
+ return NULL;
+ }
+ }
+
+ java_handle_objectarray_t* oa = (java_handle_objectarray_t*) vm_call_method(m_parseAnnotationsIntoArray, NULL, annotations, cp.get_handle(), klass);
+ return (jobjectArray) oa;
+}
+#endif
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getEnclosingClass
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClass_getEnclosingClass(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+ classinfo *result;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ result = class_get_enclosingclass(c);
+
+ return (jclass) LLNI_classinfo_wrap(result);
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getEnclosingConstructor
+ * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getEnclosingConstructor(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo* c;
+ java_handle_t* h;
+
+ c = LLNI_classinfo_unwrap(klass);
+ h = class_get_enclosingconstructor(c);
+
+ return (jobject) h;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getEnclosingMethod
+ * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClass_getEnclosingMethod(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo* c;
+ java_handle_t* h;
+
+ c = LLNI_classinfo_unwrap(klass);
+ h = class_get_enclosingmethod(c);
+
+ return (jobject) h;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: getClassSignature
+ * Signature: (Ljava/lang/Class;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_VMClass_getClassSignature(JNIEnv *env, jclass clazz, jclass klass)
+{
+ classinfo *c;
+ utf *u;
+ java_handle_t *s;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ u = class_get_signature(c);
+
+ if (u == NULL)
+ return NULL;
+
+ s = javastring_new(u);
+
+ /* in error case s is NULL */
+
+ return (jstring) s;
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isAnonymousClass
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isAnonymousClass(JNIEnv *env, jclass clazz, jclass klass)
+{
+ return class_is_anonymousclass(LLNI_classinfo_unwrap(klass));
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isLocalClass
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isLocalClass(JNIEnv *env, jclass clazz, jclass klass)
+{
+ return class_is_localclass(LLNI_classinfo_unwrap(klass));
+}
+
+
+/*
+ * Class: java/lang/VMClass
+ * Method: isMemberClass
+ * Signature: (Ljava/lang/Class;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClass_isMemberClass(JNIEnv *env, jclass clazz, jclass klass)
+{
+ return class_is_memberclass(LLNI_classinfo_unwrap(klass));
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "isInstance", (char*) "(Ljava/lang/Class;Ljava/lang/Object;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isInstance },
+ { (char*) "isAssignableFrom", (char*) "(Ljava/lang/Class;Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isAssignableFrom },
+ { (char*) "isInterface", (char*) "(Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isInterface },
+ { (char*) "isPrimitive", (char*) "(Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isPrimitive },
+ { (char*) "getName", (char*) "(Ljava/lang/Class;)Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_VMClass_getName },
+ { (char*) "getSuperclass", (char*) "(Ljava/lang/Class;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClass_getSuperclass },
+ { (char*) "getInterfaces", (char*) "(Ljava/lang/Class;)[Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClass_getInterfaces },
+ { (char*) "getComponentType", (char*) "(Ljava/lang/Class;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClass_getComponentType },
+ { (char*) "getModifiers", (char*) "(Ljava/lang/Class;Z)I", (void*) (uintptr_t) &Java_java_lang_VMClass_getModifiers },
+ { (char*) "getDeclaringClass", (char*) "(Ljava/lang/Class;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClass_getDeclaringClass },
+ { (char*) "getDeclaredClasses", (char*) "(Ljava/lang/Class;Z)[Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClass_getDeclaredClasses },
+ { (char*) "getDeclaredFields", (char*) "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;", (void*) (uintptr_t) &Java_java_lang_VMClass_getDeclaredFields },
+ { (char*) "getDeclaredMethods", (char*) "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;", (void*) (uintptr_t) &Java_java_lang_VMClass_getDeclaredMethods },
+ { (char*) "getDeclaredConstructors", (char*) "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;", (void*) (uintptr_t) &Java_java_lang_VMClass_getDeclaredConstructors },
+ { (char*) "getClassLoader", (char*) "(Ljava/lang/Class;)Ljava/lang/ClassLoader;", (void*) (uintptr_t) &Java_java_lang_VMClass_getClassLoader },
+ { (char*) "forName", (char*) "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClass_forName },
+ { (char*) "isArray", (char*) "(Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isArray },
+ { (char*) "throwException", (char*) "(Ljava/lang/Throwable;)V", (void*) (uintptr_t) &Java_java_lang_VMClass_throwException },
+#if defined(ENABLE_ANNOTATIONS)
+ { (char*) "getDeclaredAnnotations", (char*) "(Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;", (void*) (uintptr_t) &Java_java_lang_VMClass_getDeclaredAnnotations },
+#endif
+ { (char*) "getEnclosingClass", (char*) "(Ljava/lang/Class;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClass_getEnclosingClass },
+ { (char*) "getEnclosingConstructor", (char*) "(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", (void*) (uintptr_t) &Java_java_lang_VMClass_getEnclosingConstructor },
+ { (char*) "getEnclosingMethod", (char*) "(Ljava/lang/Class;)Ljava/lang/reflect/Method;", (void*) (uintptr_t) &Java_java_lang_VMClass_getEnclosingMethod },
+ { (char*) "getClassSignature", (char*) "(Ljava/lang/Class;)Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_VMClass_getClassSignature },
+ { (char*) "isAnonymousClass", (char*) "(Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isAnonymousClass },
+ { (char*) "isLocalClass", (char*) "(Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isLocalClass },
+ { (char*) "isMemberClass", (char*) "(Ljava/lang/Class;)Z", (void*) (uintptr_t) &Java_java_lang_VMClass_isMemberClass },
+};
+
+
+/* _Jv_java_lang_VMClass_init **************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_VMClass_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMClass");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_VMClassLoader.c
-
- 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 <stdint.h>
-#include <sys/stat.h>
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_security_ProtectionDomain.h" /* required by... */
-#include "native/include/java_lang_ClassLoader.h"
-#include "native/include/java_util_Vector.h"
-#include "native/include/java_util_HashMap.h"
-#include "native/include/java_util_Map.h"
-#include "native/include/java_lang_Boolean.h"
-
-#include "native/include/java_lang_VMClassLoader.h"
-
-#include "toolbox/logging.h"
-#include "toolbox/list.h"
-
-#if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
-#endif
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/initialize.h"
-#include "vm/primitive.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/asmpart.h"
-
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vmcore/suck.h"
-#include "vmcore/zip.h"
-
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "defineClass", "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defineClass },
- { "getPrimitiveClass", "(C)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_getPrimitiveClass },
- { "resolveClass", "(Ljava/lang/Class;)V", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_resolveClass },
- { "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_loadClass },
- { "nativeGetResources", "(Ljava/lang/String;)Ljava/util/Vector;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_nativeGetResources },
- { "defaultAssertionStatus", "()Z", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defaultAssertionStatus },
- { "defaultUserAssertionStatus", "()Z", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defaultUserAssertionStatus },
- { "packageAssertionStatus0", "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_packageAssertionStatus0 },
- { "classAssertionStatus0", "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_classAssertionStatus0 },
- { "findLoadedClass", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_findLoadedClass },
-};
-
-
-/* _Jv_java_lang_VMClassLoader_init ********************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMClassLoader_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMClassLoader");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: defineClass
- * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_handle_bytearray_t *data, int32_t offset, int32_t len, java_security_ProtectionDomain *pd)
-{
- utf *utfname;
- classinfo *c;
- classloader_t *loader;
- java_lang_Class *o;
-
-#if defined(ENABLE_JVMTI)
- jint new_class_data_len = 0;
- unsigned char* new_class_data = NULL;
-#endif
-
- /* check if data was passed */
-
- if (data == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* check the indexes passed */
-
- if ((offset < 0) || (len < 0) || ((offset + len) > LLNI_array_size(data))) {
- exceptions_throw_arrayindexoutofboundsexception();
- return NULL;
- }
-
- /* add classloader to classloader hashtable */
-
- loader = loader_hashtable_classloader_add((java_handle_t *) cl);
-
- if (name != NULL) {
- /* convert '.' to '/' in java string */
-
- utfname = javastring_toutf((java_handle_t *) name, true);
- }
- else {
- utfname = NULL;
- }
-
-#if defined(ENABLE_JVMTI)
- /* XXX again this will not work because of the indirection cell for classloaders */
- assert(0);
- /* fire Class File Load Hook JVMTI event */
-
- if (jvmti)
- jvmti_ClassFileLoadHook(utfname, len, (unsigned char *) data->data,
- loader, (java_handle_t *) pd,
- &new_class_data_len, &new_class_data);
-#endif
-
- /* define the class */
-
-#if defined(ENABLE_JVMTI)
- /* check if the JVMTI wants to modify the class */
-
- if (new_class_data == NULL)
- c = class_define(utfname, loader, new_class_data_len, new_class_data, pd);
- else
-#endif
- c = class_define(utfname, loader, len, (uint8_t *) &LLNI_array_direct(data, offset), (java_handle_t *) pd);
-
- if (c == NULL)
- return NULL;
-
- /* for convenience */
-
- o = LLNI_classinfo_wrap(c);
-
- /* set ProtectionDomain */
-
- LLNI_field_set_ref(o, pd, pd);
-
- return o;
-}
-
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: getPrimitiveClass
- * Signature: (C)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, int32_t type)
-{
- classinfo *c;
-
- c = primitive_class_get_by_char(type);
-
- if (c == NULL) {
- exceptions_throw_classnotfoundexception(utf_null);
- return NULL;
- }
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: resolveClass
- * Signature: (Ljava/lang/Class;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jclass clazz, java_lang_Class *c)
-{
- classinfo *ci;
-
- ci = LLNI_classinfo_unwrap(c);
-
- if (!ci) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- /* link the class */
-
- if (!(ci->state & CLASS_LINKED))
- (void) link_class(ci);
-
- return;
-}
-
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: loadClass
- * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, int32_t resolve)
-{
- classinfo *c;
- utf *u;
-
- if (name == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* create utf string in which '.' is replaced by '/' */
-
- u = javastring_toutf((java_handle_t *) name, true);
-
- /* load class */
-
- c = load_class_bootstrap(u);
-
- if (c == NULL)
- return NULL;
-
- /* resolve class -- if requested */
-
-/* if (resolve) */
- if (!link_class(c))
- return NULL;
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: nativeGetResources
- * Signature: (Ljava/lang/String;)Ljava/util/Vector;
- */
-JNIEXPORT java_util_Vector* JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, java_lang_String *name)
-{
- java_handle_t *o; /* vector being created */
- methodinfo *m; /* "add" method of vector */
- java_handle_t *path; /* path to be added */
- list_classpath_entry *lce; /* classpath entry */
- utf *utfname; /* utf to look for */
- char *buffer; /* char buffer */
- char *namestart; /* start of name to use */
- char *tmppath; /* temporary buffer */
- int32_t namelen; /* length of name to use */
- int32_t searchlen; /* length of name to search */
- int32_t bufsize; /* size of buffer allocated */
- int32_t pathlen; /* name of path to assemble */
- struct stat buf; /* buffer for stat */
- jboolean ret; /* return value of "add" */
-
- /* get the resource name as utf string */
-
- utfname = javastring_toutf((java_handle_t *) name, false);
-
- if (utfname == NULL)
- return NULL;
-
- /* copy it to a char buffer */
-
- namelen = utf_bytes(utfname);
- searchlen = namelen;
- bufsize = namelen + strlen("0");
- buffer = MNEW(char, bufsize);
-
- utf_copy(buffer, utfname);
- namestart = buffer;
-
- /* skip leading '/' */
-
- if (namestart[0] == '/') {
- namestart++;
- namelen--;
- searchlen--;
- }
-
- /* remove trailing `.class' */
-
- if (namelen >= 6 && strcmp(namestart + (namelen - 6), ".class") == 0) {
- searchlen -= 6;
- }
-
- /* create a new needle to look for, if necessary */
-
- if (searchlen != bufsize-1) {
- utfname = utf_new(namestart, searchlen);
- if (utfname == NULL)
- goto return_NULL;
- }
-
- /* new Vector() */
-
- o = native_new_and_init(class_java_util_Vector);
-
- if (o == NULL)
- goto return_NULL;
-
- /* get Vector.add() method */
-
- m = class_resolveclassmethod(class_java_util_Vector,
- utf_add,
- utf_new_char("(Ljava/lang/Object;)Z"),
- NULL,
- true);
-
- if (m == NULL)
- goto return_NULL;
-
- /* iterate over all classpath entries */
-
- for (lce = list_first(list_classpath_entries); lce != NULL;
- lce = list_next(list_classpath_entries, lce)) {
- /* clear path pointer */
- path = NULL;
-
-#if defined(ENABLE_ZLIB)
- if (lce->type == CLASSPATH_ARCHIVE) {
-
- if (zip_find(lce, utfname)) {
- pathlen = strlen("jar:file://") + lce->pathlen + strlen("!/") +
- namelen + strlen("0");
-
- tmppath = MNEW(char, pathlen);
-
- sprintf(tmppath, "jar:file://%s!/%s", lce->path, namestart);
- path = javastring_new_from_utf_string(tmppath),
-
- MFREE(tmppath, char, pathlen);
- }
-
- } else {
-#endif /* defined(ENABLE_ZLIB) */
- pathlen = strlen("file://") + lce->pathlen + namelen + strlen("0");
-
- tmppath = MNEW(char, pathlen);
-
- sprintf(tmppath, "file://%s%s", lce->path, namestart);
-
- /* Does this file exist? */
-
- if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
- if (!S_ISDIR(buf.st_mode))
- path = javastring_new_from_utf_string(tmppath);
-
- MFREE(tmppath, char, pathlen);
-#if defined(ENABLE_ZLIB)
- }
-#endif
-
- /* if a resource was found, add it to the vector */
-
- if (path != NULL) {
- ret = vm_call_method_int(m, o, path);
-
- if (exceptions_get_exception() != NULL)
- goto return_NULL;
-
- if (ret == 0)
- goto return_NULL;
- }
- }
-
- MFREE(buffer, char, bufsize);
-
- return (java_util_Vector *) o;
-
-return_NULL:
- MFREE(buffer, char, bufsize);
-
- return NULL;
-}
-
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: defaultAssertionStatus
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
-{
-#if defined(ENABLE_ASSERTION)
- return assertion_system_enabled;
-#else
- return false;
-#endif
-}
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: userAssertionStatus
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMClassLoader_defaultUserAssertionStatus(JNIEnv *env, jclass clazz)
-{
-#if defined(ENABLE_ASSERTION)
- return assertion_user_enabled;
-#else
- return false;
-#endif
-}
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: packageAssertionStatus
- * Signature: ()Ljava_util_Map;
- */
-JNIEXPORT java_util_Map* JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(JNIEnv *env, jclass clazz, java_lang_Boolean *jtrue, java_lang_Boolean *jfalse)
-{
- java_handle_t *hm;
-#if defined(ENABLE_ASSERTION)
- java_handle_t *js;
- methodinfo *m;
- assertion_name_t *item;
-#endif
-
- /* new HashMap() */
-
- hm = native_new_and_init(class_java_util_HashMap);
- if (hm == NULL) {
- return NULL;
- }
-
-#if defined(ENABLE_ASSERTION)
- /* if nothing todo, return now */
-
- if (assertion_package_count == 0) {
- return (java_util_Map *) hm;
- }
-
- /* get HashMap.put method */
-
- m = class_resolveclassmethod(class_java_util_HashMap,
- utf_put,
- utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
- NULL,
- true);
-
- if (m == NULL) {
- return NULL;
- }
-
- item = (assertion_name_t *)list_first(list_assertion_names);
-
- while (item != NULL) {
- if (item->package == false) {
- item = (assertion_name_t *)list_next(list_assertion_names, item);
- continue;
- }
-
- if (strcmp(item->name, "") == 0) {
- /* unnamed package wanted */
- js = NULL;
- }
- else {
- js = javastring_new_from_ascii(item->name);
- if (js == NULL) {
- return NULL;
- }
- }
-
- if (item->enabled == true) {
- vm_call_method(m, hm, js, jtrue);
- }
- else {
- vm_call_method(m, hm, js, jfalse);
- }
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
- }
-#endif
-
- return (java_util_Map *) hm;
-}
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: classAssertionStatus
- * Signature: ()Ljava_util_Map;
- */
-JNIEXPORT java_util_Map* JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNIEnv *env, jclass clazz, java_lang_Boolean *jtrue, java_lang_Boolean *jfalse)
-{
- java_handle_t *hm;
-#if defined(ENABLE_ASSERTION)
- java_handle_t *js;
- methodinfo *m;
- assertion_name_t *item;
-#endif
-
- /* new HashMap() */
-
- hm = native_new_and_init(class_java_util_HashMap);
- if (hm == NULL) {
- return NULL;
- }
-
-#if defined(ENABLE_ASSERTION)
- /* if nothing todo, return now */
-
- if (assertion_class_count == 0) {
- return (java_util_Map *) hm;
- }
-
- /* get HashMap.put method */
-
- m = class_resolveclassmethod(class_java_util_HashMap,
- utf_put,
- utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
- NULL,
- true);
-
- if (m == NULL) {
- return NULL;
- }
-
- item = (assertion_name_t *)list_first(list_assertion_names);
-
- while (item != NULL) {
- if (item->package == true) {
- item = (assertion_name_t *)list_next(list_assertion_names, item);
- continue;
- }
-
- js = javastring_new_from_ascii(item->name);
- if (js == NULL) {
- return NULL;
- }
-
- if (item->enabled == true) {
- vm_call_method(m, hm, js, jtrue);
- }
- else {
- vm_call_method(m, hm, js, jfalse);
- }
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
- }
-#endif
-
- return (java_util_Map *) hm;
-}
-
-
-/*
- * Class: java/lang/VMClassLoader
- * Method: findLoadedClass
- * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *loader, java_lang_String *name)
-{
- classloader_t *cl;
- classinfo *c;
- utf *u;
-
- /* XXX is it correct to add the classloader to the hashtable here? */
-
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- /* replace `.' by `/', this is required by the classcache */
-
- u = javastring_toutf((java_handle_t *) name, true);
-
- /* lookup for defining classloader */
-
- c = classcache_lookup_defined(cl, u);
-
- /* if not found, lookup for initiating classloader */
-
- if (c == NULL)
- c = classcache_lookup(cl, u);
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp
+
+ 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 <stdint.h>
+#include <sys/stat.h>
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMClassLoader.h"
+#endif
+
+#include "toolbox/logging.h"
+#include "toolbox/list.h"
+
+#if defined(ENABLE_ASSERTION)
+#include "vm/assertion.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/statistics.h"
+#include "vm/string.hpp"
+#include "vm/suck.h"
+#include "vm/vm.hpp"
+#include "vm/zip.h"
+
+#include "vm/jit/asmpart.h"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: defineClass
+ * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, jobject cl, jstring name, jbyteArray data, jint offset, jint len, jobject pd)
+{
+ utf *utfname;
+ classinfo *c;
+ classloader_t *loader;
+ java_handle_bytearray_t* ba;
+ uint8_t* stream;
+
+#if defined(ENABLE_JVMTI)
+ jint new_class_data_len = 0;
+ unsigned char* new_class_data = NULL;
+#endif
+
+ /* check if data was passed */
+
+ if (data == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* check the indexes passed */
+
+ if ((offset < 0) || (len < 0) || ((offset + len) > LLNI_array_size(data))) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return NULL;
+ }
+
+ /* add classloader to classloader hashtable */
+
+ loader = loader_hashtable_classloader_add((java_handle_t *) cl);
+
+ if (name != NULL) {
+ /* convert '.' to '/' in java string */
+
+ utfname = javastring_toutf((java_handle_t *) name, true);
+ }
+ else {
+ utfname = NULL;
+ }
+
+#if defined(ENABLE_JVMTI)
+ /* XXX again this will not work because of the indirection cell for classloaders */
+ assert(0);
+ /* fire Class File Load Hook JVMTI event */
+
+ if (jvmti)
+ jvmti_ClassFileLoadHook(utfname, len, (unsigned char *) data->data,
+ loader, (java_handle_t *) pd,
+ &new_class_data_len, &new_class_data);
+#endif
+
+ /* define the class */
+
+#if defined(ENABLE_JVMTI)
+ /* check if the JVMTI wants to modify the class */
+
+ if (new_class_data == NULL)
+ c = class_define(utfname, loader, new_class_data_len, new_class_data, pd);
+ else
+#endif
+ {
+ ba = (java_handle_bytearray_t*) data;
+ stream = (uint8_t *) &LLNI_array_direct(ba, offset);
+ c = class_define(utfname, loader, len, stream, (java_handle_t *) pd);
+ }
+
+ if (c == NULL)
+ return NULL;
+
+ // REMOVEME
+ java_handle_t* h = LLNI_classinfo_wrap(c);
+
+ // Set ProtectionDomain.
+ java_lang_Class jlc(h);
+ jlc.set_pd(pd);
+
+ return (jclass) jlc.get_handle();
+}
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: getPrimitiveClass
+ * Signature: (C)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, jchar type)
+{
+ classinfo *c;
+
+ c = Primitive::get_class_by_char(type);
+
+ if (c == NULL) {
+ exceptions_throw_classnotfoundexception(utf_null);
+ return NULL;
+ }
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: resolveClass
+ * Signature: (Ljava/lang/Class;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMClassLoader_resolveClass(JNIEnv *env, jclass clazz, jclass c)
+{
+ classinfo *ci;
+
+ ci = LLNI_classinfo_unwrap(c);
+
+ if (!ci) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ /* link the class */
+
+ if (!(ci->state & CLASS_LINKED))
+ (void) link_class(ci);
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: loadClass
+ * Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, jstring name, jboolean resolve)
+{
+ classinfo *c;
+ utf *u;
+
+ if (name == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* create utf string in which '.' is replaced by '/' */
+
+ u = javastring_toutf((java_handle_t *) name, true);
+
+ /* load class */
+
+ c = load_class_bootstrap(u);
+
+ if (c == NULL)
+ return NULL;
+
+ /* resolve class -- if requested */
+
+/* if (resolve) */
+ if (!link_class(c))
+ return NULL;
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: nativeGetResources
+ * Signature: (Ljava/lang/String;)Ljava/util/Vector;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv *env, jclass clazz, jstring name)
+{
+ java_handle_t *o; /* vector being created */
+ methodinfo *m; /* "add" method of vector */
+ java_handle_t *path; /* path to be added */
+ list_classpath_entry *lce; /* classpath entry */
+ utf *utfname; /* utf to look for */
+ char *buffer; /* char buffer */
+ char *namestart; /* start of name to use */
+ char *tmppath; /* temporary buffer */
+ int32_t namelen; /* length of name to use */
+ int32_t searchlen; /* length of name to search */
+ int32_t bufsize; /* size of buffer allocated */
+ int32_t pathlen; /* name of path to assemble */
+ struct stat buf; /* buffer for stat */
+ jboolean ret; /* return value of "add" */
+
+ /* get the resource name as utf string */
+
+ utfname = javastring_toutf((java_handle_t *) name, false);
+
+ if (utfname == NULL)
+ return NULL;
+
+ /* copy it to a char buffer */
+
+ namelen = utf_bytes(utfname);
+ searchlen = namelen;
+ bufsize = namelen + strlen("0");
+ buffer = MNEW(char, bufsize);
+
+ utf_copy(buffer, utfname);
+ namestart = buffer;
+
+ /* skip leading '/' */
+
+ if (namestart[0] == '/') {
+ namestart++;
+ namelen--;
+ searchlen--;
+ }
+
+ /* remove trailing `.class' */
+
+ if (namelen >= 6 && strcmp(namestart + (namelen - 6), ".class") == 0) {
+ searchlen -= 6;
+ }
+
+ /* create a new needle to look for, if necessary */
+
+ if (searchlen != bufsize-1) {
+ utfname = utf_new(namestart, searchlen);
+ if (utfname == NULL)
+ goto return_NULL;
+ }
+
+ /* new Vector() */
+
+ o = native_new_and_init(class_java_util_Vector);
+
+ if (o == NULL)
+ goto return_NULL;
+
+ /* get Vector.add() method */
+
+ m = class_resolveclassmethod(class_java_util_Vector,
+ utf_add,
+ utf_new_char("(Ljava/lang/Object;)Z"),
+ NULL,
+ true);
+
+ if (m == NULL)
+ goto return_NULL;
+
+ /* iterate over all classpath entries */
+
+ for (lce = (list_classpath_entry*) list_first(list_classpath_entries); lce != NULL;
+ lce = (list_classpath_entry*) list_next(list_classpath_entries, lce)) {
+ /* clear path pointer */
+ path = NULL;
+
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+
+ if (zip_find(lce, utfname)) {
+ pathlen = strlen("jar:file://") + lce->pathlen + strlen("!/") +
+ namelen + strlen("0");
+
+ tmppath = MNEW(char, pathlen);
+
+ sprintf(tmppath, "jar:file://%s!/%s", lce->path, namestart);
+ path = javastring_new_from_utf_string(tmppath),
+
+ MFREE(tmppath, char, pathlen);
+ }
+
+ } else {
+#endif /* defined(ENABLE_ZLIB) */
+ pathlen = strlen("file://") + lce->pathlen + namelen + strlen("0");
+
+ tmppath = MNEW(char, pathlen);
+
+ sprintf(tmppath, "file://%s%s", lce->path, namestart);
+
+ /* Does this file exist? */
+
+ if (stat(tmppath + strlen("file://") - 1, &buf) == 0)
+ if (!S_ISDIR(buf.st_mode))
+ path = javastring_new_from_utf_string(tmppath);
+
+ MFREE(tmppath, char, pathlen);
+#if defined(ENABLE_ZLIB)
+ }
+#endif
+
+ /* if a resource was found, add it to the vector */
+
+ if (path != NULL) {
+ ret = vm_call_method_int(m, o, path);
+
+ if (exceptions_get_exception() != NULL)
+ goto return_NULL;
+
+ if (ret == 0)
+ goto return_NULL;
+ }
+ }
+
+ MFREE(buffer, char, bufsize);
+
+ return (jobject) o;
+
+return_NULL:
+ MFREE(buffer, char, bufsize);
+
+ return NULL;
+}
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: defaultAssertionStatus
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
+{
+#if defined(ENABLE_ASSERTION)
+ return assertion_system_enabled;
+#else
+ return false;
+#endif
+}
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: userAssertionStatus
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMClassLoader_defaultUserAssertionStatus(JNIEnv *env, jclass clazz)
+{
+#if defined(ENABLE_ASSERTION)
+ return assertion_user_enabled;
+#else
+ return false;
+#endif
+}
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: packageAssertionStatus
+ * Signature: (Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_packageAssertionStatus0(JNIEnv *env, jclass clazz, jobject jtrue, jobject jfalse)
+{
+ java_handle_t *hm;
+#if defined(ENABLE_ASSERTION)
+ java_handle_t *js;
+ methodinfo *m;
+ assertion_name_t *item;
+#endif
+
+ /* new HashMap() */
+
+ hm = native_new_and_init(class_java_util_HashMap);
+ if (hm == NULL) {
+ return NULL;
+ }
+
+#if defined(ENABLE_ASSERTION)
+ /* if nothing todo, return now */
+
+ if (assertion_package_count == 0) {
+ return (jobject) hm;
+ }
+
+ /* get HashMap.put method */
+
+ m = class_resolveclassmethod(class_java_util_HashMap,
+ utf_put,
+ utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+ NULL,
+ true);
+
+ if (m == NULL) {
+ return NULL;
+ }
+
+ item = (assertion_name_t *)list_first(list_assertion_names);
+
+ while (item != NULL) {
+ if (item->package == false) {
+ item = (assertion_name_t *)list_next(list_assertion_names, item);
+ continue;
+ }
+
+ if (strcmp(item->name, "") == 0) {
+ /* unnamed package wanted */
+ js = NULL;
+ }
+ else {
+ js = javastring_new_from_ascii(item->name);
+ if (js == NULL) {
+ return NULL;
+ }
+ }
+
+ if (item->enabled == true) {
+ vm_call_method(m, hm, js, jtrue);
+ }
+ else {
+ vm_call_method(m, hm, js, jfalse);
+ }
+
+ item = (assertion_name_t *)list_next(list_assertion_names, item);
+ }
+#endif
+
+ return (jobject) hm;
+}
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: classAssertionStatus
+ * Signature: (Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_classAssertionStatus0(JNIEnv *env, jclass clazz, jobject jtrue, jobject jfalse)
+{
+ java_handle_t *hm;
+#if defined(ENABLE_ASSERTION)
+ java_handle_t *js;
+ methodinfo *m;
+ assertion_name_t *item;
+#endif
+
+ /* new HashMap() */
+
+ hm = native_new_and_init(class_java_util_HashMap);
+ if (hm == NULL) {
+ return NULL;
+ }
+
+#if defined(ENABLE_ASSERTION)
+ /* if nothing todo, return now */
+
+ if (assertion_class_count == 0) {
+ return (jobject) hm;
+ }
+
+ /* get HashMap.put method */
+
+ m = class_resolveclassmethod(class_java_util_HashMap,
+ utf_put,
+ utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+ NULL,
+ true);
+
+ if (m == NULL) {
+ return NULL;
+ }
+
+ item = (assertion_name_t *)list_first(list_assertion_names);
+
+ while (item != NULL) {
+ if (item->package == true) {
+ item = (assertion_name_t *)list_next(list_assertion_names, item);
+ continue;
+ }
+
+ js = javastring_new_from_ascii(item->name);
+ if (js == NULL) {
+ return NULL;
+ }
+
+ if (item->enabled == true) {
+ vm_call_method(m, hm, js, jtrue);
+ }
+ else {
+ vm_call_method(m, hm, js, jfalse);
+ }
+
+ item = (assertion_name_t *)list_next(list_assertion_names, item);
+ }
+#endif
+
+ return (jobject) hm;
+}
+
+
+/*
+ * Class: java/lang/VMClassLoader
+ * Method: findLoadedClass
+ * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, jobject loader, jstring name)
+{
+ classloader_t *cl;
+ classinfo *c;
+ utf *u;
+
+ /* XXX is it correct to add the classloader to the hashtable here? */
+
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ /* replace `.' by `/', this is required by the classcache */
+
+ u = javastring_toutf((java_handle_t *) name, true);
+
+ /* lookup for defining classloader */
+
+ c = classcache_lookup_defined(cl, u);
+
+ /* if not found, lookup for initiating classloader */
+
+ if (c == NULL)
+ c = classcache_lookup(cl, u);
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "defineClass", (char*) "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_defineClass },
+ { (char*) "getPrimitiveClass", (char*) "(C)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_getPrimitiveClass },
+ { (char*) "resolveClass", (char*) "(Ljava/lang/Class;)V", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_resolveClass },
+ { (char*) "loadClass", (char*) "(Ljava/lang/String;Z)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_loadClass },
+ { (char*) "nativeGetResources", (char*) "(Ljava/lang/String;)Ljava/util/Vector;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_nativeGetResources },
+ { (char*) "defaultAssertionStatus", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_defaultAssertionStatus },
+ { (char*) "defaultUserAssertionStatus", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_defaultUserAssertionStatus },
+ { (char*) "packageAssertionStatus0", (char*) "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_packageAssertionStatus0 },
+ { (char*) "classAssertionStatus0", (char*) "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_classAssertionStatus0 },
+ { (char*) "findLoadedClass", (char*) "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMClassLoader_findLoadedClass },
+};
+
+
+/* _Jv_java_lang_VMClassLoader_init ********************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_VMClassLoader_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMClassLoader");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_VMObject.c - java/lang/VMObject
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Class.h" /* required by j.l.VMO */
-#include "native/include/java_lang_Cloneable.h" /* required by j.l.VMO */
-#include "native/include/java_lang_Object.h" /* required by j.l.VMO */
-
-#include "native/include/java_lang_VMObject.h"
-
-#include "threads/lock-common.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getClass", "(Ljava/lang/Object;)Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_VMObject_getClass },
- { "clone", "(Ljava/lang/Cloneable;)Ljava/lang/Object;", (void *) (intptr_t) &Java_java_lang_VMObject_clone },
- { "notify", "(Ljava/lang/Object;)V", (void *) (intptr_t) &Java_java_lang_VMObject_notify },
- { "notifyAll", "(Ljava/lang/Object;)V", (void *) (intptr_t) &Java_java_lang_VMObject_notifyAll },
- { "wait", "(Ljava/lang/Object;JI)V", (void *) (intptr_t) &Java_java_lang_VMObject_wait },
-};
-
-
-/* _Jv_java_lang_VMObject_init *************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMObject_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMObject");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/VMObject
- * Method: getClass
- * Signature: (Ljava/lang/Object;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMObject_getClass(JNIEnv *env, jclass clazz, java_lang_Object *obj)
-{
- classinfo *c;
-
- if (obj == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- LLNI_class_get(obj, c);
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: java/lang/VMObject
- * Method: clone
- * Signature: (Ljava/lang/Cloneable;)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_VMObject_clone(JNIEnv *env, jclass clazz, java_lang_Cloneable *this)
-{
- java_handle_t *o;
- java_handle_t *co;
-
- o = (java_handle_t *) this;
-
- co = builtin_clone(NULL, o);
-
- return (java_lang_Object *) co;
-}
-
-
-/*
- * Class: java/lang/VMObject
- * Method: notify
- * Signature: (Ljava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(JNIEnv *env, jclass clazz, java_lang_Object *this)
-{
-#if defined(ENABLE_THREADS)
- lock_notify_object((java_handle_t *) this);
-#endif
-}
-
-
-/*
- * Class: java/lang/VMObject
- * Method: notifyAll
- * Signature: (Ljava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(JNIEnv *env, jclass clazz, java_lang_Object *this)
-{
-#if defined(ENABLE_THREADS)
- lock_notify_all_object((java_handle_t *) this);
-#endif
-}
-
-
-/*
- * Class: java/lang/VMObject
- * Method: wait
- * Signature: (Ljava/lang/Object;JI)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnv *env, jclass clazz, java_lang_Object *o, int64_t ms, int32_t ns)
-{
-#if defined(ENABLE_JVMTI)
- /* Monitor Wait */
- if (jvmti) jvmti_MonitorWaiting(true, o, ms);
-#endif
-
-#if defined(ENABLE_THREADS)
- lock_wait_for_object((java_handle_t *) o, ms, ns);
-#endif
-
-#if defined(ENABLE_JVMTI)
- /* Monitor Waited */
- /* XXX: How do you know if wait timed out ?*/
- if (jvmti) jvmti_MonitorWaiting(false, o, 0);
-#endif
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMObject.cpp - java/lang/VMObject
+
+ 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 "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMObject.h"
+#endif
+
+#include "threads/lock-common.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/utf8.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMObject
+ * Method: getClass
+ * Signature: (Ljava/lang/Object;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_VMObject_getClass(JNIEnv *env, jclass clazz, jobject obj)
+{
+ classinfo *c;
+
+ if (obj == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ LLNI_class_get(obj, c);
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: java/lang/VMObject
+ * Method: clone
+ * Signature: (Ljava/lang/Cloneable;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone(JNIEnv *env, jclass clazz, jobject _this)
+{
+ java_handle_t *o;
+ java_handle_t *co;
+
+ o = (java_handle_t *) _this;
+
+ co = builtin_clone(NULL, o);
+
+ return (jobject) co;
+}
+
+
+/*
+ * Class: java/lang/VMObject
+ * Method: notify
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(JNIEnv *env, jclass clazz, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ lock_notify_object((java_handle_t *) _this);
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMObject
+ * Method: notifyAll
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(JNIEnv *env, jclass clazz, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ lock_notify_all_object((java_handle_t *) _this);
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMObject
+ * Method: wait
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnv *env, jclass clazz, jobject o, jlong ms, jint ns)
+{
+#if defined(ENABLE_JVMTI)
+ /* Monitor Wait */
+ if (jvmti) jvmti_MonitorWaiting(true, o, ms);
+#endif
+
+#if defined(ENABLE_THREADS)
+ lock_wait_for_object((java_handle_t *) o, ms, ns);
+#endif
+
+#if defined(ENABLE_JVMTI)
+ /* Monitor Waited */
+ /* XXX: How do you know if wait timed out ?*/
+ if (jvmti) jvmti_MonitorWaiting(false, o, 0);
+#endif
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getClass", (char*) "(Ljava/lang/Object;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_VMObject_getClass },
+ { (char*) "clone", (char*) "(Ljava/lang/Cloneable;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_java_lang_VMObject_clone },
+ { (char*) "notify", (char*) "(Ljava/lang/Object;)V", (void*) (uintptr_t) &Java_java_lang_VMObject_notify },
+ { (char*) "notifyAll", (char*) "(Ljava/lang/Object;)V", (void*) (uintptr_t) &Java_java_lang_VMObject_notifyAll },
+ { (char*) "wait", (char*) "(Ljava/lang/Object;JI)V", (void*) (uintptr_t) &Java_java_lang_VMObject_wait },
+};
+
+
+/* _Jv_java_lang_VMObject_init *************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_VMObject_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMObject");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_VMRuntime.c
-
- 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 <string.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/utsname.h>
-
-#if defined(__DARWIN__)
-# if defined(__POWERPC__)
-# define OS_INLINE /* required for <libkern/ppc/OSByteOrder.h> */
-# endif
-# include <mach/mach.h>
-#endif
-
-#include "mm/dumpmemory.h"
-#include "mm/gc-common.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_io_File.h"
-#include "native/include/java_lang_ClassLoader.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Process.h"
-
-#include "native/include/java_lang_VMRuntime.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/system.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "exit", "(I)V", (void *) (intptr_t) &Java_java_lang_VMRuntime_exit },
- { "freeMemory", "()J", (void *) (intptr_t) &Java_java_lang_VMRuntime_freeMemory },
- { "totalMemory", "()J", (void *) (intptr_t) &Java_java_lang_VMRuntime_totalMemory },
- { "maxMemory", "()J", (void *) (intptr_t) &Java_java_lang_VMRuntime_maxMemory },
- { "gc", "()V", (void *) (intptr_t) &Java_java_lang_VMRuntime_gc },
- { "runFinalization", "()V", (void *) (intptr_t) &Java_java_lang_VMRuntime_runFinalization },
- { "runFinalizersOnExit", "(Z)V", (void *) (intptr_t) &Java_java_lang_VMRuntime_runFinalizersOnExit },
- { "runFinalizationForExit", "()V", (void *) (intptr_t) &Java_java_lang_VMRuntime_runFinalizationForExit },
- { "traceInstructions", "(Z)V", (void *) (intptr_t) &Java_java_lang_VMRuntime_traceInstructions },
- { "traceMethodCalls", "(Z)V", (void *) (intptr_t) &Java_java_lang_VMRuntime_traceMethodCalls },
- { "availableProcessors", "()I", (void *) (intptr_t) &Java_java_lang_VMRuntime_availableProcessors },
- { "nativeLoad", "(Ljava/lang/String;Ljava/lang/ClassLoader;)I", (void *) (intptr_t) &Java_java_lang_VMRuntime_nativeLoad },
- { "mapLibraryName", "(Ljava/lang/String;)Ljava/lang/String;", (void *) (intptr_t) &Java_java_lang_VMRuntime_mapLibraryName },
-};
-
-
-/* _Jv_java_lang_VMRuntime_init ************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMRuntime_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMRuntime");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-static bool finalizeOnExit = false;
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: exit
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMRuntime_exit(JNIEnv *env, jclass clazz, int32_t status)
-{
- if (finalizeOnExit)
- gc_finalize_all();
-
- vm_shutdown(status);
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: freeMemory
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_java_lang_VMRuntime_freeMemory(JNIEnv *env, jclass clazz)
-{
- return gc_get_free_bytes();
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: totalMemory
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_java_lang_VMRuntime_totalMemory(JNIEnv *env, jclass clazz)
-{
- return gc_get_heap_size();
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: maxMemory
- * Signature: ()J
- */
-JNIEXPORT int64_t JNICALL Java_java_lang_VMRuntime_maxMemory(JNIEnv *env, jclass clazz)
-{
- return gc_get_max_heap_size();
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: gc
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMRuntime_gc(JNIEnv *env, jclass clazz)
-{
- gc_call();
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: runFinalization
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalization(JNIEnv *env, jclass clazz)
-{
- gc_invoke_finalizers();
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: runFinalizersOnExit
- * Signature: (Z)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizersOnExit(JNIEnv *env, jclass clazz, int32_t value)
-{
- /* XXX threading */
-
- finalizeOnExit = value;
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: runFinalizationsForExit
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizationForExit(JNIEnv *env, jclass clazz)
-{
-/* if (finalizeOnExit) { */
-/* gc_call(); */
- /* gc_finalize_all(); */
-/* } */
-/* log_text("Java_java_lang_VMRuntime_runFinalizationForExit called"); */
- /*gc_finalize_all();*/
- /*gc_invoke_finalizers();*/
- /*gc_call();*/
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: traceInstructions
- * Signature: (Z)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceInstructions(JNIEnv *env, jclass clazz, int32_t par1)
-{
- /* not supported */
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: traceMethodCalls
- * Signature: (Z)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceMethodCalls(JNIEnv *env, jclass clazz, int32_t par1)
-{
- /* not supported */
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: availableProcessors
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMRuntime_availableProcessors(JNIEnv *env, jclass clazz)
-{
- return system_processors_online();
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: nativeLoad
- * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass clazz, java_lang_String *libname, java_lang_ClassLoader *loader)
-{
- classloader_t *cl;
- utf *name;
-
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- /* REMOVEME When we use Java-strings internally. */
-
- if (libname == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- name = javastring_toutf((java_handle_t *) libname, false);
-
- return native_library_load(env, name, cl);
-}
-
-
-/*
- * Class: java/lang/VMRuntime
- * Method: mapLibraryName
- * Signature: (Ljava/lang/String;)Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMRuntime_mapLibraryName(JNIEnv *env, jclass clazz, java_lang_String *libname)
-{
- utf *u;
- char *buffer;
- int32_t buffer_len;
- java_handle_t *o;
- int32_t dumpmarker;
-
- if (libname == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- u = javastring_toutf((java_handle_t *) libname, false);
-
- /* calculate length of library name */
-
- buffer_len =
- strlen(NATIVE_LIBRARY_PREFIX) +
- utf_bytes(u) +
- strlen(NATIVE_LIBRARY_SUFFIX) +
- strlen("0");
-
- DMARKER;
-
- buffer = DMNEW(char, buffer_len);
-
- /* generate library name */
-
- strcpy(buffer, NATIVE_LIBRARY_PREFIX);
- utf_cat(buffer, u);
- strcat(buffer, NATIVE_LIBRARY_SUFFIX);
-
- o = javastring_new_from_utf_string(buffer);
-
- /* release memory */
-
- DRELEASE;
-
- return (java_lang_String *) o;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMRuntime.cpp
+
+ 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 <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+#if defined(__DARWIN__)
+# if defined(__POWERPC__)
+# define OS_INLINE /* required for <libkern/ppc/OSByteOrder.h> */
+# endif
+# include <mach/mach.h>
+#endif
+
+#include "mm/dumpmemory.h"
+#include "mm/gc.hpp"
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMRuntime.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/os.hpp"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+static bool finalizeOnExit = false;
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: exit
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_exit(JNIEnv *env, jclass clazz, jint status)
+{
+ if (finalizeOnExit)
+ gc_finalize_all();
+
+ vm_shutdown(status);
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: freeMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_VMRuntime_freeMemory(JNIEnv *env, jclass clazz)
+{
+ return gc_get_free_bytes();
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: totalMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_VMRuntime_totalMemory(JNIEnv *env, jclass clazz)
+{
+ return gc_get_heap_size();
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: maxMemory
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_VMRuntime_maxMemory(JNIEnv *env, jclass clazz)
+{
+ return gc_get_max_heap_size();
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: gc
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_gc(JNIEnv *env, jclass clazz)
+{
+ gc_call();
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: runFinalization
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalization(JNIEnv *env, jclass clazz)
+{
+ gc_invoke_finalizers();
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: runFinalizersOnExit
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizersOnExit(JNIEnv *env, jclass clazz, jboolean value)
+{
+ /* XXX threading */
+
+ finalizeOnExit = value;
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: runFinalizationsForExit
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizationForExit(JNIEnv *env, jclass clazz)
+{
+/* if (finalizeOnExit) { */
+/* gc_call(); */
+ /* gc_finalize_all(); */
+/* } */
+/* log_text("Java_java_lang_VMRuntime_runFinalizationForExit called"); */
+ /*gc_finalize_all();*/
+ /*gc_invoke_finalizers();*/
+ /*gc_call();*/
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: traceInstructions
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceInstructions(JNIEnv *env, jclass clazz, jboolean par1)
+{
+ /* not supported */
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: traceMethodCalls
+ * Signature: (Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMRuntime_traceMethodCalls(JNIEnv *env, jclass clazz, jboolean par1)
+{
+ /* not supported */
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: availableProcessors
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMRuntime_availableProcessors(JNIEnv *env, jclass clazz)
+{
+ return os::processors_online();
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: nativeLoad
+ * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass clazz, jstring libname, jobject loader)
+{
+ classloader_t *cl;
+ utf *name;
+
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ /* REMOVEME When we use Java-strings internally. */
+
+ if (libname == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ name = javastring_toutf((java_handle_t *) libname, false);
+
+ return native_library_load(env, name, cl);
+}
+
+
+/*
+ * Class: java/lang/VMRuntime
+ * Method: mapLibraryName
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_VMRuntime_mapLibraryName(JNIEnv *env, jclass clazz, jstring libname)
+{
+ utf *u;
+ char *buffer;
+ int32_t buffer_len;
+ java_handle_t *o;
+ int32_t dumpmarker;
+
+ if (libname == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ u = javastring_toutf((java_handle_t *) libname, false);
+
+ /* calculate length of library name */
+
+ buffer_len =
+ strlen(NATIVE_LIBRARY_PREFIX) +
+ utf_bytes(u) +
+ strlen(NATIVE_LIBRARY_SUFFIX) +
+ strlen("0");
+
+ DMARKER;
+
+ buffer = DMNEW(char, buffer_len);
+
+ /* generate library name */
+
+ strcpy(buffer, NATIVE_LIBRARY_PREFIX);
+ utf_cat(buffer, u);
+ strcat(buffer, NATIVE_LIBRARY_SUFFIX);
+
+ o = javastring_new_from_utf_string(buffer);
+
+ /* release memory */
+
+ DRELEASE;
+
+ return (jstring) o;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "exit", (char*) "(I)V", (void*) (uintptr_t) &Java_java_lang_VMRuntime_exit },
+ { (char*) "freeMemory", (char*) "()J", (void*) (uintptr_t) &Java_java_lang_VMRuntime_freeMemory },
+ { (char*) "totalMemory", (char*) "()J", (void*) (uintptr_t) &Java_java_lang_VMRuntime_totalMemory },
+ { (char*) "maxMemory", (char*) "()J", (void*) (uintptr_t) &Java_java_lang_VMRuntime_maxMemory },
+ { (char*) "gc", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_VMRuntime_gc },
+ { (char*) "runFinalization", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_VMRuntime_runFinalization },
+ { (char*) "runFinalizersOnExit", (char*) "(Z)V", (void*) (uintptr_t) &Java_java_lang_VMRuntime_runFinalizersOnExit },
+ { (char*) "runFinalizationForExit", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_VMRuntime_runFinalizationForExit },
+ { (char*) "traceInstructions", (char*) "(Z)V", (void*) (uintptr_t) &Java_java_lang_VMRuntime_traceInstructions },
+ { (char*) "traceMethodCalls", (char*) "(Z)V", (void*) (uintptr_t) &Java_java_lang_VMRuntime_traceMethodCalls },
+ { (char*) "availableProcessors", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_VMRuntime_availableProcessors },
+ { (char*) "nativeLoad", (char*) "(Ljava/lang/String;Ljava/lang/ClassLoader;)I", (void*) (uintptr_t) &Java_java_lang_VMRuntime_nativeLoad },
+ { (char*) "mapLibraryName", (char*) "(Ljava/lang/String;)Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_VMRuntime_mapLibraryName },
+};
+
+
+/* _Jv_java_lang_VMRuntime_init ************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_VMRuntime_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMRuntime");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_VMString.c - java/lang/VMString
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 <stdlib.h>
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_VMString.h"
-
-#include "vm/stringlocal.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "intern", "(Ljava/lang/String;)Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_VMString_intern },
-};
-
-
-/* _Jv_java_lang_VMString_init *************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMString_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMString");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/VMString
- * Method: intern
- * Signature: (Ljava/lang/String;)Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMString_intern(JNIEnv *env, jclass clazz, java_lang_String *str)
-{
- if (str == NULL)
- return NULL;
-
- return (java_lang_String *) javastring_intern((java_handle_t *) str);
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMString.cpp - java/lang/VMString
+
+ 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 <stdlib.h>
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMString.h"
+#endif
+
+#include "vm/string.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMString
+ * Method: intern
+ * Signature: (Ljava/lang/String;)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_VMString_intern(JNIEnv *env, jclass clazz, jstring str)
+{
+ if (str == NULL)
+ return NULL;
+
+ return (jstring) javastring_intern((java_handle_t *) str);
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "intern", (char*) "(Ljava/lang/String;)Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_VMString_intern },
+};
+
+
+/* _Jv_java_lang_VMString_init *************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_VMString_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMString");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_VMSystem.c - java/lang/VMSystem
-
- 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>
-
-#include "mm/gc-common.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_io_InputStream.h" /* required by j.l.VMS */
-#include "native/include/java_io_PrintStream.h" /* required by j.l.VMS */
-
-#include "native/include/java_lang_VMSystem.h"
-
-#include "vm/builtin.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", (void *) (uintptr_t) &Java_java_lang_VMSystem_arraycopy },
- { "identityHashCode", "(Ljava/lang/Object;)I", (void *) (uintptr_t) &Java_java_lang_VMSystem_identityHashCode },
-};
-
-
-/* _Jv_java_lang_VMSystem_init *************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMSystem_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMSystem");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/VMSystem
- * Method: arraycopy
- * Signature: (Ljava/lang/Object;ILjava/lang/Object;II)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy(JNIEnv *env, jclass clazz, java_lang_Object *src, int32_t srcStart, java_lang_Object *dest, int32_t destStart, int32_t len)
-{
- builtin_arraycopy((java_handle_t *) src, srcStart,
- (java_handle_t *) dest, destStart, len);
-}
-
-
-/*
- * Class: java/lang/VMSystem
- * Method: identityHashCode
- * Signature: (Ljava/lang/Object;)I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, java_lang_Object *o)
-{
- int32_t hashcode;
-
- LLNI_CRITICAL_START;
-
- hashcode = heap_hashcode(LLNI_UNWRAP((java_handle_t *) o));
-
- LLNI_CRITICAL_END;
-
- return hashcode;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMSystem.cpp - java/lang/VMSystem
+
+ 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>
+
+#include "mm/gc.hpp"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vminclude/java_lang_VMSystem.h"
+#endif
+
+#include "vm/builtin.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMSystem
+ * Method: arraycopy
+ * Signature: (Ljava/lang/Object;ILjava/lang/Object;II)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy(JNIEnv *env, jclass clazz, jobject src, jint srcStart, jobject dest, jint destStart, jint len)
+{
+ builtin_arraycopy((java_handle_t *) src, srcStart,
+ (java_handle_t *) dest, destStart, len);
+}
+
+
+/*
+ * Class: java/lang/VMSystem
+ * Method: identityHashCode
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, jobject o)
+{
+ int32_t hashcode;
+
+ // XXX This critical section should be inside the heap function.
+ LLNI_CRITICAL_START;
+
+ hashcode = heap_hashcode(LLNI_UNWRAP((java_handle_t *) o));
+
+ LLNI_CRITICAL_END;
+
+ return hashcode;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "arraycopy", (char*) "(Ljava/lang/Object;ILjava/lang/Object;II)V", (void*) (uintptr_t) &Java_java_lang_VMSystem_arraycopy },
+ { (char*) "identityHashCode", (char*) "(Ljava/lang/Object;)I", (void*) (uintptr_t) &Java_java_lang_VMSystem_identityHashCode },
+};
+
+
+/* _Jv_java_lang_VMSystem_init *************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_VMSystem_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMSystem");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_VMThread.c
-
- 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 "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_ThreadGroup.h"
-#include "native/include/java_lang_Object.h" /* java_lang_Thread.h */
-#include "native/include/java_lang_Throwable.h" /* java_lang_Thread.h */
-#include "native/include/java_lang_VMThread.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Thread.h"
-
-#include "threads/lock-common.h"
-#include "threads/thread.h"
-
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "countStackFrames", "()I", (void *) (intptr_t) &Java_java_lang_VMThread_countStackFrames },
- { "start", "(J)V", (void *) (intptr_t) &Java_java_lang_VMThread_start },
- { "interrupt", "()V", (void *) (intptr_t) &Java_java_lang_VMThread_interrupt },
- { "isInterrupted", "()Z", (void *) (intptr_t) &Java_java_lang_VMThread_isInterrupted },
- { "suspend", "()V", (void *) (intptr_t) &Java_java_lang_VMThread_suspend },
- { "resume", "()V", (void *) (intptr_t) &Java_java_lang_VMThread_resume },
- { "nativeSetPriority", "(I)V", (void *) (intptr_t) &Java_java_lang_VMThread_nativeSetPriority },
- { "nativeStop", "(Ljava/lang/Throwable;)V", (void *) (intptr_t) &Java_java_lang_VMThread_nativeStop },
- { "currentThread", "()Ljava/lang/Thread;", (void *) (intptr_t) &Java_java_lang_VMThread_currentThread },
- { "yield", "()V", (void *) (intptr_t) &Java_java_lang_VMThread_yield },
- { "interrupted", "()Z", (void *) (intptr_t) &Java_java_lang_VMThread_interrupted },
- { "holdsLock", "(Ljava/lang/Object;)Z", (void *) (intptr_t) &Java_java_lang_VMThread_holdsLock },
- { "getState", "()Ljava/lang/String;", (void *) (intptr_t) &Java_java_lang_VMThread_getState },
-};
-
-
-/* _Jv_java_lang_VMThread_init *************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMThread_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMThread");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: countStackFrames
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMThread_countStackFrames(JNIEnv *env, java_lang_VMThread *this)
-{
- log_println("Java_java_lang_VMThread_countStackFrames: Deprecated. Not implemented.");
-
- return 0;
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: start
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMThread_start(JNIEnv *env, java_lang_VMThread *this, int64_t stacksize)
-{
- java_lang_Thread *thread;
-
- LLNI_field_get_ref(this, thread, thread);
-
-#if defined(ENABLE_THREADS)
- threads_thread_start((java_handle_t *) thread);
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: interrupt
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMThread_interrupt(JNIEnv *env, java_lang_VMThread *this)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *h;
- threadobject *t;
-
- h = (java_handle_t *) this;
- t = thread_get_thread(h);
-
- threads_thread_interrupt(t);
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: isInterrupted
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMThread_isInterrupted(JNIEnv *env, java_lang_VMThread *this)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *h;
- threadobject *t;
-
- h = (java_handle_t *) this;
- t = thread_get_thread(h);
-
- return thread_is_interrupted(t);
-#else
- return 0;
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: suspend
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMThread_suspend(JNIEnv *env, java_lang_VMThread *this)
-{
-#if defined(ENABLE_THREADS)
- log_println("Java_java_lang_VMThread_suspend: Deprecated. Not implemented.");
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: resume
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMThread_resume(JNIEnv *env, java_lang_VMThread *this)
-{
-#if defined(ENABLE_THREADS)
- log_println("Java_java_lang_VMThread_resume: Deprecated. Not implemented.");
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: nativeSetPriority
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeSetPriority(JNIEnv *env, java_lang_VMThread *this, int32_t priority)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *h;
- threadobject *t;
-
- h = (java_handle_t *) this;
- t = thread_get_thread(h);
-
- threads_set_thread_priority(t->tid, priority);
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: nativeStop
- * Signature: (Ljava/lang/Throwable;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeStop(JNIEnv *env, java_lang_VMThread *this, java_lang_Throwable *t)
-{
-#if defined(ENABLE_THREADS)
- log_println("Java_java_lang_VMThread_nativeStop: Deprecated. Not implemented.");
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: currentThread
- * Signature: ()Ljava/lang/Thread;
- */
-JNIEXPORT java_lang_Thread* JNICALL Java_java_lang_VMThread_currentThread(JNIEnv *env, jclass clazz)
-{
- java_lang_Thread *to;
-
- to = (java_lang_Thread *) thread_get_current_object();
-
- return to;
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: yield
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_lang_VMThread_yield(JNIEnv *env, jclass clazz)
-{
-#if defined(ENABLE_THREADS)
- threads_yield();
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: interrupted
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMThread_interrupted(JNIEnv *env, jclass clazz)
-{
-#if defined(ENABLE_THREADS)
- threadobject *t;
- int32_t interrupted;
-
- t = thread_get_current();
-
- interrupted = thread_is_interrupted(t);
-
- if (interrupted)
- thread_set_interrupted(t, false);
-
- return interrupted;
-#else
- return 0;
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: holdsLock
- * Signature: (Ljava/lang/Object;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_VMThread_holdsLock(JNIEnv *env, jclass clazz, java_lang_Object* o)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *h;
-
- h = (java_handle_t *) o;
-
- if (h == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- return lock_is_held_by_current_thread(h);
-#else
- return 0;
-#endif
-}
-
-
-/*
- * Class: java/lang/VMThread
- * Method: getState
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMThread_getState(JNIEnv *env, java_lang_VMThread *this)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *h;
- threadobject *t;
- int state;
- utf *u;
- java_handle_t *o;
-
- h = (java_handle_t *) this;
- t = thread_get_thread(h);
-
- state = cacaothread_get_state(t);
-
- switch (state) {
- case THREAD_STATE_NEW:
- u = utf_new_char("NEW");
- break;
- case THREAD_STATE_RUNNABLE:
- u = utf_new_char("RUNNABLE");
- break;
- case THREAD_STATE_BLOCKED:
- u = utf_new_char("BLOCKED");
- break;
- case THREAD_STATE_WAITING:
- u = utf_new_char("WAITING");
- break;
- case THREAD_STATE_TIMED_WAITING:
- u = utf_new_char("TIMED_WAITING");
- break;
- case THREAD_STATE_TERMINATED:
- u = utf_new_char("TERMINATED");
- break;
- default:
- vm_abort("Java_java_lang_VMThread_getState: unknown thread state %d", state);
-
- /* Keep compiler happy. */
-
- u = NULL;
- }
-
- o = javastring_new(u);
-
- return (java_lang_String *) o;
-#else
- return NULL;
-#endif
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMThread.cpp
+
+ 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 "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMThread.h"
+#endif
+
+#include "threads/lock-common.h"
+#include "threads/thread.hpp"
+
+#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMThread
+ * Method: countStackFrames
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_VMThread_countStackFrames(JNIEnv *env, jobject _this)
+{
+ log_println("Java_java_lang_VMThread_countStackFrames: Deprecated. Not implemented.");
+
+ return 0;
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: start
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_start(JNIEnv *env, jobject _this, jlong stacksize)
+{
+#if defined(ENABLE_THREADS)
+ java_lang_VMThread jlvmt(_this);
+
+ threads_thread_start(jlvmt.get_thread());
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: interrupt
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_interrupt(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+ threadobject *t;
+
+ h = (java_handle_t *) _this;
+ t = thread_get_thread(h);
+
+ threads_thread_interrupt(t);
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: isInterrupted
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_isInterrupted(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+ threadobject *t;
+
+ h = (java_handle_t *) _this;
+ t = thread_get_thread(h);
+
+ return thread_is_interrupted(t);
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: suspend
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_suspend(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ log_println("Java_java_lang_VMThread_suspend: Deprecated. Not implemented.");
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: resume
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_resume(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ log_println("Java_java_lang_VMThread_resume: Deprecated. Not implemented.");
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: nativeSetPriority
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeSetPriority(JNIEnv *env, jobject _this, jint priority)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+ threadobject *t;
+
+ h = (java_handle_t *) _this;
+ t = thread_get_thread(h);
+
+ threads_set_thread_priority(t->tid, priority);
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: nativeStop
+ * Signature: (Ljava/lang/Throwable;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeStop(JNIEnv *env, jobject _this, jobject t)
+{
+#if defined(ENABLE_THREADS)
+ log_println("Java_java_lang_VMThread_nativeStop: Deprecated. Not implemented.");
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: currentThread
+ * Signature: ()Ljava/lang/Thread;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMThread_currentThread(JNIEnv *env, jclass clazz)
+{
+ java_handle_t* h;
+
+ h = thread_get_current_object();
+
+ return (jobject) h;
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: yield
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_yield(JNIEnv *env, jclass clazz)
+{
+#if defined(ENABLE_THREADS)
+ threads_yield();
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: sleep
+ * Signature: (JI)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_VMThread_sleep(JNIEnv *env, jclass clazz, int64_t ms, int32_t ns)
+{
+#if defined(ENABLE_THREADS)
+ threads_sleep(ms, ns);
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: interrupted
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_interrupted(JNIEnv *env, jclass clazz)
+{
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+ int32_t interrupted;
+
+ t = thread_get_current();
+
+ interrupted = thread_is_interrupted(t);
+
+ if (interrupted)
+ thread_set_interrupted(t, false);
+
+ return interrupted;
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: holdsLock
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_holdsLock(JNIEnv *env, jclass clazz, jobject o)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+
+ h = (java_handle_t *) o;
+
+ if (h == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ return lock_is_held_by_current_thread(h);
+#else
+ return 0;
+#endif
+}
+
+
+/*
+ * Class: java/lang/VMThread
+ * Method: getState
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_VMThread_getState(JNIEnv *env, jobject _this)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+ threadobject *t;
+ int state;
+ utf *u;
+ java_handle_t *o;
+
+ h = (java_handle_t *) _this;
+ t = thread_get_thread(h);
+
+ state = cacaothread_get_state(t);
+
+ switch (state) {
+ case THREAD_STATE_NEW:
+ u = utf_new_char("NEW");
+ break;
+ case THREAD_STATE_RUNNABLE:
+ u = utf_new_char("RUNNABLE");
+ break;
+ case THREAD_STATE_BLOCKED:
+ u = utf_new_char("BLOCKED");
+ break;
+ case THREAD_STATE_WAITING:
+ u = utf_new_char("WAITING");
+ break;
+ case THREAD_STATE_TIMED_WAITING:
+ u = utf_new_char("TIMED_WAITING");
+ break;
+ case THREAD_STATE_TERMINATED:
+ u = utf_new_char("TERMINATED");
+ break;
+ default:
+ vm_abort("Java_java_lang_VMThread_getState: unknown thread state %d", state);
+
+ /* Keep compiler happy. */
+
+ u = NULL;
+ }
+
+ o = javastring_new(u);
+
+ return (jstring) o;
+#else
+ return NULL;
+#endif
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "countStackFrames", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_VMThread_countStackFrames },
+ { (char*) "start", (char*) "(J)V", (void*) (uintptr_t) &Java_java_lang_VMThread_start },
+ { (char*) "interrupt", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_VMThread_interrupt },
+ { (char*) "isInterrupted", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_VMThread_isInterrupted },
+ { (char*) "suspend", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_VMThread_suspend },
+ { (char*) "resume", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_VMThread_resume },
+ { (char*) "nativeSetPriority", (char*) "(I)V", (void*) (uintptr_t) &Java_java_lang_VMThread_nativeSetPriority },
+ { (char*) "nativeStop", (char*) "(Ljava/lang/Throwable;)V", (void*) (uintptr_t) &Java_java_lang_VMThread_nativeStop },
+ { (char*) "currentThread", (char*) "()Ljava/lang/Thread;", (void*) (uintptr_t) &Java_java_lang_VMThread_currentThread },
+ { (char*) "yield", (char*) "()V", (void*) (uintptr_t) &Java_java_lang_VMThread_yield },
+ { (char*) "sleep", (char*) "(JI)V", (void*) (uintptr_t) &Java_java_lang_VMThread_sleep },
+ { (char*) "interrupted", (char*) "()Z", (void*) (uintptr_t) &Java_java_lang_VMThread_interrupted },
+ { (char*) "holdsLock", (char*) "(Ljava/lang/Object;)Z", (void*) (uintptr_t) &Java_java_lang_VMThread_holdsLock },
+ { (char*) "getState", (char*) "()Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_VMThread_getState },
+};
+
+
+/* _Jv_java_lang_VMThread_init *************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_VMThread_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMThread");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_VMThrowable.c
-
- 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 "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_StackTraceElement.h"
-#include "native/include/java_lang_Throwable.h"
-
-#include "native/include/java_lang_VMThrowable.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-
-#include "vm/jit/code.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "fillInStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/VMThrowable;", (void *) (ptrint) &Java_java_lang_VMThrowable_fillInStackTrace },
- { "getStackTrace", "(Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;", (void *) (ptrint) &Java_java_lang_VMThrowable_getStackTrace },
-};
-
-
-/* _Jv_java_lang_VMThrowable_init **********************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_VMThrowable_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/VMThrowable");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/VMThrowable
- * Method: fillInStackTrace
- * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable;
- */
-JNIEXPORT java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, java_lang_Throwable *t)
-{
- java_lang_VMThrowable *vmto;
- java_handle_bytearray_t *ba;
- java_lang_Object *o;
-
- vmto = (java_lang_VMThrowable *)
- native_new_and_init(class_java_lang_VMThrowable);
-
- if (vmto == NULL)
- return NULL;
-
- ba = stacktrace_get_current();
-
- if (ba == NULL)
- return NULL;
-
- o = (java_lang_Object *) ba;
-
- LLNI_field_set_ref(vmto, vmdata, o);
-
- return vmto;
-}
-
-
-/*
- * Class: java/lang/VMThrowable
- * Method: getStackTrace
- * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, java_lang_VMThrowable *this, java_lang_Throwable *t)
-{
- java_lang_Object *o;
- java_handle_bytearray_t *ba;
- stacktrace_t *st;
- stacktrace_entry_t *ste;
- java_handle_objectarray_t *oa;
- java_lang_StackTraceElement *steo;
- codeinfo *code;
- methodinfo *m;
- java_lang_String *filename;
- s4 linenumber;
- java_handle_t *declaringclass;
- int i;
-
- /* Get the stacktrace from the VMThrowable object. */
-
- LLNI_field_get_ref(this, vmdata, o);
-
- ba = (java_handle_bytearray_t *) o;
-
- st = (stacktrace_t *) LLNI_array_data(ba);
-
- assert(st != NULL);
-
- ste = st->entries;
-
- /* Create the stacktrace element array. */
-
- oa = builtin_anewarray(st->length, class_java_lang_StackTraceElement);
-
- if (oa == NULL)
- return NULL;
-
- for (i = 0; i < st->length; i++, ste++) {
- /* allocate a new stacktrace element */
-
- steo = (java_lang_StackTraceElement *)
- builtin_new(class_java_lang_StackTraceElement);
-
- if (steo == NULL)
- return NULL;
-
- /* Get the codeinfo and methodinfo. */
-
- code = ste->code;
- m = code->m;
-
- /* Get filename. */
-
- if (!(m->flags & ACC_NATIVE)) {
- if (m->clazz->sourcefile)
- filename = (java_lang_String *) javastring_new(m->clazz->sourcefile);
- else
- filename = NULL;
- }
- else
- filename = NULL;
-
- /* get line number */
-
- if (m->flags & ACC_NATIVE) {
- linenumber = -1;
- }
- else {
- /* FIXME The linenumbertable_linenumber_for_pc could
- change the methodinfo pointer when hitting an inlined
- method. */
-
- linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
- linenumber = (linenumber == 0) ? -1 : linenumber;
- }
-
- /* get declaring class name */
-
- declaringclass = class_get_classname(m->clazz);
-
- /* Fill the java.lang.StackTraceElement object. */
-
- LLNI_field_set_ref(steo, fileName , filename);
- LLNI_field_set_val(steo, lineNumber , linenumber);
- LLNI_field_set_ref(steo, declaringClass, (java_lang_String*) declaringclass);
- LLNI_field_set_ref(steo, methodName , (java_lang_String *) javastring_new(m->name));
- LLNI_field_set_val(steo, isNative , (m->flags & ACC_NATIVE) ? 1 : 0);
-
- array_objectarray_element_set(oa, i, (java_handle_t *) steo);
- }
-
- return oa;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_VMThrowable.cpp
+
+ 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 <assert.h>
+
+#include "vm/types.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMThrowable.h"
+#endif
+
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/string.hpp"
+
+#include "vm/jit/code.h"
+#include "vm/jit/linenumbertable.h"
+#include "vm/jit/stacktrace.hpp"
+
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/VMThrowable
+ * Method: fillInStackTrace
+ * Signature: (Ljava/lang/Throwable;)Ljava/lang/VMThrowable;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, jobject t)
+{
+ java_handle_t* h;
+ java_handle_bytearray_t* ba;
+
+ h = native_new_and_init(class_java_lang_VMThrowable);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_VMThrowable vmt(h);
+
+ ba = stacktrace_get_current();
+
+ if (ba == NULL)
+ return NULL;
+
+ vmt.set_vmdata(ba);
+
+ return (jobject) vmt.get_handle();
+}
+
+
+/*
+ * Class: java/lang/VMThrowable
+ * Method: getStackTrace
+ * Signature: (Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, jobject _this, jobject t)
+{
+ java_lang_VMThrowable vmt(_this);
+
+ // Get the stacktrace from the VMThrowable object.
+
+ java_handle_bytearray_t* ba = vmt.get_vmdata();
+
+ // XXX Critical GC section?
+ stacktrace_t* st = (stacktrace_t*) LLNI_array_data(ba);
+
+ assert(st != NULL);
+
+ stacktrace_entry_t* ste = st->entries;
+
+ /* Create the stacktrace element array. */
+
+ java_handle_objectarray_t* oa = builtin_anewarray(st->length, class_java_lang_StackTraceElement);
+
+ if (oa == NULL)
+ return NULL;
+
+ for (int i = 0; i < st->length; i++, ste++) {
+ /* Get the codeinfo and methodinfo. */
+
+ codeinfo* code = ste->code;
+ methodinfo* m = code->m;
+
+ /* Get filename. */
+
+ java_handle_t* filename;
+
+ if (!(m->flags & ACC_NATIVE)) {
+ if (m->clazz->sourcefile)
+ filename = javastring_new(m->clazz->sourcefile);
+ else
+ filename = NULL;
+ }
+ else
+ filename = NULL;
+
+ /* get line number */
+
+ int32_t linenumber;
+
+ if (m->flags & ACC_NATIVE) {
+ linenumber = -1;
+ }
+ else {
+ /* FIXME The linenumbertable_linenumber_for_pc could
+ change the methodinfo pointer when hitting an inlined
+ method. */
+
+ linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
+ linenumber = (linenumber == 0) ? -1 : linenumber;
+ }
+
+ /* get declaring class name */
+
+ java_handle_t* declaringclass = class_get_classname(m->clazz);
+
+ /* allocate a new stacktrace element */
+
+ java_handle_t* h = builtin_new(class_java_lang_StackTraceElement);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_StackTraceElement ste(h, filename, linenumber, declaringclass, javastring_new(m->name), ((m->flags & ACC_NATIVE) ? 1 : 0));
+
+ array_objectarray_element_set(oa, i, ste.get_handle());
+ }
+
+ return (jobjectArray) oa;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "fillInStackTrace", (char*) "(Ljava/lang/Throwable;)Ljava/lang/VMThrowable;", (void*) (uintptr_t) &Java_java_lang_VMThrowable_fillInStackTrace },
+ { (char*) "getStackTrace", (char*) "(Ljava/lang/Throwable;)[Ljava/lang/StackTraceElement;", (void*) (uintptr_t) &Java_java_lang_VMThrowable_getStackTrace },
+};
+
+
+/* _Jv_java_lang_VMThrowable_init **********************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+extern "C" {
+void _Jv_java_lang_VMThrowable_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/VMThrowable");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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:
+ */
-/* src/native/vm/gnu/java_lang_management_VMManagementFactory.c
+/* src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.c
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/jni.h"
#include "native/native.h"
-#include "native/include/java_lang_management_VMManagementFactory.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_management_VMManagementFactory.h"
+#endif
#include "toolbox/logging.h"
#include "vm/builtin.h"
-
-#include "vmcore/class.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getMemoryPoolNames", "()[Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_management_VMManagementFactory_getMemoryPoolNames },
- { "getMemoryManagerNames", "()[Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_management_VMManagementFactory_getMemoryManagerNames },
- { "getGarbageCollectorNames", "()[Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames },
-};
-
-
-/* _Jv_java_lang_management_VMManagementFactory_init ***************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_management_VMManagementFactory_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/management/VMManagementFactory");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+#include "vm/globals.hpp"
/*
* Method: getMemoryPoolNames
* Signature: ()[Ljava/lang/String;
*/
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_management_VMManagementFactory_getMemoryPoolNames(JNIEnv *env, jclass clazz)
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryPoolNames(JNIEnv *env, jclass clazz)
{
java_handle_objectarray_t *oa;
* Method: getMemoryManagerNames
* Signature: ()[Ljava/lang/String;
*/
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_management_VMManagementFactory_getMemoryManagerNames(JNIEnv *env, jclass clazz)
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryManagerNames(JNIEnv *env, jclass clazz)
{
java_handle_objectarray_t *oa;
* Method: getGarbageCollectorNames
* Signature: ()[Ljava/lang/String;
*/
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames(JNIEnv *env, jclass clazz)
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames(JNIEnv *env, jclass clazz)
{
java_handle_objectarray_t *oa;
}
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { "getMemoryPoolNames", "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryPoolNames },
+ { "getMemoryManagerNames", "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryManagerNames },
+ { "getGarbageCollectorNames", "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames },
+};
+
+
+/* _Jv_java_lang_management_VMManagementFactory_init ***************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+void _Jv_java_lang_management_VMManagementFactory_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/management/VMManagementFactory");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+
+
/*
* 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
+++ /dev/null
-/* src/native/vm/gnu/java_lang_reflect_VMConstructor.c
-
- 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 <stdlib.h>
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "vm/vm.h"
-#include "vm/exceptions.h"
-#endif
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-# include "native/include/java_util_Map.h"
-# include "native/include/sun_reflect_ConstantPool.h"
-#endif
-
-#include "native/include/java_lang_reflect_Constructor.h"
-#include "native/include/java_lang_reflect_VMConstructor.h"
-
-#include "native/vm/reflect.h"
-
-#include "vm/stringlocal.h"
-
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getModifiersInternal", "()I", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getModifiersInternal },
- { "getParameterTypes", "()[Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getParameterTypes },
- { "getExceptionTypes", "()[Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getExceptionTypes },
- { "construct", "([Ljava/lang/Object;)Ljava/lang/Object;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_construct },
- { "getSignature", "()Ljava/lang/String;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getSignature },
-#if defined(ENABLE_ANNOTATIONS)
- { "declaredAnnotations", "()Ljava/util/Map;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_declaredAnnotations },
- { "getParameterAnnotations", "()[[Ljava/lang/annotation/Annotation;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getParameterAnnotations },
-#endif
-};
-
-
-/* _Jv_java_lang_reflect_VMConstructor_init ************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_reflect_VMConstructor_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/reflect/VMConstructor");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/reflect/VMConstructor
- * Method: getModifiersInternal
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMConstructor_getModifiersInternal(JNIEnv *env, java_lang_reflect_VMConstructor *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot, slot);
-
- m = &(c->methods[slot]);
-
- return m->flags;
-}
-
-
-/*
- * Class: java/lang/reflect/VMConstructor
- * Method: getParameterTypes
- * Signature: ()[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMConstructor_getParameterTypes(JNIEnv *env, java_lang_reflect_VMConstructor *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot, slot);
-
- m = &(c->methods[slot]);
-
- return method_get_parametertypearray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/VMConstructor
- * Method: getExceptionTypes
- * Signature: ()[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMConstructor_getExceptionTypes(JNIEnv *env, java_lang_reflect_VMConstructor *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot, slot);
-
- m = &(c->methods[slot]);
-
- return method_get_exceptionarray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/VMConstructor
- * Method: construct
- * Signature: ([Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_VMConstructor_construct(JNIEnv *env, java_lang_reflect_VMConstructor *this, java_handle_objectarray_t *args)
-{
- classinfo *c;
- int32_t slot;
- java_lang_reflect_Constructor *rc;
- int32_t override;
- methodinfo *m;
- java_handle_t *o;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot, slot);
-
- LLNI_field_get_ref(this, cons, rc);
- LLNI_field_get_val(rc, flag, override);
-
- m = &(c->methods[slot]);
-
- o = reflect_constructor_newinstance(m, args, override);
-
- return (java_lang_Object *) o;
-}
-
-
-/*
- * Class: java/lang/reflect/VMConstructor
- * Method: getSignature
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_VMConstructor_getSignature(JNIEnv *env, java_lang_reflect_VMConstructor *this)
-{
- classinfo *c;
- methodinfo *m;
- java_handle_t *o;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot, slot);
-
- m = &(c->methods[slot]);
-
- if (m->signature == NULL)
- return NULL;
-
- o = javastring_new(m->signature);
-
- /* In error case o is NULL. */
-
- return (java_lang_String *) o;
-}
-
-
-#if defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/reflect/VMConstructor
- * Method: declaredAnnotations
- * Signature: ()Ljava/util/Map;
- *
- * Parses the annotations (if they aren't parsed yet) and stores them into
- * the declaredAnnotations map and return this map.
- */
-JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_VMConstructor_declaredAnnotations(JNIEnv *env, java_lang_reflect_VMConstructor *this)
-{
- java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
-
- /* are the annotations parsed yet? */
- if (declaredAnnotations == NULL) {
- LLNI_field_get_ref(this, annotations, annotations);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
-
- LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
- }
-
- return declaredAnnotations;
-}
-
-
-/*
- * Class: java/lang/reflect/VMConstructor
- * Method: getParameterAnnotations
- * Signature: ()[[Ljava/lang/annotation/Annotation;
- *
- * Parses the parameter annotations and returns them in an 2 dimensional array.
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMConstructor_getParameterAnnotations(JNIEnv *env, java_lang_reflect_VMConstructor *this)
-{
- java_handle_bytearray_t *parameterAnnotations = NULL; /* unparsed parameter annotations */
- int32_t slot = -1; /* slot of the method */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, parameterAnnotations, parameterAnnotations);
- LLNI_field_get_val(this, slot, slot);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- return reflect_get_parameterannotations((java_handle_t*)parameterAnnotations, slot, declaringClass, referer);
-}
-#endif
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_reflect_VMConstructor.cpp
+
+ 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 <stdlib.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_reflect_VMConstructor.h"
+#endif
+
+#include "native/vm/reflection.hpp"
+
+#include "vm/javaobjects.hpp"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_VMConstructor_getModifiersInternal(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMConstructor rvmc(_this);
+ methodinfo* m = rvmc.get_method();
+ return m->flags;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getParameterTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMConstructor_getParameterTypes(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMConstructor rvmc(_this);
+ methodinfo* m = rvmc.get_method();
+
+ java_handle_objectarray_t* hoa = method_get_parametertypearray(m);
+
+ return (jobjectArray) hoa;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getExceptionTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMConstructor_getExceptionTypes(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMConstructor rvmc(_this);
+ methodinfo* m = rvmc.get_method();
+
+ java_handle_objectarray_t* hoa = method_get_exceptionarray(m);
+
+ return (jobjectArray) hoa;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: construct
+ * Signature: ([Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMConstructor_construct(JNIEnv *env, jobject _this, jobjectArray args)
+{
+ java_lang_reflect_VMConstructor jlrvmc(_this);
+ java_lang_reflect_Constructor jlrc(jlrvmc.get_cons());
+
+ java_handle_t* o = jlrc.new_instance((java_handle_objectarray_t*) args);
+
+ return (jobject) o;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_reflect_VMConstructor_getSignature(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMConstructor rvmc(_this);
+ methodinfo* m = rvmc.get_method();
+ java_handle_t *o;
+
+ if (m->signature == NULL)
+ return NULL;
+
+ o = javastring_new(m->signature);
+
+ /* In error case o is NULL. */
+
+ return (jstring) o;
+}
+
+
+#if defined(ENABLE_ANNOTATIONS)
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: declaredAnnotations
+ * Signature: ()Ljava/util/Map;
+ *
+ * Parses the annotations (if they aren't parsed yet) and stores them into
+ * the declaredAnnotations map and return this map.
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMConstructor_declaredAnnotations(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMConstructor rvmc(_this);
+
+ java_handle_t* declaredAnnotations = rvmc.get_declaredAnnotations();
+
+ /* are the annotations parsed yet? */
+ if (declaredAnnotations == NULL) {
+ java_handle_bytearray_t* annotations = rvmc.get_annotations();
+ classinfo* declaringClass = rvmc.get_clazz();
+
+ classinfo *referer;
+ LLNI_class_get(_this, referer);
+
+ declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
+
+ rvmc.set_declaredAnnotations(declaredAnnotations);
+ }
+
+ return (jobject) declaredAnnotations;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getParameterAnnotations
+ * Signature: ()[[Ljava/lang/annotation/Annotation;
+ *
+ * Parses the parameter annotations and returns them in an 2 dimensional array.
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMConstructor_getParameterAnnotations(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMConstructor rvmc(_this);
+
+ java_handle_bytearray_t* parameterAnnotations = rvmc.get_parameterAnnotations();
+ methodinfo* m = rvmc.get_method();
+
+ classinfo* referer;
+ LLNI_class_get((java_lang_reflect_VMConstructor*) _this, referer);
+
+ java_handle_objectarray_t* oa = Reflection::get_parameterannotations(parameterAnnotations, m, referer);
+
+ return (jobjectArray) oa;
+}
+#endif
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getModifiersInternal", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_reflect_VMConstructor_getModifiersInternal },
+ { (char*) "getParameterTypes", (char*) "()[Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_reflect_VMConstructor_getParameterTypes },
+ { (char*) "getExceptionTypes", (char*) "()[Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_reflect_VMConstructor_getExceptionTypes },
+ { (char*) "construct", (char*) "([Ljava/lang/Object;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_java_lang_reflect_VMConstructor_construct },
+ { (char*) "getSignature", (char*) "()Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_reflect_VMConstructor_getSignature },
+#if defined(ENABLE_ANNOTATIONS)
+ { (char*) "declaredAnnotations", (char*) "()Ljava/util/Map;", (void*) (uintptr_t) &Java_java_lang_reflect_VMConstructor_declaredAnnotations },
+ { (char*) "getParameterAnnotations", (char*) "()[[Ljava/lang/annotation/Annotation;", (void*) (uintptr_t) &Java_java_lang_reflect_VMConstructor_getParameterAnnotations },
+#endif
+};
+
+
+/* _Jv_java_lang_reflect_VMConstructor_init ************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+extern "C" {
+void _Jv_java_lang_reflect_VMConstructor_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/reflect/VMConstructor");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_reflect_VMField.c
-
- 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 <stdint.h>
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Boolean.h"
-#include "native/include/java_lang_Byte.h"
-#include "native/include/java_lang_Character.h"
-#include "native/include/java_lang_Short.h"
-#include "native/include/java_lang_Integer.h"
-#include "native/include/java_lang_Long.h"
-#include "native/include/java_lang_Float.h"
-#include "native/include/java_lang_Double.h"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_String.h"
-
-#include "native/include/java_lang_reflect_Field.h"
-#include "native/include/java_lang_reflect_VMField.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "native/include/java_util_Map.h"
-#include "native/include/sun_reflect_ConstantPool.h"
-#include "native/vm/reflect.h"
-#endif
-
-#include "vm/access.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-#include "vm/primitive.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getModifiersInternal", "()I", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getModifiersInternal },
- { "getType", "()Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getType },
- { "get", "(Ljava/lang/Object;)Ljava/lang/Object;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_get },
- { "getBoolean", "(Ljava/lang/Object;)Z", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getBoolean },
- { "getByte", "(Ljava/lang/Object;)B", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getByte },
- { "getChar", "(Ljava/lang/Object;)C", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getChar },
- { "getShort", "(Ljava/lang/Object;)S", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getShort },
- { "getInt", "(Ljava/lang/Object;)I", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getInt },
- { "getLong", "(Ljava/lang/Object;)J", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getLong },
- { "getFloat", "(Ljava/lang/Object;)F", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getFloat },
- { "getDouble", "(Ljava/lang/Object;)D", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getDouble },
- { "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_set },
- { "setBoolean", "(Ljava/lang/Object;Z)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setBoolean },
- { "setByte", "(Ljava/lang/Object;B)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setByte },
- { "setChar", "(Ljava/lang/Object;C)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setChar },
- { "setShort", "(Ljava/lang/Object;S)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setShort },
- { "setInt", "(Ljava/lang/Object;I)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setInt },
- { "setLong", "(Ljava/lang/Object;J)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setLong },
- { "setFloat", "(Ljava/lang/Object;F)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setFloat },
- { "setDouble", "(Ljava/lang/Object;D)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setDouble },
- { "getSignature", "()Ljava/lang/String;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getSignature },
-#if defined(ENABLE_ANNOTATIONS)
- { "declaredAnnotations", "()Ljava/util/Map;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_declaredAnnotations },
-#endif
-};
-
-
-/* _Jv_java_lang_reflect_VMField_init ******************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_reflect_VMField_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/reflect/VMField");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/* _field_access_check *********************************************************
-
- Checks if the field can be accessed.
-
- RETURN VALUE:
- true......field can be accessed, or
- false.....otherwise (maybe an Exception was thrown).
-
-*******************************************************************************/
-
-static bool _field_access_check(java_lang_reflect_VMField *this,
- fieldinfo *f, classinfo *c, java_handle_t *o)
-{
- java_lang_reflect_Field *rf;
- int32_t flag;
-
- /* check if we should bypass security checks (AccessibleObject) */
-
- LLNI_field_get_ref(this, f, rf);
- LLNI_field_get_val(rf, flag, flag);
-
- if (flag == false) {
- /* This function is always called like this:
- [0] java.lang.reflect.VMField.xxx (Native Method)
- [1] java.lang.reflect.Field.xxx
- [2] <caller>
- */
-
- if (!access_check_field(f, 2))
- return false;
- }
-
- /* some general checks */
-
- if (f->flags & ACC_STATIC) {
- /* initialize class if required */
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return false;
-
- /* everything is ok */
-
- return true;
- }
- else {
- /* obj is required for not-static fields */
-
- if (o == NULL) {
- exceptions_throw_nullpointerexception();
- return false;
- }
-
- if (builtin_instanceof(o, c))
- return true;
- }
-
- /* exception path */
-
- exceptions_throw_illegalargumentexception();
- return false;
-}
-
-
-/* _field_get_type *************************************************************
-
- Returns the content of the given field.
-
-*******************************************************************************/
-
-#define _FIELD_GET_TYPE(name, type, uniontype) \
-static inline type _field_get_##name(fieldinfo *f, java_lang_Object *o) \
-{ \
- type ret; \
- if (f->flags & ACC_STATIC) { \
- ret = f->value->uniontype; \
- } else { \
- LLNI_CRITICAL_START; \
- ret = *(type *) (((intptr_t) LLNI_DIRECT(o)) + f->offset); \
- LLNI_CRITICAL_END; \
- } \
- return ret; \
-}
-
-static inline java_handle_t *_field_get_handle(fieldinfo *f, java_lang_Object *o)
-{
- java_object_t *obj;
- java_handle_t *hdl;
-
- LLNI_CRITICAL_START;
-
- if (f->flags & ACC_STATIC) {
- obj = f->value->a;
- } else {
- obj = *(java_object_t **) (((intptr_t) LLNI_DIRECT(o)) + f->offset);
- }
-
- hdl = LLNI_WRAP(obj);
-
- LLNI_CRITICAL_END;
-
- return hdl;
-}
-
-_FIELD_GET_TYPE(int, int32_t, i)
-_FIELD_GET_TYPE(long, int64_t, l)
-_FIELD_GET_TYPE(float, float, f)
-_FIELD_GET_TYPE(double, double, d)
-
-
-/* _field_set_type *************************************************************
-
- Sets the content of the given field to the given value.
-
-*******************************************************************************/
-
-#define _FIELD_SET_TYPE(name, type, uniontype) \
-static inline void _field_set_##name(fieldinfo *f, java_lang_Object *o, type value) \
-{ \
- if (f->flags & ACC_STATIC) { \
- f->value->uniontype = value; \
- } else { \
- LLNI_CRITICAL_START; \
- *(type *) (((intptr_t) LLNI_DIRECT(o)) + f->offset) = value; \
- LLNI_CRITICAL_END; \
- } \
-}
-
-static inline void _field_set_handle(fieldinfo *f, java_lang_Object *o, java_handle_t *value)
-{
- LLNI_CRITICAL_START;
-
- if (f->flags & ACC_STATIC) {
- f->value->a = LLNI_DIRECT(value);
- } else {
- *(java_object_t **) (((intptr_t) LLNI_DIRECT(o)) + f->offset) = LLNI_DIRECT(value);
- }
-
- LLNI_CRITICAL_END;
-}
-
-_FIELD_SET_TYPE(int, int32_t, i)
-_FIELD_SET_TYPE(long, int64_t, l)
-_FIELD_SET_TYPE(float, float, f)
-_FIELD_SET_TYPE(double, double, d)
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getModifiersInternal
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getModifiersInternal(JNIEnv *env, java_lang_reflect_VMField *this)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &(c->fields[slot]);
-
- return f->flags;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getType
- * Signature: ()Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_reflect_VMField_getType(JNIEnv *env, java_lang_reflect_VMField *this)
-{
- classinfo *c;
- typedesc *desc;
- classinfo *ret;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- desc = c->fields[slot].parseddesc;
-
- if (desc == NULL)
- return NULL;
-
- if (!resolve_class_from_typedesc(desc, true, false, &ret))
- return NULL;
-
- return LLNI_classinfo_wrap(ret);
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: get
- * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_VMField_get(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
- imm_union value;
- java_handle_t *object;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return NULL;
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- value.i = _field_get_int(f, o);
- break;
-
- case PRIMITIVETYPE_LONG:
- value.l = _field_get_long(f, o);
- break;
-
- case PRIMITIVETYPE_FLOAT:
- value.f = _field_get_float(f, o);
- break;
-
- case PRIMITIVETYPE_DOUBLE:
- value.d = _field_get_double(f, o);
- break;
-
- case TYPE_ADR:
- return (java_lang_Object *) _field_get_handle(f, o);
- }
-
- /* Now box the primitive types. */
-
- object = primitive_box(f->parseddesc->decltype, value);
-
- return (java_lang_Object *) object;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getBoolean
- * Signature: (Ljava/lang/Object;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getBoolean(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getByte
- * Signature: (Ljava/lang/Object;)B
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getByte(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getChar
- * Signature: (Ljava/lang/Object;)C
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getChar(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_CHAR:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getShort
- * Signature: (Ljava/lang/Object;)S
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getShort(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getInt
- * Signature: (Ljava/lang/Object;)I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getInt(JNIEnv *env , java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getLong
- * Signature: (Ljava/lang/Object;)J
- */
-JNIEXPORT int64_t JNICALL Java_java_lang_reflect_VMField_getLong(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (int64_t) _field_get_int(f, o);
- case PRIMITIVETYPE_LONG:
- return (int64_t) _field_get_long(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getFloat
- * Signature: (Ljava/lang/Object;)F
- */
-JNIEXPORT float JNICALL Java_java_lang_reflect_VMField_getFloat(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (float) _field_get_int(f, o);
- case PRIMITIVETYPE_LONG:
- return (float) _field_get_long(f, o);
- case PRIMITIVETYPE_FLOAT:
- return (float) _field_get_float(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getDouble
- * Signature: (Ljava/lang/Object;)D
- */
-JNIEXPORT double JNICALL Java_java_lang_reflect_VMField_getDouble(JNIEnv *env , java_lang_reflect_VMField *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (double) _field_get_int(f, o);
- case PRIMITIVETYPE_LONG:
- return (double) _field_get_long(f, o);
- case PRIMITIVETYPE_FLOAT:
- return (double) _field_get_float(f, o);
- case PRIMITIVETYPE_DOUBLE:
- return (double) _field_get_double(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: set
- * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, java_lang_Object *value)
-{
- classinfo *sc;
- classinfo *dc;
- fieldinfo *sf;
- fieldinfo *df;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, dc);
- LLNI_field_get_val(this, slot , slot);
- df = &dc->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, df, dc, (java_handle_t *) o))
- return;
-
- /* get the source classinfo from the object */
-
- if (value == NULL)
- sc = NULL;
- else
- LLNI_class_get(value, sc);
-
- /* The fieldid is used to set the new value, for primitive
- types the value has to be retrieved from the wrapping
- object */
-
- switch (df->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN: {
- int32_t val;
-
- /* determine the field to read the value */
-
- if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_Z)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- LLNI_field_get_val((java_lang_Boolean *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_BYTE: {
- int32_t val;
-
- if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_B)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_CHAR: {
- int32_t val;
-
- if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_C)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_SHORT: {
- int32_t val;
-
- /* get field only by name, it can be one of B, S */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_INT: {
- int32_t val;
-
- /* get field only by name, it can be one of B, S, C, I */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_LONG: {
- int64_t val;
-
- /* get field only by name, it can be one of B, S, C, I, J */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- case PRIMITIVETYPE_LONG:
- LLNI_field_get_val((java_lang_Long *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_long(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_FLOAT: {
- float val;
-
- /* get field only by name, it can be one of B, S, C, I, J, F */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- case PRIMITIVETYPE_LONG:
- LLNI_field_get_val((java_lang_Long *) value, value, val);
- break;
- case PRIMITIVETYPE_FLOAT:
- LLNI_field_get_val((java_lang_Float *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_float(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_DOUBLE: {
- double val;
-
- /* get field only by name, it can be one of B, S, C, I, J, F, D */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- case PRIMITIVETYPE_LONG:
- LLNI_field_get_val((java_lang_Long *) value, value, val);
- break;
- case PRIMITIVETYPE_FLOAT:
- LLNI_field_get_val((java_lang_Float *) value, value, val);
- break;
- case PRIMITIVETYPE_DOUBLE:
- LLNI_field_get_val((java_lang_Double *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_double(df, o, val);
- return;
- }
-
- case TYPE_ADR:
- /* check if value is an instance of the destination class */
-
- /* XXX TODO */
- /* if (!builtin_instanceof((java_handle_t *) value, df->class)) */
- /* break; */
-
- _field_set_handle(df, o, (java_handle_t *) value);
- return;
- }
-
- /* raise exception */
-
- exceptions_throw_illegalargumentexception();
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setBoolean
- * Signature: (Ljava/lang/Object;Z)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setBoolean(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- _field_set_int(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setByte
- * Signature: (Ljava/lang/Object;B)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setByte(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setChar
- * Signature: (Ljava/lang/Object;C)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setChar(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setShort
- * Signature: (Ljava/lang/Object;S)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setShort(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setInt
- * Signature: (Ljava/lang/Object;I)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setInt(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setLong
- * Signature: (Ljava/lang/Object;J)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setLong(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int64_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setFloat
- * Signature: (Ljava/lang/Object;F)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setFloat(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, float value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: setDouble
- * Signature: (Ljava/lang/Object;D)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setDouble(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, double value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/VMField
- * Method: getSignature
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_VMField_getSignature(JNIEnv *env, java_lang_reflect_VMField* this)
-{
- classinfo *c;
- fieldinfo *f;
- java_handle_t *o;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- if (f->signature == NULL)
- return NULL;
-
- o = javastring_new(f->signature);
-
- /* in error case o is NULL */
-
- return (java_lang_String *) o;
-}
-
-
-#if defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/reflect/VMField
- * Method: declaredAnnotations
- * Signature: ()Ljava/util/Map;
- */
-JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_VMField_declaredAnnotations(JNIEnv *env, java_lang_reflect_VMField *this)
-{
- java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
-
- /* are the annotations parsed yet? */
- if (declaredAnnotations == NULL) {
- LLNI_field_get_ref(this, annotations, annotations);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
-
- LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
- }
-
- return declaredAnnotations;
-}
-#endif
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_reflect_VMField.cpp
+
+ 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 <stdint.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_reflect_VMField.h"
+#endif
+
+#if defined(ENABLE_ANNOTATIONS)
+// REMOVEME
+# include "native/vm/reflection.hpp"
+#endif
+
+#include "vm/access.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/primitive.hpp"
+#include "vm/resolve.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+
+
+/* _field_access_check *********************************************************
+
+ Checks if the field can be accessed.
+
+ RETURN VALUE:
+ true......field can be accessed, or
+ false.....otherwise (maybe an Exception was thrown).
+
+*******************************************************************************/
+
+static bool _field_access_check(const java_lang_reflect_VMField& rvmf, fieldinfo *f, java_handle_t *o)
+{
+ // Check if we should bypass security checks (AccessibleObject).
+
+ java_lang_reflect_Field rf(rvmf.get_f());
+ int32_t override = rf.get_flag();
+
+ if (override == false) {
+ /* This function is always called like this:
+ [0] java.lang.reflect.VMField.xxx (Native Method)
+ [1] java.lang.reflect.Field.xxx
+ [2] <caller>
+ */
+
+ if (!access_check_field(f, 2))
+ return false;
+ }
+
+ /* some general checks */
+
+ if (f->flags & ACC_STATIC) {
+ /* initialize class if required */
+
+ if (!(f->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(f->clazz))
+ return false;
+
+ /* everything is ok */
+
+ return true;
+ }
+ else {
+ /* obj is required for not-static fields */
+
+ if (o == NULL) {
+ exceptions_throw_nullpointerexception();
+ return false;
+ }
+
+ if (builtin_instanceof(o, f->clazz))
+ return true;
+ }
+
+ /* exception path */
+
+ exceptions_throw_illegalargumentexception();
+ return false;
+}
+
+
+/* _field_get_type *************************************************************
+
+ Returns the content of the given field.
+
+*******************************************************************************/
+
+#define _FIELD_GET_TYPE(name, type, uniontype) \
+static inline type _field_get_##name(fieldinfo *f, java_handle_t* h) \
+{ \
+ type ret; \
+ if (f->flags & ACC_STATIC) { \
+ ret = f->value->uniontype; \
+ } else { \
+ LLNI_CRITICAL_START; \
+ ret = *(type *) (((intptr_t) LLNI_DIRECT(h)) + f->offset); \
+ LLNI_CRITICAL_END; \
+ } \
+ return ret; \
+}
+
+static inline java_handle_t *_field_get_handle(fieldinfo *f, java_handle_t* h)
+{
+ java_object_t* result;
+ java_handle_t* hresult;
+
+ LLNI_CRITICAL_START;
+
+ if (f->flags & ACC_STATIC) {
+ result = (java_object_t*) f->value->a;
+ } else {
+ result = *(java_object_t**) (((intptr_t) LLNI_DIRECT(h)) + f->offset);
+ }
+
+ hresult = LLNI_WRAP(result);
+
+ LLNI_CRITICAL_END;
+
+ return hresult;
+}
+
+_FIELD_GET_TYPE(int, int32_t, i)
+_FIELD_GET_TYPE(long, int64_t, l)
+_FIELD_GET_TYPE(float, float, f)
+_FIELD_GET_TYPE(double, double, d)
+
+
+/* _field_set_type *************************************************************
+
+ Sets the content of the given field to the given value.
+
+*******************************************************************************/
+
+#define _FIELD_SET_TYPE(name, type, uniontype) \
+static inline void _field_set_##name(fieldinfo* f, java_handle_t* h, type value) \
+{ \
+ if (f->flags & ACC_STATIC) { \
+ f->value->uniontype = value; \
+ } else { \
+ LLNI_CRITICAL_START; \
+ *(type *) (((intptr_t) LLNI_DIRECT(h)) + f->offset) = value; \
+ LLNI_CRITICAL_END; \
+ } \
+}
+
+static inline void _field_set_handle(fieldinfo* f, java_handle_t* h, java_handle_t* hvalue)
+{
+ LLNI_CRITICAL_START;
+
+ if (f->flags & ACC_STATIC) {
+ f->value->a = LLNI_DIRECT(hvalue);
+ } else {
+ *(java_object_t**) (((intptr_t) LLNI_DIRECT(h)) + f->offset) = LLNI_DIRECT(hvalue);
+ }
+
+ LLNI_CRITICAL_END;
+}
+
+_FIELD_SET_TYPE(int, int32_t, i)
+_FIELD_SET_TYPE(long, int64_t, l)
+_FIELD_SET_TYPE(float, float, f)
+_FIELD_SET_TYPE(double, double, d)
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_VMField_getModifiersInternal(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+ return f->flags;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getType
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_reflect_VMField_getType(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+ classinfo *ret;
+
+ typedesc* desc = f->parseddesc;
+
+ if (desc == NULL)
+ return NULL;
+
+ if (!resolve_class_from_typedesc(desc, true, false, &ret))
+ return NULL;
+
+ return (jclass) LLNI_classinfo_wrap(ret);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: get
+ * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMField_get(JNIEnv *env, jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return NULL;
+
+ imm_union value;
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ value.i = _field_get_int(f, ho);
+ break;
+
+ case PRIMITIVETYPE_LONG:
+ value.l = _field_get_long(f, ho);
+ break;
+
+ case PRIMITIVETYPE_FLOAT:
+ value.f = _field_get_float(f, ho);
+ break;
+
+ case PRIMITIVETYPE_DOUBLE:
+ value.d = _field_get_double(f, ho);
+ break;
+
+ case TYPE_ADR:
+ return (jobject) _field_get_handle(f, ho);
+ }
+
+ /* Now box the primitive types. */
+
+ java_handle_t* object = Primitive::box(f->parseddesc->primitivetype, value);
+
+ return (jobject) object;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getBoolean
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_lang_reflect_VMField_getBoolean(JNIEnv *env, jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ return (int32_t) _field_get_int(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getByte
+ * Signature: (Ljava/lang/Object;)B
+ */
+JNIEXPORT jbyte JNICALL Java_java_lang_reflect_VMField_getByte(JNIEnv *env, jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ return (int32_t) _field_get_int(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getChar
+ * Signature: (Ljava/lang/Object;)C
+ */
+JNIEXPORT jchar JNICALL Java_java_lang_reflect_VMField_getChar(JNIEnv *env, jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_CHAR:
+ return (int32_t) _field_get_int(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getShort
+ * Signature: (Ljava/lang/Object;)S
+ */
+JNIEXPORT jshort JNICALL Java_java_lang_reflect_VMField_getShort(JNIEnv *env, jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ return (int32_t) _field_get_int(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getInt
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_VMField_getInt(JNIEnv *env , jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (int32_t) _field_get_int(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getLong
+ * Signature: (Ljava/lang/Object;)J
+ */
+JNIEXPORT jlong JNICALL Java_java_lang_reflect_VMField_getLong(JNIEnv *env, jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (int64_t) _field_get_int(f, ho);
+ case PRIMITIVETYPE_LONG:
+ return (int64_t) _field_get_long(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getFloat
+ * Signature: (Ljava/lang/Object;)F
+ */
+JNIEXPORT jfloat JNICALL Java_java_lang_reflect_VMField_getFloat(JNIEnv *env, jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (float) _field_get_int(f, ho);
+ case PRIMITIVETYPE_LONG:
+ return (float) _field_get_long(f, ho);
+ case PRIMITIVETYPE_FLOAT:
+ return (float) _field_get_float(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getDouble
+ * Signature: (Ljava/lang/Object;)D
+ */
+JNIEXPORT jdouble JNICALL Java_java_lang_reflect_VMField_getDouble(JNIEnv *env , jobject _this, jobject o)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (jdouble) _field_get_int(f, ho);
+ case PRIMITIVETYPE_LONG:
+ return (jdouble) _field_get_long(f, ho);
+ case PRIMITIVETYPE_FLOAT:
+ return (jdouble) _field_get_float(f, ho);
+ case PRIMITIVETYPE_DOUBLE:
+ return (jdouble) _field_get_double(f, ho);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: set
+ * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, jobject _this, jobject o, jobject value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* df = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+ java_handle_t* hvalue = (java_handle_t*) value;
+
+ classinfo *sc;
+ fieldinfo *sf;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, df, ho))
+ return;
+
+ /* get the source classinfo from the object */
+
+ if (hvalue == NULL)
+ sc = NULL;
+ else
+ LLNI_class_get(hvalue, sc);
+
+ /* The fieldid is used to set the new value, for primitive
+ types the value has to be retrieved from the wrapping
+ object */
+
+ switch (df->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BOOLEAN: {
+ int32_t val;
+
+ /* determine the field to read the value */
+
+ if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_Z)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ val = java_lang_Boolean(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, ho, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_BYTE: {
+ int32_t val;
+
+ if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_B)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ val = java_lang_Byte(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, ho, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_CHAR: {
+ int32_t val;
+
+ if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_C)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_CHAR:
+ val = java_lang_Character(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, ho, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_SHORT: {
+ int32_t val;
+
+ /* get field only by name, it can be one of B, S */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ val = java_lang_Byte(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_SHORT:
+ val = java_lang_Short(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, ho, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_INT: {
+ int32_t val;
+
+ /* get field only by name, it can be one of B, S, C, I */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ val = java_lang_Byte(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_CHAR:
+ val = java_lang_Character(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_SHORT:
+ val = java_lang_Short(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_INT:
+ val = java_lang_Integer(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, ho, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_LONG: {
+ int64_t val;
+
+ /* get field only by name, it can be one of B, S, C, I, J */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ val = java_lang_Byte(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_CHAR:
+ val = java_lang_Character(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_SHORT:
+ val = java_lang_Short(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_INT:
+ val = java_lang_Integer(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_LONG:
+ val = java_lang_Long(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_long(df, ho, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_FLOAT: {
+ float val;
+
+ /* get field only by name, it can be one of B, S, C, I, J, F */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ val = java_lang_Byte(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_CHAR:
+ val = java_lang_Character(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_SHORT:
+ val = java_lang_Short(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_INT:
+ val = java_lang_Integer(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_LONG:
+ val = java_lang_Long(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ val = java_lang_Float(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_float(df, ho, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_DOUBLE: {
+ double val;
+
+ /* get field only by name, it can be one of B, S, C, I, J, F, D */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ val = java_lang_Byte(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_CHAR:
+ val = java_lang_Character(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_SHORT:
+ val = java_lang_Short(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_INT:
+ val = java_lang_Integer(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_LONG:
+ val = java_lang_Long(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ val = java_lang_Float(hvalue).get_value();
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ val = java_lang_Double(hvalue).get_value();
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_double(df, ho, val);
+ return;
+ }
+
+ case TYPE_ADR:
+ /* check if value is an instance of the destination class */
+
+ /* XXX TODO */
+ /* if (!builtin_instanceof((java_handle_t *) value, df->class)) */
+ /* break; */
+
+ _field_set_handle(df, ho, hvalue);
+ return;
+ }
+
+ /* raise exception */
+
+ exceptions_throw_illegalargumentexception();
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setBoolean
+ * Signature: (Ljava/lang/Object;Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setBoolean(JNIEnv *env, jobject _this, jobject o, jboolean value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ _field_set_int(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setByte
+ * Signature: (Ljava/lang/Object;B)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setByte(JNIEnv *env, jobject _this, jobject o, jbyte value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, ho, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, ho, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, ho, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setChar
+ * Signature: (Ljava/lang/Object;C)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setChar(JNIEnv *env, jobject _this, jobject o, jchar value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, ho, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, ho, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, ho, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setShort
+ * Signature: (Ljava/lang/Object;S)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setShort(JNIEnv *env, jobject _this, jobject o, jshort value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, ho, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, ho, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, ho, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setInt
+ * Signature: (Ljava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setInt(JNIEnv *env, jobject _this, jobject o, jint value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, ho, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, ho, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, ho, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setLong
+ * Signature: (Ljava/lang/Object;J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setLong(JNIEnv *env, jobject _this, jobject o, jlong value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, ho, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, ho, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setFloat
+ * Signature: (Ljava/lang/Object;F)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setFloat(JNIEnv *env, jobject _this, jobject o, jfloat value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, ho, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setDouble
+ * Signature: (Ljava/lang/Object;D)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setDouble(JNIEnv *env, jobject _this, jobject o, jdouble value)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ java_handle_t* ho = (java_handle_t*) o;
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(rvmf, f, ho))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->primitivetype) {
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, ho, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_reflect_VMField_getSignature(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMField rvmf(_this);
+ fieldinfo* f = rvmf.get_field();
+
+ if (f->signature == NULL)
+ return NULL;
+
+ java_handle_t* o = javastring_new(f->signature);
+
+ /* in error case o is NULL */
+
+ return (jstring) o;
+}
+
+
+#if defined(ENABLE_ANNOTATIONS)
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: declaredAnnotations
+ * Signature: ()Ljava/util/Map;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMField_declaredAnnotations(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMField rvmf(_this);
+
+ java_handle_t* declaredAnnotations = rvmf.get_declaredAnnotations();
+
+ // Are the annotations parsed yet?
+ if (declaredAnnotations == NULL) {
+ java_handle_bytearray_t* annotations = rvmf.get_annotations();
+ classinfo* declaringClass = rvmf.get_clazz();
+
+ classinfo* referer;
+ LLNI_class_get(_this, referer);
+
+ declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
+
+ rvmf.set_declaredAnnotations(declaredAnnotations);
+ }
+
+ return (jobject) declaredAnnotations;
+}
+#endif
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static const JNINativeMethod methods[] = {
+ { (char*) "getModifiersInternal", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getModifiersInternal },
+ { (char*) "getType", (char*) "()Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getType },
+ { (char*) "get", (char*) "(Ljava/lang/Object;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_get },
+ { (char*) "getBoolean", (char*) "(Ljava/lang/Object;)Z", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getBoolean },
+ { (char*) "getByte", (char*) "(Ljava/lang/Object;)B", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getByte },
+ { (char*) "getChar", (char*) "(Ljava/lang/Object;)C", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getChar },
+ { (char*) "getShort", (char*) "(Ljava/lang/Object;)S", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getShort },
+ { (char*) "getInt", (char*) "(Ljava/lang/Object;)I", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getInt },
+ { (char*) "getLong", (char*) "(Ljava/lang/Object;)J", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getLong },
+ { (char*) "getFloat", (char*) "(Ljava/lang/Object;)F", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getFloat },
+ { (char*) "getDouble", (char*) "(Ljava/lang/Object;)D", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getDouble },
+ { (char*) "set", (char*) "(Ljava/lang/Object;Ljava/lang/Object;)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_set },
+ { (char*) "setBoolean", (char*) "(Ljava/lang/Object;Z)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setBoolean },
+ { (char*) "setByte", (char*) "(Ljava/lang/Object;B)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setByte },
+ { (char*) "setChar", (char*) "(Ljava/lang/Object;C)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setChar },
+ { (char*) "setShort", (char*) "(Ljava/lang/Object;S)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setShort },
+ { (char*) "setInt", (char*) "(Ljava/lang/Object;I)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setInt },
+ { (char*) "setLong", (char*) "(Ljava/lang/Object;J)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setLong },
+ { (char*) "setFloat", (char*) "(Ljava/lang/Object;F)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setFloat },
+ { (char*) "setDouble", (char*) "(Ljava/lang/Object;D)V", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_setDouble },
+ { (char*) "getSignature", (char*) "()Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_getSignature },
+#if defined(ENABLE_ANNOTATIONS)
+ { (char*) "declaredAnnotations", (char*) "()Ljava/util/Map;", (void*) (uintptr_t) &Java_java_lang_reflect_VMField_declaredAnnotations },
+#endif
+};
+
+
+/* _Jv_java_lang_reflect_VMField_init ******************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_reflect_VMField_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/reflect/VMField");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_lang_reflect_VMMethod.c
-
- 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>
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "vm/vm.h"
-#endif
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_String.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-# include "native/include/java_util_Map.h"
-# include "native/include/sun_reflect_ConstantPool.h"
-#endif
-
-#include "native/include/java_lang_reflect_Method.h"
-#include "native/include/java_lang_reflect_VMMethod.h"
-
-#include "native/vm/reflect.h"
-
-#include "vm/access.h"
-#include "vm/global.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/initialize.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/method.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getModifiersInternal", "()I", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getModifiersInternal },
- { "getReturnType", "()Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getReturnType },
- { "getParameterTypes", "()[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getParameterTypes },
- { "getExceptionTypes", "()[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getExceptionTypes },
- { "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_invoke },
- { "getSignature", "()Ljava/lang/String;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getSignature },
-#if defined(ENABLE_ANNOTATIONS)
- { "getDefaultValue", "()Ljava/lang/Object;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getDefaultValue },
- { "declaredAnnotations", "()Ljava/util/Map;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_declaredAnnotations },
- { "getParameterAnnotations", "()[[Ljava/lang/annotation/Annotation;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getParameterAnnotations },
-#endif
-};
-
-
-/* _Jv_java_lang_reflect_VMMethod_init *******************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_reflect_VMMethod_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/reflect/VMMethod");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: getModifiersInternal
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMMethod_getModifiersInternal(JNIEnv *env, java_lang_reflect_VMMethod *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return m->flags;
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: getReturnType
- * Signature: ()Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_reflect_VMMethod_getReturnType(JNIEnv *env, java_lang_reflect_VMMethod *this)
-{
- classinfo *c;
- methodinfo *m;
- classinfo *result;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- result = method_returntype_get(m);
-
- return LLNI_classinfo_wrap(result);
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: getParameterTypes
- * Signature: ()[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMMethod_getParameterTypes(JNIEnv *env, java_lang_reflect_VMMethod *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return method_get_parametertypearray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: getExceptionTypes
- * Signature: ()[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMMethod_getExceptionTypes(JNIEnv *env, java_lang_reflect_VMMethod *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return method_get_exceptionarray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: invoke
- * Signature: (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_VMMethod_invoke(JNIEnv *env, java_lang_reflect_VMMethod *this, java_lang_Object *o, java_handle_objectarray_t *args)
-{
- classinfo *c;
- int32_t slot;
- java_lang_reflect_Method *rm;
- int32_t override;
- methodinfo *m;
- java_handle_t *ro;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot, slot);
-
- LLNI_field_get_ref(this, m, rm);
- LLNI_field_get_val(rm, flag, override);
-
- m = &(c->methods[slot]);
-
- ro = reflect_method_invoke(m, (java_handle_t *) o, args, override);
-
- return (java_lang_Object *) ro;
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: getSignature
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_VMMethod_getSignature(JNIEnv *env, java_lang_reflect_VMMethod* this)
-{
- classinfo *c;
- methodinfo *m;
- java_handle_t *o;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- if (m->signature == NULL)
- return NULL;
-
- o = javastring_new(m->signature);
-
- /* in error case o is NULL */
-
- return (java_lang_String *) o;
-}
-
-#if defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: getDefaultValue
- * Signature: ()Ljava/lang/Object;
- *
- * Parses the annotation default value and returnes it (boxed, if it's a primitive).
- */
-JNIEXPORT struct java_lang_Object* JNICALL Java_java_lang_reflect_VMMethod_getDefaultValue(JNIEnv *env, struct java_lang_reflect_VMMethod* this)
-{
- java_handle_bytearray_t *annotationDefault = NULL; /* unparsed annotation default value */
- static methodinfo *m_parseAnnotationDefault = NULL; /* parser method (will be chached, therefore static) */
- utf *utf_parseAnnotationDefault = NULL; /* parser method name */
- utf *utf_desc = NULL; /* parser method descriptor (signature) */
- sun_reflect_ConstantPool *constantPool = NULL; /* constant pool object to use */
- java_lang_Class *constantPoolOop = NULL; /* methods declaring class */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
- java_lang_reflect_Method* rm;
- java_handle_t* h;
-
- if (this == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- constantPool =
- (sun_reflect_ConstantPool*)native_new_and_init(
- class_sun_reflect_ConstantPool);
-
- if (constantPool == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_field_get_ref(this, clazz, constantPoolOop);
- LLNI_field_set_ref(constantPool, constantPoolOop, (java_lang_Object*)constantPoolOop);
-
- /* only resolve the parser method the first time */
- if (m_parseAnnotationDefault == NULL) {
- utf_parseAnnotationDefault = utf_new_char("parseAnnotationDefault");
- utf_desc = utf_new_char(
- "(Ljava/lang/reflect/Method;[BLsun/reflect/ConstantPool;)"
- "Ljava/lang/Object;");
-
- if (utf_parseAnnotationDefault == NULL || utf_desc == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_class_get(this, referer);
-
- m_parseAnnotationDefault = class_resolveclassmethod(
- class_sun_reflect_annotation_AnnotationParser,
- utf_parseAnnotationDefault,
- utf_desc,
- referer,
- true);
-
- if (m_parseAnnotationDefault == NULL) {
- /* method not found */
- return NULL;
- }
- }
-
- LLNI_field_get_ref(this, m, rm);
- LLNI_field_get_ref(this, annotationDefault, annotationDefault);
-
- h = vm_call_method(m_parseAnnotationDefault, NULL, rm, annotationDefault, constantPool);
-
- return (java_lang_Object*) h;
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: declaredAnnotations
- * Signature: ()Ljava/util/Map;
- *
- * Parses the annotations (if they aren't parsed yet) and stores them into
- * the declaredAnnotations map and return this map.
- */
-JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_VMMethod_declaredAnnotations(JNIEnv *env, java_lang_reflect_VMMethod *this)
-{
- java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
-
- /* are the annotations parsed yet? */
- if (declaredAnnotations == NULL) {
- LLNI_field_get_ref(this, annotations, annotations);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
-
- LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
- }
-
- return declaredAnnotations;
-}
-
-
-/*
- * Class: java/lang/reflect/VMMethod
- * Method: getParameterAnnotations
- * Signature: ()[[Ljava/lang/annotation/Annotation;
- *
- * Parses the parameter annotations and returns them in an 2 dimensional array.
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMMethod_getParameterAnnotations(JNIEnv *env, java_lang_reflect_VMMethod *this)
-{
- java_handle_bytearray_t *parameterAnnotations = NULL; /* unparsed parameter annotations */
- int32_t slot = -1; /* slot of the method */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, parameterAnnotations, parameterAnnotations);
- LLNI_field_get_val(this, slot, slot);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- return reflect_get_parameterannotations((java_handle_t*)parameterAnnotations, slot, declaringClass, referer);
-}
-#endif
-
-
-/*
- * 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/native/vm/gnuclasspath/java_lang_reflect_VMMethod.cpp
+
+ 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>
+
+#if defined(ENABLE_ANNOTATIONS)
+#include "vm/vm.hpp"
+#endif
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_reflect_VMMethod.h"
+#endif
+
+#include "native/vm/reflection.hpp"
+
+#include "vm/access.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/method.h"
+#include "vm/resolve.h"
+#include "vm/string.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_java_lang_reflect_VMMethod_getModifiersInternal(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMMethod rvmm(_this);
+ methodinfo* m = rvmm.get_method();
+ return m->flags;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getReturnType
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_java_lang_reflect_VMMethod_getReturnType(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMMethod rvmm(_this);
+ methodinfo* m = rvmm.get_method();
+ classinfo* c = method_returntype_get(m);
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getParameterTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMMethod_getParameterTypes(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMMethod rvmm(_this);
+ methodinfo* m = rvmm.get_method();
+ java_handle_objectarray_t* oa = method_get_parametertypearray(m);
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getExceptionTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMMethod_getExceptionTypes(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMMethod rvmm(_this);
+ methodinfo* m = rvmm.get_method();
+ java_handle_objectarray_t* oa = method_get_exceptionarray(m);
+ return (jobjectArray) oa;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: invoke
+ * Signature: (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMMethod_invoke(JNIEnv *env, jobject _this, jobject o, jobjectArray args)
+{
+ java_lang_reflect_VMMethod jlrvmm(_this);
+ java_lang_reflect_Method jlrm(jlrvmm.get_m());
+
+ java_handle_t* result = jlrm.invoke((java_handle_t*) o, (java_handle_objectarray_t*) args);
+
+ return (jobject) result;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_java_lang_reflect_VMMethod_getSignature(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMMethod rvmm(_this);
+ methodinfo* m = rvmm.get_method();
+
+ if (m->signature == NULL)
+ return NULL;
+
+ java_handle_t* s = javastring_new(m->signature);
+
+ /* in error case o is NULL */
+
+ return (jstring) s;
+}
+
+
+#if defined(ENABLE_ANNOTATIONS)
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getDefaultValue
+ * Signature: ()Ljava/lang/Object;
+ *
+ * Parses the annotation default value and returnes it (boxed, if it's a primitive).
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMMethod_getDefaultValue(JNIEnv *env, jobject _this)
+{
+ static methodinfo *m_parseAnnotationDefault = NULL; /* parser method (will be chached, therefore static) */
+ utf *utf_parseAnnotationDefault = NULL; /* parser method name */
+ utf *utf_desc = NULL; /* parser method descriptor (signature) */
+
+ if (_this == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ // TODO Use a constructor.
+ java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
+
+ if (h == NULL)
+ return NULL;
+
+ sun_reflect_ConstantPool cp(h);
+
+ java_lang_reflect_VMMethod rvmm(_this);
+ classinfo* declaringClass = rvmm.get_clazz();
+ cp.set_constantPoolOop(declaringClass);
+
+ /* only resolve the parser method the first time */
+ if (m_parseAnnotationDefault == NULL) {
+ utf_parseAnnotationDefault = utf_new_char("parseAnnotationDefault");
+ utf_desc = utf_new_char(
+ "(Ljava/lang/reflect/Method;[BLsun/reflect/ConstantPool;)"
+ "Ljava/lang/Object;");
+
+ if (utf_parseAnnotationDefault == NULL || utf_desc == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+
+ classinfo *referer;
+ LLNI_class_get((java_lang_reflect_VMMethod *) _this, referer);
+
+ m_parseAnnotationDefault = class_resolveclassmethod(
+ class_sun_reflect_annotation_AnnotationParser,
+ utf_parseAnnotationDefault,
+ utf_desc,
+ referer,
+ true);
+
+ if (m_parseAnnotationDefault == NULL) {
+ /* method not found */
+ return NULL;
+ }
+ }
+
+ java_lang_reflect_Method rm(rvmm.get_m());
+ java_handle_bytearray_t* annotationDefault = rvmm.get_annotationDefault();
+
+ java_handle_t* result = vm_call_method(m_parseAnnotationDefault, NULL, rm.get_handle(), annotationDefault, cp.get_handle());
+
+ return (jobject) result;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: declaredAnnotations
+ * Signature: ()Ljava/util/Map;
+ */
+JNIEXPORT jobject JNICALL Java_java_lang_reflect_VMMethod_declaredAnnotations(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMMethod rvmm(_this);
+ java_handle_t* declaredAnnotations = rvmm.get_declaredAnnotations();
+
+ // Are the annotations parsed yet?
+ if (declaredAnnotations == NULL) {
+ java_handle_bytearray_t* annotations = rvmm.get_annotations();
+ classinfo* declaringClass = rvmm.get_clazz();
+
+ classinfo *referer;
+ LLNI_class_get((java_lang_reflect_VMMethod *) _this, referer);
+
+ declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
+
+ rvmm.set_declaredAnnotations(declaredAnnotations);
+ }
+
+ return (jobject) declaredAnnotations;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getParameterAnnotations
+ * Signature: ()[[Ljava/lang/annotation/Annotation;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_reflect_VMMethod_getParameterAnnotations(JNIEnv *env, jobject _this)
+{
+ java_lang_reflect_VMMethod rvmm(_this);
+ java_handle_bytearray_t* parameterAnnotations = rvmm.get_parameterAnnotations();
+ methodinfo* m = rvmm.get_method();
+
+ classinfo* referer;
+ LLNI_class_get((java_lang_reflect_VMMethod *) _this, referer);
+
+ java_handle_objectarray_t* oa = Reflection::get_parameterannotations(parameterAnnotations, m, referer);
+ return (jobjectArray) oa;
+}
+#endif
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getModifiersInternal", (char*) "()I", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_getModifiersInternal },
+ { (char*) "getReturnType", (char*) "()Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_getReturnType },
+ { (char*) "getParameterTypes", (char*) "()[Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_getParameterTypes },
+ { (char*) "getExceptionTypes", (char*) "()[Ljava/lang/Class;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_getExceptionTypes },
+ { (char*) "invoke", (char*) "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_invoke },
+ { (char*) "getSignature", (char*) "()Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_getSignature },
+#if defined(ENABLE_ANNOTATIONS)
+ { (char*) "getDefaultValue", (char*) "()Ljava/lang/Object;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_getDefaultValue },
+ { (char*) "declaredAnnotations", (char*) "()Ljava/util/Map;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_declaredAnnotations },
+ { (char*) "getParameterAnnotations", (char*) "()[[Ljava/lang/annotation/Annotation;", (void*) (uintptr_t) &Java_java_lang_reflect_VMMethod_getParameterAnnotations },
+#endif
+};
+
+
+/* _Jv_java_lang_reflect_VMMethod_init *****************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_lang_reflect_VMMethod_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/reflect/VMMethod");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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:
+ */
-/* src/native/vm/gnu/java_lang_reflect_VMProxy.c - java/lang/reflect/VMProxy
+/* src/native/vm/gnuclasspath/java_lang_reflect_VMProxy.c - java/lang/reflect/VMProxy
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/jni.h"
#include "native/native.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_ClassLoader.h"
-
-#include "native/include/java_lang_reflect_VMProxy.h"
+// FIXME
+//#include "native/include/java_lang_reflect_VMProxy.h"
/* native methods implemented by this file ************************************/
+++ /dev/null
-/* src/native/vm/gnu/java_security_VMAccessController.c
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_security_VMAccessController.h"
-
-#include "vm/global.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getStack", "()[[Ljava/lang/Object;", (void *) (uintptr_t) &Java_java_security_VMAccessController_getStack },
-};
-
-
-/* _Jv_java_security_VMAccessController_init ***********************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_security_VMAccessController_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/security/VMAccessController");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/security/VMAccessController
- * Method: getStack
- * Signature: ()[[Ljava/lang/Object;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_security_VMAccessController_getStack(JNIEnv *env, jclass clazz)
-{
- return stacktrace_get_stack();
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_security_VMAccessController.cpp
+
+ 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 "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_security_VMAccessController.h"
+#endif
+
+#include "vm/global.h"
+#include "vm/utf8.h"
+
+#include "vm/jit/stacktrace.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/security/VMAccessController
+ * Method: getStack
+ * Signature: ()[[Ljava/lang/Object;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_security_VMAccessController_getStack(JNIEnv *env, jclass clazz)
+{
+ return (jobjectArray) stacktrace_get_stack();
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getStack", (char*) "()[[Ljava/lang/Object;", (void*) (uintptr_t) &Java_java_security_VMAccessController_getStack },
+};
+
+
+/* _Jv_java_security_VMAccessController_init ***********************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_security_VMAccessController_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/security/VMAccessController");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/java_util_concurrent_atomic_AtomicLong.c
-
- 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
-
- 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 "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_util_concurrent_atomic_AtomicLong.h"
-
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "VMSupportsCS8", "()Z", (void *) (intptr_t) &Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8 },
-};
-
-
-/* _Jv_java_util_concurrent_atomic_AtomicLong_init *****************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_util_concurrent_atomic_AtomicLong_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/util/concurrent/atomic/AtomicLong");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/util/concurrent/atomic/AtomicLong
- * Method: VMSupportsCS8
- * Signature: ()Z
- */
-JNIEXPORT int32_t JNICALL Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8(JNIEnv *env, jclass clazz)
-{
- /* IMPLEMENT ME */
-
- return 0;
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/java_util_concurrent_atomic_AtomicLong.cpp
+
+ 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.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/java_util_concurrent_atomic_AtomicLong.h"
+#endif
+
+#include "vm/utf8.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/util/concurrent/atomic/AtomicLong
+ * Method: VMSupportsCS8
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8(JNIEnv *env, jclass clazz)
+{
+ // IMPLEMENT ME
+ return 0;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "VMSupportsCS8", (char*) "()Z", (void*) (uintptr_t) &Java_java_util_concurrent_atomic_AtomicLong_VMSupportsCS8 },
+};
+
+
+/* _Jv_java_util_concurrent_atomic_AtomicLong_init *****************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_java_util_concurrent_atomic_AtomicLong_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/util/concurrent/atomic/AtomicLong");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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/native/vm/gnu/sun_reflect_ConstantPool.c
-
- 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, M. S. Panzenböck Institut f. Computersprachen - TU Wien
-
- 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.
-
-*/
-
-/*******************************************************************************
-
- XXX: The Methods in this file are very redundant to thouse in
- src/native/vm/sun/jvm.c Unless someone has a good idea how to cover
- such redundancy I leave it how it is.
-
- The ConstantPool class represents an interface to the constant pool of a
- class and is used by the annotations parser (sun.reflect.annotation.
- AnnotationParser) to get the values of the constants refered by the
- annotations.
-
-*******************************************************************************/
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/sun_reflect_ConstantPool.h"
-
-#include "native/vm/reflect.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/vm.h"
-#include "vm/exceptions.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/class.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getSize0", "(Ljava/lang/Object;I)I", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getSize0 },
- { "getClassAt0", "(Ljava/lang/Object;I)Ljava/lang/Class;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getClassAt0 },
- { "getClassAtIfLoaded0", "(Ljava/lang/Object;I)Ljava/lang/Class;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getClassAtIfLoaded0 },
- { "getMethodAt0", "(Ljava/lang/Object;I)Ljava/lang/reflect/Member;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getMethodAt0 },
- { "getMethodAtIfLoaded0", "(Ljava/lang/Object;I)Ljava/lang/reflect/Member;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getMethodAtIfLoaded0 },
- { "getFieldAt0", "(Ljava/lang/Object;I)Ljava/lang/reflect/Field;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getFieldAt0 },
- { "getFieldAtIfLoaded0", "(Ljava/lang/Object;I)Ljava/lang/reflect/Field;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0 },
- { "getMemberRefInfoAt0", "(Ljava/lang/Object;I)[Ljava/lang/String;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getMemberRefInfoAt0 },
- { "getIntAt0", "(Ljava/lang/Object;I)I", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getIntAt0 },
- { "getLongAt0", "(Ljava/lang/Object;I)J", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getLongAt0 },
- { "getFloatAt0", "(Ljava/lang/Object;I)F", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getFloatAt0 },
- { "getDoubleAt0", "(Ljava/lang/Object;I)D", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getDoubleAt0 },
- { "getStringAt0", "(Ljava/lang/Object;I)Ljava/lang/String;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getStringAt0 },
- { "getUTF8At0", "(Ljava/lang/Object;I)Ljava/lang/String;", (void *) (intptr_t) &Java_sun_reflect_ConstantPool_getUTF8At0 },
-};
-
-
-/* _Jv_sun_reflect_ConstantPool_init ******************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_sun_reflect_ConstantPool_init(void)
-{
- native_method_register(utf_new_char("sun/reflect/ConstantPool"), methods, NATIVE_METHODS_COUNT);
-}
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getSize0
- * Signature: (Ljava/lang/Object;)I
- */
-JNIEXPORT int32_t JNICALL Java_sun_reflect_ConstantPool_getSize0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool)
-{
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
- return cls->cpcount;
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getClassAt0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/Class;
- */
-JNIEXPORT struct java_lang_Class* JNICALL Java_sun_reflect_ConstantPool_getClassAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_classref *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_classref*)class_getconstant(
- cls, index, CONSTANT_Class);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- return LLNI_classinfo_wrap(resolve_classref_eager(ref));
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getClassAtIfLoaded0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/Class;
- */
-JNIEXPORT struct java_lang_Class* JNICALL Java_sun_reflect_ConstantPool_getClassAtIfLoaded0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_classref *ref;
- classinfo *c = NULL;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_classref*)class_getconstant(
- cls, index, CONSTANT_Class);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- if (!resolve_classref(NULL,ref,resolveLazy,true,true,&c)) {
- return NULL;
- }
-
- if (c == NULL || !(c->state & CLASS_LOADED)) {
- return NULL;
- }
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getMethodAt0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Member;
- */
-JNIEXPORT struct java_lang_reflect_Member* JNICALL Java_sun_reflect_ConstantPool_getMethodAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_FMIref *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_FMIref*)class_getconstant(
- cls, index, CONSTANT_Methodref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* XXX: is that right? or do I have to use resolve_method_*? */
- return (jobject)reflect_method_new(ref->p.method);
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getMethodAtIfLoaded0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Member;
- */
-JNIEXPORT struct java_lang_reflect_Member* JNICALL Java_sun_reflect_ConstantPool_getMethodAtIfLoaded0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_FMIref *ref;
- classinfo *c = NULL;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_FMIref*)class_getconstant(
- cls, index, CONSTANT_Methodref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- if (!resolve_classref(NULL,ref->p.classref,resolveLazy,true,true,&c)) {
- return NULL;
- }
-
- if (c == NULL || !(c->state & CLASS_LOADED)) {
- return NULL;
- }
-
- return (jobject)reflect_method_new(ref->p.method);
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getFieldAt0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Field;
- */
-JNIEXPORT struct java_lang_reflect_Field* JNICALL Java_sun_reflect_ConstantPool_getFieldAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_FMIref *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_FMIref*)class_getconstant(
- cls, index, CONSTANT_Fieldref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- return (jobject)reflect_field_new(ref->p.field);
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getFieldAtIfLoaded0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Field;
- */
-JNIEXPORT struct java_lang_reflect_Field* JNICALL Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_FMIref *ref;
- classinfo *c;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_FMIref*)class_getconstant(
- cls, index, CONSTANT_Fieldref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- if (!resolve_classref(NULL,ref->p.classref,resolveLazy,true,true,&c)) {
- return NULL;
- }
-
- if (c == NULL || !(c->state & CLASS_LOADED)) {
- return NULL;
- }
-
- return (jobject)reflect_field_new(ref->p.field);
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getMemberRefInfoAt0
- * Signature: (Ljava/lang/Object;I)[Ljava/lang/String;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_sun_reflect_ConstantPool_getMemberRefInfoAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- log_println("Java_sun_reflect_ConstantPool_getMemberRefInfoAt0(env=%p, jcpool=%p, index=%d): IMPLEMENT ME!", env, jcpool, index);
- return NULL;
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getIntAt0
- * Signature: (Ljava/lang/Object;I)I
- */
-JNIEXPORT int32_t JNICALL Java_sun_reflect_ConstantPool_getIntAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_integer *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_integer*)class_getconstant(
- cls, index, CONSTANT_Integer);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getLongAt0
- * Signature: (Ljava/lang/Object;I)J
- */
-JNIEXPORT int64_t JNICALL Java_sun_reflect_ConstantPool_getLongAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_long *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_long*)class_getconstant(
- cls, index, CONSTANT_Long);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getFloatAt0
- * Signature: (Ljava/lang/Object;I)F
- */
-JNIEXPORT float JNICALL Java_sun_reflect_ConstantPool_getFloatAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_float *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_float*)class_getconstant(
- cls, index, CONSTANT_Float);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getDoubleAt0
- * Signature: (Ljava/lang/Object;I)D
- */
-JNIEXPORT double JNICALL Java_sun_reflect_ConstantPool_getDoubleAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- constant_double *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_double*)class_getconstant(
- cls, index, CONSTANT_Double);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getStringAt0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/String;
- */
-JNIEXPORT struct java_lang_String* JNICALL Java_sun_reflect_ConstantPool_getStringAt0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- utf *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (utf*)class_getconstant(cls, index, CONSTANT_String);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* XXX: I hope literalstring_new is the right Function. */
- return (java_lang_String*)literalstring_new(ref);
-}
-
-
-/*
- * Class: sun/reflect/ConstantPool
- * Method: getUTF8At0
- * Signature: (Ljava/lang/Object;I)Ljava/lang/String;
- */
-JNIEXPORT struct java_lang_String* JNICALL Java_sun_reflect_ConstantPool_getUTF8At0(JNIEnv *env, struct sun_reflect_ConstantPool* this, struct java_lang_Object* jcpool, int32_t index)
-{
- utf *ref;
- classinfo *cls = LLNI_classinfo_unwrap(jcpool);
-
- ref = (utf*)class_getconstant(cls, index, CONSTANT_Utf8);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* XXX: I hope literalstring_new is the right Function. */
- return (java_lang_String*)literalstring_new(ref);
-}
-
-
-/*
- * 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/native/vm/gnuclasspath/sun_reflect_ConstantPool.cpp
+
+ 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.
+
+*/
+
+/*******************************************************************************
+
+ XXX: The Methods in this file are very redundant to thouse in
+ src/native/vm/sun/jvm.c Unless someone has a good idea how to cover
+ such redundancy I leave it how it is.
+
+ The ConstantPool class represents an interface to the constant pool of a
+ class and is used by the annotations parser (sun.reflect.annotation.
+ AnnotationParser) to get the values of the constants refered by the
+ annotations.
+
+*******************************************************************************/
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+// FIXME
+//#include "native/include/sun_reflect_ConstantPool.h"
+
+#include "native/vm/reflection.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/resolve.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getSize0
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT jint JNICALL Java_sun_reflect_ConstantPool_getSize0(JNIEnv *env, jobject _this, jobject jcpool)
+{
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+ return cls->cpcount;
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getClassAt0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_sun_reflect_ConstantPool_getClassAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_classref *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_classref*)class_getconstant(
+ cls, index, CONSTANT_Class);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ return (jclass) LLNI_classinfo_wrap(resolve_classref_eager(ref));
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getClassAtIfLoaded0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_sun_reflect_ConstantPool_getClassAtIfLoaded0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_classref *ref;
+ classinfo *c = NULL;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_classref*)class_getconstant(
+ cls, index, CONSTANT_Class);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ if (!resolve_classref(NULL,ref,resolveLazy,true,true,&c)) {
+ return NULL;
+ }
+
+ if (c == NULL || !(c->state & CLASS_LOADED)) {
+ return NULL;
+ }
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getMethodAt0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Member;
+ */
+JNIEXPORT jobject JNICALL Java_sun_reflect_ConstantPool_getMethodAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_FMIref *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_FMIref*)class_getconstant(
+ cls, index, CONSTANT_Methodref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* XXX: is that right? or do I have to use resolve_method_*? */
+ java_lang_reflect_Method jlrm(ref->p.method);
+
+ return (jobject) jlrm.get_handle();
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getMethodAtIfLoaded0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Member;
+ */
+JNIEXPORT jobject JNICALL Java_sun_reflect_ConstantPool_getMethodAtIfLoaded0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_FMIref *ref;
+ classinfo *c = NULL;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_FMIref*)class_getconstant(
+ cls, index, CONSTANT_Methodref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ if (!resolve_classref(NULL,ref->p.classref,resolveLazy,true,true,&c)) {
+ return NULL;
+ }
+
+ if (c == NULL || !(c->state & CLASS_LOADED)) {
+ return NULL;
+ }
+
+ java_lang_reflect_Method jlrm(ref->p.method);
+
+ return (jobject) jlrm.get_handle();
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getFieldAt0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Field;
+ */
+JNIEXPORT jobject JNICALL Java_sun_reflect_ConstantPool_getFieldAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_FMIref *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_FMIref*) class_getconstant(cls, index, CONSTANT_Fieldref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ // Create a new java.lang.reflect.Field Java object.
+ java_lang_reflect_Field jlrf(ref->p.field);
+
+ return (jobject) jlrf.get_handle();
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getFieldAtIfLoaded0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/reflect/Field;
+ */
+JNIEXPORT jobject JNICALL Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_FMIref *ref;
+ classinfo *c;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_FMIref*) class_getconstant(cls, index, CONSTANT_Fieldref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ if (!resolve_classref(NULL,ref->p.classref,resolveLazy,true,true,&c)) {
+ return NULL;
+ }
+
+ if (c == NULL || !(c->state & CLASS_LOADED)) {
+ return NULL;
+ }
+
+ // Create a new java.lang.reflect.Field Java object.
+ java_lang_reflect_Field jlrf(ref->p.field);
+
+ return (jobject) jlrf.get_handle();
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getMemberRefInfoAt0
+ * Signature: (Ljava/lang/Object;I)[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_sun_reflect_ConstantPool_getMemberRefInfoAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ log_println("Java_sun_reflect_ConstantPool_getMemberRefInfoAt0(env=%p, jcpool=%p, index=%d): IMPLEMENT ME!", env, jcpool, index);
+ return NULL;
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getIntAt0
+ * Signature: (Ljava/lang/Object;I)I
+ */
+JNIEXPORT jint JNICALL Java_sun_reflect_ConstantPool_getIntAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_integer *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_integer*) class_getconstant(cls, index, CONSTANT_Integer);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getLongAt0
+ * Signature: (Ljava/lang/Object;I)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_reflect_ConstantPool_getLongAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_long *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_long*)class_getconstant(
+ cls, index, CONSTANT_Long);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getFloatAt0
+ * Signature: (Ljava/lang/Object;I)F
+ */
+JNIEXPORT float JNICALL Java_sun_reflect_ConstantPool_getFloatAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_float *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_float*)class_getconstant(
+ cls, index, CONSTANT_Float);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getDoubleAt0
+ * Signature: (Ljava/lang/Object;I)D
+ */
+JNIEXPORT double JNICALL Java_sun_reflect_ConstantPool_getDoubleAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ constant_double *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_double*)class_getconstant(
+ cls, index, CONSTANT_Double);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getStringAt0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_sun_reflect_ConstantPool_getStringAt0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ utf *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (utf*)class_getconstant(cls, index, CONSTANT_String);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* XXX: I hope literalstring_new is the right Function. */
+ return (jstring) literalstring_new(ref);
+}
+
+
+/*
+ * Class: sun/reflect/ConstantPool
+ * Method: getUTF8At0
+ * Signature: (Ljava/lang/Object;I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_sun_reflect_ConstantPool_getUTF8At0(JNIEnv *env, jobject _this, jobject jcpool, jint index)
+{
+ utf *ref;
+ classinfo *cls = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (utf*)class_getconstant(cls, index, CONSTANT_Utf8);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* XXX: I hope literalstring_new is the right Function. */
+ return (jstring) literalstring_new(ref);
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getSize0", (char*) "(Ljava/lang/Object;I)I", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getSize0 },
+ { (char*) "getClassAt0", (char*) "(Ljava/lang/Object;I)Ljava/lang/Class;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getClassAt0 },
+ { (char*) "getClassAtIfLoaded0", (char*) "(Ljava/lang/Object;I)Ljava/lang/Class;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getClassAtIfLoaded0 },
+ { (char*) "getMethodAt0", (char*) "(Ljava/lang/Object;I)Ljava/lang/reflect/Member;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getMethodAt0 },
+ { (char*) "getMethodAtIfLoaded0", (char*) "(Ljava/lang/Object;I)Ljava/lang/reflect/Member;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getMethodAtIfLoaded0 },
+ { (char*) "getFieldAt0", (char*) "(Ljava/lang/Object;I)Ljava/lang/reflect/Field;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getFieldAt0 },
+ { (char*) "getFieldAtIfLoaded0", (char*) "(Ljava/lang/Object;I)Ljava/lang/reflect/Field;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getFieldAtIfLoaded0 },
+ { (char*) "getMemberRefInfoAt0", (char*) "(Ljava/lang/Object;I)[Ljava/lang/String;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getMemberRefInfoAt0 },
+ { (char*) "getIntAt0", (char*) "(Ljava/lang/Object;I)I", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getIntAt0 },
+ { (char*) "getLongAt0", (char*) "(Ljava/lang/Object;I)J", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getLongAt0 },
+ { (char*) "getFloatAt0", (char*) "(Ljava/lang/Object;I)F", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getFloatAt0 },
+ { (char*) "getDoubleAt0", (char*) "(Ljava/lang/Object;I)D", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getDoubleAt0 },
+ { (char*) "getStringAt0", (char*) "(Ljava/lang/Object;I)Ljava/lang/String;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getStringAt0 },
+ { (char*) "getUTF8At0", (char*) "(Ljava/lang/Object;I)Ljava/lang/String;", (void*) (uintptr_t) &Java_sun_reflect_ConstantPool_getUTF8At0 },
+};
+
+
+/* _Jv_sun_reflect_ConstantPool_init ******************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_sun_reflect_ConstantPool_init(void)
+{
+ native_method_register(utf_new_char("sun/reflect/ConstantPool"), methods, NATIVE_METHODS_COUNT);
+}
+}
+
+
+/*
+ * 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 "native/vm/nativevm.h"
+#include "vm/class.h"
#include "vm/initialize.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/system.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
# include "mm/memory.h"
# include "native/vm/openjdk/hpi.h"
+# include "vm/globals.hpp"
# include "vm/properties.h"
-# include "vm/vm.h"
-
-# include "vmcore/utf8.h"
+# include "vm/utf8.h"
+# include "vm/vm.hpp"
#endif
# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- char* boot_library_path;
+ const char* boot_library_path;
int len;
char* p;
utf* u;
boot_library_path = properties_get("sun.boot.library.path");
len =
- system_strlen(boot_library_path) +
- system_strlen("/libjava.so") +
- system_strlen("0");
+ os_strlen(boot_library_path) +
+ os_strlen("/libjava.so") +
+ os_strlen("0");
p = MNEW(char, len);
- system_strcpy(p, boot_library_path);
- system_strcat(p, "/libjava.so");
+ os_strcpy(p, boot_library_path);
+ os_strcat(p, "/libjava.so");
u = utf_new_char(p);
#define _NATIVEVM_H
#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/types.h"
#include "vm/global.h"
# error unknown Java configuration
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _NATIVEVM_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
-## src/native/vm/sun/Makefile.am
+## src/native/vm/openjdk/Makefile.am
##
## Copyright (C) 2007, 2008
## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
libnativevmcore_la_SOURCES = \
hpi.c \
hpi.h \
- jvm.c
+ jvm.cpp
## Local variables:
#include "native/jni.h"
#include "native/native.h"
-#include "vm/properties.h"
-#include "vm/vm.h"
+#include "native/vm/openjdk/hpi.h"
-#include "vmcore/options.h"
-#include "vmcore/system.h"
-#include "vmcore/utf8.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/properties.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
/* VM callback functions ******************************************************/
void hpi_initialize(void)
{
- char* boot_library_path;
+ const char* boot_library_path;
int len;
char* p;
utf* u;
boot_library_path = properties_get("sun.boot.library.path");
len =
- system_strlen(boot_library_path) +
- system_strlen("/native_threads/libhpi.so") +
- system_strlen("0");
+ os_strlen(boot_library_path) +
+ os_strlen("/native_threads/libhpi.so") +
+ os_strlen("0");
p = MNEW(char, len);
- system_strcpy(p, boot_library_path);
- system_strcat(p, "/native_threads/libhpi.so");
+ os_strcpy(p, boot_library_path);
+ os_strcat(p, "/native_threads/libhpi.so");
u = utf_new_char(p);
/* Resolve the DLL_Initialize function from the library. */
- dll_initialize = system_dlsym(handle, "DLL_Initialize");
+ dll_initialize = os_dlsym(handle, "DLL_Initialize");
DLL_Initialize = (jint (JNICALL *)(GetInterfaceFunc *, void *)) (intptr_t) dll_initialize;
if (opt_TraceHPI && DLL_Initialize == NULL)
- log_println("hpi_init: HPI dlsym of DLL_Initialize failed: %s",
- system_dlerror());
+ log_println("hpi_init: HPI dlsym of DLL_Initialize failed: %s", os_dlerror());
if (DLL_Initialize == NULL ||
(*DLL_Initialize)(&hpi_get_interface, &callbacks) < 0) {
#ifndef _HPI_H
#define _HPI_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "config.h"
/* HPI headers *****************************************************************
void hpi_initialize(void);
int hpi_initialize_socket_library(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _HPI_H */
+++ /dev/null
-/* src/native/vm/openjdk/jvm.c - HotSpot JVM interface 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.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#if defined(HAVE_SYS_IOCTL_H)
-#define BSD_COMP /* Get FIONREAD on Solaris2 */
-#include <sys/ioctl.h>
-#endif
-
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_AssertionStatusDirectives.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" /* required by j.l.C */
-#include "native/include/java_lang_StackTraceElement.h"
-#include "native/include/java_lang_Throwable.h"
-#include "native/include/java_security_ProtectionDomain.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "native/include/sun_reflect_ConstantPool.h"
-#endif
-
-#include "native/vm/reflect.h"
-
-#include "native/vm/openjdk/hpi.h"
-
-#include "threads/lock-common.h"
-#include "threads/thread.h"
-
-#include "toolbox/logging.h"
-#include "toolbox/list.h"
-
-#include "vm/array.h"
-
-#if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
-#endif
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-#include "vm/package.hpp"
-#include "vm/primitive.h"
-#include "vm/properties.h"
-#include "vm/resolve.h"
-#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/classcache.h"
-#include "vmcore/options.h"
-#include "vmcore/system.h"
-
-
-/* debugging macros ***********************************************************/
-
-#if !defined(NDEBUG)
-
-# define TRACEJVMCALLS(x) \
- do { \
- if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
- log_println x; \
- } \
- } while (0)
-
-# define TRACEJVMCALLSENTER(x) \
- do { \
- if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
- log_start(); \
- log_print x; \
- } \
- } while (0)
-
-# define TRACEJVMCALLSEXIT(x) \
- do { \
- if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
- log_print x; \
- log_finish(); \
- } \
- } while (0)
-
-# define TRACEJVMCALLSVERBOSE(x) \
- do { \
- if (opt_TraceJVMCallsVerbose) { \
- log_println x; \
- } \
- } while (0)
-
-# define PRINTJVMWARNINGS(x)
-/* do { \ */
-/* if (opt_PrintJVMWarnings) { \ */
-/* log_println x; \ */
-/* } \ */
-/* } while (0) */
-
-#else
-
-# define TRACEJVMCALLS(x)
-# define TRACEJVMCALLSENTER(x)
-# define TRACEJVMCALLSEXIT(x)
-# define TRACEJVMCALLSVERBOSE(x)
-# define PRINTJVMWARNINGS(x)
-
-#endif
-
-
-typedef struct {
- /* Naming convention of RE build version string: n.n.n[_uu[c]][-<identifier>]-bxx */
- unsigned int jvm_version; /* Consists of major, minor, micro (n.n.n) */
- /* and build number (xx) */
- unsigned int update_version : 8; /* Update release version (uu) */
- unsigned int special_update_version : 8; /* Special update release version (c) */
- unsigned int reserved1 : 16;
- unsigned int reserved2;
-
- /* The following bits represents JVM supports that JDK has dependency on.
- * JDK can use these bits to determine which JVM version
- * and support it has to maintain runtime compatibility.
- *
- * When a new bit is added in a minor or update release, make sure
- * the new bit is also added in the main/baseline.
- */
- unsigned int is_attachable : 1;
- unsigned int : 31;
- unsigned int : 32;
- unsigned int : 32;
-} jvm_version_info;
-
-
-/*
- * A structure used to a capture exception table entry in a Java method.
- */
-typedef struct {
- jint start_pc;
- jint end_pc;
- jint handler_pc;
- jint catchType;
-} JVM_ExceptionTableEntryType;
-
-
-int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
-{
- if ((intptr_t) count <= 0)
- return -1;
-
- return vsnprintf(str, count, fmt, args);
-}
-
-
-int jio_snprintf(char *str, size_t count, const char *fmt, ...)
-{
- va_list ap;
- int len;
-
- va_start(ap, fmt);
- len = jio_vsnprintf(str, count, fmt, ap);
- va_end(ap);
-
- return len;
-}
-
-
-int jio_fprintf(FILE* f, const char *fmt, ...)
-{
- log_println("jio_fprintf: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-int jio_vfprintf(FILE* f, const char *fmt, va_list args)
-{
- log_println("jio_vfprintf: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-int jio_printf(const char *fmt, ...)
-{
- log_println("jio_printf: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetInterfaceVersion */
-
-jint JVM_GetInterfaceVersion()
-{
- /* This is defined in hotspot/src/share/vm/prims/jvm.h */
-
-#define JVM_INTERFACE_VERSION 4
-
- return JVM_INTERFACE_VERSION;
-}
-
-
-/* JVM_CurrentTimeMillis */
-
-jlong JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored)
-{
- TRACEJVMCALLS(("JVM_CurrentTimeMillis(env=%p, ignored=%p)", env, ignored));
-
- return (jlong) builtin_currenttimemillis();
-}
-
-
-/* JVM_NanoTime */
-
-jlong JVM_NanoTime(JNIEnv *env, jclass ignored)
-{
- TRACEJVMCALLS(("JVM_NanoTime(env=%p, ignored=%p)", env, ignored));
-
- return (jlong) builtin_nanotime();
-}
-
-
-/* JVM_ArrayCopy */
-
-void JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length)
-{
- java_handle_t *s;
- java_handle_t *d;
-
- s = (java_handle_t *) src;
- d = (java_handle_t *) dst;
-
- TRACEJVMCALLSVERBOSE(("JVM_ArrayCopy(env=%p, ignored=%p, src=%p, src_pos=%d, dst=%p, dst_pos=%d, length=%d)", env, ignored, src, src_pos, dst, dst_pos, length));
-
- builtin_arraycopy(s, src_pos, d, dst_pos, length);
-}
-
-
-/* JVM_InitProperties */
-
-jobject JVM_InitProperties(JNIEnv *env, jobject properties)
-{
- java_handle_t *h;
- char buf[256];
-
- TRACEJVMCALLS(("JVM_InitProperties(env=%p, properties=%p)", env, properties));
-
- h = (java_handle_t *) properties;
-
- /* Convert the -XX:MaxDirectMemorySize= command line flag to the
- sun.nio.MaxDirectMemorySize property. Do this after setting
- user properties to prevent people from setting the value with a
- -D option, as requested. */
-
- jio_snprintf(buf, sizeof(buf), PRINTF_FORMAT_INT64_T, opt_MaxDirectMemorySize);
- properties_add("sun.nio.MaxDirectMemorySize", buf);
-
- /* Add all properties. */
-
- properties_system_add_all(h);
-
- return properties;
-}
-
-
-/* JVM_Exit */
-
-void JVM_Exit(jint code)
-{
- log_println("JVM_Exit: IMPLEMENT ME!");
-}
-
-
-/* JVM_Halt */
-
-void JVM_Halt(jint code)
-{
- TRACEJVMCALLS(("JVM_Halt(code=%d)", code));
-
-/* vm_exit(code); */
- vm_shutdown(code);
-}
-
-
-/* JVM_OnExit(void (*func)) */
-
-void JVM_OnExit(void (*func)(void))
-{
- log_println("JVM_OnExit(void (*func): IMPLEMENT ME!");
-}
-
-
-/* JVM_GC */
-
-void JVM_GC(void)
-{
- TRACEJVMCALLS(("JVM_GC()"));
-
- gc_call();
-}
-
-
-/* JVM_MaxObjectInspectionAge */
-
-jlong JVM_MaxObjectInspectionAge(void)
-{
- log_println("JVM_MaxObjectInspectionAge: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_TraceInstructions */
-
-void JVM_TraceInstructions(jboolean on)
-{
- log_println("JVM_TraceInstructions: IMPLEMENT ME!");
-}
-
-
-/* JVM_TraceMethodCalls */
-
-void JVM_TraceMethodCalls(jboolean on)
-{
- log_println("JVM_TraceMethodCalls: IMPLEMENT ME!");
-}
-
-
-/* JVM_TotalMemory */
-
-jlong JVM_TotalMemory(void)
-{
- TRACEJVMCALLS(("JVM_TotalMemory()"));
-
- return gc_get_heap_size();
-}
-
-
-/* JVM_FreeMemory */
-
-jlong JVM_FreeMemory(void)
-{
- TRACEJVMCALLS(("JVM_FreeMemory()"));
-
- return gc_get_free_bytes();
-}
-
-
-/* JVM_MaxMemory */
-
-jlong JVM_MaxMemory(void)
-{
- TRACEJVMCALLS(("JVM_MaxMemory()"));
-
- return gc_get_max_heap_size();
-}
-
-
-/* JVM_ActiveProcessorCount */
-
-jint JVM_ActiveProcessorCount(void)
-{
- TRACEJVMCALLS(("JVM_ActiveProcessorCount()"));
-
- return system_processors_online();
-}
-
-
-/* JVM_FillInStackTrace */
-
-void JVM_FillInStackTrace(JNIEnv *env, jobject receiver)
-{
- java_lang_Throwable *o;
- java_handle_bytearray_t *ba;
-
- TRACEJVMCALLS(("JVM_FillInStackTrace(env=%p, receiver=%p)", env, receiver));
-
- o = (java_lang_Throwable *) receiver;
-
- ba = stacktrace_get_current();
-
- if (ba == NULL)
- return;
-
- LLNI_field_set_ref(o, backtrace, (java_lang_Object *) ba);
-}
-
-
-/* JVM_PrintStackTrace */
-
-void JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable)
-{
- log_println("JVM_PrintStackTrace: IMPLEMENT ME!");
-}
-
-
-/* JVM_GetStackTraceDepth */
-
-jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)
-{
- java_lang_Throwable *to;
- java_lang_Object *o;
- java_handle_bytearray_t *ba;
- stacktrace_t *st;
- int32_t depth;
-
- TRACEJVMCALLS(("JVM_GetStackTraceDepth(env=%p, throwable=%p)", env, throwable));
-
- if (throwable == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- to = (java_lang_Throwable *) throwable;
-
- LLNI_field_get_ref(to, backtrace, o);
-
- ba = (java_handle_bytearray_t *) o;
-
- if (ba == NULL)
- return 0;
-
- /* We need a critical section here as the stacktrace structure is
- mapped onto a Java byte-array. */
-
- LLNI_CRITICAL_START;
-
- st = (stacktrace_t *) LLNI_array_data(ba);
-
- depth = st->length;
-
- LLNI_CRITICAL_END;
-
- return depth;
-}
-
-
-/* JVM_GetStackTraceElement */
-
-jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
-{
- java_lang_Throwable *to;
- java_lang_Object *o;
- java_handle_bytearray_t *ba;
- stacktrace_t *st;
- stacktrace_entry_t *ste;
- codeinfo *code;
- methodinfo *m;
- classinfo *c;
- java_lang_StackTraceElement *steo;
- java_handle_t* declaringclass;
- java_lang_String *filename;
- int32_t linenumber;
-
- TRACEJVMCALLS(("JVM_GetStackTraceElement(env=%p, throwable=%p, index=%d)", env, throwable, index));
-
- to = (java_lang_Throwable *) throwable;
-
- LLNI_field_get_ref(to, backtrace, o);
-
- ba = (java_handle_bytearray_t *) o;
-
- /* FIXME critical section */
-
- st = (stacktrace_t *) LLNI_array_data(ba);
-
- if ((index < 0) || (index >= st->length)) {
- /* XXX This should be an IndexOutOfBoundsException (check this
- again). */
-
- exceptions_throw_arrayindexoutofboundsexception();
- return NULL;
- }
-
- /* Get the stacktrace entry. */
-
- ste = &(st->entries[index]);
-
- /* Get the codeinfo, methodinfo and classinfo. */
-
- code = ste->code;
- m = code->m;
- c = m->clazz;
-
- /* allocate a new StackTraceElement */
-
- steo = (java_lang_StackTraceElement *)
- builtin_new(class_java_lang_StackTraceElement);
-
- if (steo == NULL)
- return NULL;
-
- /* get filename */
-
- if (!(m->flags & ACC_NATIVE)) {
- if (c->sourcefile != NULL)
- filename = (java_lang_String *) javastring_new(c->sourcefile);
- else
- filename = NULL;
- }
- else
- filename = NULL;
-
- /* get line number */
-
- if (m->flags & ACC_NATIVE) {
- linenumber = -2;
- }
- else {
- /* FIXME The linenumbertable_linenumber_for_pc could change
- the methodinfo pointer when hitting an inlined method. */
-
- linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
- linenumber = (linenumber == 0) ? -1 : linenumber;
- }
-
- /* get declaring class name */
-
- declaringclass = class_get_classname(c);
-
- /* fill the java.lang.StackTraceElement element */
-
- /* FIXME critical section */
-
- steo->declaringClass = (java_lang_String*) declaringclass;
- steo->methodName = (java_lang_String*) javastring_new(m->name);
- steo->fileName = filename;
- steo->lineNumber = linenumber;
-
- return (jobject) steo;
-}
-
-
-/* JVM_IHashCode */
-
-jint JVM_IHashCode(JNIEnv* env, jobject handle)
-{
- TRACEJVMCALLS(("JVM_IHashCode(env=%p, jobject=%p)", env, handle));
-
- return (jint) ((ptrint) handle);
-}
-
-
-/* JVM_MonitorWait */
-
-void JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *o;
-#endif
-
- TRACEJVMCALLS(("JVM_MonitorWait(env=%p, handle=%p, ms=%ld)", env, handle, ms));
- if (ms < 0) {
-/* exceptions_throw_illegalargumentexception("argument out of range"); */
- exceptions_throw_illegalargumentexception();
- return;
- }
-
-#if defined(ENABLE_THREADS)
- o = (java_handle_t *) handle;
-
- lock_wait_for_object(o, ms, 0);
-#endif
-}
-
-
-/* JVM_MonitorNotify */
-
-void JVM_MonitorNotify(JNIEnv* env, jobject handle)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *o;
-#endif
-
- TRACEJVMCALLS(("JVM_MonitorNotify(env=%p, handle=%p)", env, handle));
-
-#if defined(ENABLE_THREADS)
- o = (java_handle_t *) handle;
-
- lock_notify_object(o);
-#endif
-}
-
-
-/* JVM_MonitorNotifyAll */
-
-void JVM_MonitorNotifyAll(JNIEnv* env, jobject handle)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *o;
-#endif
-
- TRACEJVMCALLS(("JVM_MonitorNotifyAll(env=%p, handle=%p)", env, handle));
-
-#if defined(ENABLE_THREADS)
- o = (java_handle_t *) handle;
-
- lock_notify_all_object(o);
-#endif
-}
-
-
-/* JVM_Clone */
-
-jobject JVM_Clone(JNIEnv* env, jobject handle)
-{
- TRACEJVMCALLS(("JVM_Clone(env=%p, handle=%p)", env, handle));
-
- return (jobject) builtin_clone(env, (java_handle_t *) handle);
-}
-
-
-/* JVM_InitializeCompiler */
-
-void JVM_InitializeCompiler (JNIEnv *env, jclass compCls)
-{
- log_println("JVM_InitializeCompiler : IMPLEMENT ME!");
-}
-
-
-/* JVM_IsSilentCompiler */
-
-jboolean JVM_IsSilentCompiler(JNIEnv *env, jclass compCls)
-{
- log_println("JVM_IsSilentCompiler: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_CompileClass */
-
-jboolean JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls)
-{
- log_println("JVM_CompileClass: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_CompileClasses */
-
-jboolean JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname)
-{
- log_println("JVM_CompileClasses: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_CompilerCommand */
-
-jobject JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg)
-{
- log_println("JVM_CompilerCommand: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_EnableCompiler */
-
-void JVM_EnableCompiler(JNIEnv *env, jclass compCls)
-{
- TRACEJVMCALLS(("JVM_EnableCompiler(env=%p, compCls=%p)", env, compCls));
- PRINTJVMWARNINGS(("JVM_EnableCompiler not supported"));
-}
-
-
-/* JVM_DisableCompiler */
-
-void JVM_DisableCompiler(JNIEnv *env, jclass compCls)
-{
- TRACEJVMCALLS(("JVM_DisableCompiler(env=%p, compCls=%p)", env, compCls));
- PRINTJVMWARNINGS(("JVM_DisableCompiler not supported"));
-}
-
-
-/* JVM_GetLastErrorString */
-
-jint JVM_GetLastErrorString(char *buf, int len)
-{
- TRACEJVMCALLS(("JVM_GetLastErrorString(buf=%p, len=%d", buf, len));
-
- return hpi_system->GetLastErrorString(buf, len);
-}
-
-
-/* JVM_NativePath */
-
-char *JVM_NativePath(char *path)
-{
- TRACEJVMCALLS(("JVM_NativePath(path=%s)", path));
-
- return hpi_file->NativePath(path);
-}
-
-
-/* JVM_GetCallerClass */
-
-jclass JVM_GetCallerClass(JNIEnv* env, int depth)
-{
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_GetCallerClass(env=%p, depth=%d)", env, depth));
-
- c = stacktrace_get_caller_class(depth);
-
- return (jclass) c;
-}
-
-
-/* JVM_FindPrimitiveClass */
-
-jclass JVM_FindPrimitiveClass(JNIEnv* env, const char* s)
-{
- classinfo *c;
- utf *u;
-
- TRACEJVMCALLS(("JVM_FindPrimitiveClass(env=%p, s=%s)", env, s));
-
- u = utf_new_char(s);
- c = primitive_class_get_by_name(u);
-
- return (jclass) LLNI_classinfo_wrap(c);
-}
-
-
-/* JVM_ResolveClass */
-
-void JVM_ResolveClass(JNIEnv* env, jclass cls)
-{
- TRACEJVMCALLS(("JVM_ResolveClass(env=%p, cls=%p)", env, cls));
- PRINTJVMWARNINGS(("JVM_ResolveClass not implemented"));
-}
-
-
-/* JVM_FindClassFromClassLoader */
-
-jclass JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init, jobject loader, jboolean throwError)
-{
- classinfo *c;
- utf *u;
- classloader_t *cl;
-
- TRACEJVMCALLS(("JVM_FindClassFromClassLoader(name=%s, init=%d, loader=%p, throwError=%d)", name, init, loader, throwError));
-
- /* As of now, OpenJDK does not call this function with throwError
- is true. */
-
- assert(throwError == false);
-
- u = utf_new_char(name);
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- c = load_class_from_classloader(u, cl);
-
- if (c == NULL)
- return NULL;
-
- if (init)
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return NULL;
-
- return (jclass) LLNI_classinfo_wrap(c);
-}
-
-
-/* JVM_FindClassFromClass */
-
-jclass JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init, jclass from)
-{
- log_println("JVM_FindClassFromClass: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_DefineClass */
-
-jclass JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)
-{
- log_println("JVM_DefineClass: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_DefineClassWithSource */
-
-jclass JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)
-{
- classinfo *c;
- utf *u;
- classloader_t *cl;
-
- TRACEJVMCALLS(("JVM_DefineClassWithSource(env=%p, name=%s, loader=%p, buf=%p, len=%d, pd=%p, source=%s)", env, name, loader, buf, len, pd, source));
-
- if (name != NULL)
- u = utf_new_char(name);
- else
- u = NULL;
-
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- /* XXX do something with source */
-
- c = class_define(u, cl, len, (uint8_t *) buf, (java_handle_t *) pd);
-
- return (jclass) LLNI_classinfo_wrap(c);
-}
-
-
-/* JVM_FindLoadedClass */
-
-jclass JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
-{
- classloader_t *cl;
- utf *u;
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_FindLoadedClass(env=%p, loader=%p, name=%p)", env, loader, name));
-
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- u = javastring_toutf((java_handle_t *) name, true);
- c = classcache_lookup(cl, u);
-
- return (jclass) LLNI_classinfo_wrap(c);
-}
-
-
-/* JVM_GetClassName */
-
-jstring JVM_GetClassName(JNIEnv *env, jclass cls)
-{
- classinfo* c;
-
- TRACEJVMCALLS(("JVM_GetClassName(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- return (jstring) class_get_classname(c);
-}
-
-
-/* JVM_GetClassInterfaces */
-
-jobjectArray JVM_GetClassInterfaces(JNIEnv *env, jclass cls)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS(("JVM_GetClassInterfaces(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- oa = class_get_interfaces(c);
-
- return (jobjectArray) oa;
-}
-
-
-/* JVM_GetClassLoader */
-
-jobject JVM_GetClassLoader(JNIEnv *env, jclass cls)
-{
- classinfo *c;
- classloader_t *cl;
-
- TRACEJVMCALLSENTER(("JVM_GetClassLoader(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
- cl = class_get_classloader(c);
-
- TRACEJVMCALLSEXIT(("->%p", cl));
-
- return (jobject) cl;
-}
-
-
-/* JVM_IsInterface */
-
-jboolean JVM_IsInterface(JNIEnv *env, jclass cls)
-{
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_IsInterface(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- return class_is_interface(c);
-}
-
-
-/* JVM_GetClassSigners */
-
-jobjectArray JVM_GetClassSigners(JNIEnv *env, jclass cls)
-{
- log_println("JVM_GetClassSigners: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_SetClassSigners */
-
-void JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers)
-{
- classinfo *c;
- java_handle_objectarray_t *hoa;
-
- TRACEJVMCALLS(("JVM_SetClassSigners(env=%p, cls=%p, signers=%p)", env, cls, signers));
-
- c = LLNI_classinfo_unwrap(cls);
-
- hoa = (java_handle_objectarray_t *) signers;
-
- /* This call is ignored for primitive types and arrays. Signers
- are only set once, ClassLoader.java, and thus shouldn't be
- called with an array. Only the bootstrap loader creates
- arrays. */
-
- if (class_is_primitive(c) || class_is_array(c))
- return;
-
- LLNI_classinfo_field_set(c, signers, hoa);
-}
-
-
-/* JVM_GetProtectionDomain */
-
-jobject JVM_GetProtectionDomain(JNIEnv *env, jclass cls)
-{
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_GetProtectionDomain(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- if (c == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* Primitive types do not have a protection domain. */
-
- if (class_is_primitive(c))
- return NULL;
-
- return (jobject) c->protectiondomain;
-}
-
-
-/* JVM_SetProtectionDomain */
-
-void JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain)
-{
- log_println("JVM_SetProtectionDomain: IMPLEMENT ME!");
-}
-
-
-/* JVM_DoPrivileged */
-
-jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)
-{
- java_handle_t *h;
- classinfo *c;
- methodinfo *m;
- java_handle_t *result;
- java_handle_t *e;
-
- TRACEJVMCALLS(("JVM_DoPrivileged(env=%p, cls=%p, action=%p, context=%p, wrapException=%d)", env, cls, action, context, wrapException));
-
- h = (java_handle_t *) action;
- LLNI_class_get(h, c);
-
- if (action == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* lookup run() method (throw no exceptions) */
-
- m = class_resolveclassmethod(c, utf_run, utf_void__java_lang_Object, c,
- false);
-
- if ((m == NULL) || !(m->flags & ACC_PUBLIC) || (m->flags & ACC_STATIC)) {
- exceptions_throw_internalerror("No run method");
- return NULL;
- }
-
- /* XXX It seems something with a privileged stack needs to be done
- here. */
-
- result = vm_call_method(m, h);
-
- e = exceptions_get_exception();
-
- if (e != NULL) {
- if ( builtin_instanceof(e, class_java_lang_Exception) &&
- !builtin_instanceof(e, class_java_lang_RuntimeException)) {
- exceptions_clear_exception();
- exceptions_throw_privilegedactionexception(e);
- }
-
- return NULL;
- }
-
- return (jobject) result;
-}
-
-
-/* JVM_GetInheritedAccessControlContext */
-
-jobject JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls)
-{
- log_println("JVM_GetInheritedAccessControlContext: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetStackAccessControlContext */
-
-jobject JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)
-{
- TRACEJVMCALLS(("JVM_GetStackAccessControlContext(env=%p, cls=%p): IMPLEMENT ME!", env, cls));
-
- /* XXX All stuff I tested so far works without that function. At
- some point we have to implement it, but I disable the output
- for now to make IcedTea happy. */
-
- return NULL;
-}
-
-
-/* JVM_IsArrayClass */
-
-jboolean JVM_IsArrayClass(JNIEnv *env, jclass cls)
-{
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_IsArrayClass(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- return class_is_array(c);
-}
-
-
-/* JVM_IsPrimitiveClass */
-
-jboolean JVM_IsPrimitiveClass(JNIEnv *env, jclass cls)
-{
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_IsPrimitiveClass(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- return class_is_primitive(c);
-}
-
-
-/* JVM_GetComponentType */
-
-jclass JVM_GetComponentType(JNIEnv *env, jclass cls)
-{
- classinfo *component;
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_GetComponentType(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- component = class_get_componenttype(c);
-
- return (jclass) LLNI_classinfo_wrap(component);
-}
-
-
-/* JVM_GetClassModifiers */
-
-jint JVM_GetClassModifiers(JNIEnv *env, jclass cls)
-{
- classinfo *c;
- int32_t flags;
-
- TRACEJVMCALLS(("JVM_GetClassModifiers(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- flags = class_get_modifiers(c, false);
-
- return flags;
-}
-
-
-/* JVM_GetDeclaredClasses */
-
-jobjectArray JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS(("JVM_GetDeclaredClasses(env=%p, ofClass=%p)", env, ofClass));
-
- c = LLNI_classinfo_unwrap(ofClass);
-
- oa = class_get_declaredclasses(c, false);
-
- return (jobjectArray) oa;
-}
-
-
-/* JVM_GetDeclaringClass */
-
-jclass JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)
-{
- classinfo *c;
- classinfo *dc;
-
- TRACEJVMCALLS(("JVM_GetDeclaringClass(env=%p, ofClass=%p)", env, ofClass));
-
- c = LLNI_classinfo_unwrap(ofClass);
-
- dc = class_get_declaringclass(c);
-
- return (jclass) LLNI_classinfo_wrap(dc);
-}
-
-
-/* JVM_GetClassSignature */
-
-jstring JVM_GetClassSignature(JNIEnv *env, jclass cls)
-{
- classinfo *c;
- utf *u;
- java_handle_t *s;
-
- TRACEJVMCALLS(("JVM_GetClassSignature(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- /* Get the signature of the class. */
-
- u = class_get_signature(c);
-
- if (u == NULL)
- return NULL;
-
- /* Convert UTF-string to a Java-string. */
-
- s = javastring_new(u);
-
- return (jstring) s;
-}
-
-
-/* JVM_GetClassAnnotations */
-
-jbyteArray JVM_GetClassAnnotations(JNIEnv *env, jclass cls)
-{
- classinfo *c = NULL; /* classinfo for 'cls' */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
-
- TRACEJVMCALLS(("JVM_GetClassAnnotations: cls=%p", cls));
-
- if (cls == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- c = LLNI_classinfo_unwrap(cls);
-
- /* get annotations: */
- annotations = class_get_annotations(c);
-
- return (jbyteArray)annotations;
-}
-
-
-/* JVM_GetFieldAnnotations */
-
-jbyteArray JVM_GetFieldAnnotations(JNIEnv *env, jobject field)
-{
- java_lang_reflect_Field *rf = NULL; /* java.lang.reflect.Field for 'field' */
- java_handle_bytearray_t *ba = NULL; /* unparsed annotations */
-
- TRACEJVMCALLS(("JVM_GetFieldAnnotations: field=%p", field));
-
- if (field == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- rf = (java_lang_reflect_Field*)field;
-
- LLNI_field_get_ref(rf, annotations, ba);
-
- return (jbyteArray)ba;
-}
-
-
-/* JVM_GetMethodAnnotations */
-
-jbyteArray JVM_GetMethodAnnotations(JNIEnv *env, jobject method)
-{
- java_lang_reflect_Method *rm = NULL; /* java.lang.reflect.Method for 'method' */
- java_handle_bytearray_t *ba = NULL; /* unparsed annotations */
-
- TRACEJVMCALLS(("JVM_GetMethodAnnotations: method=%p", method));
-
- if (method == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- rm = (java_lang_reflect_Method*)method;
-
- LLNI_field_get_ref(rm, annotations, ba);
-
- return (jbyteArray)ba;
-}
-
-
-/* JVM_GetMethodDefaultAnnotationValue */
-
-jbyteArray JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject method)
-{
- java_lang_reflect_Method *rm = NULL; /* java.lang.reflect.Method for 'method' */
- java_handle_bytearray_t *ba = NULL; /* unparsed annotation default value */
-
- TRACEJVMCALLS(("JVM_GetMethodDefaultAnnotationValue: method=%p", method));
-
- if (method == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- rm = (java_lang_reflect_Method*)method;
-
- LLNI_field_get_ref(rm, annotationDefault, ba);
-
- return (jbyteArray)ba;
-}
-
-
-/* JVM_GetMethodParameterAnnotations */
-
-jbyteArray JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject method)
-{
- java_lang_reflect_Method *rm = NULL; /* java.lang.reflect.Method for 'method' */
- java_handle_bytearray_t *ba = NULL; /* unparsed parameter annotations */
-
- TRACEJVMCALLS(("JVM_GetMethodParameterAnnotations: method=%p", method));
-
- if (method == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- rm = (java_lang_reflect_Method*)method;
-
- LLNI_field_get_ref(rm, parameterAnnotations, ba);
-
- return (jbyteArray)ba;
-}
-
-
-/* JVM_GetClassDeclaredFields */
-
-jobjectArray JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS(("JVM_GetClassDeclaredFields(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
-
- c = LLNI_classinfo_unwrap(ofClass);
-
- oa = class_get_declaredfields(c, publicOnly);
-
- return (jobjectArray) oa;
-}
-
-
-/* JVM_GetClassDeclaredMethods */
-
-jobjectArray JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS(("JVM_GetClassDeclaredMethods(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
-
- c = LLNI_classinfo_unwrap(ofClass);
-
- oa = class_get_declaredmethods(c, publicOnly);
-
- return (jobjectArray) oa;
-}
-
-
-/* JVM_GetClassDeclaredConstructors */
-
-jobjectArray JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS(("JVM_GetClassDeclaredConstructors(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
-
- c = LLNI_classinfo_unwrap(ofClass);
-
- oa = class_get_declaredconstructors(c, publicOnly);
-
- return (jobjectArray) oa;
-}
-
-
-/* JVM_GetClassAccessFlags */
-
-jint JVM_GetClassAccessFlags(JNIEnv *env, jclass cls)
-{
- classinfo *c;
-
- TRACEJVMCALLS(("JVM_GetClassAccessFlags(env=%p, cls=%p)", env, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- /* Primitive type classes have the correct access flags. */
-
- return c->flags & ACC_CLASS_REFLECT_MASK;
-}
-
-
-/* JVM_GetClassConstantPool */
-
-jobject JVM_GetClassConstantPool(JNIEnv *env, jclass cls)
-{
-#if defined(ENABLE_ANNOTATIONS)
- sun_reflect_ConstantPool *constantPool = NULL;
- /* constant pool object for the class refered by 'cls' */
- java_lang_Object *constantPoolOop = (java_lang_Object*)cls;
- /* constantPoolOop field of the constant pool object */
-
- TRACEJVMCALLS(("JVM_GetClassConstantPool(env=%p, cls=%p)", env, cls));
-
- constantPool =
- (sun_reflect_ConstantPool*)native_new_and_init(
- class_sun_reflect_ConstantPool);
-
- if (constantPool == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
-
- return (jobject)constantPool;
-#else
- log_println("JVM_GetClassConstantPool(env=%p, cls=%p): not implemented in this configuration!", env, cls);
- return NULL;
-#endif
-}
-
-
-/* JVM_ConstantPoolGetSize */
-
-jint JVM_ConstantPoolGetSize(JNIEnv *env, jobject unused, jobject jcpool)
-{
- classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetSize(env=%p, unused=%p, jcpool=%p)", env, unused, jcpool));
-
- c = LLNI_classinfo_unwrap(jcpool);
-
- return c->cpcount;
-}
-
-
-/* JVM_ConstantPoolGetClassAt */
-
-jclass JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_classref *ref; /* classref to the class at constant pool index 'index' */
- classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
- classinfo *result; /* classinfo of the class at constant pool index 'index' */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetClassAt(env=%p, jcpool=%p, index=%d)", env, jcpool, index));
-
- c = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_classref *) class_getconstant(c, index, CONSTANT_Class);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- result = resolve_classref_eager(ref);
-
- return (jclass) LLNI_classinfo_wrap(result);
-}
-
-
-/* JVM_ConstantPoolGetClassAtIfLoaded */
-
-jclass JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_classref *ref; /* classref to the class at constant pool index 'index' */
- classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
- classinfo *result; /* classinfo of the class at constant pool index 'index' */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetClassAtIfLoaded(env=%p, unused=%p, jcpool=%p, index=%d)", env, unused, jcpool, index));
-
- c = LLNI_classinfo_unwrap(jcpool);
-
- ref = (constant_classref *) class_getconstant(c, index, CONSTANT_Class);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- if (!resolve_classref(NULL, ref, resolveLazy, true, true, &result)) {
- return NULL;
- }
-
- if ((result == NULL) || !(result->state & CLASS_LOADED)) {
- return NULL;
- }
-
- return (jclass) LLNI_classinfo_wrap(result);
-}
-
-
-/* JVM_ConstantPoolGetMethodAt */
-
-jobject JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_FMIref *ref; /* reference to the method in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetMethodAt: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Methodref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* XXX: is that right? or do I have to use resolve_method_*? */
- return (jobject)reflect_method_new(ref->p.method);
-}
-
-
-/* JVM_ConstantPoolGetMethodAtIfLoaded */
-
-jobject JVM_ConstantPoolGetMethodAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_FMIref *ref; /* reference to the method in constant pool at index 'index' */
- classinfo *c = NULL; /* resolved declaring class of the method */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetMethodAtIfLoaded: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Methodref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- if (!resolve_classref(NULL, ref->p.classref, resolveLazy, true, true, &c)) {
- return NULL;
- }
-
- if (c == NULL || !(c->state & CLASS_LOADED)) {
- return NULL;
- }
-
- return (jobject)reflect_method_new(ref->p.method);
-}
-
-
-/* JVM_ConstantPoolGetFieldAt */
-
-jobject JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_FMIref *ref; /* reference to the field in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetFieldAt: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Fieldref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- return (jobject)reflect_field_new(ref->p.field);
-}
-
-
-/* JVM_ConstantPoolGetFieldAtIfLoaded */
-
-jobject JVM_ConstantPoolGetFieldAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_FMIref *ref; /* reference to the field in constant pool at index 'index' */
- classinfo *c; /* resolved declaring class for the field */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetFieldAtIfLoaded: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Fieldref);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- if (!resolve_classref(NULL, ref->p.classref, resolveLazy, true, true, &c)) {
- return NULL;
- }
-
- if (c == NULL || !(c->state & CLASS_LOADED)) {
- return NULL;
- }
-
- return (jobject)reflect_field_new(ref->p.field);
-}
-
-
-/* JVM_ConstantPoolGetMemberRefInfoAt */
-
-jobjectArray JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- log_println("JVM_ConstantPoolGetMemberRefInfoAt: jcpool=%p, index=%d, IMPLEMENT ME!", jcpool, index);
-
- /* TODO: implement. (this is yet unused be OpenJDK but, so very low priority) */
-
- return NULL;
-}
-
-
-/* JVM_ConstantPoolGetIntAt */
-
-jint JVM_ConstantPoolGetIntAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_integer *ref; /* reference to the int value in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetIntAt: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_integer*)class_getconstant(cls, index, CONSTANT_Integer);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/* JVM_ConstantPoolGetLongAt */
-
-jlong JVM_ConstantPoolGetLongAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_long *ref; /* reference to the long value in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetLongAt: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_long*)class_getconstant(cls, index, CONSTANT_Long);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/* JVM_ConstantPoolGetFloatAt */
-
-jfloat JVM_ConstantPoolGetFloatAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_float *ref; /* reference to the float value in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetFloatAt: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_float*)class_getconstant(cls, index, CONSTANT_Float);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/* JVM_ConstantPoolGetDoubleAt */
-
-jdouble JVM_ConstantPoolGetDoubleAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- constant_double *ref; /* reference to the double value in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetDoubleAt: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (constant_double*)class_getconstant(cls, index, CONSTANT_Double);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- return ref->value;
-}
-
-
-/* JVM_ConstantPoolGetStringAt */
-
-jstring JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- utf *ref; /* utf object for the string in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetStringAt: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (utf*)class_getconstant(cls, index, CONSTANT_String);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* XXX: I hope literalstring_new is the right Function. */
- return (jstring)literalstring_new(ref);
-}
-
-
-/* JVM_ConstantPoolGetUTF8At */
-
-jstring JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject unused, jobject jcpool, jint index)
-{
- utf *ref; /* utf object for the utf8 data in constant pool at index 'index' */
- classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
-
- TRACEJVMCALLS(("JVM_ConstantPoolGetUTF8At: jcpool=%p, index=%d", jcpool, index));
-
- cls = LLNI_classinfo_unwrap(jcpool);
- ref = (utf*)class_getconstant(cls, index, CONSTANT_Utf8);
-
- if (ref == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* XXX: I hope literalstring_new is the right Function. */
- return (jstring)literalstring_new(ref);
-}
-
-
-/* JVM_DesiredAssertionStatus */
-
-jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
-{
-#if defined(ENABLE_ASSERTION)
- assertion_name_t *item;
- classinfo *c;
- jboolean status;
- utf *name;
-
- TRACEJVMCALLS(("JVM_DesiredAssertionStatus(env=%p, unused=%p, cls=%p)", env, unused, cls));
-
- c = LLNI_classinfo_unwrap(cls);
-
- if (c->classloader == NULL) {
- status = (jboolean)assertion_system_enabled;
- }
- else {
- status = (jboolean)assertion_user_enabled;
- }
-
- if (list_assertion_names != NULL) {
- item = (assertion_name_t *)list_first(list_assertion_names);
- while (item != NULL) {
- name = utf_new_char(item->name);
- if (name == c->packagename) {
- status = (jboolean)item->enabled;
- }
- else if (name == c->name) {
- status = (jboolean)item->enabled;
- }
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
- }
- }
-
- return status;
-#else
- return (jboolean)false;
-#endif
-}
-
-
-/* JVM_AssertionStatusDirectives */
-
-jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)
-{
- classinfo *c;
- java_lang_AssertionStatusDirectives *o;
- java_handle_objectarray_t *classes;
- java_handle_objectarray_t *packages;
- java_booleanarray_t *classEnabled;
- java_booleanarray_t *packageEnabled;
-#if defined(ENABLE_ASSERTION)
- assertion_name_t *item;
- java_handle_t *js;
- s4 i, j;
-#endif
-
- TRACEJVMCALLS(("JVM_AssertionStatusDirectives(env=%p, unused=%p)", env, unused));
-
- c = load_class_bootstrap(utf_new_char("java/lang/AssertionStatusDirectives"));
-
- if (c == NULL)
- return NULL;
-
- o = (java_lang_AssertionStatusDirectives *) builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
-#if defined(ENABLE_ASSERTION)
- classes = builtin_anewarray(assertion_class_count, class_java_lang_Object);
-#else
- classes = builtin_anewarray(0, class_java_lang_Object);
-#endif
- if (classes == NULL)
- return NULL;
-
-#if defined(ENABLE_ASSERTION)
- packages = builtin_anewarray(assertion_package_count, class_java_lang_Object);
-#else
- packages = builtin_anewarray(0, class_java_lang_Object);
-#endif
- if (packages == NULL)
- return NULL;
-
-#if defined(ENABLE_ASSERTION)
- classEnabled = builtin_newarray_boolean(assertion_class_count);
-#else
- classEnabled = builtin_newarray_boolean(0);
-#endif
- if (classEnabled == NULL)
- return NULL;
-
-#if defined(ENABLE_ASSERTION)
- packageEnabled = builtin_newarray_boolean(assertion_package_count);
-#else
- packageEnabled = builtin_newarray_boolean(0);
-#endif
- if (packageEnabled == NULL)
- return NULL;
-
-#if defined(ENABLE_ASSERTION)
- /* initialize arrays */
-
- if (list_assertion_names != NULL) {
- i = 0;
- j = 0;
-
- item = (assertion_name_t *)list_first(list_assertion_names);
- while (item != NULL) {
- js = javastring_new_from_ascii(item->name);
- if (js == NULL) {
- return NULL;
- }
-
- if (item->package == false) {
- classes->data[i] = js;
- classEnabled->data[i] = (jboolean) item->enabled;
- i += 1;
- }
- else {
- packages->data[j] = js;
- packageEnabled->data[j] = (jboolean) item->enabled;
- j += 1;
- }
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
- }
- }
-#endif
-
- /* set instance fields */
-
- o->classes = classes;
- o->packages = packages;
- o->classEnabled = classEnabled;
- o->packageEnabled = packageEnabled;
-
- return (jobject) o;
-}
-
-
-/* JVM_GetClassNameUTF */
-
-const char *JVM_GetClassNameUTF(JNIEnv *env, jclass cls)
-{
- log_println("JVM_GetClassNameUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetClassCPTypes */
-
-void JVM_GetClassCPTypes(JNIEnv *env, jclass cls, unsigned char *types)
-{
- log_println("JVM_GetClassCPTypes: IMPLEMENT ME!");
-}
-
-
-/* JVM_GetClassCPEntriesCount */
-
-jint JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cls)
-{
- log_println("JVM_GetClassCPEntriesCount: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetClassFieldsCount */
-
-jint JVM_GetClassFieldsCount(JNIEnv *env, jclass cls)
-{
- log_println("JVM_GetClassFieldsCount: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetClassMethodsCount */
-
-jint JVM_GetClassMethodsCount(JNIEnv *env, jclass cls)
-{
- log_println("JVM_GetClassMethodsCount: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxExceptionIndexes */
-
-void JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cls, jint method_index, unsigned short *exceptions)
-{
- log_println("JVM_GetMethodIxExceptionIndexes: IMPLEMENT ME!");
-}
-
-
-/* JVM_GetMethodIxExceptionsCount */
-
-jint JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cls, jint method_index)
-{
- log_println("JVM_GetMethodIxExceptionsCount: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxByteCode */
-
-void JVM_GetMethodIxByteCode(JNIEnv *env, jclass cls, jint method_index, unsigned char *code)
-{
- log_println("JVM_GetMethodIxByteCode: IMPLEMENT ME!");
-}
-
-
-/* JVM_GetMethodIxByteCodeLength */
-
-jint JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cls, jint method_index)
-{
- log_println("JVM_GetMethodIxByteCodeLength: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxExceptionTableEntry */
-
-void JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cls, jint method_index, jint entry_index, JVM_ExceptionTableEntryType *entry)
-{
- log_println("JVM_GetMethodIxExceptionTableEntry: IMPLEMENT ME!");
-}
-
-
-/* JVM_GetMethodIxExceptionTableLength */
-
-jint JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cls, int method_index)
-{
- log_println("JVM_GetMethodIxExceptionTableLength: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxModifiers */
-
-jint JVM_GetMethodIxModifiers(JNIEnv *env, jclass cls, int method_index)
-{
- log_println("JVM_GetMethodIxModifiers: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetFieldIxModifiers */
-
-jint JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index)
-{
- log_println("JVM_GetFieldIxModifiers: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxLocalsCount */
-
-jint JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index)
-{
- log_println("JVM_GetMethodIxLocalsCount: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxArgsSize */
-
-jint JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cls, int method_index)
-{
- log_println("JVM_GetMethodIxArgsSize: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxMaxStack */
-
-jint JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cls, int method_index)
-{
- log_println("JVM_GetMethodIxMaxStack: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_IsConstructorIx */
-
-jboolean JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index)
-{
- log_println("JVM_IsConstructorIx: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetMethodIxNameUTF */
-
-const char *JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)
-{
- log_println("JVM_GetMethodIxNameUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetMethodIxSignatureUTF */
-
-const char *JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cls, jint method_index)
-{
- log_println("JVM_GetMethodIxSignatureUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPFieldNameUTF */
-
-const char *JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cls, jint cp_index)
-{
- log_println("JVM_GetCPFieldNameUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPMethodNameUTF */
-
-const char *JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_index)
-{
- log_println("JVM_GetCPMethodNameUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPMethodSignatureUTF */
-
-const char *JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
-{
- log_println("JVM_GetCPMethodSignatureUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPFieldSignatureUTF */
-
-const char *JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
-{
- log_println("JVM_GetCPFieldSignatureUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPClassNameUTF */
-
-const char *JVM_GetCPClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
-{
- log_println("JVM_GetCPClassNameUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPFieldClassNameUTF */
-
-const char *JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
-{
- log_println("JVM_GetCPFieldClassNameUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPMethodClassNameUTF */
-
-const char *JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
-{
- log_println("JVM_GetCPMethodClassNameUTF: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetCPFieldModifiers */
-
-jint JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)
-{
- log_println("JVM_GetCPFieldModifiers: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetCPMethodModifiers */
-
-jint JVM_GetCPMethodModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)
-{
- log_println("JVM_GetCPMethodModifiers: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_ReleaseUTF */
-
-void JVM_ReleaseUTF(const char *utf)
-{
- log_println("JVM_ReleaseUTF: IMPLEMENT ME!");
-}
-
-
-/* JVM_IsSameClassPackage */
-
-jboolean JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2)
-{
- log_println("JVM_IsSameClassPackage: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_Open */
-
-/* Taken from: hotspot/src/share/vm/prims/jvm.h */
-
-/*
- * JVM I/O error codes
- */
-#define JVM_EEXIST -100
-
-jint JVM_Open(const char *fname, jint flags, jint mode)
-{
- int result;
-
- TRACEJVMCALLS(("JVM_Open(fname=%s, flags=%d, mode=%d)", fname, flags, mode));
-
- result = hpi_file->Open(fname, flags, mode);
-
- if (result >= 0) {
- return result;
- }
- else {
- switch (errno) {
- case EEXIST:
- return JVM_EEXIST;
- default:
- return -1;
- }
- }
-}
-
-
-/* JVM_Close */
-
-jint JVM_Close(jint fd)
-{
- TRACEJVMCALLS(("JVM_Close(fd=%d)", fd));
-
- return hpi_file->Close(fd);
-}
-
-
-/* JVM_Read */
-
-jint JVM_Read(jint fd, char *buf, jint nbytes)
-{
- TRACEJVMCALLS(("JVM_Read(fd=%d, buf=%p, nbytes=%d)", fd, buf, nbytes));
-
- return (jint) hpi_file->Read(fd, buf, nbytes);
-}
-
-
-/* JVM_Write */
-
-jint JVM_Write(jint fd, char *buf, jint nbytes)
-{
- TRACEJVMCALLS(("JVM_Write(fd=%d, buf=%s, nbytes=%d)", fd, buf, nbytes));
-
- return (jint) hpi_file->Write(fd, buf, nbytes);
-}
-
-
-/* JVM_Available */
-
-jint JVM_Available(jint fd, jlong *pbytes)
-{
- TRACEJVMCALLS(("JVM_Available(fd=%d, pbytes=%p)", fd, pbytes));
-
- return hpi_file->Available(fd, pbytes);
-}
-
-
-/* JVM_Lseek */
-
-jlong JVM_Lseek(jint fd, jlong offset, jint whence)
-{
- TRACEJVMCALLS(("JVM_Lseek(fd=%d, offset=%ld, whence=%d)", fd, offset, whence));
-
- return hpi_file->Seek(fd, (off_t) offset, whence);
-}
-
-
-/* JVM_SetLength */
-
-jint JVM_SetLength(jint fd, jlong length)
-{
- TRACEJVMCALLS(("JVM_SetLength(fd=%d, length=%ld)", length));
-
- return hpi_file->SetLength(fd, length);
-}
-
-
-/* JVM_Sync */
-
-jint JVM_Sync(jint fd)
-{
- TRACEJVMCALLS(("JVM_Sync(fd=%d)", fd));
-
- return hpi_file->Sync(fd);
-}
-
-
-/* JVM_StartThread */
-
-void JVM_StartThread(JNIEnv* env, jobject jthread)
-{
- TRACEJVMCALLS(("JVM_StartThread(env=%p, jthread=%p)", env, jthread));
-
- threads_thread_start((java_handle_t *) jthread);
-}
-
-
-/* JVM_StopThread */
-
-void JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)
-{
- log_println("JVM_StopThread: Deprecated. Not implemented.");
-}
-
-
-/* JVM_IsThreadAlive */
-
-jboolean JVM_IsThreadAlive(JNIEnv* env, jobject jthread)
-{
- java_handle_t *h;
- threadobject *t;
- bool result;
-
- TRACEJVMCALLS(("JVM_IsThreadAlive(env=%p, jthread=%p)", env, jthread));
-
- h = (java_handle_t *) jthread;
- t = thread_get_thread(h);
-
- /* The threadobject is null when a thread is created in Java. The
- priority is set later during startup. */
-
- if (t == NULL)
- return 0;
-
- result = threads_thread_is_alive(t);
-
- return result;
-}
-
-
-/* JVM_SuspendThread */
-
-void JVM_SuspendThread(JNIEnv* env, jobject jthread)
-{
- log_println("JVM_SuspendThread: Deprecated. Not implemented.");
-}
-
-
-/* JVM_ResumeThread */
-
-void JVM_ResumeThread(JNIEnv* env, jobject jthread)
-{
- log_println("JVM_ResumeThread: Deprecated. Not implemented.");
-}
-
-
-/* JVM_SetThreadPriority */
-
-void JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)
-{
- java_handle_t *h;
- threadobject *t;
-
- TRACEJVMCALLS(("JVM_SetThreadPriority(env=%p, jthread=%p, prio=%d)", env, jthread, prio));
-
- h = (java_handle_t *) jthread;
- t = thread_get_thread(h);
-
- /* The threadobject is null when a thread is created in Java. The
- priority is set later during startup. */
-
- if (t == NULL)
- return;
-
- threads_set_thread_priority(t->tid, prio);
-}
-
-
-/* JVM_Yield */
-
-void JVM_Yield(JNIEnv *env, jclass threadClass)
-{
- TRACEJVMCALLS(("JVM_Yield(env=%p, threadClass=%p)", env, threadClass));
-
- threads_yield();
-}
-
-
-/* JVM_Sleep */
-
-void JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)
-{
- TRACEJVMCALLS(("JVM_Sleep(env=%p, threadClass=%p, millis=%ld)", env, threadClass, millis));
-
- threads_sleep(millis, 0);
-}
-
-
-/* JVM_CurrentThread */
-
-jobject JVM_CurrentThread(JNIEnv* env, jclass threadClass)
-{
- java_object_t *o;
-
- TRACEJVMCALLSVERBOSE(("JVM_CurrentThread(env=%p, threadClass=%p)", env, threadClass));
-
- o = thread_get_current_object();
-
- return (jobject) o;
-}
-
-
-/* JVM_CountStackFrames */
-
-jint JVM_CountStackFrames(JNIEnv* env, jobject jthread)
-{
- log_println("JVM_CountStackFrames: Deprecated. Not implemented.");
-
- return 0;
-}
-
-
-/* JVM_Interrupt */
-
-void JVM_Interrupt(JNIEnv* env, jobject jthread)
-{
- java_handle_t *h;
- threadobject *t;
-
- TRACEJVMCALLS(("JVM_Interrupt(env=%p, jthread=%p)", env, jthread));
-
- h = (java_handle_t *) jthread;
- t = thread_get_thread(h);
-
- if (t == NULL)
- return;
-
- threads_thread_interrupt(t);
-}
-
-
-/* JVM_IsInterrupted */
-
-jboolean JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted)
-{
- java_handle_t *h;
- threadobject *t;
- jboolean interrupted;
-
- TRACEJVMCALLS(("JVM_IsInterrupted(env=%p, jthread=%p, clear_interrupted=%d)", env, jthread, clear_interrupted));
-
- h = (java_handle_t *) jthread;
- t = thread_get_thread(h);
-
- interrupted = thread_is_interrupted(t);
-
- if (interrupted && clear_interrupted)
- thread_set_interrupted(t, false);
-
- return interrupted;
-}
-
-
-/* JVM_HoldsLock */
-
-jboolean JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj)
-{
- java_handle_t *h;
- bool result;
-
- TRACEJVMCALLS(("JVM_HoldsLock(env=%p, threadClass=%p, obj=%p)", env, threadClass, obj));
-
- h = (java_handle_t *) obj;
-
- if (h == NULL) {
- exceptions_throw_nullpointerexception();
- return JNI_FALSE;
- }
-
- result = lock_is_held_by_current_thread(h);
-
- return result;
-}
-
-
-/* JVM_DumpAllStacks */
-
-void JVM_DumpAllStacks(JNIEnv* env, jclass unused)
-{
- log_println("JVM_DumpAllStacks: IMPLEMENT ME!");
-}
-
-
-/* JVM_CurrentLoadedClass */
-
-jclass JVM_CurrentLoadedClass(JNIEnv *env)
-{
- log_println("JVM_CurrentLoadedClass: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_CurrentClassLoader */
-
-jobject JVM_CurrentClassLoader(JNIEnv *env)
-{
- /* XXX if a method in a class in a trusted loader is in a
- doPrivileged, return NULL */
-
- log_println("JVM_CurrentClassLoader: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetClassContext */
-
-jobjectArray JVM_GetClassContext(JNIEnv *env)
-{
- TRACEJVMCALLS(("JVM_GetClassContext(env=%p)", env));
-
- return (jobjectArray) stacktrace_getClassContext();
-}
-
-
-/* JVM_ClassDepth */
-
-jint JVM_ClassDepth(JNIEnv *env, jstring name)
-{
- log_println("JVM_ClassDepth: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_ClassLoaderDepth */
-
-jint JVM_ClassLoaderDepth(JNIEnv *env)
-{
- log_println("JVM_ClassLoaderDepth: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetSystemPackage */
-
-jstring JVM_GetSystemPackage(JNIEnv *env, jstring name)
-{
- java_handle_t *s;
- utf *u;
- utf *result;
-
- TRACEJVMCALLS(("JVM_GetSystemPackage(env=%p, name=%p)", env, name));
-
-/* s = Package_find(name); */
- u = javastring_toutf((java_handle_t *) name, false);
-
- result = Package_find(u);
-
- if (result != NULL)
- s = javastring_new(result);
- else
- s = NULL;
-
- return (jstring) s;
-}
-
-
-/* JVM_GetSystemPackages */
-
-jobjectArray JVM_GetSystemPackages(JNIEnv *env)
-{
- log_println("JVM_GetSystemPackages: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_AllocateNewObject */
-
-jobject JVM_AllocateNewObject(JNIEnv *env, jobject receiver, jclass currClass, jclass initClass)
-{
- log_println("JVM_AllocateNewObject: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_AllocateNewArray */
-
-jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint length)
-{
- log_println("JVM_AllocateNewArray: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_LatestUserDefinedLoader */
-
-jobject JVM_LatestUserDefinedLoader(JNIEnv *env)
-{
- classloader_t *cl;
-
- TRACEJVMCALLS(("JVM_LatestUserDefinedLoader(env=%p)", env));
-
- cl = stacktrace_first_nonnull_classloader();
-
- return (jobject) cl;
-}
-
-
-/* JVM_LoadClass0 */
-
-jclass JVM_LoadClass0(JNIEnv *env, jobject receiver, jclass currClass, jstring currClassName)
-{
- log_println("JVM_LoadClass0: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetArrayLength */
-
-jint JVM_GetArrayLength(JNIEnv *env, jobject arr)
-{
- java_handle_t *a;
-
- TRACEJVMCALLS(("JVM_GetArrayLength(arr=%p)", arr));
-
- a = (java_handle_t *) arr;
-
- return array_length_get(a);
-}
-
-
-/* JVM_GetArrayElement */
-
-jobject JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index)
-{
- java_handle_t *a;
- java_handle_t *o;
-
- TRACEJVMCALLS(("JVM_GetArrayElement(env=%p, arr=%p, index=%d)", env, arr, index));
-
- a = (java_handle_t *) arr;
-
-/* if (!class_is_array(a->objheader.vftbl->class)) { */
-/* exceptions_throw_illegalargumentexception(); */
-/* return NULL; */
-/* } */
-
- o = array_element_get(a, index);
-
- return (jobject) o;
-}
-
-
-/* JVM_GetPrimitiveArrayElement */
-
-jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode)
-{
- jvalue jv;
-
- log_println("JVM_GetPrimitiveArrayElement: IMPLEMENT ME!");
-
- jv.l = NULL;
-
- return jv;
-}
-
-
-/* JVM_SetArrayElement */
-
-void JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val)
-{
- java_handle_t *a;
- java_handle_t *value;
-
- TRACEJVMCALLS(("JVM_SetArrayElement(env=%p, arr=%p, index=%d, val=%p)", env, arr, index, val));
-
- a = (java_handle_t *) arr;
- value = (java_handle_t *) val;
-
- array_element_set(a, index, value);
-}
-
-
-/* JVM_SetPrimitiveArrayElement */
-
-void JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v, unsigned char vCode)
-{
- log_println("JVM_SetPrimitiveArrayElement: IMPLEMENT ME!");
-}
-
-
-/* JVM_NewArray */
-
-jobject JVM_NewArray(JNIEnv *env, jclass eltClass, jint length)
-{
- classinfo *c;
- classinfo *pc;
- java_handle_t *a;
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS(("JVM_NewArray(env=%p, eltClass=%p, length=%d)", env, eltClass, length));
-
- if (eltClass == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* NegativeArraySizeException is checked in builtin_newarray. */
-
- c = LLNI_classinfo_unwrap(eltClass);
-
- /* Create primitive or object array. */
-
- if (class_is_primitive(c)) {
- pc = primitive_arrayclass_get_by_name(c->name);
-
- /* void arrays are not allowed. */
-
- if (pc == NULL) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- a = builtin_newarray(length, pc);
-
- return (jobject) a;
- }
- else {
- oa = builtin_anewarray(length, c);
-
- return (jobject) oa;
- }
-}
-
-
-/* JVM_NewMultiArray */
-
-jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim)
-{
- classinfo *c;
- java_handle_intarray_t *ia;
- int32_t length;
- long *dims;
- int32_t value;
- int32_t i;
- classinfo *ac;
- java_handle_objectarray_t *a;
-
- TRACEJVMCALLS(("JVM_NewMultiArray(env=%p, eltClass=%p, dim=%p)", env, eltClass, dim));
-
- if (eltClass == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* NegativeArraySizeException is checked in builtin_newarray. */
-
- c = LLNI_classinfo_unwrap(eltClass);
-
- ia = (java_handle_intarray_t *) dim;
-
- length = array_length_get((java_handle_t *) ia);
-
- /* We check here for exceptions thrown in array_length_get,
- otherwise these exceptions get overwritten by the following
- IllegalArgumentException. */
-
- if (length < 0)
- return NULL;
-
- if ((length <= 0) || (length > /* MAX_DIM */ 255)) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* XXX This is just a quick hack to get it working. */
-
- dims = MNEW(long, length);
-
- for (i = 0; i < length; i++) {
- value = LLNI_array_direct(ia, i);
- dims[i] = (long) value;
- }
-
- /* Create an array-class if necessary. */
-
- if (class_is_primitive(c))
- ac = primitive_arrayclass_get_by_name(c->name);
- else
- ac = class_array_of(c, true);
-
- if (ac == NULL)
- return NULL;
-
- a = builtin_multianewarray(length, (java_handle_t *) ac, dims);
-
- return (jobject) a;
-}
-
-
-/* JVM_InitializeSocketLibrary */
-
-jint JVM_InitializeSocketLibrary()
-{
- TRACEJVMCALLS(("JVM_InitializeSocketLibrary()"));
-
- return hpi_initialize_socket_library();
-}
-
-
-/* JVM_Socket */
-
-jint JVM_Socket(jint domain, jint type, jint protocol)
-{
- TRACEJVMCALLS(("JVM_Socket(domain=%d, type=%d, protocol=%d)", domain, type, protocol));
-
- return system_socket(domain, type, protocol);
-}
-
-
-/* JVM_SocketClose */
-
-jint JVM_SocketClose(jint fd)
-{
- TRACEJVMCALLS(("JVM_SocketClose(fd=%d)", fd));
-
- return system_close(fd);
-}
-
-
-/* JVM_SocketShutdown */
-
-jint JVM_SocketShutdown(jint fd, jint howto)
-{
- TRACEJVMCALLS(("JVM_SocketShutdown(fd=%d, howto=%d)", fd, howto));
-
- return system_shutdown(fd, howto);
-}
-
-
-/* JVM_Recv */
-
-jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags)
-{
- log_println("JVM_Recv: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_Send */
-
-jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags)
-{
- log_println("JVM_Send: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_Timeout */
-
-jint JVM_Timeout(int fd, long timeout)
-{
- log_println("JVM_Timeout: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_Listen */
-
-jint JVM_Listen(jint fd, jint count)
-{
- TRACEJVMCALLS(("JVM_Listen(fd=%d, count=%d)", fd, count));
-
- return system_listen(fd, count);
-}
-
-
-/* JVM_Connect */
-
-jint JVM_Connect(jint fd, struct sockaddr *him, jint len)
-{
- TRACEJVMCALLS(("JVM_Connect(fd=%d, him=%p, len=%d)", fd, him, len));
-
- return system_connect(fd, him, len);
-}
-
-
-/* JVM_Bind */
-
-jint JVM_Bind(jint fd, struct sockaddr *him, jint len)
-{
- log_println("JVM_Bind: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_Accept */
-
-jint JVM_Accept(jint fd, struct sockaddr *him, jint *len)
-{
- TRACEJVMCALLS(("JVM_Accept(fd=%d, him=%p, len=%p)", fd, him, len));
-
- return system_accept(fd, him, (socklen_t *) len);
-}
-
-
-/* JVM_RecvFrom */
-
-jint JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen)
-{
- log_println("JVM_RecvFrom: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetSockName */
-
-jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len)
-{
- TRACEJVMCALLS(("JVM_GetSockName(fd=%d, him=%p, len=%p)", fd, him, len));
-
- return system_getsockname(fd, him, (socklen_t *) len);
-}
-
-
-/* JVM_SendTo */
-
-jint JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen)
-{
- log_println("JVM_SendTo: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_SocketAvailable */
-
-jint JVM_SocketAvailable(jint fd, jint *pbytes)
-{
-#if defined(FIONREAD)
- int bytes;
- int result;
-
- TRACEJVMCALLS(("JVM_SocketAvailable(fd=%d, pbytes=%p)", fd, pbytes));
-
- *pbytes = 0;
-
- result = ioctl(fd, FIONREAD, &bytes);
-
- if (result < 0)
- return 0;
-
- *pbytes = bytes;
-
- return 1;
-#else
-# error FIONREAD not defined
-#endif
-}
-
-
-/* JVM_GetSockOpt */
-
-jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen)
-{
- TRACEJVMCALLS(("JVM_GetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%p)", fd, level, optname, optval, optlen));
-
- return system_getsockopt(fd, level, optname, optval, (socklen_t *) optlen);
-}
-
-
-/* JVM_SetSockOpt */
-
-jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen)
-{
- TRACEJVMCALLS(("JVM_SetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%d)", fd, level, optname, optval, optlen));
-
- return system_setsockopt(fd, level, optname, optval, optlen);
-}
-
-
-/* JVM_GetHostName */
-
-int JVM_GetHostName(char *name, int namelen)
-{
- int result;
-
- TRACEJVMCALLSENTER(("JVM_GetHostName(name=%s, namelen=%d)", name, namelen));
-
- result = system_gethostname(name, namelen);
-
- TRACEJVMCALLSEXIT(("->%d (name=%s)", result, name));
-
- return result;
-}
-
-
-/* JVM_GetHostByAddr */
-
-struct hostent *JVM_GetHostByAddr(const char* name, int len, int type)
-{
- log_println("JVM_GetHostByAddr: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetHostByName */
-
-struct hostent *JVM_GetHostByName(char* name)
-{
- log_println("JVM_GetHostByName: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetProtoByName */
-
-struct protoent *JVM_GetProtoByName(char* name)
-{
- log_println("JVM_GetProtoByName: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_LoadLibrary */
-
-void *JVM_LoadLibrary(const char *name)
-{
- utf* u;
- void* handle;
-
- TRACEJVMCALLSENTER(("JVM_LoadLibrary(name=%s)", name));
-
- u = utf_new_char(name);
-
- handle = native_library_open(u);
-
- TRACEJVMCALLSEXIT(("->%p", handle));
-
- return handle;
-}
-
-
-/* JVM_UnloadLibrary */
-
-void JVM_UnloadLibrary(void* handle)
-{
- TRACEJVMCALLS(("JVM_UnloadLibrary(handle=%p)", handle));
-
- native_library_close(handle);
-}
-
-
-/* JVM_FindLibraryEntry */
-
-void *JVM_FindLibraryEntry(void *handle, const char *name)
-{
- void* symbol;
-
- TRACEJVMCALLSENTER(("JVM_FindLibraryEntry(handle=%p, name=%s)", handle, name));
-
- symbol = hpi_library->FindLibraryEntry(handle, name);
-
- TRACEJVMCALLSEXIT(("->%p", symbol));
-
- return symbol;
-}
-
-
-/* JVM_IsNaN */
-
-jboolean JVM_IsNaN(jdouble a)
-{
- log_println("JVM_IsNaN: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_IsSupportedJNIVersion */
-
-jboolean JVM_IsSupportedJNIVersion(jint version)
-{
- TRACEJVMCALLS(("JVM_IsSupportedJNIVersion(version=%d)", version));
-
- return jni_version_check(version);
-}
-
-
-/* JVM_InternString */
-
-jstring JVM_InternString(JNIEnv *env, jstring str)
-{
- TRACEJVMCALLS(("JVM_InternString(env=%p, str=%p)", env, str));
-
- return (jstring) javastring_intern((java_handle_t *) str);
-}
-
-
-/* JVM_RawMonitorCreate */
-
-JNIEXPORT void* JNICALL JVM_RawMonitorCreate(void)
-{
- java_object_t *o;
-
- TRACEJVMCALLS(("JVM_RawMonitorCreate()"));
-
- o = NEW(java_object_t);
-
- lock_init_object_lock(o);
-
- return o;
-}
-
-
-/* JVM_RawMonitorDestroy */
-
-JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon)
-{
- TRACEJVMCALLS(("JVM_RawMonitorDestroy(mon=%p)", mon));
-
- FREE(mon, java_object_t);
-}
-
-
-/* JVM_RawMonitorEnter */
-
-JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon)
-{
- TRACEJVMCALLS(("JVM_RawMonitorEnter(mon=%p)", mon));
-
- (void) lock_monitor_enter((java_object_t *) mon);
-
- return 0;
-}
-
-
-/* JVM_RawMonitorExit */
-
-JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon)
-{
- TRACEJVMCALLS(("JVM_RawMonitorExit(mon=%p)", mon));
-
- (void) lock_monitor_exit((java_object_t *) mon);
-}
-
-
-/* JVM_SetPrimitiveFieldValues */
-
-void JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)
-{
- log_println("JVM_SetPrimitiveFieldValues: IMPLEMENT ME!");
-}
-
-
-/* JVM_GetPrimitiveFieldValues */
-
-void JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)
-{
- log_println("JVM_GetPrimitiveFieldValues: IMPLEMENT ME!");
-}
-
-
-/* JVM_AccessVMBooleanFlag */
-
-jboolean JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get)
-{
- log_println("JVM_AccessVMBooleanFlag: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_AccessVMIntFlag */
-
-jboolean JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get)
-{
- log_println("JVM_AccessVMIntFlag: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_VMBreakPoint */
-
-void JVM_VMBreakPoint(JNIEnv *env, jobject obj)
-{
- log_println("JVM_VMBreakPoint: IMPLEMENT ME!");
-}
-
-
-/* JVM_GetClassFields */
-
-jobjectArray JVM_GetClassFields(JNIEnv *env, jclass cls, jint which)
-{
- log_println("JVM_GetClassFields: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetClassMethods */
-
-jobjectArray JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which)
-{
- log_println("JVM_GetClassMethods: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetClassConstructors */
-
-jobjectArray JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which)
-{
- log_println("JVM_GetClassConstructors: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetClassField */
-
-jobject JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which)
-{
- log_println("JVM_GetClassField: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetClassMethod */
-
-jobject JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which)
-{
- log_println("JVM_GetClassMethod: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetClassConstructor */
-
-jobject JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which)
-{
- log_println("JVM_GetClassConstructor: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_NewInstance */
-
-jobject JVM_NewInstance(JNIEnv *env, jclass cls)
-{
- log_println("JVM_NewInstance: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetField */
-
-jobject JVM_GetField(JNIEnv *env, jobject field, jobject obj)
-{
- log_println("JVM_GetField: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetPrimitiveField */
-
-jvalue JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode)
-{
- jvalue jv;
-
- log_println("JVM_GetPrimitiveField: IMPLEMENT ME!");
-
- jv.l = NULL;
-
- return jv;
-}
-
-
-/* JVM_SetField */
-
-void JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val)
-{
- log_println("JVM_SetField: IMPLEMENT ME!");
-}
-
-
-/* JVM_SetPrimitiveField */
-
-void JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode)
-{
- log_println("JVM_SetPrimitiveField: IMPLEMENT ME!");
-}
-
-
-/* JVM_InvokeMethod */
-
-jobject JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)
-{
- java_lang_reflect_Method *rm;
- classinfo *c;
- int32_t slot;
- int32_t override;
- methodinfo *m;
- java_handle_t *ro;
-
- TRACEJVMCALLS(("JVM_InvokeMethod(env=%p, method=%p, obj=%p, args0=%p)", env, method, obj, args0));
-
- rm = (java_lang_reflect_Method *) method;
-
- LLNI_field_get_cls(rm, clazz, c);
- LLNI_field_get_val(rm, slot, slot);
- LLNI_field_get_val(rm, override, override);
-
- m = &(c->methods[slot]);
-
- ro = reflect_method_invoke(m, (java_handle_t *) obj, (java_handle_objectarray_t *) args0, override);
-
- return (jobject) ro;
-}
-
-
-/* JVM_NewInstanceFromConstructor */
-
-jobject JVM_NewInstanceFromConstructor(JNIEnv *env, jobject con, jobjectArray args0)
-{
- java_lang_reflect_Constructor *rc;
- classinfo *c;
- int32_t slot;
- int32_t override;
- methodinfo *m;
- java_handle_t *o;
-
- TRACEJVMCALLS(("JVM_NewInstanceFromConstructor(env=%p, c=%p, args0=%p)", env, con, args0));
-
- rc = (java_lang_reflect_Constructor *) con;
-
- LLNI_field_get_cls(rc, clazz, c);
- LLNI_field_get_val(rc, slot, slot);
- LLNI_field_get_val(rc, override, override);
-
- m = &(c->methods[slot]);
-
- o = reflect_constructor_newinstance(m, (java_handle_objectarray_t *) args0, override);
-
- return (jobject) o;
-}
-
-
-/* JVM_SupportsCX8 */
-
-jboolean JVM_SupportsCX8()
-{
- TRACEJVMCALLS(("JVM_SupportsCX8()"));
-
- /* IMPLEMENT ME */
-
- return 0;
-}
-
-
-/* JVM_CX8Field */
-
-jboolean JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong oldVal, jlong newVal)
-{
- log_println("JVM_CX8Field: IMPLEMENT ME!");
-
- return 0;
-}
-
-
-/* JVM_GetAllThreads */
-
-jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy)
-{
- log_println("JVM_GetAllThreads: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_DumpThreads */
-
-jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads)
-{
- log_println("JVM_DumpThreads: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetManagement */
-
-void *JVM_GetManagement(jint version)
-{
- TRACEJVMCALLS(("JVM_GetManagement(version=%d)", version));
-
- /* TODO We current don't support the management interface. */
-
- return NULL;
-}
-
-
-/* JVM_InitAgentProperties */
-
-jobject JVM_InitAgentProperties(JNIEnv *env, jobject properties)
-{
- log_println("JVM_InitAgentProperties: IMPLEMENT ME!");
-
- return NULL;
-}
-
-
-/* JVM_GetEnclosingMethodInfo */
-
-jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)
-{
- classinfo *c;
- methodinfo *m;
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS(("JVM_GetEnclosingMethodInfo(env=%p, ofClass=%p)", env, ofClass));
-
- c = LLNI_classinfo_unwrap(ofClass);
-
- if ((c == NULL) || class_is_primitive(c))
- return NULL;
-
- m = class_get_enclosingmethod_raw(c);
-
- if (m == NULL)
- return NULL;
-
- oa = builtin_anewarray(3, class_java_lang_Object);
-
- if (oa == NULL)
- return NULL;
-
- array_objectarray_element_set(oa, 0, (java_handle_t *) LLNI_classinfo_wrap(m->clazz));
- array_objectarray_element_set(oa, 1, javastring_new(m->name));
- array_objectarray_element_set(oa, 2, javastring_new(m->descriptor));
-
- return (jobjectArray) oa;
-}
-
-
-/* JVM_GetThreadStateValues */
-
-jintArray JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState)
-{
- java_handle_intarray_t *ia;
-
- TRACEJVMCALLS(("JVM_GetThreadStateValues(env=%p, javaThreadState=%d)",
- env, javaThreadState));
-
- /* If new thread states are added in future JDK and VM versions,
- this should check if the JDK version is compatible with thread
- states supported by the VM. Return NULL if not compatible.
-
- This function must map the VM java_lang_Thread::ThreadStatus
- to the Java thread state that the JDK supports. */
-
- switch (javaThreadState) {
- case THREAD_STATE_NEW:
- ia = builtin_newarray_int(1);
-
- if (ia == NULL)
- return NULL;
-
- array_intarray_element_set(ia, 0, THREAD_STATE_NEW);
- break;
-
- case THREAD_STATE_RUNNABLE:
- ia = builtin_newarray_int(1);
-
- if (ia == NULL)
- return NULL;
-
- array_intarray_element_set(ia, 0, THREAD_STATE_RUNNABLE);
- break;
-
- case THREAD_STATE_BLOCKED:
- ia = builtin_newarray_int(1);
-
- if (ia == NULL)
- return NULL;
-
- array_intarray_element_set(ia, 0, THREAD_STATE_BLOCKED);
- break;
-
- case THREAD_STATE_WAITING:
- ia = builtin_newarray_int(2);
-
- if (ia == NULL)
- return NULL;
-
- array_intarray_element_set(ia, 0, THREAD_STATE_WAITING);
- /* XXX Implement parked stuff. */
-/* array_intarray_element_set(ia, 1, PARKED); */
- break;
-
- case THREAD_STATE_TIMED_WAITING:
- ia = builtin_newarray_int(3);
-
- if (ia == NULL)
- return NULL;
-
- /* XXX Not sure about that one. */
-/* array_intarray_element_set(ia, 0, SLEEPING); */
- array_intarray_element_set(ia, 0, THREAD_STATE_TIMED_WAITING);
- /* XXX Implement parked stuff. */
-/* array_intarray_element_set(ia, 2, PARKED); */
- break;
-
- case THREAD_STATE_TERMINATED:
- ia = builtin_newarray_int(1);
-
- if (ia == NULL)
- return NULL;
-
- array_intarray_element_set(ia, 0, THREAD_STATE_TERMINATED);
- break;
-
- default:
- /* Unknown state - probably incompatible JDK version */
- return NULL;
- }
-
- return (jintArray) ia;
-}
-
-
-/* JVM_GetThreadStateNames */
-
-jobjectArray JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values)
-{
- java_handle_intarray_t *ia;
- java_handle_objectarray_t *oa;
- java_object_t *s;
-
- TRACEJVMCALLS(("JVM_GetThreadStateNames(env=%p, javaThreadState=%d, values=%p)",
- env, javaThreadState, values));
-
- ia = (java_handle_intarray_t *) values;
-
- /* If new thread states are added in future JDK and VM versions,
- this should check if the JDK version is compatible with thread
- states supported by the VM. Return NULL if not compatible.
-
- This function must map the VM java_lang_Thread::ThreadStatus
- to the Java thread state that the JDK supports. */
-
- if (values == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- switch (javaThreadState) {
- case THREAD_STATE_NEW:
- assert(ia->header.size == 1 && ia->data[0] == THREAD_STATE_NEW);
-
- oa = builtin_anewarray(1, class_java_lang_String);
-
- if (oa == NULL)
- return NULL;
-
- s = javastring_new(utf_new_char("NEW"));
-
- if (s == NULL)
- return NULL;
-
- array_objectarray_element_set(oa, 0, s);
- break;
-
- case THREAD_STATE_RUNNABLE:
- oa = builtin_anewarray(1, class_java_lang_String);
-
- if (oa == NULL)
- return NULL;
-
- s = javastring_new(utf_new_char("RUNNABLE"));
-
- if (s == NULL)
- return NULL;
-
- array_objectarray_element_set(oa, 0, s);
- break;
-
- case THREAD_STATE_BLOCKED:
- oa = builtin_anewarray(1, class_java_lang_String);
-
- if (oa == NULL)
- return NULL;
-
- s = javastring_new(utf_new_char("BLOCKED"));
-
- if (s == NULL)
- return NULL;
-
- array_objectarray_element_set(oa, 0, s);
- break;
-
- case THREAD_STATE_WAITING:
- oa = builtin_anewarray(2, class_java_lang_String);
-
- if (oa == NULL)
- return NULL;
-
- s = javastring_new(utf_new_char("WAITING.OBJECT_WAIT"));
-/* s = javastring_new(utf_new_char("WAITING.PARKED")); */
-
- if (s == NULL)
- return NULL;
-
- array_objectarray_element_set(oa, 0, s);
-/* array_objectarray_element_set(oa, 1, s); */
- break;
-
- case THREAD_STATE_TIMED_WAITING:
- oa = builtin_anewarray(3, class_java_lang_String);
-
- if (oa == NULL)
- return NULL;
-
-/* s = javastring_new(utf_new_char("TIMED_WAITING.SLEEPING")); */
- s = javastring_new(utf_new_char("TIMED_WAITING.OBJECT_WAIT"));
-/* s = javastring_new(utf_new_char("TIMED_WAITING.PARKED")); */
-
- if (s == NULL)
- return NULL;
-
-/* array_objectarray_element_set(oa, 0, s); */
- array_objectarray_element_set(oa, 0, s);
-/* array_objectarray_element_set(oa, 2, s); */
- break;
-
- case THREAD_STATE_TERMINATED:
- oa = builtin_anewarray(1, class_java_lang_String);
-
- if (oa == NULL)
- return NULL;
-
- s = javastring_new(utf_new_char("TERMINATED"));
-
- if (s == NULL)
- return NULL;
-
- array_objectarray_element_set(oa, 0, s);
- break;
-
- default:
- /* Unknown state - probably incompatible JDK version */
- return NULL;
- }
-
- return (jobjectArray) oa;
-}
-
-
-/* JVM_GetVersionInfo */
-
-void JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size)
-{
- log_println("JVM_GetVersionInfo: IMPLEMENT ME!");
-}
-
-
-/* OS: JVM_RegisterSignal */
-
-void *JVM_RegisterSignal(jint sig, void *handler)
-{
- functionptr newHandler;
-
- TRACEJVMCALLS(("JVM_RegisterSignal(sig=%d, handler=%p)", sig, handler));
-
- if (handler == (void *) 2)
- newHandler = (functionptr) signal_thread_handler;
- else
- newHandler = (functionptr) (uintptr_t) handler;
-
- switch (sig) {
- case SIGILL:
- case SIGFPE:
- case SIGUSR1:
- case SIGSEGV:
- /* These signals are already used by the VM. */
- return (void *) -1;
-
- case SIGQUIT:
- /* This signal is used by the VM to dump thread stacks unless
- ReduceSignalUsage is set, in which case the user is allowed
- to set his own _native_ handler for this signal; thus, in
- either case, we do not allow JVM_RegisterSignal to change
- the handler. */
- return (void *) -1;
-
- case SIGHUP:
- case SIGINT:
- case SIGTERM:
- break;
- }
-
- signal_register_signal(sig, newHandler, 0);
-
- /* XXX Should return old handler. */
-
- return (void *) 2;
-}
-
-
-/* OS: JVM_RaiseSignal */
-
-jboolean JVM_RaiseSignal(jint sig)
-{
- log_println("JVM_RaiseSignal: IMPLEMENT ME! sig=%s", sig);
-
- return false;
-}
-
-
-/* OS: JVM_FindSignal */
-
-jint JVM_FindSignal(const char *name)
-{
- TRACEJVMCALLS(("JVM_FindSignal(name=%s)", name));
-
-#if defined(__LINUX__)
- if (strcmp(name, "HUP") == 0)
- return SIGHUP;
-
- if (strcmp(name, "INT") == 0)
- return SIGINT;
-
- if (strcmp(name, "TERM") == 0)
- return SIGTERM;
-#else
-# error not implemented for this OS
-#endif
-
- return -1;
-}
-
-
-/*
- * 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/native/vm/openjdk/jvm.cpp - HotSpot VM interface 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.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#if defined(HAVE_SYS_IOCTL_H)
+#define BSD_COMP /* Get FIONREAD on Solaris2 */
+#include <sys/ioctl.h>
+#endif
+
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "native/vm/reflection.hpp"
+
+#include "native/vm/openjdk/hpi.h"
+
+#include "threads/lock-common.h"
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+#include "toolbox/list.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/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/package.hpp"
+#include "vm/primitive.hpp"
+#include "vm/properties.h"
+#include "vm/resolve.h"
+#include "vm/signallocal.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/stacktrace.hpp"
+
+
+/* debugging macros ***********************************************************/
+
+#if !defined(NDEBUG)
+
+# define TRACEJVMCALLS(x) \
+ do { \
+ if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
+ log_println x; \
+ } \
+ } while (0)
+
+# define TRACEJVMCALLSENTER(x) \
+ do { \
+ if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
+ log_start(); \
+ log_print x; \
+ } \
+ } while (0)
+
+# define TRACEJVMCALLSEXIT(x) \
+ do { \
+ if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
+ log_print x; \
+ log_finish(); \
+ } \
+ } while (0)
+
+# define TRACEJVMCALLSVERBOSE(x) \
+ do { \
+ if (opt_TraceJVMCallsVerbose) { \
+ log_println x; \
+ } \
+ } while (0)
+
+# define PRINTJVMWARNINGS(x)
+/* do { \ */
+/* if (opt_PrintJVMWarnings) { \ */
+/* log_println x; \ */
+/* } \ */
+/* } while (0) */
+
+#else
+
+# define TRACEJVMCALLS(x)
+# define TRACEJVMCALLSENTER(x)
+# define TRACEJVMCALLSEXIT(x)
+# define TRACEJVMCALLSVERBOSE(x)
+# define PRINTJVMWARNINGS(x)
+
+#endif
+
+
+typedef struct {
+ /* Naming convention of RE build version string: n.n.n[_uu[c]][-<identifier>]-bxx */
+ unsigned int jvm_version; /* Consists of major, minor, micro (n.n.n) */
+ /* and build number (xx) */
+ unsigned int update_version : 8; /* Update release version (uu) */
+ unsigned int special_update_version : 8; /* Special update release version (c) */
+ unsigned int reserved1 : 16;
+ unsigned int reserved2;
+
+ /* The following bits represents JVM supports that JDK has dependency on.
+ * JDK can use these bits to determine which JVM version
+ * and support it has to maintain runtime compatibility.
+ *
+ * When a new bit is added in a minor or update release, make sure
+ * the new bit is also added in the main/baseline.
+ */
+ unsigned int is_attachable : 1;
+ unsigned int : 31;
+ unsigned int : 32;
+ unsigned int : 32;
+} jvm_version_info;
+
+
+/*
+ * A structure used to a capture exception table entry in a Java method.
+ */
+typedef struct {
+ jint start_pc;
+ jint end_pc;
+ jint handler_pc;
+ jint catchType;
+} JVM_ExceptionTableEntryType;
+
+
+// Interface functions are exported as C functions.
+extern "C" {
+
+int jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args)
+{
+ if ((intptr_t) count <= 0)
+ return -1;
+
+ return vsnprintf(str, count, fmt, args);
+}
+
+
+int jio_snprintf(char *str, size_t count, const char *fmt, ...)
+{
+ va_list ap;
+ int len;
+
+ va_start(ap, fmt);
+ len = jio_vsnprintf(str, count, fmt, ap);
+ va_end(ap);
+
+ return len;
+}
+
+
+int jio_fprintf(FILE* f, const char *fmt, ...)
+{
+ log_println("jio_fprintf: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+int jio_vfprintf(FILE* f, const char *fmt, va_list args)
+{
+ log_println("jio_vfprintf: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+int jio_printf(const char *fmt, ...)
+{
+ log_println("jio_printf: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetInterfaceVersion */
+
+jint JVM_GetInterfaceVersion()
+{
+ /* This is defined in hotspot/src/share/vm/prims/jvm.h */
+
+#define JVM_INTERFACE_VERSION 4
+
+ return JVM_INTERFACE_VERSION;
+}
+
+
+/* JVM_CurrentTimeMillis */
+
+jlong JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored)
+{
+ TRACEJVMCALLS(("JVM_CurrentTimeMillis(env=%p, ignored=%p)", env, ignored));
+
+ return (jlong) builtin_currenttimemillis();
+}
+
+
+/* JVM_NanoTime */
+
+jlong JVM_NanoTime(JNIEnv *env, jclass ignored)
+{
+ TRACEJVMCALLS(("JVM_NanoTime(env=%p, ignored=%p)", env, ignored));
+
+ return (jlong) builtin_nanotime();
+}
+
+
+/* JVM_ArrayCopy */
+
+void JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length)
+{
+ java_handle_t *s;
+ java_handle_t *d;
+
+ s = (java_handle_t *) src;
+ d = (java_handle_t *) dst;
+
+ TRACEJVMCALLSVERBOSE(("JVM_ArrayCopy(env=%p, ignored=%p, src=%p, src_pos=%d, dst=%p, dst_pos=%d, length=%d)", env, ignored, src, src_pos, dst, dst_pos, length));
+
+ builtin_arraycopy(s, src_pos, d, dst_pos, length);
+}
+
+
+/* JVM_InitProperties */
+
+jobject JVM_InitProperties(JNIEnv *env, jobject properties)
+{
+ java_handle_t *h;
+ char buf[256];
+
+ TRACEJVMCALLS(("JVM_InitProperties(env=%p, properties=%p)", env, properties));
+
+ h = (java_handle_t *) properties;
+
+ /* Convert the -XX:MaxDirectMemorySize= command line flag to the
+ sun.nio.MaxDirectMemorySize property. Do this after setting
+ user properties to prevent people from setting the value with a
+ -D option, as requested. */
+
+ jio_snprintf(buf, sizeof(buf), PRINTF_FORMAT_INT64_T, opt_MaxDirectMemorySize);
+ properties_add("sun.nio.MaxDirectMemorySize", buf);
+
+ /* Add all properties. */
+
+ properties_system_add_all(h);
+
+ return properties;
+}
+
+
+/* JVM_Exit */
+
+void JVM_Exit(jint code)
+{
+ log_println("JVM_Exit: IMPLEMENT ME!");
+}
+
+
+/* JVM_Halt */
+
+void JVM_Halt(jint code)
+{
+ TRACEJVMCALLS(("JVM_Halt(code=%d)", code));
+
+/* vm_exit(code); */
+ vm_shutdown(code);
+}
+
+
+/* JVM_OnExit(void (*func)) */
+
+void JVM_OnExit(void (*func)(void))
+{
+ log_println("JVM_OnExit(void (*func): IMPLEMENT ME!");
+}
+
+
+/* JVM_GC */
+
+void JVM_GC(void)
+{
+ TRACEJVMCALLS(("JVM_GC()"));
+
+ gc_call();
+}
+
+
+/* JVM_MaxObjectInspectionAge */
+
+jlong JVM_MaxObjectInspectionAge(void)
+{
+ log_println("JVM_MaxObjectInspectionAge: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_TraceInstructions */
+
+void JVM_TraceInstructions(jboolean on)
+{
+ log_println("JVM_TraceInstructions: IMPLEMENT ME!");
+}
+
+
+/* JVM_TraceMethodCalls */
+
+void JVM_TraceMethodCalls(jboolean on)
+{
+ log_println("JVM_TraceMethodCalls: IMPLEMENT ME!");
+}
+
+
+/* JVM_TotalMemory */
+
+jlong JVM_TotalMemory(void)
+{
+ TRACEJVMCALLS(("JVM_TotalMemory()"));
+
+ return gc_get_heap_size();
+}
+
+
+/* JVM_FreeMemory */
+
+jlong JVM_FreeMemory(void)
+{
+ TRACEJVMCALLS(("JVM_FreeMemory()"));
+
+ return gc_get_free_bytes();
+}
+
+
+/* JVM_MaxMemory */
+
+jlong JVM_MaxMemory(void)
+{
+ TRACEJVMCALLS(("JVM_MaxMemory()"));
+
+ return gc_get_max_heap_size();
+}
+
+
+/* JVM_ActiveProcessorCount */
+
+jint JVM_ActiveProcessorCount(void)
+{
+ TRACEJVMCALLS(("JVM_ActiveProcessorCount()"));
+
+ return os::processors_online();
+}
+
+
+/* JVM_FillInStackTrace */
+
+void JVM_FillInStackTrace(JNIEnv *env, jobject receiver)
+{
+ TRACEJVMCALLS(("JVM_FillInStackTrace(env=%p, receiver=%p)", env, receiver));
+
+ java_handle_bytearray_t* ba = stacktrace_get_current();
+
+ if (ba == NULL)
+ return;
+
+ java_lang_Throwable jlt(receiver, ba);
+}
+
+
+/* JVM_PrintStackTrace */
+
+void JVM_PrintStackTrace(JNIEnv *env, jobject receiver, jobject printable)
+{
+ log_println("JVM_PrintStackTrace: IMPLEMENT ME!");
+}
+
+
+/* JVM_GetStackTraceDepth */
+
+jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)
+{
+ TRACEJVMCALLS(("JVM_GetStackTraceDepth(env=%p, throwable=%p)", env, throwable));
+
+ java_lang_Throwable jlt(throwable);
+
+ if (jlt.is_null()) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ java_handle_bytearray_t* ba = jlt.get_backtrace();
+
+ if (ba == NULL)
+ return 0;
+
+ // We need a critical section here as the stacktrace structure is
+ // mapped onto a Java byte-array.
+
+ LLNI_CRITICAL_START;
+
+ stacktrace_t* st = (stacktrace_t *) LLNI_array_data(ba);
+
+ int32_t depth = st->length;
+
+ LLNI_CRITICAL_END;
+
+ return depth;
+}
+
+
+/* JVM_GetStackTraceElement */
+
+jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
+{
+ TRACEJVMCALLS(("JVM_GetStackTraceElement(env=%p, throwable=%p, index=%d)", env, throwable, index));
+
+ java_lang_Throwable jlt(throwable);
+ java_handle_bytearray_t* ba = jlt.get_backtrace();
+
+ // We need a critical section here as the stacktrace structure is
+ // mapped onto a Java byte-array.
+ LLNI_CRITICAL_START;
+
+ stacktrace_t* st = (stacktrace_t *) LLNI_array_data(ba);
+
+ if ((index < 0) || (index >= st->length)) {
+ /* XXX This should be an IndexOutOfBoundsException (check this
+ again). */
+ exceptions_throw_arrayindexoutofboundsexception();
+ return NULL;
+ }
+
+ // Get the stacktrace entry.
+ stacktrace_entry_t* ste = &(st->entries[index]);
+
+ // Get the codeinfo, methodinfo and classinfo.
+ codeinfo* code = ste->code;
+ methodinfo* m = code->m;
+ classinfo* c = m->clazz;
+
+ // Get filename.
+ java_handle_t* filename;
+
+ if (!(m->flags & ACC_NATIVE)) {
+ if (c->sourcefile != NULL)
+ filename = javastring_new(c->sourcefile);
+ else
+ filename = NULL;
+ }
+ else
+ filename = NULL;
+
+ // Get line number.
+ int32_t linenumber;
+
+ if (m->flags & ACC_NATIVE) {
+ linenumber = -2;
+ }
+ else {
+ /* FIXME The linenumbertable_linenumber_for_pc could change
+ the methodinfo pointer when hitting an inlined method. */
+
+ linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
+ linenumber = (linenumber == 0) ? -1 : linenumber;
+ }
+
+ LLNI_CRITICAL_END;
+
+ // Get declaring class name.
+ java_handle_t* declaringclass = class_get_classname(c);
+
+ // Allocate a new StackTraceElement object.
+ java_lang_StackTraceElement jlste(declaringclass, javastring_new(m->name), filename, linenumber);
+
+ if (jlste.is_null())
+ return NULL;
+
+ return (jobject) jlste.get_handle();
+}
+
+
+/* JVM_IHashCode */
+
+jint JVM_IHashCode(JNIEnv* env, jobject handle)
+{
+ TRACEJVMCALLS(("JVM_IHashCode(env=%p, jobject=%p)", env, handle));
+
+ return (jint) ((ptrint) handle);
+}
+
+
+/* JVM_MonitorWait */
+
+void JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *o;
+#endif
+
+ TRACEJVMCALLS(("JVM_MonitorWait(env=%p, handle=%p, ms=%ld)", env, handle, ms));
+ if (ms < 0) {
+/* exceptions_throw_illegalargumentexception("argument out of range"); */
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+#if defined(ENABLE_THREADS)
+ o = (java_handle_t *) handle;
+
+ lock_wait_for_object(o, ms, 0);
+#endif
+}
+
+
+/* JVM_MonitorNotify */
+
+void JVM_MonitorNotify(JNIEnv* env, jobject handle)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *o;
+#endif
+
+ TRACEJVMCALLS(("JVM_MonitorNotify(env=%p, handle=%p)", env, handle));
+
+#if defined(ENABLE_THREADS)
+ o = (java_handle_t *) handle;
+
+ lock_notify_object(o);
+#endif
+}
+
+
+/* JVM_MonitorNotifyAll */
+
+void JVM_MonitorNotifyAll(JNIEnv* env, jobject handle)
+{
+#if defined(ENABLE_THREADS)
+ java_handle_t *o;
+#endif
+
+ TRACEJVMCALLS(("JVM_MonitorNotifyAll(env=%p, handle=%p)", env, handle));
+
+#if defined(ENABLE_THREADS)
+ o = (java_handle_t *) handle;
+
+ lock_notify_all_object(o);
+#endif
+}
+
+
+/* JVM_Clone */
+
+jobject JVM_Clone(JNIEnv* env, jobject handle)
+{
+ TRACEJVMCALLS(("JVM_Clone(env=%p, handle=%p)", env, handle));
+
+ return (jobject) builtin_clone(env, (java_handle_t *) handle);
+}
+
+
+/* JVM_InitializeCompiler */
+
+void JVM_InitializeCompiler (JNIEnv *env, jclass compCls)
+{
+ log_println("JVM_InitializeCompiler : IMPLEMENT ME!");
+}
+
+
+/* JVM_IsSilentCompiler */
+
+jboolean JVM_IsSilentCompiler(JNIEnv *env, jclass compCls)
+{
+ log_println("JVM_IsSilentCompiler: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_CompileClass */
+
+jboolean JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls)
+{
+ log_println("JVM_CompileClass: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_CompileClasses */
+
+jboolean JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname)
+{
+ log_println("JVM_CompileClasses: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_CompilerCommand */
+
+jobject JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg)
+{
+ log_println("JVM_CompilerCommand: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_EnableCompiler */
+
+void JVM_EnableCompiler(JNIEnv *env, jclass compCls)
+{
+ TRACEJVMCALLS(("JVM_EnableCompiler(env=%p, compCls=%p)", env, compCls));
+ PRINTJVMWARNINGS(("JVM_EnableCompiler not supported"));
+}
+
+
+/* JVM_DisableCompiler */
+
+void JVM_DisableCompiler(JNIEnv *env, jclass compCls)
+{
+ TRACEJVMCALLS(("JVM_DisableCompiler(env=%p, compCls=%p)", env, compCls));
+ PRINTJVMWARNINGS(("JVM_DisableCompiler not supported"));
+}
+
+
+/* JVM_GetLastErrorString */
+
+jint JVM_GetLastErrorString(char *buf, int len)
+{
+ TRACEJVMCALLS(("JVM_GetLastErrorString(buf=%p, len=%d", buf, len));
+
+ return hpi_system->GetLastErrorString(buf, len);
+}
+
+
+/* JVM_NativePath */
+
+char *JVM_NativePath(char *path)
+{
+ TRACEJVMCALLS(("JVM_NativePath(path=%s)", path));
+
+ return hpi_file->NativePath(path);
+}
+
+
+/* JVM_GetCallerClass */
+
+jclass JVM_GetCallerClass(JNIEnv* env, int depth)
+{
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_GetCallerClass(env=%p, depth=%d)", env, depth));
+
+ c = stacktrace_get_caller_class(depth);
+
+ return (jclass) c;
+}
+
+
+/* JVM_FindPrimitiveClass */
+
+jclass JVM_FindPrimitiveClass(JNIEnv* env, const char* s)
+{
+ classinfo *c;
+ utf *u;
+
+ TRACEJVMCALLS(("JVM_FindPrimitiveClass(env=%p, s=%s)", env, s));
+
+ u = utf_new_char(s);
+ c = Primitive::get_class_by_name(u);
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/* JVM_ResolveClass */
+
+void JVM_ResolveClass(JNIEnv* env, jclass cls)
+{
+ TRACEJVMCALLS(("JVM_ResolveClass(env=%p, cls=%p)", env, cls));
+ PRINTJVMWARNINGS(("JVM_ResolveClass not implemented"));
+}
+
+
+/* JVM_FindClassFromClassLoader */
+
+jclass JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init, jobject loader, jboolean throwError)
+{
+ classinfo *c;
+ utf *u;
+ classloader_t *cl;
+
+ TRACEJVMCALLS(("JVM_FindClassFromClassLoader(name=%s, init=%d, loader=%p, throwError=%d)", name, init, loader, throwError));
+
+ /* As of now, OpenJDK does not call this function with throwError
+ is true. */
+
+ assert(throwError == false);
+
+ u = utf_new_char(name);
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ c = load_class_from_classloader(u, cl);
+
+ if (c == NULL)
+ return NULL;
+
+ if (init)
+ if (!(c->state & CLASS_INITIALIZED))
+ if (!initialize_class(c))
+ return NULL;
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/* JVM_FindClassFromClass */
+
+jclass JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init, jclass from)
+{
+ log_println("JVM_FindClassFromClass: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_DefineClass */
+
+jclass JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)
+{
+ log_println("JVM_DefineClass: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_DefineClassWithSource */
+
+jclass JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)
+{
+ classinfo *c;
+ utf *u;
+ classloader_t *cl;
+
+ TRACEJVMCALLS(("JVM_DefineClassWithSource(env=%p, name=%s, loader=%p, buf=%p, len=%d, pd=%p, source=%s)", env, name, loader, buf, len, pd, source));
+
+ if (name != NULL)
+ u = utf_new_char(name);
+ else
+ u = NULL;
+
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ /* XXX do something with source */
+
+ c = class_define(u, cl, len, (uint8_t *) buf, (java_handle_t *) pd);
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/* JVM_FindLoadedClass */
+
+jclass JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
+{
+ classloader_t *cl;
+ utf *u;
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_FindLoadedClass(env=%p, loader=%p, name=%p)", env, loader, name));
+
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ u = javastring_toutf((java_handle_t *) name, true);
+ c = classcache_lookup(cl, u);
+
+ return (jclass) LLNI_classinfo_wrap(c);
+}
+
+
+/* JVM_GetClassName */
+
+jstring JVM_GetClassName(JNIEnv *env, jclass cls)
+{
+ classinfo* c;
+
+ TRACEJVMCALLS(("JVM_GetClassName(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ return (jstring) class_get_classname(c);
+}
+
+
+/* JVM_GetClassInterfaces */
+
+jobjectArray JVM_GetClassInterfaces(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetClassInterfaces(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ oa = class_get_interfaces(c);
+
+ return (jobjectArray) oa;
+}
+
+
+/* JVM_GetClassLoader */
+
+jobject JVM_GetClassLoader(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+ classloader_t *cl;
+
+ TRACEJVMCALLSENTER(("JVM_GetClassLoader(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+ cl = class_get_classloader(c);
+
+ TRACEJVMCALLSEXIT(("->%p", cl));
+
+ return (jobject) cl;
+}
+
+
+/* JVM_IsInterface */
+
+jboolean JVM_IsInterface(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_IsInterface(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ return class_is_interface(c);
+}
+
+
+/* JVM_GetClassSigners */
+
+jobjectArray JVM_GetClassSigners(JNIEnv *env, jclass cls)
+{
+ log_println("JVM_GetClassSigners: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_SetClassSigners */
+
+void JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers)
+{
+ classinfo *c;
+ java_handle_objectarray_t *hoa;
+
+ TRACEJVMCALLS(("JVM_SetClassSigners(env=%p, cls=%p, signers=%p)", env, cls, signers));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ hoa = (java_handle_objectarray_t *) signers;
+
+ /* This call is ignored for primitive types and arrays. Signers
+ are only set once, ClassLoader.java, and thus shouldn't be
+ called with an array. Only the bootstrap loader creates
+ arrays. */
+
+ if (class_is_primitive(c) || class_is_array(c))
+ return;
+
+ LLNI_classinfo_field_set(c, signers, hoa);
+}
+
+
+/* JVM_GetProtectionDomain */
+
+jobject JVM_GetProtectionDomain(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_GetProtectionDomain(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ if (c == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* Primitive types do not have a protection domain. */
+
+ if (class_is_primitive(c))
+ return NULL;
+
+ return (jobject) c->protectiondomain;
+}
+
+
+/* JVM_SetProtectionDomain */
+
+void JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain)
+{
+ log_println("JVM_SetProtectionDomain: IMPLEMENT ME!");
+}
+
+
+/* JVM_DoPrivileged */
+
+jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)
+{
+ java_handle_t *h;
+ classinfo *c;
+ methodinfo *m;
+ java_handle_t *result;
+ java_handle_t *e;
+
+ TRACEJVMCALLS(("JVM_DoPrivileged(env=%p, cls=%p, action=%p, context=%p, wrapException=%d)", env, cls, action, context, wrapException));
+
+ h = (java_handle_t *) action;
+ LLNI_class_get(h, c);
+
+ if (action == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* lookup run() method (throw no exceptions) */
+
+ m = class_resolveclassmethod(c, utf_run, utf_void__java_lang_Object, c,
+ false);
+
+ if ((m == NULL) || !(m->flags & ACC_PUBLIC) || (m->flags & ACC_STATIC)) {
+ exceptions_throw_internalerror("No run method");
+ return NULL;
+ }
+
+ /* XXX It seems something with a privileged stack needs to be done
+ here. */
+
+ result = vm_call_method(m, h);
+
+ e = exceptions_get_exception();
+
+ if (e != NULL) {
+ if ( builtin_instanceof(e, class_java_lang_Exception) &&
+ !builtin_instanceof(e, class_java_lang_RuntimeException)) {
+ exceptions_clear_exception();
+ exceptions_throw_privilegedactionexception(e);
+ }
+
+ return NULL;
+ }
+
+ return (jobject) result;
+}
+
+
+/* JVM_GetInheritedAccessControlContext */
+
+jobject JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls)
+{
+ log_println("JVM_GetInheritedAccessControlContext: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetStackAccessControlContext */
+
+jobject JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)
+{
+ TRACEJVMCALLS(("JVM_GetStackAccessControlContext(env=%p, cls=%p): IMPLEMENT ME!", env, cls));
+
+ /* XXX All stuff I tested so far works without that function. At
+ some point we have to implement it, but I disable the output
+ for now to make IcedTea happy. */
+
+ return NULL;
+}
+
+
+/* JVM_IsArrayClass */
+
+jboolean JVM_IsArrayClass(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_IsArrayClass(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ return class_is_array(c);
+}
+
+
+/* JVM_IsPrimitiveClass */
+
+jboolean JVM_IsPrimitiveClass(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_IsPrimitiveClass(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ return class_is_primitive(c);
+}
+
+
+/* JVM_GetComponentType */
+
+jclass JVM_GetComponentType(JNIEnv *env, jclass cls)
+{
+ classinfo *component;
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_GetComponentType(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ component = class_get_componenttype(c);
+
+ return (jclass) LLNI_classinfo_wrap(component);
+}
+
+
+/* JVM_GetClassModifiers */
+
+jint JVM_GetClassModifiers(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+ int32_t flags;
+
+ TRACEJVMCALLS(("JVM_GetClassModifiers(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ flags = class_get_modifiers(c, false);
+
+ return flags;
+}
+
+
+/* JVM_GetDeclaredClasses */
+
+jobjectArray JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetDeclaredClasses(env=%p, ofClass=%p)", env, ofClass));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ oa = class_get_declaredclasses(c, false);
+
+ return (jobjectArray) oa;
+}
+
+
+/* JVM_GetDeclaringClass */
+
+jclass JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass)
+{
+ classinfo *c;
+ classinfo *dc;
+
+ TRACEJVMCALLS(("JVM_GetDeclaringClass(env=%p, ofClass=%p)", env, ofClass));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ dc = class_get_declaringclass(c);
+
+ return (jclass) LLNI_classinfo_wrap(dc);
+}
+
+
+/* JVM_GetClassSignature */
+
+jstring JVM_GetClassSignature(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+ utf *u;
+ java_handle_t *s;
+
+ TRACEJVMCALLS(("JVM_GetClassSignature(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ /* Get the signature of the class. */
+
+ u = class_get_signature(c);
+
+ if (u == NULL)
+ return NULL;
+
+ /* Convert UTF-string to a Java-string. */
+
+ s = javastring_new(u);
+
+ return (jstring) s;
+}
+
+
+/* JVM_GetClassAnnotations */
+
+jbyteArray JVM_GetClassAnnotations(JNIEnv *env, jclass cls)
+{
+ TRACEJVMCALLS(("JVM_GetClassAnnotations(env=%p, cls=%p)", env, cls));
+
+ if (cls == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ classinfo* c = LLNI_classinfo_unwrap(cls);
+
+ /* get annotations: */
+ java_handle_bytearray_t* annotations = class_get_annotations(c);
+
+ return (jbyteArray) annotations;
+}
+
+
+/* JVM_GetFieldAnnotations */
+
+jbyteArray JVM_GetFieldAnnotations(JNIEnv *env, jobject field)
+{
+ TRACEJVMCALLS(("JVM_GetFieldAnnotations(env=%p, field=%p)", env, field));
+
+ java_lang_reflect_Field jlrf(field);
+
+ if (jlrf.is_null()) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ return (jbyteArray) jlrf.get_annotations();
+}
+
+
+/* JVM_GetMethodAnnotations */
+
+jbyteArray JVM_GetMethodAnnotations(JNIEnv *env, jobject method)
+{
+ TRACEJVMCALLS(("JVM_GetMethodAnnotations(env=%p, method=%p)", env, method));
+
+ java_lang_reflect_Method jlrm(method);
+
+ if (jlrm.is_null()) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ return (jbyteArray) jlrm.get_annotations();
+}
+
+
+/* JVM_GetMethodDefaultAnnotationValue */
+
+jbyteArray JVM_GetMethodDefaultAnnotationValue(JNIEnv *env, jobject method)
+{
+ TRACEJVMCALLS(("JVM_GetMethodDefaultAnnotationValue(env=%p, method=%p)", env, method));
+
+ java_lang_reflect_Method jlrm(method);
+
+ if (jlrm.is_null()) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ return (jbyteArray) jlrm.get_annotationDefault();
+}
+
+
+/* JVM_GetMethodParameterAnnotations */
+
+jbyteArray JVM_GetMethodParameterAnnotations(JNIEnv *env, jobject method)
+{
+ TRACEJVMCALLS(("JVM_GetMethodParameterAnnotations(env=%p, method=%p)", env, method));
+
+ java_lang_reflect_Method jlrm(method);
+
+ if (jlrm.is_null()) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ return (jbyteArray) jlrm.get_parameterAnnotations();
+}
+
+
+/* JVM_GetClassDeclaredFields */
+
+jobjectArray JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetClassDeclaredFields(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ oa = class_get_declaredfields(c, publicOnly);
+
+ return (jobjectArray) oa;
+}
+
+
+/* JVM_GetClassDeclaredMethods */
+
+jobjectArray JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)
+{
+ TRACEJVMCALLS(("JVM_GetClassDeclaredMethods(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
+
+ classinfo* c = LLNI_classinfo_unwrap(ofClass);
+
+ java_handle_objectarray_t* oa = class_get_declaredmethods(c, publicOnly);
+
+ return (jobjectArray) oa;
+}
+
+
+/* JVM_GetClassDeclaredConstructors */
+
+jobjectArray JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly)
+{
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetClassDeclaredConstructors(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ oa = class_get_declaredconstructors(c, publicOnly);
+
+ return (jobjectArray) oa;
+}
+
+
+/* JVM_GetClassAccessFlags */
+
+jint JVM_GetClassAccessFlags(JNIEnv *env, jclass cls)
+{
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_GetClassAccessFlags(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ /* Primitive type classes have the correct access flags. */
+
+ return c->flags & ACC_CLASS_REFLECT_MASK;
+}
+
+
+/* JVM_GetClassConstantPool */
+
+jobject JVM_GetClassConstantPool(JNIEnv *env, jclass cls)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ TRACEJVMCALLS(("JVM_GetClassConstantPool(env=%p, cls=%p)", env, cls));
+
+ java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
+ sun_reflect_ConstantPool cp(h, cls);
+
+ if (cp.is_null()) {
+ return NULL;
+ }
+
+ return (jobject) cp.get_handle();
+#else
+ log_println("JVM_GetClassConstantPool(env=%p, cls=%p): not implemented in this configuration!", env, cls);
+ return NULL;
+#endif
+}
+
+
+/* JVM_ConstantPoolGetSize */
+
+jint JVM_ConstantPoolGetSize(JNIEnv *env, jobject unused, jobject jcpool)
+{
+ classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetSize(env=%p, unused=%p, jcpool=%p)", env, unused, jcpool));
+
+ c = LLNI_classinfo_unwrap(jcpool);
+
+ return c->cpcount;
+}
+
+
+/* JVM_ConstantPoolGetClassAt */
+
+jclass JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_classref *ref; /* classref to the class at constant pool index 'index' */
+ classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
+ classinfo *result; /* classinfo of the class at constant pool index 'index' */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetClassAt(env=%p, jcpool=%p, index=%d)", env, jcpool, index));
+
+ c = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_classref *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ result = resolve_classref_eager(ref);
+
+ return (jclass) LLNI_classinfo_wrap(result);
+}
+
+
+/* JVM_ConstantPoolGetClassAtIfLoaded */
+
+jclass JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_classref *ref; /* classref to the class at constant pool index 'index' */
+ classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
+ classinfo *result; /* classinfo of the class at constant pool index 'index' */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetClassAtIfLoaded(env=%p, unused=%p, jcpool=%p, index=%d)", env, unused, jcpool, index));
+
+ c = LLNI_classinfo_unwrap(jcpool);
+
+ ref = (constant_classref *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ if (!resolve_classref(NULL, ref, resolveLazy, true, true, &result)) {
+ return NULL;
+ }
+
+ if ((result == NULL) || !(result->state & CLASS_LOADED)) {
+ return NULL;
+ }
+
+ return (jclass) LLNI_classinfo_wrap(result);
+}
+
+
+/* JVM_ConstantPoolGetMethodAt */
+
+jobject JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_FMIref *ref; /* reference to the method in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetMethodAt: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Methodref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ // Create a new java.lang.reflect.Method Java object.
+ /* XXX: is that right? or do I have to use resolve_method_*? */
+ java_lang_reflect_Method jlrm(ref->p.method);
+
+ return (jobject) jlrm.get_handle();
+}
+
+
+/* JVM_ConstantPoolGetMethodAtIfLoaded */
+
+jobject JVM_ConstantPoolGetMethodAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_FMIref *ref; /* reference to the method in constant pool at index 'index' */
+ classinfo *c = NULL; /* resolved declaring class of the method */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetMethodAtIfLoaded: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Methodref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ if (!resolve_classref(NULL, ref->p.classref, resolveLazy, true, true, &c)) {
+ return NULL;
+ }
+
+ if (c == NULL || !(c->state & CLASS_LOADED)) {
+ return NULL;
+ }
+
+ // Create a new java.lang.reflect.Method Java object.
+ java_lang_reflect_Method jlrm(ref->p.method);
+
+ return (jobject) jlrm.get_handle();
+}
+
+
+/* JVM_ConstantPoolGetFieldAt */
+
+jobject JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_FMIref *ref; /* reference to the field in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetFieldAt: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Fieldref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ // Create a new java.lang.reflect.Field Java object.
+ java_lang_reflect_Field jlrf(ref->p.field);
+
+ return (jobject) jlrf.get_handle();
+}
+
+
+/* JVM_ConstantPoolGetFieldAtIfLoaded */
+
+jobject JVM_ConstantPoolGetFieldAtIfLoaded(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_FMIref *ref; /* reference to the field in constant pool at index 'index' */
+ classinfo *c; /* resolved declaring class for the field */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetFieldAtIfLoaded: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Fieldref);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ if (!resolve_classref(NULL, ref->p.classref, resolveLazy, true, true, &c)) {
+ return NULL;
+ }
+
+ if (c == NULL || !(c->state & CLASS_LOADED)) {
+ return NULL;
+ }
+
+ // Create a new java.lang.reflect.Field Java object.
+ java_lang_reflect_Field jlrf(ref->p.field);
+
+ return (jobject) jlrf.get_handle();
+}
+
+
+/* JVM_ConstantPoolGetMemberRefInfoAt */
+
+jobjectArray JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ log_println("JVM_ConstantPoolGetMemberRefInfoAt: jcpool=%p, index=%d, IMPLEMENT ME!", jcpool, index);
+
+ /* TODO: implement. (this is yet unused be OpenJDK but, so very low priority) */
+
+ return NULL;
+}
+
+
+/* JVM_ConstantPoolGetIntAt */
+
+jint JVM_ConstantPoolGetIntAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_integer *ref; /* reference to the int value in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetIntAt: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_integer*)class_getconstant(cls, index, CONSTANT_Integer);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/* JVM_ConstantPoolGetLongAt */
+
+jlong JVM_ConstantPoolGetLongAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_long *ref; /* reference to the long value in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetLongAt: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_long*)class_getconstant(cls, index, CONSTANT_Long);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/* JVM_ConstantPoolGetFloatAt */
+
+jfloat JVM_ConstantPoolGetFloatAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_float *ref; /* reference to the float value in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetFloatAt: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_float*)class_getconstant(cls, index, CONSTANT_Float);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/* JVM_ConstantPoolGetDoubleAt */
+
+jdouble JVM_ConstantPoolGetDoubleAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ constant_double *ref; /* reference to the double value in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetDoubleAt: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (constant_double*)class_getconstant(cls, index, CONSTANT_Double);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ return ref->value;
+}
+
+
+/* JVM_ConstantPoolGetStringAt */
+
+jstring JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ utf *ref; /* utf object for the string in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetStringAt: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (utf*)class_getconstant(cls, index, CONSTANT_String);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* XXX: I hope literalstring_new is the right Function. */
+ return (jstring)literalstring_new(ref);
+}
+
+
+/* JVM_ConstantPoolGetUTF8At */
+
+jstring JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject unused, jobject jcpool, jint index)
+{
+ utf *ref; /* utf object for the utf8 data in constant pool at index 'index' */
+ classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
+
+ TRACEJVMCALLS(("JVM_ConstantPoolGetUTF8At: jcpool=%p, index=%d", jcpool, index));
+
+ cls = LLNI_classinfo_unwrap(jcpool);
+ ref = (utf*)class_getconstant(cls, index, CONSTANT_Utf8);
+
+ if (ref == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* XXX: I hope literalstring_new is the right Function. */
+ return (jstring)literalstring_new(ref);
+}
+
+
+/* JVM_DesiredAssertionStatus */
+
+jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
+{
+#if defined(ENABLE_ASSERTION)
+ assertion_name_t *item;
+ classinfo *c;
+ jboolean status;
+ utf *name;
+
+ TRACEJVMCALLS(("JVM_DesiredAssertionStatus(env=%p, unused=%p, cls=%p)", env, unused, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ if (c->classloader == NULL) {
+ status = (jboolean)assertion_system_enabled;
+ }
+ else {
+ status = (jboolean)assertion_user_enabled;
+ }
+
+ if (list_assertion_names != NULL) {
+ item = (assertion_name_t *)list_first(list_assertion_names);
+ while (item != NULL) {
+ name = utf_new_char(item->name);
+ if (name == c->packagename) {
+ status = (jboolean)item->enabled;
+ }
+ else if (name == c->name) {
+ status = (jboolean)item->enabled;
+ }
+
+ item = (assertion_name_t *)list_next(list_assertion_names, item);
+ }
+ }
+
+ return status;
+#else
+ return (jboolean)false;
+#endif
+}
+
+
+/* JVM_AssertionStatusDirectives */
+
+jobject JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused)
+{
+ java_handle_objectarray_t *classes;
+ java_handle_objectarray_t *packages;
+ java_booleanarray_t *classEnabled;
+ java_booleanarray_t *packageEnabled;
+#if defined(ENABLE_ASSERTION)
+ assertion_name_t *item;
+ java_handle_t *js;
+ s4 i, j;
+#endif
+
+ TRACEJVMCALLS(("JVM_AssertionStatusDirectives(env=%p, unused=%p)", env, unused));
+
+#if defined(ENABLE_ASSERTION)
+ classes = builtin_anewarray(assertion_class_count, class_java_lang_Object);
+#else
+ classes = builtin_anewarray(0, class_java_lang_Object);
+#endif
+ if (classes == NULL)
+ return NULL;
+
+#if defined(ENABLE_ASSERTION)
+ packages = builtin_anewarray(assertion_package_count, class_java_lang_Object);
+#else
+ packages = builtin_anewarray(0, class_java_lang_Object);
+#endif
+ if (packages == NULL)
+ return NULL;
+
+#if defined(ENABLE_ASSERTION)
+ classEnabled = builtin_newarray_boolean(assertion_class_count);
+#else
+ classEnabled = builtin_newarray_boolean(0);
+#endif
+ if (classEnabled == NULL)
+ return NULL;
+
+#if defined(ENABLE_ASSERTION)
+ packageEnabled = builtin_newarray_boolean(assertion_package_count);
+#else
+ packageEnabled = builtin_newarray_boolean(0);
+#endif
+ if (packageEnabled == NULL)
+ return NULL;
+
+#if defined(ENABLE_ASSERTION)
+ /* initialize arrays */
+
+ if (list_assertion_names != NULL) {
+ i = 0;
+ j = 0;
+
+ item = (assertion_name_t *)list_first(list_assertion_names);
+ while (item != NULL) {
+ js = javastring_new_from_ascii(item->name);
+ if (js == NULL) {
+ return NULL;
+ }
+
+ if (item->package == false) {
+ classes->data[i] = js;
+ classEnabled->data[i] = (jboolean) item->enabled;
+ i += 1;
+ }
+ else {
+ packages->data[j] = js;
+ packageEnabled->data[j] = (jboolean) item->enabled;
+ j += 1;
+ }
+
+ item = (assertion_name_t *)list_next(list_assertion_names, item);
+ }
+ }
+#endif
+
+ /* set instance fields */
+
+ java_lang_AssertionStatusDirectives jlasd(classes, classEnabled, packages, packageEnabled);
+
+ return (jobject) jlasd.get_handle();
+}
+
+
+/* JVM_GetClassNameUTF */
+
+const char *JVM_GetClassNameUTF(JNIEnv *env, jclass cls)
+{
+ log_println("JVM_GetClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetClassCPTypes */
+
+void JVM_GetClassCPTypes(JNIEnv *env, jclass cls, unsigned char *types)
+{
+ log_println("JVM_GetClassCPTypes: IMPLEMENT ME!");
+}
+
+
+/* JVM_GetClassCPEntriesCount */
+
+jint JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cls)
+{
+ log_println("JVM_GetClassCPEntriesCount: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetClassFieldsCount */
+
+jint JVM_GetClassFieldsCount(JNIEnv *env, jclass cls)
+{
+ log_println("JVM_GetClassFieldsCount: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetClassMethodsCount */
+
+jint JVM_GetClassMethodsCount(JNIEnv *env, jclass cls)
+{
+ log_println("JVM_GetClassMethodsCount: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxExceptionIndexes */
+
+void JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cls, jint method_index, unsigned short *exceptions)
+{
+ log_println("JVM_GetMethodIxExceptionIndexes: IMPLEMENT ME!");
+}
+
+
+/* JVM_GetMethodIxExceptionsCount */
+
+jint JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cls, jint method_index)
+{
+ log_println("JVM_GetMethodIxExceptionsCount: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxByteCode */
+
+void JVM_GetMethodIxByteCode(JNIEnv *env, jclass cls, jint method_index, unsigned char *code)
+{
+ log_println("JVM_GetMethodIxByteCode: IMPLEMENT ME!");
+}
+
+
+/* JVM_GetMethodIxByteCodeLength */
+
+jint JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cls, jint method_index)
+{
+ log_println("JVM_GetMethodIxByteCodeLength: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxExceptionTableEntry */
+
+void JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cls, jint method_index, jint entry_index, JVM_ExceptionTableEntryType *entry)
+{
+ log_println("JVM_GetMethodIxExceptionTableEntry: IMPLEMENT ME!");
+}
+
+
+/* JVM_GetMethodIxExceptionTableLength */
+
+jint JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cls, int method_index)
+{
+ log_println("JVM_GetMethodIxExceptionTableLength: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxModifiers */
+
+jint JVM_GetMethodIxModifiers(JNIEnv *env, jclass cls, int method_index)
+{
+ log_println("JVM_GetMethodIxModifiers: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetFieldIxModifiers */
+
+jint JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index)
+{
+ log_println("JVM_GetFieldIxModifiers: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxLocalsCount */
+
+jint JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index)
+{
+ log_println("JVM_GetMethodIxLocalsCount: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxArgsSize */
+
+jint JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cls, int method_index)
+{
+ log_println("JVM_GetMethodIxArgsSize: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxMaxStack */
+
+jint JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cls, int method_index)
+{
+ log_println("JVM_GetMethodIxMaxStack: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_IsConstructorIx */
+
+jboolean JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index)
+{
+ log_println("JVM_IsConstructorIx: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetMethodIxNameUTF */
+
+const char *JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)
+{
+ log_println("JVM_GetMethodIxNameUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetMethodIxSignatureUTF */
+
+const char *JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cls, jint method_index)
+{
+ log_println("JVM_GetMethodIxSignatureUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPFieldNameUTF */
+
+const char *JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+{
+ log_println("JVM_GetCPFieldNameUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPMethodNameUTF */
+
+const char *JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+{
+ log_println("JVM_GetCPMethodNameUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPMethodSignatureUTF */
+
+const char *JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
+{
+ log_println("JVM_GetCPMethodSignatureUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPFieldSignatureUTF */
+
+const char *JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
+{
+ log_println("JVM_GetCPFieldSignatureUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPClassNameUTF */
+
+const char *JVM_GetCPClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+{
+ log_println("JVM_GetCPClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPFieldClassNameUTF */
+
+const char *JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+{
+ log_println("JVM_GetCPFieldClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPMethodClassNameUTF */
+
+const char *JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+{
+ log_println("JVM_GetCPMethodClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetCPFieldModifiers */
+
+jint JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)
+{
+ log_println("JVM_GetCPFieldModifiers: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetCPMethodModifiers */
+
+jint JVM_GetCPMethodModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)
+{
+ log_println("JVM_GetCPMethodModifiers: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_ReleaseUTF */
+
+void JVM_ReleaseUTF(const char *utf)
+{
+ log_println("JVM_ReleaseUTF: IMPLEMENT ME!");
+}
+
+
+/* JVM_IsSameClassPackage */
+
+jboolean JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2)
+{
+ log_println("JVM_IsSameClassPackage: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_Open */
+
+/* Taken from: hotspot/src/share/vm/prims/jvm.h */
+
+/*
+ * JVM I/O error codes
+ */
+#define JVM_EEXIST -100
+
+jint JVM_Open(const char *fname, jint flags, jint mode)
+{
+ int result;
+
+ TRACEJVMCALLS(("JVM_Open(fname=%s, flags=%d, mode=%d)", fname, flags, mode));
+
+ result = hpi_file->Open(fname, flags, mode);
+
+ if (result >= 0) {
+ return result;
+ }
+ else {
+ switch (errno) {
+ case EEXIST:
+ return JVM_EEXIST;
+ default:
+ return -1;
+ }
+ }
+}
+
+
+/* JVM_Close */
+
+jint JVM_Close(jint fd)
+{
+ TRACEJVMCALLS(("JVM_Close(fd=%d)", fd));
+
+ return hpi_file->Close(fd);
+}
+
+
+/* JVM_Read */
+
+jint JVM_Read(jint fd, char *buf, jint nbytes)
+{
+ TRACEJVMCALLS(("JVM_Read(fd=%d, buf=%p, nbytes=%d)", fd, buf, nbytes));
+
+ return (jint) hpi_file->Read(fd, buf, nbytes);
+}
+
+
+/* JVM_Write */
+
+jint JVM_Write(jint fd, char *buf, jint nbytes)
+{
+ TRACEJVMCALLS(("JVM_Write(fd=%d, buf=%s, nbytes=%d)", fd, buf, nbytes));
+
+ return (jint) hpi_file->Write(fd, buf, nbytes);
+}
+
+
+/* JVM_Available */
+
+jint JVM_Available(jint fd, jlong *pbytes)
+{
+ TRACEJVMCALLS(("JVM_Available(fd=%d, pbytes=%p)", fd, pbytes));
+
+ return hpi_file->Available(fd, pbytes);
+}
+
+
+/* JVM_Lseek */
+
+jlong JVM_Lseek(jint fd, jlong offset, jint whence)
+{
+ TRACEJVMCALLS(("JVM_Lseek(fd=%d, offset=%ld, whence=%d)", fd, offset, whence));
+
+ return hpi_file->Seek(fd, (off_t) offset, whence);
+}
+
+
+/* JVM_SetLength */
+
+jint JVM_SetLength(jint fd, jlong length)
+{
+ TRACEJVMCALLS(("JVM_SetLength(fd=%d, length=%ld)", length));
+
+ return hpi_file->SetLength(fd, length);
+}
+
+
+/* JVM_Sync */
+
+jint JVM_Sync(jint fd)
+{
+ TRACEJVMCALLS(("JVM_Sync(fd=%d)", fd));
+
+ return hpi_file->Sync(fd);
+}
+
+
+/* JVM_StartThread */
+
+void JVM_StartThread(JNIEnv* env, jobject jthread)
+{
+ TRACEJVMCALLS(("JVM_StartThread(env=%p, jthread=%p)", env, jthread));
+
+ threads_thread_start((java_handle_t *) jthread);
+}
+
+
+/* JVM_StopThread */
+
+void JVM_StopThread(JNIEnv* env, jobject jthread, jobject throwable)
+{
+ log_println("JVM_StopThread: Deprecated. Not implemented.");
+}
+
+
+/* JVM_IsThreadAlive */
+
+jboolean JVM_IsThreadAlive(JNIEnv* env, jobject jthread)
+{
+ java_handle_t *h;
+ threadobject *t;
+ bool result;
+
+ TRACEJVMCALLS(("JVM_IsThreadAlive(env=%p, jthread=%p)", env, jthread));
+
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
+
+ /* The threadobject is null when a thread is created in Java. The
+ priority is set later during startup. */
+
+ if (t == NULL)
+ return 0;
+
+ result = threads_thread_is_alive(t);
+
+ return result;
+}
+
+
+/* JVM_SuspendThread */
+
+void JVM_SuspendThread(JNIEnv* env, jobject jthread)
+{
+ log_println("JVM_SuspendThread: Deprecated. Not implemented.");
+}
+
+
+/* JVM_ResumeThread */
+
+void JVM_ResumeThread(JNIEnv* env, jobject jthread)
+{
+ log_println("JVM_ResumeThread: Deprecated. Not implemented.");
+}
+
+
+/* JVM_SetThreadPriority */
+
+void JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)
+{
+ java_handle_t *h;
+ threadobject *t;
+
+ TRACEJVMCALLS(("JVM_SetThreadPriority(env=%p, jthread=%p, prio=%d)", env, jthread, prio));
+
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
+
+ /* The threadobject is null when a thread is created in Java. The
+ priority is set later during startup. */
+
+ if (t == NULL)
+ return;
+
+ threads_set_thread_priority(t->tid, prio);
+}
+
+
+/* JVM_Yield */
+
+void JVM_Yield(JNIEnv *env, jclass threadClass)
+{
+ TRACEJVMCALLS(("JVM_Yield(env=%p, threadClass=%p)", env, threadClass));
+
+ threads_yield();
+}
+
+
+/* JVM_Sleep */
+
+void JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)
+{
+ TRACEJVMCALLS(("JVM_Sleep(env=%p, threadClass=%p, millis=%ld)", env, threadClass, millis));
+
+ threads_sleep(millis, 0);
+}
+
+
+/* JVM_CurrentThread */
+
+jobject JVM_CurrentThread(JNIEnv* env, jclass threadClass)
+{
+ java_object_t *o;
+
+ TRACEJVMCALLSVERBOSE(("JVM_CurrentThread(env=%p, threadClass=%p)", env, threadClass));
+
+ o = thread_get_current_object();
+
+ return (jobject) o;
+}
+
+
+/* JVM_CountStackFrames */
+
+jint JVM_CountStackFrames(JNIEnv* env, jobject jthread)
+{
+ log_println("JVM_CountStackFrames: Deprecated. Not implemented.");
+
+ return 0;
+}
+
+
+/* JVM_Interrupt */
+
+void JVM_Interrupt(JNIEnv* env, jobject jthread)
+{
+ java_handle_t *h;
+ threadobject *t;
+
+ TRACEJVMCALLS(("JVM_Interrupt(env=%p, jthread=%p)", env, jthread));
+
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
+
+ if (t == NULL)
+ return;
+
+ threads_thread_interrupt(t);
+}
+
+
+/* JVM_IsInterrupted */
+
+jboolean JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted)
+{
+ java_handle_t *h;
+ threadobject *t;
+ jboolean interrupted;
+
+ TRACEJVMCALLS(("JVM_IsInterrupted(env=%p, jthread=%p, clear_interrupted=%d)", env, jthread, clear_interrupted));
+
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
+
+ interrupted = thread_is_interrupted(t);
+
+ if (interrupted && clear_interrupted)
+ thread_set_interrupted(t, false);
+
+ return interrupted;
+}
+
+
+/* JVM_HoldsLock */
+
+jboolean JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj)
+{
+ java_handle_t *h;
+ bool result;
+
+ TRACEJVMCALLS(("JVM_HoldsLock(env=%p, threadClass=%p, obj=%p)", env, threadClass, obj));
+
+ h = (java_handle_t *) obj;
+
+ if (h == NULL) {
+ exceptions_throw_nullpointerexception();
+ return JNI_FALSE;
+ }
+
+ result = lock_is_held_by_current_thread(h);
+
+ return result;
+}
+
+
+/* JVM_DumpAllStacks */
+
+void JVM_DumpAllStacks(JNIEnv* env, jclass unused)
+{
+ log_println("JVM_DumpAllStacks: IMPLEMENT ME!");
+}
+
+
+/* JVM_CurrentLoadedClass */
+
+jclass JVM_CurrentLoadedClass(JNIEnv *env)
+{
+ log_println("JVM_CurrentLoadedClass: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_CurrentClassLoader */
+
+jobject JVM_CurrentClassLoader(JNIEnv *env)
+{
+ /* XXX if a method in a class in a trusted loader is in a
+ doPrivileged, return NULL */
+
+ log_println("JVM_CurrentClassLoader: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetClassContext */
+
+jobjectArray JVM_GetClassContext(JNIEnv *env)
+{
+ TRACEJVMCALLS(("JVM_GetClassContext(env=%p)", env));
+
+ return (jobjectArray) stacktrace_getClassContext();
+}
+
+
+/* JVM_ClassDepth */
+
+jint JVM_ClassDepth(JNIEnv *env, jstring name)
+{
+ log_println("JVM_ClassDepth: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_ClassLoaderDepth */
+
+jint JVM_ClassLoaderDepth(JNIEnv *env)
+{
+ log_println("JVM_ClassLoaderDepth: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetSystemPackage */
+
+jstring JVM_GetSystemPackage(JNIEnv *env, jstring name)
+{
+ java_handle_t *s;
+ utf *u;
+ utf *result;
+
+ TRACEJVMCALLS(("JVM_GetSystemPackage(env=%p, name=%p)", env, name));
+
+/* s = Package::find(name); */
+ u = javastring_toutf((java_handle_t *) name, false);
+
+ result = Package::find(u);
+
+ if (result != NULL)
+ s = javastring_new(result);
+ else
+ s = NULL;
+
+ return (jstring) s;
+}
+
+
+/* JVM_GetSystemPackages */
+
+jobjectArray JVM_GetSystemPackages(JNIEnv *env)
+{
+ log_println("JVM_GetSystemPackages: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_AllocateNewObject */
+
+jobject JVM_AllocateNewObject(JNIEnv *env, jobject receiver, jclass currClass, jclass initClass)
+{
+ log_println("JVM_AllocateNewObject: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_AllocateNewArray */
+
+jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint length)
+{
+ log_println("JVM_AllocateNewArray: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_LatestUserDefinedLoader */
+
+jobject JVM_LatestUserDefinedLoader(JNIEnv *env)
+{
+ classloader_t *cl;
+
+ TRACEJVMCALLS(("JVM_LatestUserDefinedLoader(env=%p)", env));
+
+ cl = stacktrace_first_nonnull_classloader();
+
+ return (jobject) cl;
+}
+
+
+/* JVM_LoadClass0 */
+
+jclass JVM_LoadClass0(JNIEnv *env, jobject receiver, jclass currClass, jstring currClassName)
+{
+ log_println("JVM_LoadClass0: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetArrayLength */
+
+jint JVM_GetArrayLength(JNIEnv *env, jobject arr)
+{
+ java_handle_t *a;
+
+ TRACEJVMCALLS(("JVM_GetArrayLength(arr=%p)", arr));
+
+ a = (java_handle_t *) arr;
+
+ return array_length_get(a);
+}
+
+
+/* JVM_GetArrayElement */
+
+jobject JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index)
+{
+ java_handle_t *a;
+ java_handle_t *o;
+
+ TRACEJVMCALLS(("JVM_GetArrayElement(env=%p, arr=%p, index=%d)", env, arr, index));
+
+ a = (java_handle_t *) arr;
+
+/* if (!class_is_array(a->objheader.vftbl->class)) { */
+/* exceptions_throw_illegalargumentexception(); */
+/* return NULL; */
+/* } */
+
+ o = array_element_get(a, index);
+
+ return (jobject) o;
+}
+
+
+/* JVM_GetPrimitiveArrayElement */
+
+jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode)
+{
+ jvalue jv;
+
+ log_println("JVM_GetPrimitiveArrayElement: IMPLEMENT ME!");
+
+ jv.l = NULL;
+
+ return jv;
+}
+
+
+/* JVM_SetArrayElement */
+
+void JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val)
+{
+ java_handle_t *a;
+ java_handle_t *value;
+
+ TRACEJVMCALLS(("JVM_SetArrayElement(env=%p, arr=%p, index=%d, val=%p)", env, arr, index, val));
+
+ a = (java_handle_t *) arr;
+ value = (java_handle_t *) val;
+
+ array_element_set(a, index, value);
+}
+
+
+/* JVM_SetPrimitiveArrayElement */
+
+void JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v, unsigned char vCode)
+{
+ log_println("JVM_SetPrimitiveArrayElement: IMPLEMENT ME!");
+}
+
+
+/* JVM_NewArray */
+
+jobject JVM_NewArray(JNIEnv *env, jclass eltClass, jint length)
+{
+ classinfo *c;
+ classinfo *pc;
+ java_handle_t *a;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_NewArray(env=%p, eltClass=%p, length=%d)", env, eltClass, length));
+
+ if (eltClass == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* NegativeArraySizeException is checked in builtin_newarray. */
+
+ c = LLNI_classinfo_unwrap(eltClass);
+
+ /* Create primitive or object array. */
+
+ if (class_is_primitive(c)) {
+ pc = Primitive::get_arrayclass_by_name(c->name);
+
+ /* void arrays are not allowed. */
+
+ if (pc == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ a = builtin_newarray(length, pc);
+
+ return (jobject) a;
+ }
+ else {
+ oa = builtin_anewarray(length, c);
+
+ return (jobject) oa;
+ }
+}
+
+
+/* JVM_NewMultiArray */
+
+jobject JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim)
+{
+ classinfo *c;
+ java_handle_intarray_t *ia;
+ int32_t length;
+ long *dims;
+ int32_t value;
+ int32_t i;
+ classinfo *ac;
+ java_handle_objectarray_t *a;
+
+ TRACEJVMCALLS(("JVM_NewMultiArray(env=%p, eltClass=%p, dim=%p)", env, eltClass, dim));
+
+ if (eltClass == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* NegativeArraySizeException is checked in builtin_newarray. */
+
+ c = LLNI_classinfo_unwrap(eltClass);
+
+ ia = (java_handle_intarray_t *) dim;
+
+ length = array_length_get((java_handle_t *) ia);
+
+ /* We check here for exceptions thrown in array_length_get,
+ otherwise these exceptions get overwritten by the following
+ IllegalArgumentException. */
+
+ if (length < 0)
+ return NULL;
+
+ if ((length <= 0) || (length > /* MAX_DIM */ 255)) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* XXX This is just a quick hack to get it working. */
+
+ dims = MNEW(long, length);
+
+ for (i = 0; i < length; i++) {
+ value = LLNI_array_direct(ia, i);
+ dims[i] = (long) value;
+ }
+
+ /* Create an array-class if necessary. */
+
+ if (class_is_primitive(c))
+ ac = Primitive::get_arrayclass_by_name(c->name);
+ else
+ ac = class_array_of(c, true);
+
+ if (ac == NULL)
+ return NULL;
+
+ a = builtin_multianewarray(length, (java_handle_t *) ac, dims);
+
+ return (jobject) a;
+}
+
+
+/* JVM_InitializeSocketLibrary */
+
+jint JVM_InitializeSocketLibrary()
+{
+ TRACEJVMCALLS(("JVM_InitializeSocketLibrary()"));
+
+ return hpi_initialize_socket_library();
+}
+
+
+/* JVM_Socket */
+
+jint JVM_Socket(jint domain, jint type, jint protocol)
+{
+ TRACEJVMCALLS(("JVM_Socket(domain=%d, type=%d, protocol=%d)", domain, type, protocol));
+
+ return os::socket(domain, type, protocol);
+}
+
+
+/* JVM_SocketClose */
+
+jint JVM_SocketClose(jint fd)
+{
+ TRACEJVMCALLS(("JVM_SocketClose(fd=%d)", fd));
+
+ return os::close(fd);
+}
+
+
+/* JVM_SocketShutdown */
+
+jint JVM_SocketShutdown(jint fd, jint howto)
+{
+ TRACEJVMCALLS(("JVM_SocketShutdown(fd=%d, howto=%d)", fd, howto));
+
+ return os::shutdown(fd, howto);
+}
+
+
+/* JVM_Recv */
+
+jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags)
+{
+ log_println("JVM_Recv: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_Send */
+
+jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags)
+{
+ log_println("JVM_Send: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_Timeout */
+
+jint JVM_Timeout(int fd, long timeout)
+{
+ log_println("JVM_Timeout: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_Listen */
+
+jint JVM_Listen(jint fd, jint count)
+{
+ TRACEJVMCALLS(("JVM_Listen(fd=%d, count=%d)", fd, count));
+
+ return os::listen(fd, count);
+}
+
+
+/* JVM_Connect */
+
+jint JVM_Connect(jint fd, struct sockaddr *him, jint len)
+{
+ TRACEJVMCALLS(("JVM_Connect(fd=%d, him=%p, len=%d)", fd, him, len));
+
+ return os::connect(fd, him, len);
+}
+
+
+/* JVM_Bind */
+
+jint JVM_Bind(jint fd, struct sockaddr *him, jint len)
+{
+ log_println("JVM_Bind: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_Accept */
+
+jint JVM_Accept(jint fd, struct sockaddr *him, jint *len)
+{
+ TRACEJVMCALLS(("JVM_Accept(fd=%d, him=%p, len=%p)", fd, him, len));
+
+ return os::accept(fd, him, (socklen_t *) len);
+}
+
+
+/* JVM_RecvFrom */
+
+jint JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen)
+{
+ log_println("JVM_RecvFrom: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetSockName */
+
+jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len)
+{
+ TRACEJVMCALLS(("JVM_GetSockName(fd=%d, him=%p, len=%p)", fd, him, len));
+
+ return os::getsockname(fd, him, (socklen_t *) len);
+}
+
+
+/* JVM_SendTo */
+
+jint JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen)
+{
+ log_println("JVM_SendTo: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_SocketAvailable */
+
+jint JVM_SocketAvailable(jint fd, jint *pbytes)
+{
+#if defined(FIONREAD)
+ int bytes;
+ int result;
+
+ TRACEJVMCALLS(("JVM_SocketAvailable(fd=%d, pbytes=%p)", fd, pbytes));
+
+ *pbytes = 0;
+
+ result = ioctl(fd, FIONREAD, &bytes);
+
+ if (result < 0)
+ return 0;
+
+ *pbytes = bytes;
+
+ return 1;
+#else
+# error FIONREAD not defined
+#endif
+}
+
+
+/* JVM_GetSockOpt */
+
+jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen)
+{
+ TRACEJVMCALLS(("JVM_GetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%p)", fd, level, optname, optval, optlen));
+
+ return os::getsockopt(fd, level, optname, optval, (socklen_t *) optlen);
+}
+
+
+/* JVM_SetSockOpt */
+
+jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen)
+{
+ TRACEJVMCALLS(("JVM_SetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%d)", fd, level, optname, optval, optlen));
+
+ return os::setsockopt(fd, level, optname, optval, optlen);
+}
+
+
+/* JVM_GetHostName */
+
+int JVM_GetHostName(char *name, int namelen)
+{
+ int result;
+
+ TRACEJVMCALLSENTER(("JVM_GetHostName(name=%s, namelen=%d)", name, namelen));
+
+ result = os::gethostname(name, namelen);
+
+ TRACEJVMCALLSEXIT(("->%d (name=%s)", result, name));
+
+ return result;
+}
+
+
+/* JVM_GetHostByAddr */
+
+struct hostent *JVM_GetHostByAddr(const char* name, int len, int type)
+{
+ log_println("JVM_GetHostByAddr: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetHostByName */
+
+struct hostent *JVM_GetHostByName(char* name)
+{
+ log_println("JVM_GetHostByName: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetProtoByName */
+
+struct protoent *JVM_GetProtoByName(char* name)
+{
+ log_println("JVM_GetProtoByName: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_LoadLibrary */
+
+void *JVM_LoadLibrary(const char *name)
+{
+ utf* u;
+ void* handle;
+
+ TRACEJVMCALLSENTER(("JVM_LoadLibrary(name=%s)", name));
+
+ u = utf_new_char(name);
+
+ handle = native_library_open(u);
+
+ TRACEJVMCALLSEXIT(("->%p", handle));
+
+ return handle;
+}
+
+
+/* JVM_UnloadLibrary */
+
+void JVM_UnloadLibrary(void* handle)
+{
+ TRACEJVMCALLS(("JVM_UnloadLibrary(handle=%p)", handle));
+
+ native_library_close(handle);
+}
+
+
+/* JVM_FindLibraryEntry */
+
+void *JVM_FindLibraryEntry(void *handle, const char *name)
+{
+ void* symbol;
+
+ TRACEJVMCALLSENTER(("JVM_FindLibraryEntry(handle=%p, name=%s)", handle, name));
+
+ symbol = hpi_library->FindLibraryEntry(handle, name);
+
+ TRACEJVMCALLSEXIT(("->%p", symbol));
+
+ return symbol;
+}
+
+
+/* JVM_IsNaN */
+
+jboolean JVM_IsNaN(jdouble a)
+{
+ log_println("JVM_IsNaN: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_IsSupportedJNIVersion */
+
+jboolean JVM_IsSupportedJNIVersion(jint version)
+{
+ TRACEJVMCALLS(("JVM_IsSupportedJNIVersion(version=%d)", version));
+
+ return jni_version_check(version);
+}
+
+
+/* JVM_InternString */
+
+jstring JVM_InternString(JNIEnv *env, jstring str)
+{
+ TRACEJVMCALLS(("JVM_InternString(env=%p, str=%p)", env, str));
+
+ return (jstring) javastring_intern((java_handle_t *) str);
+}
+
+
+/* JVM_RawMonitorCreate */
+
+JNIEXPORT void* JNICALL JVM_RawMonitorCreate(void)
+{
+ java_object_t *o;
+
+ TRACEJVMCALLS(("JVM_RawMonitorCreate()"));
+
+ o = NEW(java_object_t);
+
+ lock_init_object_lock(o);
+
+ return o;
+}
+
+
+/* JVM_RawMonitorDestroy */
+
+JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon)
+{
+ TRACEJVMCALLS(("JVM_RawMonitorDestroy(mon=%p)", mon));
+
+ FREE(mon, java_object_t);
+}
+
+
+/* JVM_RawMonitorEnter */
+
+JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon)
+{
+ TRACEJVMCALLS(("JVM_RawMonitorEnter(mon=%p)", mon));
+
+ (void) lock_monitor_enter((java_object_t *) mon);
+
+ return 0;
+}
+
+
+/* JVM_RawMonitorExit */
+
+JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon)
+{
+ TRACEJVMCALLS(("JVM_RawMonitorExit(mon=%p)", mon));
+
+ (void) lock_monitor_exit((java_object_t *) mon);
+}
+
+
+/* JVM_SetPrimitiveFieldValues */
+
+void JVM_SetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)
+{
+ log_println("JVM_SetPrimitiveFieldValues: IMPLEMENT ME!");
+}
+
+
+/* JVM_GetPrimitiveFieldValues */
+
+void JVM_GetPrimitiveFieldValues(JNIEnv *env, jclass cb, jobject obj, jlongArray fieldIDs, jcharArray typecodes, jbyteArray data)
+{
+ log_println("JVM_GetPrimitiveFieldValues: IMPLEMENT ME!");
+}
+
+
+/* JVM_AccessVMBooleanFlag */
+
+jboolean JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get)
+{
+ log_println("JVM_AccessVMBooleanFlag: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_AccessVMIntFlag */
+
+jboolean JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get)
+{
+ log_println("JVM_AccessVMIntFlag: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_VMBreakPoint */
+
+void JVM_VMBreakPoint(JNIEnv *env, jobject obj)
+{
+ log_println("JVM_VMBreakPoint: IMPLEMENT ME!");
+}
+
+
+/* JVM_GetClassFields */
+
+jobjectArray JVM_GetClassFields(JNIEnv *env, jclass cls, jint which)
+{
+ log_println("JVM_GetClassFields: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetClassMethods */
+
+jobjectArray JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which)
+{
+ log_println("JVM_GetClassMethods: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetClassConstructors */
+
+jobjectArray JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which)
+{
+ log_println("JVM_GetClassConstructors: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetClassField */
+
+jobject JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which)
+{
+ log_println("JVM_GetClassField: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetClassMethod */
+
+jobject JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which)
+{
+ log_println("JVM_GetClassMethod: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetClassConstructor */
+
+jobject JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which)
+{
+ log_println("JVM_GetClassConstructor: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_NewInstance */
+
+jobject JVM_NewInstance(JNIEnv *env, jclass cls)
+{
+ log_println("JVM_NewInstance: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetField */
+
+jobject JVM_GetField(JNIEnv *env, jobject field, jobject obj)
+{
+ log_println("JVM_GetField: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetPrimitiveField */
+
+jvalue JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode)
+{
+ jvalue jv;
+
+ log_println("JVM_GetPrimitiveField: IMPLEMENT ME!");
+
+ jv.l = NULL;
+
+ return jv;
+}
+
+
+/* JVM_SetField */
+
+void JVM_SetField(JNIEnv *env, jobject field, jobject obj, jobject val)
+{
+ log_println("JVM_SetField: IMPLEMENT ME!");
+}
+
+
+/* JVM_SetPrimitiveField */
+
+void JVM_SetPrimitiveField(JNIEnv *env, jobject field, jobject obj, jvalue v, unsigned char vCode)
+{
+ log_println("JVM_SetPrimitiveField: IMPLEMENT ME!");
+}
+
+
+/* JVM_InvokeMethod */
+
+jobject JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)
+{
+ TRACEJVMCALLS(("JVM_InvokeMethod(env=%p, method=%p, obj=%p, args0=%p)", env, method, obj, args0));
+
+ java_lang_reflect_Method jlrm(method);
+
+ java_handle_t* result = jlrm.invoke((java_handle_t*) obj, (java_handle_objectarray_t*) args0);
+
+ return (jobject) result;
+}
+
+
+/* JVM_NewInstanceFromConstructor */
+
+jobject JVM_NewInstanceFromConstructor(JNIEnv *env, jobject con, jobjectArray args0)
+{
+ TRACEJVMCALLS(("JVM_NewInstanceFromConstructor(env=%p, c=%p, args0=%p)", env, con, args0));
+
+ java_lang_reflect_Constructor jlrc(con);
+ java_handle_t* o = jlrc.new_instance((java_handle_objectarray_t*) args0);
+
+ return (jobject) o;
+}
+
+
+/* JVM_SupportsCX8 */
+
+jboolean JVM_SupportsCX8()
+{
+ TRACEJVMCALLS(("JVM_SupportsCX8()"));
+
+ /* IMPLEMENT ME */
+
+ return 0;
+}
+
+
+/* JVM_CX8Field */
+
+jboolean JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong oldVal, jlong newVal)
+{
+ log_println("JVM_CX8Field: IMPLEMENT ME!");
+
+ return 0;
+}
+
+
+/* JVM_GetAllThreads */
+
+jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy)
+{
+ log_println("JVM_GetAllThreads: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_DumpThreads */
+
+jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads)
+{
+ log_println("JVM_DumpThreads: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetManagement */
+
+void *JVM_GetManagement(jint version)
+{
+ TRACEJVMCALLS(("JVM_GetManagement(version=%d)", version));
+
+ /* TODO We current don't support the management interface. */
+
+ return NULL;
+}
+
+
+/* JVM_InitAgentProperties */
+
+jobject JVM_InitAgentProperties(JNIEnv *env, jobject properties)
+{
+ log_println("JVM_InitAgentProperties: IMPLEMENT ME!");
+
+ return NULL;
+}
+
+
+/* JVM_GetEnclosingMethodInfo */
+
+jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)
+{
+ classinfo *c;
+ methodinfo *m;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetEnclosingMethodInfo(env=%p, ofClass=%p)", env, ofClass));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ if ((c == NULL) || class_is_primitive(c))
+ return NULL;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ oa = builtin_anewarray(3, class_java_lang_Object);
+
+ if (oa == NULL)
+ return NULL;
+
+ array_objectarray_element_set(oa, 0, (java_handle_t *) LLNI_classinfo_wrap(m->clazz));
+ array_objectarray_element_set(oa, 1, javastring_new(m->name));
+ array_objectarray_element_set(oa, 2, javastring_new(m->descriptor));
+
+ return (jobjectArray) oa;
+}
+
+
+/* JVM_GetThreadStateValues */
+
+jintArray JVM_GetThreadStateValues(JNIEnv* env, jint javaThreadState)
+{
+ java_handle_intarray_t *ia;
+
+ TRACEJVMCALLS(("JVM_GetThreadStateValues(env=%p, javaThreadState=%d)",
+ env, javaThreadState));
+
+ /* If new thread states are added in future JDK and VM versions,
+ this should check if the JDK version is compatible with thread
+ states supported by the VM. Return NULL if not compatible.
+
+ This function must map the VM java_lang_Thread::ThreadStatus
+ to the Java thread state that the JDK supports. */
+
+ switch (javaThreadState) {
+ case THREAD_STATE_NEW:
+ ia = builtin_newarray_int(1);
+
+ if (ia == NULL)
+ return NULL;
+
+ array_intarray_element_set(ia, 0, THREAD_STATE_NEW);
+ break;
+
+ case THREAD_STATE_RUNNABLE:
+ ia = builtin_newarray_int(1);
+
+ if (ia == NULL)
+ return NULL;
+
+ array_intarray_element_set(ia, 0, THREAD_STATE_RUNNABLE);
+ break;
+
+ case THREAD_STATE_BLOCKED:
+ ia = builtin_newarray_int(1);
+
+ if (ia == NULL)
+ return NULL;
+
+ array_intarray_element_set(ia, 0, THREAD_STATE_BLOCKED);
+ break;
+
+ case THREAD_STATE_WAITING:
+ ia = builtin_newarray_int(2);
+
+ if (ia == NULL)
+ return NULL;
+
+ array_intarray_element_set(ia, 0, THREAD_STATE_WAITING);
+ /* XXX Implement parked stuff. */
+/* array_intarray_element_set(ia, 1, PARKED); */
+ break;
+
+ case THREAD_STATE_TIMED_WAITING:
+ ia = builtin_newarray_int(3);
+
+ if (ia == NULL)
+ return NULL;
+
+ /* XXX Not sure about that one. */
+/* array_intarray_element_set(ia, 0, SLEEPING); */
+ array_intarray_element_set(ia, 0, THREAD_STATE_TIMED_WAITING);
+ /* XXX Implement parked stuff. */
+/* array_intarray_element_set(ia, 2, PARKED); */
+ break;
+
+ case THREAD_STATE_TERMINATED:
+ ia = builtin_newarray_int(1);
+
+ if (ia == NULL)
+ return NULL;
+
+ array_intarray_element_set(ia, 0, THREAD_STATE_TERMINATED);
+ break;
+
+ default:
+ /* Unknown state - probably incompatible JDK version */
+ return NULL;
+ }
+
+ return (jintArray) ia;
+}
+
+
+/* JVM_GetThreadStateNames */
+
+jobjectArray JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArray values)
+{
+ java_handle_intarray_t *ia;
+ java_handle_objectarray_t *oa;
+ java_object_t *s;
+
+ TRACEJVMCALLS(("JVM_GetThreadStateNames(env=%p, javaThreadState=%d, values=%p)",
+ env, javaThreadState, values));
+
+ ia = (java_handle_intarray_t *) values;
+
+ /* If new thread states are added in future JDK and VM versions,
+ this should check if the JDK version is compatible with thread
+ states supported by the VM. Return NULL if not compatible.
+
+ This function must map the VM java_lang_Thread::ThreadStatus
+ to the Java thread state that the JDK supports. */
+
+ if (values == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ switch (javaThreadState) {
+ case THREAD_STATE_NEW:
+ assert(ia->header.size == 1 && ia->data[0] == THREAD_STATE_NEW);
+
+ oa = builtin_anewarray(1, class_java_lang_String);
+
+ if (oa == NULL)
+ return NULL;
+
+ s = javastring_new(utf_new_char("NEW"));
+
+ if (s == NULL)
+ return NULL;
+
+ array_objectarray_element_set(oa, 0, s);
+ break;
+
+ case THREAD_STATE_RUNNABLE:
+ oa = builtin_anewarray(1, class_java_lang_String);
+
+ if (oa == NULL)
+ return NULL;
+
+ s = javastring_new(utf_new_char("RUNNABLE"));
+
+ if (s == NULL)
+ return NULL;
+
+ array_objectarray_element_set(oa, 0, s);
+ break;
+
+ case THREAD_STATE_BLOCKED:
+ oa = builtin_anewarray(1, class_java_lang_String);
+
+ if (oa == NULL)
+ return NULL;
+
+ s = javastring_new(utf_new_char("BLOCKED"));
+
+ if (s == NULL)
+ return NULL;
+
+ array_objectarray_element_set(oa, 0, s);
+ break;
+
+ case THREAD_STATE_WAITING:
+ oa = builtin_anewarray(2, class_java_lang_String);
+
+ if (oa == NULL)
+ return NULL;
+
+ s = javastring_new(utf_new_char("WAITING.OBJECT_WAIT"));
+/* s = javastring_new(utf_new_char("WAITING.PARKED")); */
+
+ if (s == NULL)
+ return NULL;
+
+ array_objectarray_element_set(oa, 0, s);
+/* array_objectarray_element_set(oa, 1, s); */
+ break;
+
+ case THREAD_STATE_TIMED_WAITING:
+ oa = builtin_anewarray(3, class_java_lang_String);
+
+ if (oa == NULL)
+ return NULL;
+
+/* s = javastring_new(utf_new_char("TIMED_WAITING.SLEEPING")); */
+ s = javastring_new(utf_new_char("TIMED_WAITING.OBJECT_WAIT"));
+/* s = javastring_new(utf_new_char("TIMED_WAITING.PARKED")); */
+
+ if (s == NULL)
+ return NULL;
+
+/* array_objectarray_element_set(oa, 0, s); */
+ array_objectarray_element_set(oa, 0, s);
+/* array_objectarray_element_set(oa, 2, s); */
+ break;
+
+ case THREAD_STATE_TERMINATED:
+ oa = builtin_anewarray(1, class_java_lang_String);
+
+ if (oa == NULL)
+ return NULL;
+
+ s = javastring_new(utf_new_char("TERMINATED"));
+
+ if (s == NULL)
+ return NULL;
+
+ array_objectarray_element_set(oa, 0, s);
+ break;
+
+ default:
+ /* Unknown state - probably incompatible JDK version */
+ return NULL;
+ }
+
+ return (jobjectArray) oa;
+}
+
+
+/* JVM_GetVersionInfo */
+
+void JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size)
+{
+ log_println("JVM_GetVersionInfo: IMPLEMENT ME!");
+}
+
+
+/* OS: JVM_RegisterSignal */
+
+void *JVM_RegisterSignal(jint sig, void *handler)
+{
+ functionptr newHandler;
+
+ TRACEJVMCALLS(("JVM_RegisterSignal(sig=%d, handler=%p)", sig, handler));
+
+ if (handler == (void *) 2)
+ newHandler = (functionptr) signal_thread_handler;
+ else
+ newHandler = (functionptr) (uintptr_t) handler;
+
+ switch (sig) {
+ case SIGILL:
+ case SIGFPE:
+ case SIGUSR1:
+ case SIGSEGV:
+ /* These signals are already used by the VM. */
+ return (void *) -1;
+
+ case SIGQUIT:
+ /* This signal is used by the VM to dump thread stacks unless
+ ReduceSignalUsage is set, in which case the user is allowed
+ to set his own _native_ handler for this signal; thus, in
+ either case, we do not allow JVM_RegisterSignal to change
+ the handler. */
+ return (void *) -1;
+
+ case SIGHUP:
+ case SIGINT:
+ case SIGTERM:
+ break;
+ }
+
+ signal_register_signal(sig, newHandler, SA_RESTART | SA_SIGINFO);
+
+ /* XXX Should return old handler. */
+
+ return (void *) 2;
+}
+
+
+/* OS: JVM_RaiseSignal */
+
+jboolean JVM_RaiseSignal(jint sig)
+{
+ log_println("JVM_RaiseSignal: IMPLEMENT ME! sig=%s", sig);
+
+ return false;
+}
+
+
+/* OS: JVM_FindSignal */
+
+jint JVM_FindSignal(const char *name)
+{
+ TRACEJVMCALLS(("JVM_FindSignal(name=%s)", name));
+
+#if defined(__LINUX__)
+ if (strcmp(name, "HUP") == 0)
+ return SIGHUP;
+
+ if (strcmp(name, "INT") == 0)
+ return SIGINT;
+
+ if (strcmp(name, "TERM") == 0)
+ return SIGTERM;
+#elif defined(__SOLARIS__)
+ int signum;
+
+ if (os::str2sig(name, &signum) == -1)
+ return -1;
+
+ return signum;
+#else
+# error Not implemented for this OS.
+#endif
+
+ return -1;
+}
+
+} // extern "C"
+
+
+/*
+ * 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/native/vm/reflect.c - helper functions for java/lang/reflect
-
- 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.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-/* keep this order of the native includes */
-
-#include "native/include/java_lang_String.h"
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-#endif
-#include "native/include/java_lang_ClassLoader.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_reflect_Constructor.h"
-#include "native/include/java_lang_reflect_Field.h"
-#include "native/include/java_lang_reflect_Method.h"
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_reflect_VMConstructor.h"
-# include "native/include/java_lang_reflect_VMField.h"
-# include "native/include/java_lang_reflect_VMMethod.h"
-#endif
-
-#if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "vm/vm.h"
-# include "native/include/sun_reflect_ConstantPool.h"
-#endif
-
-#include "native/vm/reflect.h"
-
-#include "vm/access.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/method.h"
-
-
-/* reflect_constructor_new *****************************************************
-
- Allocates a new java.lang.reflect.Constructor object and
- initializes the fields with the method passed.
-
-*******************************************************************************/
-
-java_lang_reflect_Constructor *reflect_constructor_new(methodinfo *m)
-{
- java_handle_t *o;
- java_lang_reflect_Constructor *rc;
- int32_t slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_reflect_VMConstructor *rvmc;
-#endif
-
- /* Allocate a java.lang.reflect.Constructor object. */
-
- o = builtin_new(class_java_lang_reflect_Constructor);
-
- if (o == NULL)
- return NULL;
-
- /* Initialize instance fields. */
-
- rc = (java_lang_reflect_Constructor *) o;
-
- /* Calculate the slot. */
-
- slot = m - m->clazz->methods;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Allocate a java.lang.reflect.VMConstructor object. */
-
- o = builtin_new(class_java_lang_reflect_VMConstructor);
-
- if (o == NULL)
- return NULL;
-
- rvmc = (java_lang_reflect_VMConstructor *) o;
-
- /* Link the two Java objects. */
-
- LLNI_field_set_ref(rc, cons, rvmc);
- LLNI_field_set_ref(rvmc, cons, rc);
-
- /* Set Java object instance fields. */
-
- LLNI_field_set_cls(rvmc, clazz, m->clazz);
- LLNI_field_set_val(rvmc, slot, slot);
- LLNI_field_set_ref(rvmc, annotations, method_get_annotations(m));
- LLNI_field_set_ref(rvmc, parameterAnnotations, method_get_parameterannotations(m));
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* Set Java object instance fields. */
-
- LLNI_field_set_cls(rc, clazz , m->clazz);
- LLNI_field_set_ref(rc, parameterTypes , method_get_parametertypearray(m));
- LLNI_field_set_ref(rc, exceptionTypes , method_get_exceptionarray(m));
- LLNI_field_set_val(rc, modifiers , m->flags & ACC_CLASS_REFLECT_MASK);
- LLNI_field_set_val(rc, slot , slot);
- LLNI_field_set_ref(rc, signature , m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL);
- LLNI_field_set_ref(rc, annotations , method_get_annotations(m));
- LLNI_field_set_ref(rc, parameterAnnotations, method_get_parameterannotations(m));
-
-#else
-# error unknown classpath configuration
-#endif
-
- return rc;
-}
-
-
-/* reflect_field_new ***********************************************************
-
- Allocates a new java.lang.reflect.Field object and initializes the
- fields with the field passed.
-
-*******************************************************************************/
-
-java_lang_reflect_Field *reflect_field_new(fieldinfo *f)
-{
- java_handle_t *o;
- java_lang_reflect_Field *rf;
- int32_t slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_reflect_VMField *rvmf;
-#endif
-
- /* Allocate a java.lang.reflect.Field object. */
-
- o = builtin_new(class_java_lang_reflect_Field);
-
- if (o == NULL)
- return NULL;
-
- /* initialize instance fields */
-
- rf = (java_lang_reflect_Field *) o;
-
- /* Calculate the slot. */
-
- slot = f - f->clazz->fields;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Allocate a java.lang.reflect.VMField object. */
-
- o = builtin_new(class_java_lang_reflect_VMField);
-
- if (o == NULL)
- return NULL;
-
- rvmf = (java_lang_reflect_VMField *) o;
-
- /* Link the two Java objects. */
-
- LLNI_field_set_ref(rf, f, rvmf);
- LLNI_field_set_ref(rvmf, f, rf);
-
- /* Set the Java object fields. */
-
- LLNI_field_set_cls(rvmf, clazz, f->clazz);
-
- /* The name needs to be interned */
- /* XXX implement me better! */
-
- LLNI_field_set_ref(rvmf, name, (java_lang_String *) javastring_intern(javastring_new(f->name)));
- LLNI_field_set_val(rvmf, slot, slot);
- LLNI_field_set_ref(rvmf, annotations, field_get_annotations(f));
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* Set the Java object fields. */
-
- LLNI_field_set_cls(rf, clazz, f->clazz);
-
- /* The name needs to be interned */
- /* XXX implement me better! */
-
- LLNI_field_set_ref(rf, name, (java_lang_String *) javastring_intern(javastring_new(f->name)));
- LLNI_field_set_cls(rf, type, (java_lang_Class *) field_get_type(f));
- LLNI_field_set_val(rf, modifiers, f->flags);
- LLNI_field_set_val(rf, slot, slot);
- LLNI_field_set_ref(rf, signature, f->signature ? (java_lang_String *) javastring_new(f->signature) : NULL);
- LLNI_field_set_ref(rf, annotations, field_get_annotations(f));
-
-#else
-# error unknown classpath configuration
-#endif
-
- return rf;
-}
-
-
-/* reflect_method_new **********************************************************
-
- Allocates a new java.lang.reflect.Method object and initializes the
- fields with the method passed.
-
-*******************************************************************************/
-
-java_lang_reflect_Method *reflect_method_new(methodinfo *m)
-{
- java_handle_t *o;
- java_lang_reflect_Method *rm;
- int32_t slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_reflect_VMMethod *rvmm;
-#endif
-
- /* Allocate a java.lang.reflect.Method object. */
-
- o = builtin_new(class_java_lang_reflect_Method);
-
- if (o == NULL)
- return NULL;
-
- /* initialize instance fields */
-
- rm = (java_lang_reflect_Method *) o;
-
- /* Calculate the slot. */
-
- slot = m - m->clazz->methods;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Allocate a java.lang.reflect.VMMethod object. */
-
- o = builtin_new(class_java_lang_reflect_VMMethod);
-
- if (o == NULL)
- return NULL;
-
- rvmm = (java_lang_reflect_VMMethod *) o;
-
- /* Link the two Java objects. */
-
- LLNI_field_set_ref(rm, m, rvmm);
- LLNI_field_set_ref(rvmm, m, rm);
-
- /* Set Java object instance fields. */
-
- LLNI_field_set_cls(rvmm, clazz, m->clazz);
-
- /* The name needs to be interned */
- /* XXX implement me better! */
-
- LLNI_field_set_ref(rvmm, name, (java_lang_String *) javastring_intern(javastring_new(m->name)));
- LLNI_field_set_val(rvmm, slot, slot);
- LLNI_field_set_ref(rvmm, annotations, method_get_annotations(m));
- LLNI_field_set_ref(rvmm, parameterAnnotations, method_get_parameterannotations(m));
- LLNI_field_set_ref(rvmm, annotationDefault, method_get_annotationdefault(m));
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- LLNI_field_set_cls(rm, clazz, m->clazz);
-
- /* The name needs to be interned */
- /* XXX implement me better! */
-
- LLNI_field_set_ref(rm, name, (java_lang_String *) javastring_intern(javastring_new(m->name)));
- LLNI_field_set_ref(rm, parameterTypes, method_get_parametertypearray(m));
- LLNI_field_set_cls(rm, returnType, (java_lang_Class *) method_returntype_get(m));
- LLNI_field_set_ref(rm, exceptionTypes, method_get_exceptionarray(m));
- LLNI_field_set_val(rm, modifiers, m->flags & ACC_CLASS_REFLECT_MASK);
- LLNI_field_set_val(rm, slot, slot);
- LLNI_field_set_ref(rm, signature, m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL);
- LLNI_field_set_ref(rm, annotations, method_get_annotations(m));
- LLNI_field_set_ref(rm, parameterAnnotations, method_get_parameterannotations(m));
- LLNI_field_set_ref(rm, annotationDefault, method_get_annotationdefault(m));
-
-#else
-# error unknown classpath configuration
-#endif
-
- return rm;
-}
-
-
-/* reflect_invoke **************************************************************
-
- Invoke a method on the given object with the given arguments.
-
- For instance methods OBJ must be != NULL and the method is looked up
- in the vftbl of the object.
-
- For static methods, OBJ is ignored.
-
-*******************************************************************************/
-
-static java_handle_t *reflect_invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
-{
- methodinfo *resm;
- java_handle_t *ro;
- int argcount;
- int paramcount;
-
- /* Sanity check. */
-
- assert(m != NULL);
-
- argcount = m->parseddesc->paramcount;
- paramcount = argcount;
-
- /* If method is non-static, remove the `this' pointer. */
-
- if (!(m->flags & ACC_STATIC))
- paramcount--;
-
- /* For instance methods the object has to be an instance of the
- class the method belongs to. For static methods the obj
- parameter is ignored. */
-
- if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* check if we got the right number of arguments */
-
- if (((params == NULL) && (paramcount != 0)) ||
- (params && (LLNI_array_size(params) != paramcount)))
- {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* for instance methods we need an object */
-
- if (!(m->flags & ACC_STATIC) && (o == NULL)) {
- /* XXX not sure if that is the correct exception */
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* for static methods, zero object to make subsequent code simpler */
- if (m->flags & ACC_STATIC)
- o = NULL;
-
- if (o != NULL) {
- /* for instance methods we must do a vftbl lookup */
- resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
- }
- else {
- /* for static methods, just for convenience */
- resm = m;
- }
-
- ro = vm_call_method_objectarray(resm, o, params);
-
- return ro;
-}
-
-
-/* reflect_constructor_newinstance ********************************************
-
- Creates an Java object instance of the given constructor.
-
- ARGUMENTS:
- m .......... methodinfo of the constructor
- args ....... constructor arguments
- override ... override security checks
-
- RETURN:
- constructed Java object
-
-*******************************************************************************/
-
-java_handle_t *reflect_constructor_newinstance(methodinfo *m, java_handle_objectarray_t *args, bool override)
-{
- java_handle_t *o;
-
- /* Should we bypass security the checks (AccessibleObject)? */
-
- if (override == false) {
- /* This method is always called like this:
- [0] java.lang.reflect.Constructor.constructNative (Native Method)
- [1] java.lang.reflect.Constructor.newInstance
- [2] <caller>
- */
-
- if (!access_check_method(m, 2))
- return NULL;
- }
-
- /* Create a Java object. */
-
- o = builtin_new(m->clazz);
-
- if (o == NULL)
- return NULL;
-
- /* Call initializer. */
-
- (void) reflect_invoke(m, o, args);
-
- return o;
-}
-
-
-/* reflect_method_invoke *******************************************************
-
- Invokes the given method.
-
- ARGUMENTS:
- m .......... methodinfo
- args ....... method arguments
- override ... override security checks
-
- RETURN:
- return value of the method
-
-*******************************************************************************/
-
-java_handle_t *reflect_method_invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *args, bool override)
-{
- java_handle_t *ro;
-
- /* Should we bypass security the checks (AccessibleObject)? */
-
- if (override == false) {
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* This method is always called like this:
- [0] java.lang.reflect.Method.invokeNative (Native Method)
- [1] java.lang.reflect.Method.invoke (Method.java:329)
- [2] <caller>
- */
-
- if (!access_check_method(m, 2))
- return NULL;
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* We only pass 1 here as stacktrace_get_caller_class, which
- is called from access_check_method, skips
- java.lang.reflect.Method.invoke(). */
-
- if (!access_check_method(m, 1))
- return NULL;
-#else
-# error unknown classpath configuration
-#endif
- }
-
- /* Check if method class is initialized. */
-
- if (!(m->clazz->state & CLASS_INITIALIZED))
- if (!initialize_class(m->clazz))
- return NULL;
-
- /* Call the Java method. */
-
- ro = reflect_invoke(m, o, args);
-
- return ro;
-}
-
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
-/* reflect_get_declaredannotatios *********************************************
-
- Calls the annotation parser with the unparsed annotations and returnes
- the parsed annotations as a map.
-
- IN:
- annotations........the unparsed annotations
- declaringClass.....the class in which the annotated element is declared
- referer............the calling class (for the 'referer' parameter of
- vm_call_method())
-
- RETURN VALUE:
- The parsed annotations as a
- java.util.Map<Class<? extends Annotation>, Annotation>.
-
-*******************************************************************************/
-
-struct java_util_Map* reflect_get_declaredannotatios(
- java_handle_bytearray_t *annotations,
- java_lang_Class *declaringClass,
- classinfo *referer)
-{
- static methodinfo *m_parseAnnotations = NULL;
- /* parser method (chached, therefore static) */
- utf *utf_parseAnnotations = NULL;
- /* parser method name */
- utf *utf_desc = NULL;
- /* parser method descriptor (signature) */
- sun_reflect_ConstantPool *constantPool = NULL;
- /* constant pool of the declaring class */
- java_lang_Object *constantPoolOop = (java_lang_Object*)declaringClass;
- /* constantPoolOop field of the constant pool */
- /* object (sun.reflect.ConstantPool) */
-
- constantPool =
- (sun_reflect_ConstantPool*)native_new_and_init(
- class_sun_reflect_ConstantPool);
-
- if(constantPool == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
-
- /* only resolve the parser method the first time */
- if (m_parseAnnotations == NULL) {
- utf_parseAnnotations = utf_new_char("parseAnnotations");
- utf_desc = utf_new_char(
- "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
- "Ljava/util/Map;");
-
- if (utf_parseAnnotations == NULL || utf_desc == NULL) {
- /* out of memory */
- return NULL;
- }
-
- m_parseAnnotations = class_resolveclassmethod(
- class_sun_reflect_annotation_AnnotationParser,
- utf_parseAnnotations,
- utf_desc,
- referer,
- true);
-
- if (m_parseAnnotations == NULL) {
- /* method not found */
- return NULL;
- }
- }
-
- return (struct java_util_Map*)vm_call_method(
- m_parseAnnotations, NULL, annotations,
- constantPool, declaringClass);
-}
-
-
-/* reflect_get_parameterannotations *******************************************
-
- Calls the annotation parser with the unparsed parameter annotations of
- a method and returnes the parsed parameter annotations in a 2 dimensional
- array.
-
- IN:
- parameterAnnotations....the unparsed parameter annotations
- slot....................the slot of the method
- declaringClass..........the class in which the annotated element is
- declared
- referer.................the calling class (for the 'referer' parameter
- of vm_call_method())
-
- RETURN VALUE:
- The parsed parameter annotations in a 2 dimensional array.
-
-*******************************************************************************/
-
-java_handle_objectarray_t* reflect_get_parameterannotations(
- java_handle_t *parameterAnnotations,
- int32_t slot,
- java_lang_Class *declaringClass,
- classinfo *referer)
-{
- /* This method in java would be basically the following.
- * We don't do it in java because we don't want to make a
- * public method with wich you can get a ConstantPool, because
- * with that you could read any kind of constants (even private
- * ones).
- *
- * ConstantPool constPool = new ConstantPool();
- * constPool.constantPoolOop = method.getDeclaringClass();
- * return sun.reflect.AnnotationParser.parseParameterAnnotations(
- * parameterAnnotations,
- * constPool,
- * method.getDeclaringClass(),
- * method.getParameterTypes().length);
- */
- static methodinfo *m_parseParameterAnnotations = NULL;
- /* parser method (cached, therefore static) */
- utf *utf_parseParameterAnnotations = NULL;
- /* parser method name */
- utf *utf_desc = NULL;
- /* parser method descriptor (signature) */
- sun_reflect_ConstantPool *constantPool = NULL;
- /* constant pool of the declaring class */
- java_lang_Object *constantPoolOop = (java_lang_Object*)declaringClass;
- /* constantPoolOop field of the constant pool object */
- classinfo *c = NULL;
- /* classinfo of the decaring class */
- methodinfo *m = NULL;
- /* method info of the annotated method */
- int32_t numParameters = -1;
- /* parameter count of the annotated method */
-
- /* get parameter count */
-
- c = LLNI_classinfo_unwrap(declaringClass);
- m = &(c->methods[slot]);
-
- numParameters = method_get_parametercount(m);
-
- if (numParameters < 0) {
- /* error parsing descriptor */
- return NULL;
- }
-
- /* get ConstantPool */
-
- constantPool =
- (sun_reflect_ConstantPool*)native_new_and_init(
- class_sun_reflect_ConstantPool);
-
- if(constantPool == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
-
- /* only resolve the parser method the first time */
- if (m_parseParameterAnnotations == NULL) {
- utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
- utf_desc = utf_new_char(
- "([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)"
- "[[Ljava/lang/annotation/Annotation;");
-
- if (utf_parseParameterAnnotations == NULL || utf_desc == NULL) {
- /* out of memory */
- return NULL;
- }
-
- /* get parser method */
-
- m_parseParameterAnnotations = class_resolveclassmethod(
- class_sun_reflect_annotation_AnnotationParser,
- utf_parseParameterAnnotations,
- utf_desc,
- referer,
- true);
-
- if (m_parseParameterAnnotations == NULL)
- {
- /* method not found */
- return NULL;
- }
- }
-
- return (java_handle_objectarray_t*)vm_call_method(
- m_parseParameterAnnotations, NULL, parameterAnnotations,
- constantPool, declaringClass, numParameters);
-}
-#endif
-
-
-/*
- * 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/native/vm/reflect.h - helper functions for java/lang/reflect
-
- 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 _REFLECT_H
-#define _REFLECT_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "native/jni.h"
-#include "native/native.h"
-
-/* Keep this order of the native includes. */
-
-#include "native/include/java_lang_String.h"
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-# endif
-# include "native/include/java_lang_ClassLoader.h"
-#endif
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_reflect_Constructor.h"
-# include "native/include/java_lang_reflect_Field.h"
-# include "native/include/java_lang_reflect_Method.h"
-#endif
-
-#include "vmcore/field.h"
-#include "vmcore/method.h"
-
-
-/* function prototypes ********************************************************/
-
-java_lang_reflect_Constructor *reflect_constructor_new(methodinfo *m);
-java_lang_reflect_Field *reflect_field_new(fieldinfo *f);
-java_lang_reflect_Method *reflect_method_new(methodinfo *m);
-java_handle_t *reflect_constructor_newinstance(methodinfo *m, java_handle_objectarray_t *args, bool override);
-java_handle_t *reflect_method_invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *args, bool override);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
-struct java_util_Map* reflect_get_declaredannotatios(
- java_handle_bytearray_t *annotations,
- java_lang_Class *declaringClass,
- classinfo *referer);
-
-java_handle_objectarray_t* reflect_get_parameterannotations(
- java_handle_t *parameterAnnotations,
- int32_t slot,
- java_lang_Class *declaringClass,
- classinfo *referer);
-#endif
-
-#endif /* _REFLECT_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:
- */
--- /dev/null
+/* src/native/vm/reflection.cpp - helper functions for java/lang/reflect
+
+ 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.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+# include "vm/vm.hpp"
+#endif
+
+#include "native/vm/reflection.hpp"
+
+#include "vm/access.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/method.h"
+#include "vm/string.hpp"
+
+
+/**
+ * Invoke a method on the given object with the given arguments.
+ *
+ * For instance methods OBJ must be != NULL and the method is looked up
+ * in the vftbl of the object.
+ *
+ * For static methods, OBJ is ignored.
+ */
+java_handle_t* Reflection::invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
+{
+ methodinfo *resm;
+ java_handle_t *ro;
+ int argcount;
+ int paramcount;
+
+ /* Sanity check. */
+
+ assert(m != NULL);
+
+ argcount = m->parseddesc->paramcount;
+ paramcount = argcount;
+
+ /* If method is non-static, remove the `this' pointer. */
+
+ if (!(m->flags & ACC_STATIC))
+ paramcount--;
+
+ /* For instance methods the object has to be an instance of the
+ class the method belongs to. For static methods the obj
+ parameter is ignored. */
+
+ if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* check if we got the right number of arguments */
+
+ if (((params == NULL) && (paramcount != 0)) ||
+ (params && (LLNI_array_size(params) != paramcount)))
+ {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* for instance methods we need an object */
+
+ if (!(m->flags & ACC_STATIC) && (o == NULL)) {
+ /* XXX not sure if that is the correct exception */
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* for static methods, zero object to make subsequent code simpler */
+ if (m->flags & ACC_STATIC)
+ o = NULL;
+
+ if (o != NULL) {
+ /* for instance methods we must do a vftbl lookup */
+ resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
+ }
+ else {
+ /* for static methods, just for convenience */
+ resm = m;
+ }
+
+ ro = vm_call_method_objectarray(resm, o, params);
+
+ return ro;
+}
+
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
+/* reflect_get_declaredannotations *********************************************
+
+ Calls the annotation parser with the unparsed annotations and returnes
+ the parsed annotations as a map.
+
+ IN:
+ annotations........the unparsed annotations
+ declaringClass.....the class in which the annotated element is declared
+ referer............the calling class (for the 'referer' parameter of
+ vm_call_method())
+
+ RETURN VALUE:
+ The parsed annotations as a
+ java.util.Map<Class<? extends Annotation>, Annotation>.
+
+*******************************************************************************/
+
+java_handle_t* Reflection::get_declaredannotations(java_handle_bytearray_t *annotations, classinfo* declaringClass, classinfo *referer)
+{
+ static methodinfo* m_parseAnnotations = NULL;
+
+ java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
+
+ if (h == NULL)
+ return NULL;
+
+ sun_reflect_ConstantPool cp(h);
+ cp.set_constantPoolOop(declaringClass);
+
+ /* only resolve the parser method the first time */
+ if (m_parseAnnotations == NULL) {
+ // FIXME Use globals.
+ utf* utf_parseAnnotations = utf_new_char("parseAnnotations");
+ utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;)Ljava/util/Map;");
+
+ if (utf_parseAnnotations == NULL || utf_desc == NULL)
+ return NULL;
+
+ m_parseAnnotations = class_resolveclassmethod(
+ class_sun_reflect_annotation_AnnotationParser,
+ utf_parseAnnotations,
+ utf_desc,
+ referer,
+ true);
+
+ if (m_parseAnnotations == NULL)
+ return NULL;
+ }
+
+ return (java_handle_t*) vm_call_method(m_parseAnnotations, NULL, annotations, cp.get_handle(), declaringClass);
+}
+
+
+/* reflect_get_parameterannotations *******************************************
+
+ Calls the annotation parser with the unparsed parameter annotations of
+ a method and returnes the parsed parameter annotations in a 2 dimensional
+ array.
+
+ IN:
+ parameterAnnotations....the unparsed parameter annotations
+ slot....................the slot of the method
+ declaringClass..........the class in which the annotated element is
+ declared
+ referer.................the calling class (for the 'referer' parameter
+ of vm_call_method())
+
+ RETURN VALUE:
+ The parsed parameter annotations in a 2 dimensional array.
+
+*******************************************************************************/
+
+java_handle_objectarray_t* Reflection::get_parameterannotations(java_handle_bytearray_t* parameterAnnotations, methodinfo* m, classinfo* referer)
+{
+ /* This method in java would be basically the following.
+ * We don't do it in java because we don't want to make a
+ * public method with wich you can get a ConstantPool, because
+ * with that you could read any kind of constants (even private
+ * ones).
+ *
+ * ConstantPool constPool = new ConstantPool();
+ * constPool.constantPoolOop = method.getDeclaringClass();
+ * return sun.reflect.AnnotationParser.parseParameterAnnotations(
+ * parameterAnnotations,
+ * constPool,
+ * method.getDeclaringClass(),
+ * method.getParameterTypes().length);
+ */
+
+ static methodinfo* m_parseParameterAnnotations = NULL;
+
+ /* get parameter count */
+
+ int32_t numParameters = method_get_parametercount(m);
+
+ if (numParameters < 0)
+ return NULL;
+
+ /* get ConstantPool */
+
+ java_handle_t* h = native_new_and_init(class_sun_reflect_ConstantPool);
+
+ if (h == NULL)
+ return NULL;
+
+ sun_reflect_ConstantPool cp(h);
+ cp.set_constantPoolOop(m->clazz);
+
+ /* only resolve the parser method the first time */
+ if (m_parseParameterAnnotations == NULL) {
+ utf* utf_parseParameterAnnotations = utf_new_char("parseParameterAnnotations");
+ utf* utf_desc = utf_new_char("([BLsun/reflect/ConstantPool;Ljava/lang/Class;I)[[Ljava/lang/annotation/Annotation;");
+
+ if (utf_parseParameterAnnotations == NULL || utf_desc == NULL)
+ return NULL;
+
+ /* get parser method */
+
+ m_parseParameterAnnotations = class_resolveclassmethod(
+ class_sun_reflect_annotation_AnnotationParser,
+ utf_parseParameterAnnotations,
+ utf_desc,
+ referer,
+ true);
+
+ if (m_parseParameterAnnotations == NULL)
+ return NULL;
+ }
+
+ return (java_handle_objectarray_t*) vm_call_method(m_parseParameterAnnotations, NULL, parameterAnnotations, cp.get_handle(), m->clazz, numParameters);
+}
+#endif
+
+
+/*
+ * 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/native/vm/reflection.hpp - helper functions for java/lang/reflect
+
+ 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 _REFLECTION_HPP
+#define _REFLECTION_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "native/jni.h"
+#include "native/native.h"
+
+#include "vm/field.h"
+#include "vm/method.h"
+
+
+class Reflection {
+public:
+ static java_handle_t* invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) && defined(ENABLE_ANNOTATIONS)
+ static java_handle_t* get_declaredannotations(java_handle_bytearray_t *annotations, classinfo* declaringClass, classinfo *referer);
+ static java_handle_objectarray_t* get_parameterannotations(java_handle_bytearray_t* parameterAnnotations, methodinfo* m, classinfo *referer);
+#endif
+};
+
+#endif // _REFLECTION_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
-/* src/native/vm/sun_misc_Unsafe.c - sun/misc/Unsafe
-
- Copyright (C) 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 <unistd.h>
-
-#include "machine-instr.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h" /* before c.l.C */
-#include "native/include/java_lang_String.h" /* required by j.l.CL */
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-#endif
-
-#include "native/include/java_lang_ClassLoader.h" /* required by j.l.C */
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_reflect_Field.h"
-#include "native/include/java_lang_Thread.h" /* required by s.m.U */
-#include "native/include/java_lang_Throwable.h"
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_reflect_VMField.h"
-#endif
-
-#include "native/include/java_security_ProtectionDomain.h" /* required by smU */
-
-#include "native/include/sun_misc_Unsafe.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/initialize.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/system.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "registerNatives", "()V", (void *) (intptr_t) &Java_sun_misc_Unsafe_registerNatives },
- { "getInt", "(Ljava/lang/Object;J)I", (void *) (intptr_t) &Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J },
- { "putInt", "(Ljava/lang/Object;JI)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI },
- { "getObject", "(Ljava/lang/Object;J)Ljava/lang/Object;", (void *) (intptr_t) &Java_sun_misc_Unsafe_getObject },
- { "putObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putObject },
- { "getBoolean", "(Ljava/lang/Object;J)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_getBoolean },
- { "putBoolean", "(Ljava/lang/Object;JZ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putBoolean },
- { "getByte", "(Ljava/lang/Object;J)B", (void *) (intptr_t) &Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J },
- { "putByte", "(Ljava/lang/Object;JB)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB },
- { "getShort", "(Ljava/lang/Object;J)S", (void *) (intptr_t) &Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J },
- { "putShort", "(Ljava/lang/Object;JS)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS },
- { "getChar", "(Ljava/lang/Object;J)C", (void *) (intptr_t) &Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J },
- { "putChar", "(Ljava/lang/Object;JC)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC },
- { "getLong", "(Ljava/lang/Object;J)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J },
- { "putLong", "(Ljava/lang/Object;JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ },
- { "getFloat", "(Ljava/lang/Object;J)F", (void *) (intptr_t) &Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J },
- { "putFloat", "(Ljava/lang/Object;JF)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF },
- { "getDouble", "(Ljava/lang/Object;J)D", (void *) (intptr_t) &Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J },
- { "putDouble", "(Ljava/lang/Object;JD)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD },
- { "getByte", "(J)B", (void *) (intptr_t) &Java_sun_misc_Unsafe_getByte__J },
- { "putByte", "(JB)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putByte__JB },
- { "getShort", "(J)S", (void *) (intptr_t) &Java_sun_misc_Unsafe_getShort__J },
- { "putShort", "(JS)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putShort__JS },
- { "getChar", "(J)C", (void *) (intptr_t) &Java_sun_misc_Unsafe_getChar__J },
- { "putChar", "(JC)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putChar__JC },
- { "getInt", "(J)I", (void *) (intptr_t) &Java_sun_misc_Unsafe_getInt__J },
- { "putInt", "(JI)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putInt__JI },
- { "getLong", "(J)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_getLong__J },
- { "putLong", "(JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putLong__JJ },
- { "getFloat", "(J)F", (void *) (intptr_t) &Java_sun_misc_Unsafe_getFloat__J },
- { "objectFieldOffset", "(Ljava/lang/reflect/Field;)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_objectFieldOffset },
- { "allocateMemory", "(J)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_allocateMemory },
-#if 0
- /* OpenJDK 7 */
- { "setMemory", "(Ljava/lang/Object;JJB)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_setMemory },
- { "copyMemory", "(Ljava/lang/Object;JLjava/lang/Object;JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_copyMemory },
-#else
- { "setMemory", "(JJB)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_setMemory },
- { "copyMemory", "(JJJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_copyMemory },
-#endif
- { "freeMemory", "(J)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_freeMemory },
- { "staticFieldOffset", "(Ljava/lang/reflect/Field;)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldOffset },
- { "staticFieldBase", "(Ljava/lang/reflect/Field;)Ljava/lang/Object;", (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldBase },
- { "ensureClassInitialized", "(Ljava/lang/Class;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_ensureClassInitialized },
- { "arrayBaseOffset", "(Ljava/lang/Class;)I", (void *) (intptr_t) &Java_sun_misc_Unsafe_arrayBaseOffset },
- { "arrayIndexScale", "(Ljava/lang/Class;)I", (void *) (intptr_t) &Java_sun_misc_Unsafe_arrayIndexScale },
- { "addressSize", "()I", (void *) (intptr_t) &Java_sun_misc_Unsafe_addressSize },
- { "pageSize", "()I", (void *) (intptr_t) &Java_sun_misc_Unsafe_pageSize },
- { "defineClass", "(Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (intptr_t) &Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2 },
- { "allocateInstance", "(Ljava/lang/Class;)Ljava/lang/Object;", (void *) (intptr_t) &Java_sun_misc_Unsafe_allocateInstance },
- { "throwException", "(Ljava/lang/Throwable;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_throwException },
- { "compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapObject },
- { "compareAndSwapInt", "(Ljava/lang/Object;JII)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapInt },
- { "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapLong },
- { "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;", (void *) (intptr_t) &Java_sun_misc_Unsafe_getObjectVolatile },
- { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putObjectVolatile },
- { "getIntVolatile", "(Ljava/lang/Object;J)I", (void *) (intptr_t) &Java_sun_misc_Unsafe_getIntVolatile },
- { "putIntVolatile", "(Ljava/lang/Object;JI)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putIntVolatile },
- { "getLongVolatile", "(Ljava/lang/Object;J)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_getLongVolatile },
- { "putLongVolatile", "(Ljava/lang/Object;JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putLongVolatile },
- { "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedObject },
- { "putOrderedInt", "(Ljava/lang/Object;JI)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedInt },
- { "putOrderedLong", "(Ljava/lang/Object;JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedLong },
- { "unpark", "(Ljava/lang/Object;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_unpark },
- { "park", "(ZJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_park },
-};
-
-
-/* _Jv_sun_misc_Unsafe_init ****************************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_sun_misc_Unsafe_init(void)
-{
- utf *u;
-
- u = utf_new_char("sun/misc/Unsafe");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: registerNatives
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_registerNatives(JNIEnv *env, jclass clazz)
-{
- /* The native methods of this function are already registered in
- _Jv_sun_misc_Unsafe_init() which is called during VM
- startup. */
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getInt
- * Signature: (Ljava/lang/Object;J)I
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- int32_t *p;
- int32_t value;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putInt
- * Signature: (Ljava/lang/Object;JI)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
-{
- int32_t *p;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getObject
- * Signature: (Ljava/lang/Object;J)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_getObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- void **p;
- void *value;
-
- p = (void **) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putObject
- * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *x)
-{
- void **p;
-
- p = (void **) (((uint8_t *) o) + offset);
-
- *p = (void *) x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getBoolean
- * Signature: (Ljava/lang/Object;J)Z
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getBoolean(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- int32_t *p;
- int32_t value;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putBoolean
- * Signature: (Ljava/lang/Object;JZ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putBoolean(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
-{
- int32_t *p;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getByte
- * Signature: (Ljava/lang/Object;J)B
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- int32_t *p;
- int32_t value;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putByte
- * Signature: (Ljava/lang/Object;JB)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
-{
- int32_t *p;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getShort
- * Signature: (Ljava/lang/Object;J)S
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- int32_t *p;
- int32_t value;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putShort
- * Signature: (Ljava/lang/Object;JS)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
-{
- int32_t *p;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getChar
- * Signature: (Ljava/lang/Object;J)C
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- int32_t *p;
- int32_t value;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putChar
- * Signature: (Ljava/lang/Object;JC)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
-{
- int32_t *p;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getLong
- * Signature: (Ljava/lang/Object;J)J
- */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- int64_t *p;
- int64_t value;
-
- p = (int64_t *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putLong
- * Signature: (Ljava/lang/Object;JJ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
-{
- int64_t *p;
-
- p = (int64_t *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getFloat
- * Signature: (Ljava/lang/Object;J)F
- */
-JNIEXPORT float JNICALL Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- float *p;
- float value;
-
- p = (float *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putFloat
- * Signature: (Ljava/lang/Object;JF)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, float x)
-{
- float *p;
-
- p = (float *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getDouble
- * Signature: (Ljava/lang/Object;J)D
- */
-JNIEXPORT double JNICALL Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- double *p;
- double value;
-
- p = (double *) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putDouble
- * Signature: (Ljava/lang/Object;JD)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, double x)
-{
- double *p;
-
- p = (double *) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getByte
- * Signature: (J)B
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getByte__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
-{
- int8_t *p;
- int8_t value;
-
- p = (int8_t *) (intptr_t) address;
-
- value = *p;
-
- return (int32_t) value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putByte
- * Signature: (JB)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__JB(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int32_t value)
-{
- int8_t *p;
-
- p = (int8_t *) (intptr_t) address;
-
- *p = (int8_t) value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getShort
- * Signature: (J)S
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getShort__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
-{
- int16_t *p;
- int16_t value;
-
- p = (int16_t *) (intptr_t) address;
-
- value = *p;
-
- return (int32_t) value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putShort
- * Signature: (JS)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__JS(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int32_t value)
-{
- int16_t *p;
-
- p = (int16_t *) (intptr_t) address;
-
- *p = (int16_t) value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getChar
- * Signature: (J)C
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getChar__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
-{
- uint16_t *p;
- uint16_t value;
-
- p = (uint16_t *) (intptr_t) address;
-
- value = *p;
-
- return (int32_t) value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putChar
- * Signature: (JC)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__JC(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int32_t value)
-{
- uint16_t *p;
-
- p = (uint16_t *) (intptr_t) address;
-
- *p = (uint16_t) value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getInt
- * Signature: (J)I
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getInt__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
-{
- int32_t *p;
- int32_t value;
-
- p = (int32_t *) (intptr_t) address;
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putInt
- * Signature: (JI)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putInt__JI(JNIEnv *env, struct sun_misc_Unsafe* this, int64_t address, int32_t value)
-{
- int32_t *p;
-
- p = (int32_t *) (intptr_t) address;
-
- *p = value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getLong
- * Signature: (J)J
- */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_getLong__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
-{
- int64_t *p;
- int64_t value;
-
- p = (int64_t *) (intptr_t) address;
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putLong
- * Signature: (JJ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__JJ(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int64_t value)
-{
- int64_t *p;
-
- p = (int64_t *) (intptr_t) address;
-
- *p = value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getFloat
- * Signature: (J)F
- */
-JNIEXPORT float JNICALL Java_sun_misc_Unsafe_getFloat__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
-{
- float *p;
- float value;
-
- p = (float *) (intptr_t) address;
-
- value = *p;
-
- return value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: objectFieldOffset
- * Signature: (Ljava/lang/reflect/Field;)J
- */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_objectFieldOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *field)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_reflect_VMField *rvmf;
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- LLNI_field_get_ref(field, f, rvmf);
- LLNI_field_get_cls(rvmf, clazz, c);
- LLNI_field_get_val(rvmf, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- LLNI_field_get_cls(field, clazz, c);
- LLNI_field_get_val(field, slot , slot);
-
-#else
-# error unknown configuration
-#endif
-
- f = &(c->fields[slot]);
-
- return (int64_t) f->offset;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: allocateMemory
- * Signature: (J)J
- */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_allocateMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t bytes)
-{
- size_t length;
- void *p;
-
- length = (size_t) bytes;
-
- if ((length != (uint64_t) bytes) || (bytes < 0)) {
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-
- p = MNEW(uint8_t, length);
-
- return (int64_t) (intptr_t) p;
-}
-
-
-#if 0
-/* OpenJDK 7 */
-
-/*
- * Class: sun/misc/Unsafe
- * Method: setMemory
- * Signature: (Ljava/lang/Object;JJB)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_setMemory(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t bytes, int32_t value)
-{
- size_t length;
- void *p;
-
- length = (size_t) bytes;
-
- if ((length != (uint64_t) bytes) || (bytes < 0)) {
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- /* XXX Missing LLNI: we need to unwrap this object. */
-
- p = (void *) (((uint8_t *) o) + offset);
-
- /* XXX Not sure this is correct. */
-
- system_memset(p, value, length);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: copyMemory
- * Signature: (Ljava/lang/Object;JLjava/lang/Object;JJ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *srcBase, int64_t srcOffset, java_lang_Object *destBase, int64_t destOffset, int64_t bytes)
-{
- size_t length;
- void *src;
- void *dest;
-
- if (bytes == 0)
- return;
-
- length = (size_t) bytes;
-
- if ((length != (uint64_t) bytes) || (bytes < 0)) {
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- /* XXX Missing LLNI: We need to unwrap these objects. */
-
- src = (void *) (((uint8_t *) srcBase) + srcOffset);
- dest = (void *) (((uint8_t *) destBase) + destOffset);
-
- system_memcpy(dest, src, length);
-}
-#else
-/*
- * Class: sun/misc/Unsafe
- * Method: setMemory
- * Signature: (JJB)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_setMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int64_t bytes, int32_t value)
-{
- size_t length;
- void *p;
-
- length = (size_t) bytes;
-
- if ((length != (uint64_t) bytes) || (bytes < 0)) {
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- p = (void *) (intptr_t) address;
-
- /* XXX Not sure this is correct. */
-
- system_memset(p, value, length);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: copyMemory
- * Signature: (JJJ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t srcAddress, int64_t destAddress, int64_t bytes)
-{
- size_t length;
- void *src;
- void *dest;
-
- if (bytes == 0)
- return;
-
- length = (size_t) bytes;
-
- if ((length != (uint64_t) bytes) || (bytes < 0)) {
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- src = (void *) (intptr_t) srcAddress;
- dest = (void *) (intptr_t) destAddress;
-
- system_memcpy(dest, src, length);
-}
-#endif
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: freeMemory
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_freeMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
-{
- void *p;
-
- p = (void *) (intptr_t) address;
-
- if (p == NULL)
- return;
-
- /* we pass length 1 to trick the free function */
-
- MFREE(p, uint8_t, 1);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: staticFieldOffset
- * Signature: (Ljava/lang/reflect/Field;)J
- */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_staticFieldOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *f)
-{
- /* The offset of static fields is 0. */
-
- return 0;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: staticFieldBase
- * Signature: (Ljava/lang/reflect/Field;)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_staticFieldBase(JNIEnv *env, sun_misc_Unsafe *this, java_lang_reflect_Field *rf)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_reflect_VMField *rvmf;
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- LLNI_field_get_ref(rf, f, rvmf);
- LLNI_field_get_cls(rvmf, clazz, c);
- LLNI_field_get_val(rvmf, slot , slot);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- LLNI_field_get_cls(rf, clazz, c);
- LLNI_field_get_val(rf, slot , slot);
-
-#else
-# error unknown configuration
-#endif
-
- f = &(c->fields[slot]);
-
- return (java_lang_Object *) (f->value);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: ensureClassInitialized
- * Signature: (Ljava/lang/Class;)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_ensureClassInitialized(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *class)
-{
- classinfo *c;
-
- c = LLNI_classinfo_unwrap(class);
-
- if (!(c->state & CLASS_INITIALIZED))
- initialize_class(c);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: arrayBaseOffset
- * Signature: (Ljava/lang/Class;)I
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_arrayBaseOffset(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *arrayClass)
-{
- classinfo *c;
- arraydescriptor *ad;
-
- c = LLNI_classinfo_unwrap(arrayClass);
- ad = c->vftbl->arraydesc;
-
- if (ad == NULL) {
- /* XXX does that exception exist? */
- exceptions_throw_internalerror("java/lang/InvalidClassException");
- return 0;
- }
-
- return ad->dataoffset;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: arrayIndexScale
- * Signature: (Ljava/lang/Class;)I
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_arrayIndexScale(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *arrayClass)
-{
- classinfo *c;
- arraydescriptor *ad;
-
- c = LLNI_classinfo_unwrap(arrayClass);
- ad = c->vftbl->arraydesc;
-
- if (ad == NULL) {
- /* XXX does that exception exist? */
- exceptions_throw_internalerror("java/lang/InvalidClassException");
- return 0;
- }
-
- return ad->componentsize;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: addressSize
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_addressSize(JNIEnv *env, sun_misc_Unsafe *this)
-{
- return SIZEOF_VOID_P;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: pageSize
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_pageSize(JNIEnv *env, sun_misc_Unsafe *this)
-{
- int sz;
-
- sz = getpagesize();
-
- return sz;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: defineClass
- * Signature: (Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2(JNIEnv *env, sun_misc_Unsafe *this, java_lang_String *name, java_handle_bytearray_t *b, int32_t off, int32_t len, java_lang_ClassLoader *loader, java_security_ProtectionDomain *protectionDomain)
-{
- classloader_t *cl;
- utf *utfname;
- classinfo *c;
- java_lang_Class *o;
-
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-
- /* check if data was passed */
-
- if (b == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* check the indexes passed */
-
- if ((off < 0) || (len < 0) || ((off + len) > LLNI_array_size(b))) {
- exceptions_throw_arrayindexoutofboundsexception();
- return NULL;
- }
-
- if (name != NULL) {
- /* convert '.' to '/' in java string */
-
- utfname = javastring_toutf((java_handle_t *) name, true);
- }
- else {
- utfname = NULL;
- }
-
- /* define the class */
-
- c = class_define(utfname, cl, len, (uint8_t *) &(LLNI_array_direct(b, off)),
- (java_handle_t *) protectionDomain);
-
- if (c == NULL)
- return NULL;
-
- /* for convenience */
-
- o = LLNI_classinfo_wrap(c);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* set ProtectionDomain */
-
- LLNI_field_set_ref(o, pd, protectionDomain);
-#endif
-
- return o;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: allocateInstance
- * Signature: (Ljava/lang/Class;)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_allocateInstance(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Class *cls)
-{
- classinfo *c;
- java_handle_t *o;
-
- c = LLNI_classinfo_unwrap(cls);
-
- o = builtin_new(c);
-
- return (java_lang_Object *) o;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: throwException
- * Signature: (Ljava/lang/Throwable;)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_throwException(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Throwable *ee)
-{
- java_handle_t *o;
-
- o = (java_handle_t *) ee;
-
- exceptions_set_exception(o);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: compareAndSwapObject
- * Signature: (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *expected, java_lang_Object *x)
-{
-#if 1
- void **p;
- void *value;
-
- p = (void **) (((uint8_t *) o) + offset);
-
- /* XXX this should be atomic */
-
- value = *p;
-
- if (value == expected) {
- *p = x;
-
- return true;
- }
-
- return false;
-#else
- volatile void **p;
- void *result;
-
- /* XXX Use LLNI */
-
- p = (volatile void **) (((uint8_t *) o) + offset);
-
- result = atomic_compare_and_swap_address(p, expected, x);
-
- if (result == expected)
- return true;
-
- return false;
-#endif
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: compareAndSwapInt
- * Signature: (Ljava/lang/Object;JII)Z
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapInt(JNIEnv *env, sun_misc_Unsafe* this, java_lang_Object* o, int64_t offset, int32_t expected, int32_t x)
-{
-#if 1
- int32_t *p;
- int32_t value;
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- /* XXX this should be atomic */
-
- value = *p;
-
- if (value == expected) {
- *p = x;
-
- return true;
- }
-
- return false;
-#else
- int32_t *p;
- int32_t result;
-
- /* XXX Use LLNI */
-
- p = (int32_t *) (((uint8_t *) o) + offset);
-
- result = atomic_compare_and_swap_int(p, expected, x);
-
- if (result == expected)
- return true;
-
- return false;
-#endif
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: compareAndSwapLong
- * Signature: (Ljava/lang/Object;JJJ)Z
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapLong(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t expected, int64_t x)
-{
- int64_t *p;
- int64_t value;
-
- p = (int64_t *) (((uint8_t *) o) + offset);
-
- /* XXX this should be atomic */
-
- value = *p;
-
- if (value == expected) {
- *p = x;
-
- return true;
- }
-
- return false;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getObjectVolatile
- * Signature: (Ljava/lang/Object;J)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_sun_misc_Unsafe_getObjectVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- volatile void **p;
- volatile void *value;
-
- p = (volatile void **) (((uint8_t *) o) + offset);
-
- value = *p;
-
- return (java_lang_Object *) value;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putObjectVolatile
- * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *x)
-{
- volatile void **p;
-
- p = (volatile void **) (((uint8_t *) o) + offset);
-
- *p = x;
-}
-
-
-#define UNSAFE_GET_VOLATILE(type) \
- java_handle_t *_h; \
- java_object_t *_o; \
- volatile type *_p; \
- volatile type _x; \
- \
- _h = (java_handle_t *) o; \
- \
- LLNI_CRITICAL_START; \
- \
- _o = LLNI_UNWRAP(_h); \
- _p = (volatile type *) (((uint8_t *) _o) + offset); \
- \
- _x = *_p; \
- \
- LLNI_CRITICAL_END; \
- \
- return _x;
-
-
-#define UNSAFE_PUT_VOLATILE(type) \
- java_handle_t *_h; \
- java_object_t *_o; \
- volatile type *_p; \
- \
- _h = (java_handle_t *) o; \
- \
- LLNI_CRITICAL_START; \
- \
- _o = LLNI_UNWRAP(_h); \
- _p = (volatile type *) (((uint8_t *) _o) + offset); \
- \
- *_p = x; \
- \
- MEMORY_BARRIER(); \
- \
- LLNI_CRITICAL_END;
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getIntVolatile
- * Signature: (Ljava/lang/Object;J)I
- */
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- UNSAFE_GET_VOLATILE(int32_t);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putIntVolatile
- * Signature: (Ljava/lang/Object;JI)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putIntVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
-{
- UNSAFE_PUT_VOLATILE(int32_t);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: getLongVolatile
- * Signature: (Ljava/lang/Object;J)J
- */
-JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_getLongVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
-{
- UNSAFE_GET_VOLATILE(int64_t);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putLongVolatile
- * Signature: (Ljava/lang/Object;JJ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLongVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
-{
- UNSAFE_PUT_VOLATILE(int64_t);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putOrderedObject
- * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *x)
-{
- java_handle_t *_h;
- java_handle_t *_hx;
- java_object_t *_o;
- java_object_t *_x;
- volatile void **_p;
-
- _h = (java_handle_t *) o;
- _hx = (java_handle_t *) x;
-
- LLNI_CRITICAL_START;
-
- _o = LLNI_UNWRAP(_h);
- _x = LLNI_UNWRAP(_hx);
- _p = (volatile void **) (((uint8_t *) _o) + offset);
-
- *_p = _x;
-
- MEMORY_BARRIER();
-
- LLNI_CRITICAL_END;
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putOrderedInt
- * Signature: (Ljava/lang/Object;JI)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedInt(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
-{
- UNSAFE_PUT_VOLATILE(int32_t);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: putOrderedLong
- * Signature: (Ljava/lang/Object;JJ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedLong(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
-{
- UNSAFE_PUT_VOLATILE(int64_t);
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: unpark
- * Signature: (Ljava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_unpark(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *thread)
-{
- /* XXX IMPLEMENT ME */
-}
-
-
-/*
- * Class: sun/misc/Unsafe
- * Method: park
- * Signature: (ZJ)V
- */
-JNIEXPORT void JNICALL Java_sun_misc_Unsafe_park(JNIEnv *env, sun_misc_Unsafe *this, int32_t isAbsolute, int64_t time)
-{
- /* XXX IMPLEMENT ME */
-}
-
-
-/*
- * 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/native/vm/sun_misc_Unsafe.cpp - sun/misc/Unsafe
+
+ Copyright (C) 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 <unistd.h>
+
+#include "threads/atomic.hpp"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/include/sun_misc_Unsafe.h"
+#endif
+
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/os.hpp"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: registerNatives
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_registerNatives(JNIEnv *env, jclass clazz)
+{
+ /* The native methods of this function are already registered in
+ _Jv_sun_misc_Unsafe_init() which is called during VM
+ startup. */
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getInt
+ * Signature: (Ljava/lang/Object;J)I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ int32_t *p;
+ int32_t value;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putInt
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
+{
+ int32_t *p;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getObject
+ * Signature: (Ljava/lang/Object;J)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_getObject(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ void **p;
+ void *value;
+
+ p = (void **) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return (jobject) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putObject
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObject(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject x)
+{
+ void **p;
+
+ p = (void **) (((uint8_t *) o) + offset);
+
+ *p = (void *) x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getBoolean
+ * Signature: (Ljava/lang/Object;J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_getBoolean(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ int32_t *p;
+ int32_t value;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putBoolean
+ * Signature: (Ljava/lang/Object;JZ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putBoolean(JNIEnv *env, jobject _this, jobject o, jlong offset, jboolean x)
+{
+ int32_t *p;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getByte
+ * Signature: (Ljava/lang/Object;J)B
+ */
+JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ int32_t *p;
+ int32_t value;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putByte
+ * Signature: (Ljava/lang/Object;JB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB(JNIEnv *env, jobject _this, jobject o, jlong offset, jbyte x)
+{
+ int32_t *p;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getShort
+ * Signature: (Ljava/lang/Object;J)S
+ */
+JNIEXPORT jshort JNICALL Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ int32_t *p;
+ int32_t value;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putShort
+ * Signature: (Ljava/lang/Object;JS)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS(JNIEnv *env, jobject _this, jobject o, jlong offset, jshort x)
+{
+ int32_t *p;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getChar
+ * Signature: (Ljava/lang/Object;J)C
+ */
+JNIEXPORT jchar JNICALL Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ int32_t *p;
+ int32_t value;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putChar
+ * Signature: (Ljava/lang/Object;JC)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC(JNIEnv *env, jobject _this, jobject o, jlong offset, jchar x)
+{
+ int32_t *p;
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getLong
+ * Signature: (Ljava/lang/Object;J)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ int64_t *p;
+ int64_t value;
+
+ p = (int64_t *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putLong
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
+{
+ int64_t *p;
+
+ p = (int64_t *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getFloat
+ * Signature: (Ljava/lang/Object;J)F
+ */
+JNIEXPORT jfloat JNICALL Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ float *p;
+ float value;
+
+ p = (float *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putFloat
+ * Signature: (Ljava/lang/Object;JF)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF(JNIEnv *env, jobject _this, jobject o, jlong offset, jfloat x)
+{
+ float *p;
+
+ p = (float *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getDouble
+ * Signature: (Ljava/lang/Object;J)D
+ */
+JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ double *p;
+ double value;
+
+ p = (double *) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putDouble
+ * Signature: (Ljava/lang/Object;JD)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD(JNIEnv *env, jobject _this, jobject o, jlong offset, jdouble x)
+{
+ double *p;
+
+ p = (double *) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getByte
+ * Signature: (J)B
+ */
+JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByte__J(JNIEnv *env, jobject _this, jlong address)
+{
+ int8_t *p;
+ int8_t value;
+
+ p = (int8_t *) (intptr_t) address;
+
+ value = *p;
+
+ return (int32_t) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putByte
+ * Signature: (JB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putByte__JB(JNIEnv *env, jobject _this, jlong address, jbyte value)
+{
+ int8_t *p;
+
+ p = (int8_t *) (intptr_t) address;
+
+ *p = (int8_t) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getShort
+ * Signature: (J)S
+ */
+JNIEXPORT jshort JNICALL Java_sun_misc_Unsafe_getShort__J(JNIEnv *env, jobject _this, jlong address)
+{
+ int16_t *p;
+ int16_t value;
+
+ p = (int16_t *) (intptr_t) address;
+
+ value = *p;
+
+ return (int32_t) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putShort
+ * Signature: (JS)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putShort__JS(JNIEnv *env, jobject _this, jlong address, jshort value)
+{
+ int16_t *p;
+
+ p = (int16_t *) (intptr_t) address;
+
+ *p = (int16_t) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getChar
+ * Signature: (J)C
+ */
+JNIEXPORT jchar JNICALL Java_sun_misc_Unsafe_getChar__J(JNIEnv *env, jobject _this, jlong address)
+{
+ uint16_t *p;
+ uint16_t value;
+
+ p = (uint16_t *) (intptr_t) address;
+
+ value = *p;
+
+ return (int32_t) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putChar
+ * Signature: (JC)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__JC(JNIEnv *env, jobject _this, jlong address, jchar value)
+{
+ uint16_t *p;
+
+ p = (uint16_t *) (intptr_t) address;
+
+ *p = (uint16_t) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getInt
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getInt__J(JNIEnv *env, jobject _this, jlong address)
+{
+ int32_t *p;
+ int32_t value;
+
+ p = (int32_t *) (intptr_t) address;
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putInt
+ * Signature: (JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putInt__JI(JNIEnv *env, jobject _this, jlong address, jint value)
+{
+ int32_t *p;
+
+ p = (int32_t *) (intptr_t) address;
+
+ *p = value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getLong
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLong__J(JNIEnv *env, jobject _this, jlong address)
+{
+ int64_t *p;
+ int64_t value;
+
+ p = (int64_t *) (intptr_t) address;
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putLong
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLong__JJ(JNIEnv *env, jobject _this, jlong address, jlong value)
+{
+ int64_t *p;
+
+ p = (int64_t *) (intptr_t) address;
+
+ *p = value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getFloat
+ * Signature: (J)F
+ */
+JNIEXPORT jfloat JNICALL Java_sun_misc_Unsafe_getFloat__J(JNIEnv *env, jobject _this, jlong address)
+{
+ float *p;
+ float value;
+
+ p = (float *) (intptr_t) address;
+
+ value = *p;
+
+ return value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putFloat
+ * Signature: (JF)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putFloat__JF(JNIEnv *env, jobject _this, jlong address, jfloat value)
+{
+ float* p;
+
+ p = (float*) (intptr_t) address;
+
+ *p = value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: objectFieldOffset
+ * Signature: (Ljava/lang/reflect/Field;)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_objectFieldOffset(JNIEnv *env, jobject _this, jobject field)
+{
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ java_lang_reflect_Field rf(field);
+ java_lang_reflect_VMField rvmf(rf.get_f());
+ fieldinfo* f = rvmf.get_field();
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ java_lang_reflect_Field rf(field);
+ fieldinfo* f = rf.get_field();
+
+#else
+# error unknown configuration
+#endif
+
+ return (jlong) f->offset;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: allocateMemory
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_allocateMemory(JNIEnv *env, jobject _this, jlong bytes)
+{
+ size_t length;
+ void *p;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+
+ p = MNEW(uint8_t, length);
+
+ return (int64_t) (intptr_t) p;
+}
+
+
+#if 0
+/* OpenJDK 7 */
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: setMemory
+ * Signature: (Ljava/lang/Object;JJB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_setMemory(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong bytes, jbyte value)
+{
+ size_t length;
+ void *p;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ /* XXX Missing LLNI: we need to unwrap _this object. */
+
+ p = (void *) (((uint8_t *) o) + offset);
+
+ /* XXX Not sure this is correct. */
+
+ os::memset(p, value, length);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: copyMemory
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, jobject _this, jobject srcBase, jlong srcOffset, jobject destBase, jlong destOffset, jlong bytes)
+{
+ size_t length;
+ void *src;
+ void *dest;
+
+ if (bytes == 0)
+ return;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ /* XXX Missing LLNI: We need to unwrap these objects. */
+
+ src = (void *) (((uint8_t *) srcBase) + srcOffset);
+ dest = (void *) (((uint8_t *) destBase) + destOffset);
+
+ os::memcpy(dest, src, length);
+}
+#else
+/*
+ * Class: sun/misc/Unsafe
+ * Method: setMemory
+ * Signature: (JJB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_setMemory(JNIEnv *env, jobject _this, jlong address, jlong bytes, jbyte value)
+{
+ size_t length;
+ void *p;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ p = (void *) (intptr_t) address;
+
+ /* XXX Not sure this is correct. */
+
+ os::memset(p, value, length);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: copyMemory
+ * Signature: (JJJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, jobject _this, jlong srcAddress, jlong destAddress, jlong bytes)
+{
+ size_t length;
+ void *src;
+ void *dest;
+
+ if (bytes == 0)
+ return;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ src = (void *) (intptr_t) srcAddress;
+ dest = (void *) (intptr_t) destAddress;
+
+ os::memcpy(dest, src, length);
+}
+#endif
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: freeMemory
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_freeMemory(JNIEnv *env, jobject _this, jlong address)
+{
+ void *p;
+
+ p = (void *) (intptr_t) address;
+
+ if (p == NULL)
+ return;
+
+ /* we pass length 1 to trick the free function */
+
+ MFREE(p, uint8_t, 1);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: staticFieldOffset
+ * Signature: (Ljava/lang/reflect/Field;)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_staticFieldOffset(JNIEnv *env, jobject _this, jobject f)
+{
+ /* The offset of static fields is 0. */
+
+ return 0;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: staticFieldBase
+ * Signature: (Ljava/lang/reflect/Field;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_staticFieldBase(JNIEnv *env, jobject _this, jobject field)
+{
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ java_lang_reflect_Field rf(field);
+ java_lang_reflect_VMField rvmf(rf.get_f());
+ fieldinfo* f = rvmf.get_field();
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ java_lang_reflect_Field rf(field);
+ fieldinfo* f = rf.get_field();
+
+#else
+# error unknown configuration
+#endif
+
+ return (jobject) (f->value);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: ensureClassInitialized
+ * Signature: (Ljava/lang/Class;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_ensureClassInitialized(JNIEnv *env, jobject _this, jclass clazz)
+{
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(clazz);
+
+ if (!(c->state & CLASS_INITIALIZED))
+ initialize_class(c);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: arrayBaseOffset
+ * Signature: (Ljava/lang/Class;)I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_arrayBaseOffset(JNIEnv *env, jobject _this, jclass arrayClass)
+{
+ classinfo *c;
+ arraydescriptor *ad;
+
+ c = LLNI_classinfo_unwrap(arrayClass);
+ ad = c->vftbl->arraydesc;
+
+ if (ad == NULL) {
+ /* XXX does that exception exist? */
+ exceptions_throw_internalerror("java/lang/InvalidClassException");
+ return 0;
+ }
+
+ return ad->dataoffset;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: arrayIndexScale
+ * Signature: (Ljava/lang/Class;)I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_arrayIndexScale(JNIEnv *env, jobject _this, jclass arrayClass)
+{
+ classinfo *c;
+ arraydescriptor *ad;
+
+ c = LLNI_classinfo_unwrap(arrayClass);
+ ad = c->vftbl->arraydesc;
+
+ if (ad == NULL) {
+ /* XXX does that exception exist? */
+ exceptions_throw_internalerror("java/lang/InvalidClassException");
+ return 0;
+ }
+
+ return ad->componentsize;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: addressSize
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_addressSize(JNIEnv *env, jobject _this)
+{
+ return SIZEOF_VOID_P;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: pageSize
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_pageSize(JNIEnv *env, jobject _this)
+{
+ int sz;
+
+ sz = getpagesize();
+
+ return sz;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: defineClass
+ * Signature: (Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;
+ */
+JNIEXPORT jclass JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2(JNIEnv *env, jobject _this, jstring name, jbyteArray b, jint off, jint len, jobject loader, jobject protectionDomain)
+{
+ classloader_t *cl;
+ utf *utfname;
+ classinfo *c;
+
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ /* check if data was passed */
+
+ if (b == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* check the indexes passed */
+
+ if ((off < 0) || (len < 0) || ((off + len) > LLNI_array_size(b))) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return NULL;
+ }
+
+ if (name != NULL) {
+ /* convert '.' to '/' in java string */
+
+ utfname = javastring_toutf((java_handle_t *) name, true);
+ }
+ else {
+ utfname = NULL;
+ }
+
+ /* define the class */
+
+ c = class_define(utfname, cl, len, (uint8_t *) &(LLNI_array_direct((java_handle_bytearray_t*) b, off)),
+ (java_handle_t *) protectionDomain);
+
+ if (c == NULL)
+ return NULL;
+
+ java_handle_t* h = LLNI_classinfo_wrap(c);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ // Set ProtectionDomain.
+ java_lang_Class jlc(h);
+ jlc.set_pd(protectionDomain);
+#endif
+
+ return (jclass) h;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: allocateInstance
+ * Signature: (Ljava/lang/Class;)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_allocateInstance(JNIEnv *env, jobject _this, jclass cls)
+{
+ classinfo *c;
+ java_handle_t *o;
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ o = builtin_new(c);
+
+ return (jobject ) o;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: throwException
+ * Signature: (Ljava/lang/Throwable;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_throwException(JNIEnv *env, jobject _this, jobject ee)
+{
+ java_handle_t *o;
+
+ o = (java_handle_t *) ee;
+
+ exceptions_set_exception(o);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: compareAndSwapObject
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_compareAndSwapObject(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject expected, jobject x)
+{
+ volatile void **p;
+ void *result;
+
+ /* XXX Use LLNI */
+
+ p = (volatile void **) (((uint8_t *) o) + offset);
+
+ result = Atomic::compare_and_swap(p, expected, x);
+
+ if (result == expected)
+ return true;
+
+ return false;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: compareAndSwapInt
+ * Signature: (Ljava/lang/Object;JII)Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_compareAndSwapInt(JNIEnv *env, jobject _this, jobject o, jlong offset, jint expected, jint x)
+{
+ uint32_t *p;
+ uint32_t result;
+
+ /* XXX Use LLNI */
+
+ p = (uint32_t *) (((uint8_t *) o) + offset);
+
+ result = Atomic::compare_and_swap(p, expected, x);
+
+ if (result == (uint32_t) expected)
+ return true;
+
+ return false;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: compareAndSwapLong
+ * Signature: (Ljava/lang/Object;JJJ)Z
+ */
+JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_compareAndSwapLong(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong expected, jlong x)
+{
+ uint64_t *p;
+ uint64_t result;
+
+ /* XXX Use LLNI */
+
+ p = (uint64_t *) (((uint8_t *) o) + offset);
+
+ result = Atomic::compare_and_swap(p, expected, x);
+
+ if (result == (uint64_t) expected)
+ return true;
+
+ return false;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getObjectVolatile
+ * Signature: (Ljava/lang/Object;J)Ljava/lang/Object;
+ */
+JNIEXPORT jobject JNICALL Java_sun_misc_Unsafe_getObjectVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ volatile void **p;
+ volatile void *value;
+
+ p = (volatile void **) (((uint8_t *) o) + offset);
+
+ value = *p;
+
+ return (jobject ) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putObjectVolatile
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject x)
+{
+ volatile void **p;
+
+ p = (volatile void **) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+#define UNSAFE_GET_VOLATILE(type) \
+ java_handle_t *_h; \
+ java_object_t *_o; \
+ volatile type *_p; \
+ volatile type _x; \
+ \
+ _h = (java_handle_t *) o; \
+ \
+ LLNI_CRITICAL_START; \
+ \
+ _o = LLNI_UNWRAP(_h); \
+ _p = (volatile type *) (((uint8_t *) _o) + offset); \
+ \
+ _x = *_p; \
+ \
+ LLNI_CRITICAL_END; \
+ \
+ return _x;
+
+
+#define UNSAFE_PUT_VOLATILE(type) \
+ java_handle_t *_h; \
+ java_object_t *_o; \
+ volatile type *_p; \
+ \
+ _h = (java_handle_t *) o; \
+ \
+ LLNI_CRITICAL_START; \
+ \
+ _o = LLNI_UNWRAP(_h); \
+ _p = (volatile type *) (((uint8_t *) _o) + offset); \
+ \
+ *_p = x; \
+ \
+ Atomic::memory_barrier(); \
+ \
+ LLNI_CRITICAL_END;
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getIntVolatile
+ * Signature: (Ljava/lang/Object;J)I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ UNSAFE_GET_VOLATILE(int32_t);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putIntVolatile
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putIntVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
+{
+ UNSAFE_PUT_VOLATILE(int32_t);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getLongVolatile
+ * Signature: (Ljava/lang/Object;J)J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLongVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
+{
+ UNSAFE_GET_VOLATILE(int64_t);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putLongVolatile
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLongVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
+{
+ UNSAFE_PUT_VOLATILE(int64_t);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getDoubleVolatile
+ * Signature: (Ljava/lang/Object;J)D
+ */
+JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDoubleVolatile(JNIEnv *env, jobject __this, jobject o, jlong offset)
+{
+ UNSAFE_GET_VOLATILE(double);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putOrderedObject
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedObject(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject x)
+{
+ java_handle_t *_h;
+ java_handle_t *_hx;
+ java_object_t *_o;
+ java_object_t *_x;
+ volatile void **_p;
+
+ _h = (java_handle_t *) o;
+ _hx = (java_handle_t *) x;
+
+ LLNI_CRITICAL_START;
+
+ _o = LLNI_UNWRAP(_h);
+ _x = LLNI_UNWRAP(_hx);
+ _p = (volatile void **) (((uint8_t *) _o) + offset);
+
+ *_p = _x;
+
+ Atomic::memory_barrier();
+
+ LLNI_CRITICAL_END;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putOrderedInt
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedInt(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
+{
+ UNSAFE_PUT_VOLATILE(int32_t);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putOrderedLong
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedLong(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
+{
+ UNSAFE_PUT_VOLATILE(int64_t);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: unpark
+ * Signature: (Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_unpark(JNIEnv *env, jobject _this, jobject thread)
+{
+ /* XXX IMPLEMENT ME */
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: park
+ * Signature: (ZJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_park(JNIEnv *env, jobject _this, jboolean isAbsolute, jlong time)
+{
+ /* XXX IMPLEMENT ME */
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "registerNatives", (char*) "()V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_registerNatives },
+ { (char*) "getInt", (char*) "(Ljava/lang/Object;J)I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getInt__Ljava_lang_Object_2J },
+ { (char*) "putInt", (char*) "(Ljava/lang/Object;JI)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putInt__Ljava_lang_Object_2JI },
+ { (char*) "getObject", (char*) "(Ljava/lang/Object;J)Ljava/lang/Object;", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getObject },
+ { (char*) "putObject", (char*) "(Ljava/lang/Object;JLjava/lang/Object;)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putObject },
+ { (char*) "getBoolean", (char*) "(Ljava/lang/Object;J)Z", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getBoolean },
+ { (char*) "putBoolean", (char*) "(Ljava/lang/Object;JZ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putBoolean },
+ { (char*) "getByte", (char*) "(Ljava/lang/Object;J)B", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getByte__Ljava_lang_Object_2J },
+ { (char*) "putByte", (char*) "(Ljava/lang/Object;JB)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putByte__Ljava_lang_Object_2JB },
+ { (char*) "getShort", (char*) "(Ljava/lang/Object;J)S", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getShort__Ljava_lang_Object_2J },
+ { (char*) "putShort", (char*) "(Ljava/lang/Object;JS)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putShort__Ljava_lang_Object_2JS },
+ { (char*) "getChar", (char*) "(Ljava/lang/Object;J)C", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getChar__Ljava_lang_Object_2J },
+ { (char*) "putChar", (char*) "(Ljava/lang/Object;JC)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putChar__Ljava_lang_Object_2JC },
+ { (char*) "getLong", (char*) "(Ljava/lang/Object;J)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getLong__Ljava_lang_Object_2J },
+ { (char*) "putLong", (char*) "(Ljava/lang/Object;JJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putLong__Ljava_lang_Object_2JJ },
+ { (char*) "getFloat", (char*) "(Ljava/lang/Object;J)F", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getFloat__Ljava_lang_Object_2J },
+ { (char*) "putFloat", (char*) "(Ljava/lang/Object;JF)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putFloat__Ljava_lang_Object_2JF },
+ { (char*) "getDouble", (char*) "(Ljava/lang/Object;J)D", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getDouble__Ljava_lang_Object_2J },
+ { (char*) "putDouble", (char*) "(Ljava/lang/Object;JD)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putDouble__Ljava_lang_Object_2JD },
+ { (char*) "getByte", (char*) "(J)B", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getByte__J },
+ { (char*) "putByte", (char*) "(JB)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putByte__JB },
+ { (char*) "getShort", (char*) "(J)S", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getShort__J },
+ { (char*) "putShort", (char*) "(JS)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putShort__JS },
+ { (char*) "getChar", (char*) "(J)C", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getChar__J },
+ { (char*) "putChar", (char*) "(JC)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putChar__JC },
+ { (char*) "getInt", (char*) "(J)I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getInt__J },
+ { (char*) "putInt", (char*) "(JI)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putInt__JI },
+ { (char*) "getLong", (char*) "(J)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getLong__J },
+ { (char*) "putLong", (char*) "(JJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putLong__JJ },
+ { (char*) "getFloat", (char*) "(J)F", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getFloat__J },
+ { (char*) "putFloat", (char*) "(JF)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putFloat__JF },
+ { (char*) "objectFieldOffset", (char*) "(Ljava/lang/reflect/Field;)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_objectFieldOffset },
+ { (char*) "allocateMemory", (char*) "(J)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_allocateMemory },
+#if 0
+ // OpenJDK 7
+ { (char*) "setMemory", (char*) "(Ljava/lang/Object;JJB)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_setMemory },
+ { (char*) "copyMemory", (char*) "(Ljava/lang/Object;JLjava/lang/Object;JJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_copyMemory },
+#else
+ { (char*) "setMemory", (char*) "(JJB)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_setMemory },
+ { (char*) "copyMemory", (char*) "(JJJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_copyMemory },
+#endif
+ { (char*) "freeMemory", (char*) "(J)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_freeMemory },
+ { (char*) "staticFieldOffset", (char*) "(Ljava/lang/reflect/Field;)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_staticFieldOffset },
+ { (char*) "staticFieldBase", (char*) "(Ljava/lang/reflect/Field;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_sun_misc_Unsafe_staticFieldBase },
+ { (char*) "ensureClassInitialized", (char*) "(Ljava/lang/Class;)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_ensureClassInitialized },
+ { (char*) "arrayBaseOffset", (char*) "(Ljava/lang/Class;)I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_arrayBaseOffset },
+ { (char*) "arrayIndexScale", (char*) "(Ljava/lang/Class;)I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_arrayIndexScale },
+ { (char*) "addressSize", (char*) "()I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_addressSize },
+ { (char*) "pageSize", (char*) "()I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_pageSize },
+ { (char*) "defineClass", (char*) "(Ljava/lang/String;[BIILjava/lang/ClassLoader;Ljava/security/ProtectionDomain;)Ljava/lang/Class;", (void*) (uintptr_t) &Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2 },
+ { (char*) "allocateInstance", (char*) "(Ljava/lang/Class;)Ljava/lang/Object;", (void*) (uintptr_t) &Java_sun_misc_Unsafe_allocateInstance },
+ { (char*) "throwException", (char*) "(Ljava/lang/Throwable;)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_throwException },
+ { (char*) "compareAndSwapObject", (char*) "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", (void*) (uintptr_t) &Java_sun_misc_Unsafe_compareAndSwapObject },
+ { (char*) "compareAndSwapInt", (char*) "(Ljava/lang/Object;JII)Z", (void*) (uintptr_t) &Java_sun_misc_Unsafe_compareAndSwapInt },
+ { (char*) "compareAndSwapLong", (char*) "(Ljava/lang/Object;JJJ)Z", (void*) (uintptr_t) &Java_sun_misc_Unsafe_compareAndSwapLong },
+ { (char*) "getObjectVolatile", (char*) "(Ljava/lang/Object;J)Ljava/lang/Object;", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getObjectVolatile },
+ { (char*) "putObjectVolatile", (char*) "(Ljava/lang/Object;JLjava/lang/Object;)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putObjectVolatile },
+ { (char*) "getIntVolatile", (char*) "(Ljava/lang/Object;J)I", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getIntVolatile },
+ { (char*) "putIntVolatile", (char*) "(Ljava/lang/Object;JI)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putIntVolatile },
+ { (char*) "getLongVolatile", (char*) "(Ljava/lang/Object;J)J", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getLongVolatile },
+ { (char*) "putLongVolatile", (char*) "(Ljava/lang/Object;JJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putLongVolatile },
+ { (char*) "getDoubleVolatile", (char*) "(Ljava/lang/Object;J)D", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getDoubleVolatile },
+ { (char*) "putOrderedObject", (char*) "(Ljava/lang/Object;JLjava/lang/Object;)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putOrderedObject },
+ { (char*) "putOrderedInt", (char*) "(Ljava/lang/Object;JI)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putOrderedInt },
+ { (char*) "putOrderedLong", (char*) "(Ljava/lang/Object;JJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_putOrderedLong },
+ { (char*) "unpark", (char*) "(Ljava/lang/Object;)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_unpark },
+ { (char*) "park", (char*) "(ZJ)V", (void*) (uintptr_t) &Java_sun_misc_Unsafe_park },
+};
+
+
+/* _Jv_sun_misc_Unsafe_init ****************************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+// FIXME
+extern "C" {
+void _Jv_sun_misc_Unsafe_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("sun/misc/Unsafe");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+}
+
+/*
+ * 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:
+ */
if ENABLE_THREADS
libthreads_la_SOURCES = \
- critical.c \
- critical.h \
+ atomic.cpp \
+ atomic.hpp \
+ condition.hpp \
lock-common.h \
- mutex.h \
+ removeme.cpp \
+ mutex.hpp \
threadlist.c \
threadlist.h \
- thread.c \
- thread.h
+ thread.cpp \
+ thread.hpp
else
libthreads_la_SOURCES =
endif
--- /dev/null
+/* src/threads/atomic.cpp - atomic instructions
+
+ Copyright (C) 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 "threads/atomic.hpp"
+#include "threads/mutex.hpp"
+
+// Gobal mutex for generic atomic instructions.
+static Mutex lock;
+
+
+/**
+ * A generic atomic compare and swap for 32-bit integer values. This
+ * function is using a mutex to provide atomicity.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+uint32_t Atomic::generic_compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t result;
+
+ lock.lock();
+
+ // Do the compare-and-swap.
+
+ result = *p;
+
+ if (oldval == result)
+ *p = newval;
+
+ lock.unlock();
+
+ return result;
+}
+
+
+/**
+ * A generic atomic compare and swap for 64-bit integer values. This
+ * function is using a mutex to provide atomicity.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+uint64_t Atomic::generic_compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ uint64_t result;
+
+ lock.lock();
+
+ // Do the compare-and-swap.
+
+ result = *p;
+
+ if (oldval == result)
+ *p = newval;
+
+ lock.unlock();
+
+ return result;
+}
+
+
+/**
+ * A generic atomic compare and swap for pointer values. This
+ * function is using a mutex to provide atomicity.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+void* Atomic::generic_compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ void* result;
+
+ lock.lock();
+
+ // Do the compare-and-swap.
+
+ result = (void*) *p;
+
+ if (oldval == result)
+ *p = newval;
+
+ lock.lock();
+
+ return result;
+}
+
+
+/**
+ * A generic memory barrier. This function is using a mutex to
+ * provide atomicity.
+ */
+void Atomic::generic_memory_barrier(void)
+{
+ lock.lock();
+ lock.unlock();
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+uint32_t Atomic_compare_and_swap_32(volatile uint32_t *p, uint32_t oldval, uint32_t newval) { return Atomic::compare_and_swap(p, oldval, newval); }
+uint64_t Atomic_compare_and_swap_64(volatile uint64_t *p, uint64_t oldval, uint64_t newval) { return Atomic::compare_and_swap(p, oldval, newval); }
+void* Atomic_compare_and_swap_ptr(volatile void** p, void* oldval, void* newval) { return Atomic::compare_and_swap(p, oldval, newval); }
+void Atomic_memory_barrier(void) { Atomic::memory_barrier(); }
+void Atomic_write_memory_barrier(void) { Atomic::write_memory_barrier(); }
+void Atomic_instruction_barrier(void) { Atomic::instruction_barrier(); }
+}
+
+
+/*
+ * 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/threads/atomic.hpp - atomic instructions
+
+ Copyright (C) 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 _ATOMIC_HPP
+#define _ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+
+class Atomic {
+public:
+ // Generic functions.
+ static uint32_t generic_compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
+ static uint64_t generic_compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
+ static void* generic_compare_and_swap(volatile void** p, void* oldval, void* newval);
+ static void generic_memory_barrier(void);
+
+ // Machine dependent functions.
+ static uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
+ static uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
+ static void* compare_and_swap(volatile void** p, void* oldval, void* newval);
+ static void memory_barrier(void);
+ static void write_memory_barrier(void);
+ static void instruction_barrier(void);
+};
+
+// Include machine dependent implementation.
+#include "md-atomic.hpp"
+
+#else
+
+// Legacy C interface.
+
+uint32_t Atomic_compare_and_swap_32(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
+uint64_t Atomic_compare_and_swap_64(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
+void* Atomic_compare_and_swap_ptr(volatile void** p, void* oldval, void* newval);
+void Atomic_memory_barrier(void);
+void Atomic_write_memory_barrier(void);
+void Atomic_instruction_barrier(void);
+
+#endif
+
+#endif // _ATOMIC_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
+/* src/threads/condition.hpp - condition variable
+
+ Copyright (C) 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 _CONDITION_HPP
+#define _CONDITION_HPP
+
+#include "config.h"
+
+#include "threads/mutex.hpp"
+
+#if defined(ENABLE_THREADS)
+# include "threads/posix/condition-posix.hpp"
+#endif
+
+#endif /* _CONDITION_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
-/* src/threads/critical.c - restartable critical sections
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 <stddef.h>
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "threads/critical.h"
-
-#include "toolbox/avl.h"
-
-
-/* the AVL tree containing the critical sections */
-
-static avl_tree_t *criticaltree;
-
-
-/* prototypes *****************************************************************/
-
-static int critical_comparator(const void *treenode, const void *node);
-
-
-/* critical_init ***************************************************************
-
- Init global data structures.
-
-*******************************************************************************/
-
-void critical_init(void)
-{
- criticaltree = avl_create(&critical_comparator);
-}
-
-
-/* critical_comparator *********************************************************
-
- Comparison function for AVL tree of critical section.
-
- IN:
- treenode....node in the tree
- node........node to compare with tree-node
-
- RETURN VALUE:
- -1, 0, +1 for (pa <, ==, > pb)
-
-*******************************************************************************/
-
-static int critical_comparator(const void *treenode, const void *node)
-{
- const critical_section_node_t *treecsn;
- const critical_section_node_t *csn;
-
- treecsn = treenode;
- csn = node;
-
-#ifdef __S390__
-# define ADDR_MASK(x) ((u1 *)((s4)(x) & 0x7FFFFFFF))
-#else
-# define ADDR_MASK(x) (x)
-#endif
-
- /* compare for avl_find if we have found an entry */
-
- if (
- (ADDR_MASK(treecsn->start) <= ADDR_MASK(csn->start)) &&
- (ADDR_MASK(csn->start) < ADDR_MASK(treecsn->end))
- )
- return 0;
-
- /* these are for walking the tree */
-
- if (ADDR_MASK(treecsn->start) < ADDR_MASK(csn->start))
- return -1;
- else
- return 1;
-
-#undef ADDR_MASK
-}
-
-
-/* critical_section_register ***************************************************
-
- Register a critical section.
-
- IN:
- csn....node for the critical section
-
-*******************************************************************************/
-
-void critical_section_register(critical_section_node_t *csn)
-{
- (void) avl_insert(criticaltree, csn);
-}
-
-
-/* critical_find_restart_point *************************************************
-
- Find a restart point for the given PC, in case it is in a critical
- section.
-
- IN:
- pc.........PC
-
- OUT:
- PC of the restart point, or
- NULL if the given mcodeptr is not in a critical section
-
-*******************************************************************************/
-
-u1 *critical_find_restart_point(u1 *pc)
-{
- critical_section_node_t csnpc;
- const critical_section_node_t *csn;
-
- /* fill the temporary node for comparison */
-
- csnpc.start = pc;
-
- /* see if there's an entry for that PC */
-
- csn = avl_find(criticaltree, &csnpc);
-
- if (csn == NULL)
- return NULL;
-
- return csn->restart;
-}
-
-
-/*
- * 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/threads/native/critical.h - restartable critical sections
-
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- 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.
-
- Contact: cacao@cacaojvm.org
-
- Authors: Stefan Ring
- Edwin Steiner
-
- Changes: Christian Thalinger
-
-*/
-
-
-#ifndef _CRITICAL_H
-#define _CRITICAL_H
-
-#include "config.h"
-
-#include <signal.h> /* required on some older Darwin systems for ucontext.h */
-#include <ucontext.h>
-
-
-/* forward typedefs ***********************************************************/
-
-typedef struct critical_section_node_t critical_section_node_t;
-
-
-/* critical_section_node_t *****************************************************
-
- A node representing a restartable critical section.
-
-*******************************************************************************/
-
-struct critical_section_node_t {
- u1 *start;
- u1 *end;
- u1 *restart;
-};
-
-
-/* functions ******************************************************************/
-
-void critical_init(void);
-void critical_section_register(critical_section_node_t *);
-u1 *critical_find_restart_point(u1*);
-
-/* this is a machine dependent function (see src/vm/jit/$(ARCH_DIR)/md.c) */
-void md_critical_section_restart(ucontext_t *_uc);
-
-#endif /* _CRITICAL_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:
- */
#define _LOCK_COMMON_H
#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/types.h"
#include "vm/global.h"
#endif /* ENABLE_THREADS */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _LOCK_COMMON_H */
+++ /dev/null
-/* src/threads/mutex.h - machine independent mutual exclusion functions
-
- Copyright (C) 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 _MUTEX_H
-#define _MUTEX_H
-
-#include "config.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/posix/mutex-posix.h"
-#endif
-
-
-#endif /* _MUTEX_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:
- */
--- /dev/null
+/* src/threads/mutex.hpp - machine independent mutual exclusion functions
+
+ Copyright (C) 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 _MUTEX_HPP
+#define _MUTEX_HPP
+
+#include "config.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/posix/mutex-posix.hpp"
+#endif
+
+#endif /* _MUTEX_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:
+ */
#include <stdint.h>
-#include "threads/thread.h"
+#include "threads/thread.hpp"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
/* global variables ***********************************************************/
#include "vm/builtin.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
/* define some stuff we need to no-ops ****************************************/
libthreadsposix.la
libthreadsposix_la_SOURCES = \
+ condition-posix.hpp \
lock.c \
lock.h \
- mutex-posix.h \
- thread-posix.c \
- thread-posix.h
+ mutex-posix.hpp \
+ thread-posix.cpp \
+ thread-posix.hpp
## Local variables:
--- /dev/null
+/* src/threads/posix/condition-posix.hpp - POSIX condition variable
+
+ Copyright (C) 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 _CONDITION_POSIX_HPP
+#define _CONDITION_POSIX_HPP
+
+#include "config.h"
+
+#include <pthread.h>
+#include <time.h>
+
+#include "vm/vm.hpp"
+
+#ifdef __cplusplus
+
+/**
+ * POSIX condition variable.
+ */
+class Condition {
+private:
+ // POSIX condition structure.
+ pthread_cond_t _cond;
+
+public:
+ Condition();
+ ~Condition();
+
+ void broadcast();
+ void signal();
+ void timedwait(Mutex* mutex, const struct timespec* abstime);
+ void wait(Mutex* mutex);
+};
+
+
+/**
+ * Initialize a POSIX condition variable.
+ */
+inline Condition::Condition()
+{
+ int result;
+
+ result = pthread_cond_init(&_cond, NULL);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Condition::Condition(): pthread_cond_init failed");
+}
+
+
+/**
+ * Destroys a POSIX condition variable.
+ */
+inline Condition::~Condition()
+{
+ int result;
+
+ result = pthread_cond_destroy(&_cond);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Condition::~Condition(): pthread_cond_destroy failed");
+}
+
+
+/**
+ * Restarts all the threads that are waiting on the condition
+ * variable.
+ */
+inline void Condition::broadcast()
+{
+ int result;
+
+ result = pthread_cond_broadcast(&_cond);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Condition::broadcast(): pthread_cond_broadcast failed");
+}
+
+
+/**
+ * Restarts one of the threads that are waiting on this condition
+ * variable.
+ */
+inline void Condition::signal()
+{
+ int result;
+
+ result = pthread_cond_signal(&_cond);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Condition::signal(): pthread_cond_signal failed");
+}
+
+
+/**
+ * Waits on the condition variable, as wait() does, but it also bounds
+ * the duration of the wait.
+ */
+inline void Condition::timedwait(Mutex* mutex, const struct timespec* abstime)
+{
+ // This function can return return values which are valid.
+ (void) pthread_cond_timedwait(&_cond, &(mutex->_mutex), abstime);
+}
+
+
+/**
+ * Waits for the condition variable.
+ */
+inline void Condition::wait(Mutex* mutex)
+{
+ int result;
+
+ result = pthread_cond_wait(&_cond, &(mutex->_mutex));
+
+ if (result != 0)
+ vm_abort_errnum(result, "Condition::wait(): pthread_cond_wait failed");
+}
+
+#else
+
+// This structure must have the same layout as the class above.
+typedef struct Condition {
+ pthread_mutex_t _mutex;
+ pthread_cond_t _cond;
+} Condition;
+
+Condition* Condition_new();
+void Condition_delete(Condition* cond);
+void Condition_lock(Condition* cond);
+void Condition_unlock(Condition* cond);
+void Condition_broadcast(Condition* cond);
+void Condition_signal(Condition* cond);
+void Condition_timedwait(Condition* cond, Mutex *mutex, const struct timespec* abstime);
+void Condition_wait(Condition* cond, Mutex* mutex);
+
+#endif
+
+#endif /* _CONDITION_POSIX_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
-/* src/threads/native/generic-primitives.h - machine independent atomic
- operations
-
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- 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.
-
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
- Anton Ertl
-
- Changes:
-
-
-*/
-
-
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-#include <pthread.h>
-
-#include "threads/mutex.h"
-
-
-extern mutex_t _cas_lock;
-extern mutex_t _mb_lock;
-
-
-static inline long compare_and_swap(volatile long *p, long oldval, long newval)
-{
- long ret;
-
- mutex_lock(&_cas_lock);
-
- /* do the compare-and-swap */
-
- ret = *p;
-
- if (oldval == ret)
- *p = newval;
-
- mutex_unlock(&_cas_lock);
-
- return ret;
-}
-
-
-#define MEMORY_BARRIER() (mutex_lock(&_mb_lock), \
- mutex_unlock(&_mb_lock))
-#define STORE_ORDER_BARRIER() MEMORY_BARRIER()
-#define MEMORY_BARRIER_AFTER_ATOMIC() /* nothing */
-
-#endif /* _MACHINE_INSTR_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:
- */
#include "native/llni.h"
#include "threads/lock-common.h"
-#include "threads/mutex.h"
+#include "threads/mutex.hpp"
#include "threads/threadlist.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "threads/posix/lock.h"
#include "toolbox/list.h"
-#include "vm/global.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/finalizer.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/options.h"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
#if defined(ENABLE_VMLOG)
#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
#include "threads/posix/generic-primitives.h"
#else
-#include "machine-instr.h"
+#include "threads/atomic.hpp"
#endif
#if defined(ENABLE_JVMTI)
#define LOCK_INITIAL_HASHTABLE_SIZE 1613 /* a prime in the middle between 1024 and 2048 */
-#define COMPARE_AND_SWAP_OLD_VALUE(address, oldvalue, newvalue) \
- ((ptrint) compare_and_swap((long *)(address), (long)(oldvalue), (long)(newvalue)))
-
/******************************************************************************/
/* MACROS FOR THIN/FAT LOCKS */
/* initialize the mutex */
- mutex_init(&(lr->mutex));
+ lr->mutex = Mutex_new();
DEBUGLOCKS(("[lock_record_new : lr=%p]", (void *) lr));
/* Destroy the mutex. */
- mutex_destroy(&(lr->mutex));
+ Mutex_delete(lr->mutex);
#if defined(ENABLE_GC_CACAO)
/* unregister the lock object reference with the GC */
static void lock_hashtable_init(void)
{
- mutex_init(&(lock_hashtable.mutex));
+ lock_hashtable.mutex = Mutex_new();
lock_hashtable.size = LOCK_INITIAL_HASHTABLE_SIZE;
lock_hashtable.entries = 0;
/* lock the hashtable */
- mutex_lock(&(lock_hashtable.mutex));
+ Mutex_lock(lock_hashtable.mutex);
/* search the hashtable for cleared references */
/* unlock the hashtable */
- mutex_unlock(&(lock_hashtable.mutex));
+ Mutex_unlock(lock_hashtable.mutex);
}
#endif
/* lock the hashtable */
- mutex_lock(&(lock_hashtable.mutex));
+ Mutex_lock(lock_hashtable.mutex);
/* lookup the lock record in the hashtable */
/* unlock the hashtable */
- mutex_unlock(&(lock_hashtable.mutex));
+ Mutex_unlock(lock_hashtable.mutex);
/* return the new lock record */
/* lock the hashtable */
- mutex_lock(&(lock_hashtable.mutex));
+ Mutex_lock(lock_hashtable.mutex);
/* get lock record */
/* unlock the hashtable */
- mutex_unlock(&(lock_hashtable.mutex));
+ Mutex_unlock(lock_hashtable.mutex);
/* free the lock record */
static inline void lock_record_enter(threadobject *t, lock_record_t *lr)
{
- mutex_lock(&(lr->mutex));
+ Mutex_lock(lr->mutex);
lr->owner = t;
}
static inline void lock_record_exit(threadobject *t, lock_record_t *lr)
{
lr->owner = NULL;
- mutex_unlock(&(lr->mutex));
+ Mutex_unlock(lr->mutex);
}
/* failure, TODO: add statistics */
return;
- mutex_lock(&t_other->flc_lock);
+ Mutex_lock(t_other->flc_lock);
old_flc = t_other->flc_bit;
t_other->flc_bit = true;
t->index, t_other->index));
/* Set FLC bit first, then read the lockword again */
- MEMORY_BARRIER();
+ Atomic_memory_barrier();
lockword = lock_lockword_get(t, o);
/* Wait until another thread sees the flc bit and notifies
us of unlocking. */
- pthread_cond_wait(&t->flc_cond, &t_other->flc_lock);
+ Condition_wait(t->flc_cond, t_other->flc_lock);
/* Traverse FLC list looking if we're still there */
current = t_other->flc_list;
else
t_other->flc_bit = old_flc;
- mutex_unlock(&t_other->flc_lock);
+ Mutex_unlock(t_other->flc_lock);
}
static void notify_flc_waiters(threadobject *t, java_handle_t *o)
{
threadobject *current;
- mutex_lock(&t->flc_lock);
+ Mutex_lock(t->flc_lock);
current = t->flc_list;
while (current)
}
}
/* Wake the waiting thread */
- pthread_cond_broadcast(¤t->flc_cond);
+ Condition_broadcast(current->flc_cond);
current = current->flc_next;
}
t->flc_list = NULL;
t->flc_bit = false;
- mutex_unlock(&t->flc_lock);
+ Mutex_unlock(t->flc_lock);
}
/* lock_monitor_enter **********************************************************
/* most common case: try to thin-lock an unlocked object */
LLNI_CRITICAL_START_THREAD(t);
- lockword = COMPARE_AND_SWAP_OLD_VALUE(&(LLNI_DIRECT(o)->lockword), THIN_UNLOCKED, thinlock);
+ lockword = Atomic_compare_and_swap_ptr(&(LLNI_DIRECT(o)->lockword), THIN_UNLOCKED, thinlock);
LLNI_CRITICAL_END_THREAD(t);
if (lockword == THIN_UNLOCKED) {
/* success. we locked it */
/* The Java Memory Model requires a memory barrier here: */
/* Because of the CAS above, this barrier is a nop on x86 / x86_64 */
- MEMORY_BARRIER_AFTER_ATOMIC();
+ Atomic_instruction_barrier();
return true;
}
if (lockword == thinlock) {
/* memory barrier for Java Memory Model */
- STORE_ORDER_BARRIER();
+ Atomic_write_memory_barrier();
lock_lockword_set(t, o, THIN_UNLOCKED);
- /* memory barrier for thin locking */
- MEMORY_BARRIER();
+ /* Memory barrier for thin locking. */
+ Atomic_memory_barrier();
/* check if there has been a flat lock contention on this object */
/* unlock this lock record */
lr->owner = NULL;
- mutex_unlock(&(lr->mutex));
+ Mutex_unlock(lr->mutex);
return true;
}
/* Enter the wait-mutex. */
- mutex_lock(&(waitingthread->waitmutex));
+ Mutex_lock(waitingthread->waitmutex);
DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, one=%d]",
lr, t, waitingthread, one));
- pthread_cond_signal(&(waitingthread->waitcond));
+ Condition_signal(waitingthread->waitcond);
/* Mark the thread as signaled. */
/* Leave the wait-mutex. */
- mutex_unlock(&(waitingthread->waitmutex));
+ Mutex_unlock(waitingthread->waitmutex);
/* if we should only wake one, we are done */
#include "config.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <pthread.h>
#include "vm/types.h"
#include "native/llni.h"
-#include "threads/mutex.h"
+#include "threads/mutex.hpp"
#include "toolbox/list.h"
java_object_t *object; /* object for which this lock is */
struct threadobject *owner; /* current owner of this monitor */
s4 count; /* recursive lock count */
- mutex_t mutex; /* mutex for synchronizing */
+ Mutex* mutex; /* mutex for synchronizing */
list_t *waiters; /* list of threads waiting */
lock_record_t *hashlink; /* next record in hash chain */
};
*******************************************************************************/
struct lock_hashtable_t {
- mutex_t mutex; /* mutex for synch. access to the table */
+ Mutex* mutex; /* mutex for synch. access to the table */
u4 size; /* number of slots */
u4 entries; /* current number of entries */
lock_record_t **ptr; /* the table of slots, uses ext. chain. */
#define LOCK_WAIT_FOREVER(o) lock_wait_for_object((java_handle_t *) LLNI_QUICKWRAP(o), 0, 0)
#define LOCK_NOTIFY(o) lock_notify_object((java_handle_t *) LLNI_QUICKWRAP(o))
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _LOCK_H */
+++ /dev/null
-/* src/threads/posix/mutex-posix.h - POSIX mutual exclusion functions
-
- Copyright (C) 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 _MUTEX_POSIX_H
-#define _MUTEX_POSIX_H
-
-#include "config.h"
-
-#include <pthread.h>
-
-#include "vm/vm.h"
-
-
-/* POSIX mutex object *********************************************************/
-
-typedef pthread_mutex_t mutex_t;
-
-
-/* static mutex initializer ***************************************************/
-
-#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-
-
-/* inline functions ***********************************************************/
-
-/* mutex_init ******************************************************************
-
- Initializes the given mutex object and checks for errors.
-
- ARGUMENTS:
- mutex ... POSIX mutex object
-
-*******************************************************************************/
-
-inline static void mutex_init(mutex_t *mutex)
-{
- int result;
-
- result = pthread_mutex_init(mutex, NULL);
-
- if (result != 0)
- vm_abort_errnum(result, "mutex_init: pthread_mutex_init failed");
-}
-
-
-/* mutex_lock ******************************************************************
-
- Locks the given mutex object and checks for errors. If the mutex is
- already locked by another thread, the calling thread is suspended until
- the mutex is unlocked.
-
- If the mutex is already locked by the calling thread, the same applies,
- thus effectively causing the calling thread to deadlock. (This is because
- we use "fast" pthread mutexes without error checking.)
-
- ARGUMENTS:
- mutex ... POSIX mutex object
-
-*******************************************************************************/
-
-inline static void mutex_lock(mutex_t *mutex)
-{
- int result;
-
- result = pthread_mutex_lock(mutex);
-
- if (result != 0)
- vm_abort_errnum(result, "mutex_lock: pthread_mutex_lock failed");
-}
-
-
-/* mutex_unlock ****************************************************************
-
- Unlocks the given mutex object and checks for errors. The mutex is
- assumed to be locked and owned by the calling thread.
-
- ARGUMENTS:
- mutex ... POSIX mutex object
-
-*******************************************************************************/
-
-inline static void mutex_unlock(mutex_t *mutex)
-{
- int result;
-
- result = pthread_mutex_unlock(mutex);
-
- if (result != 0)
- vm_abort_errnum(result, "mutex_unlock: pthread_mutex_unlock failed");
-}
-
-
-/* mutex_destroy ***************************************************************
-
- Destroys the given mutex object and checks for errors.
-
- ARGUMENTS:
- mutex ... POSIX mutex object
-
-*******************************************************************************/
-
-inline static void mutex_destroy(mutex_t *mutex)
-{
- int result;
-
- result = pthread_mutex_destroy(mutex);
-
- if (result != 0)
- vm_abort_errnum(result, "mutex_destroy: pthread_mutex_destroy failed");
-}
-
-
-#endif /* _MUTEX_POSIX_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:
- */
--- /dev/null
+/* src/threads/posix/mutex-posix.hpp - POSIX mutual exclusion functions
+
+ Copyright (C) 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 _MUTEX_POSIX_HPP
+#define _MUTEX_POSIX_HPP
+
+#include "config.h"
+
+#include <pthread.h>
+
+#include "vm/vm.hpp"
+
+#ifdef __cplusplus
+
+/**
+ * POSIX implementation of a mutex.
+ */
+class Mutex {
+private:
+ // POSIX mutex structure.
+ pthread_mutex_t _mutex;
+
+ // Condition class needs to access _mutex for wait() and
+ // timedwait().
+ friend class Condition;
+
+public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+};
+
+
+/* static mutex initializer ***************************************************/
+
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+
+/**
+ * Initializes the given mutex object and checks for errors.
+ */
+inline Mutex::Mutex()
+{
+ int result;
+
+ result = pthread_mutex_init(&_mutex, NULL);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Mutex::Mutex(): pthread_mutex_init failed");
+}
+
+
+/**
+ * Destroys the given mutex object and checks for errors.
+ */
+inline Mutex::~Mutex()
+{
+ int result;
+
+ result = pthread_mutex_destroy(&_mutex);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
+}
+
+
+/**
+ * Locks the given mutex object and checks for errors. If the mutex is
+ * already locked by another thread, the calling thread is suspended until
+ * the mutex is unlocked.
+ *
+ * If the mutex is already locked by the calling thread, the same applies,
+ * thus effectively causing the calling thread to deadlock. (This is because
+ * we use "fast" pthread mutexes without error checking.)
+ */
+inline void Mutex::lock()
+{
+ int result;
+
+ result = pthread_mutex_lock(&_mutex);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Mutex::lock(): pthread_mutex_lock failed");
+}
+
+
+/**
+ * Unlocks the given mutex object and checks for errors. The mutex is
+ * assumed to be locked and owned by the calling thread.
+ */
+inline void Mutex::unlock()
+{
+ int result;
+
+ result = pthread_mutex_unlock(&_mutex);
+
+ if (result != 0)
+ vm_abort_errnum(result, "Mutex::unlock: pthread_mutex_unlock failed");
+}
+
+#else
+
+// This structure must have the same layout as the class above.
+typedef struct Mutex {
+ pthread_mutex_t _mutex;
+} Mutex;
+
+Mutex* Mutex_new();
+void Mutex_delete(Mutex* mutex);
+void Mutex_lock(Mutex* mutex);
+void Mutex_unlock(Mutex* mutex);
+
+#endif
+
+#endif /* _MUTEX_POSIX_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
-/* src/threads/posix/thread-posix.c - POSIX thread 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"
-
-/* XXX cleanup these includes */
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <time.h>
-#include <errno.h>
-
-#include <pthread.h>
-
-#include "vm/types.h"
-
-#include "arch.h"
-
-#if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
-# include "machine-instr.h"
-#else
-# include "threads/posix/generic-primitives.h"
-#endif
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#if defined(ENABLE_GC_CACAO)
-# include "mm/cacao-gc/gc.h"
-#endif
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Throwable.h"
-#include "native/include/java_lang_Thread.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_VMThread.h"
-#endif
-
-#include "threads/lock-common.h"
-#include "threads/mutex.h"
-#include "threads/threadlist.h"
-#include "threads/thread.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/asmpart.h"
-
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#if !defined(__DARWIN__)
-# include <semaphore.h>
-#endif
-
-#if defined(__LINUX__)
-# define GC_LINUX_THREADS
-#elif defined(__IRIX__)
-# define GC_IRIX_THREADS
-#elif defined(__DARWIN__)
-# define GC_DARWIN_THREADS
-#endif
-
-#if defined(ENABLE_GC_BOEHM)
-/* We need to include Boehm's gc.h here because it overrides
- pthread_create and friends. */
-# include "mm/boehm-gc/include/gc.h"
-#endif
-
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-#if defined(__DARWIN__)
-/* Darwin has no working semaphore implementation. This one is taken
- from Boehm-GC. */
-
-/*
- This is a very simple semaphore implementation for darwin. It
- is implemented in terms of pthreads calls so it isn't async signal
- safe. This isn't a problem because signals aren't used to
- suspend threads on darwin.
-*/
-
-static int sem_init(sem_t *sem, int pshared, int value)
-{
- if (pshared)
- assert(0);
-
- sem->value = value;
-
- mutex_init(&sem->mutex);
-
- if (pthread_cond_init(&sem->cond, NULL) < 0)
- return -1;
-
- return 0;
-}
-
-static int sem_post(sem_t *sem)
-{
- mutex_lock(&sem->mutex);
-
- sem->value++;
-
- if (pthread_cond_signal(&sem->cond) < 0) {
- mutex_unlock(&sem->mutex);
- return -1;
- }
-
- mutex_unlock(&sem->mutex);
-
- return 0;
-}
-
-static int sem_wait(sem_t *sem)
-{
- mutex_lock(&sem->mutex);
-
- while (sem->value == 0) {
- pthread_cond_wait(&sem->cond, &sem->mutex);
- }
-
- sem->value--;
-
- mutex_unlock(&sem->mutex);
-
- return 0;
-}
-
-static int sem_destroy(sem_t *sem)
-{
- if (pthread_cond_destroy(&sem->cond) < 0)
- return -1;
-
- mutex_destroy(&sem->mutex);
-
- return 0;
-}
-#endif /* defined(__DARWIN__) */
-
-
-/* internally used constants **************************************************/
-
-/* CAUTION: Do not change these values. Boehm GC code depends on them. */
-#define STOPWORLD_FROM_GC 1
-#define STOPWORLD_FROM_CLASS_NUMBERING 2
-
-
-/* startupinfo *****************************************************************
-
- Struct used to pass info from threads_start_thread to
- threads_startup_thread.
-
-******************************************************************************/
-
-typedef struct {
- threadobject *thread; /* threadobject for this thread */
- functionptr function; /* function to run in the new thread */
- sem_t *psem; /* signals when thread has been entered */
- /* in the thread list */
- sem_t *psem_first; /* signals when pthread_create has returned */
-} startupinfo;
-
-
-/* prototypes *****************************************************************/
-
-static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
-
-
-/******************************************************************************/
-/* GLOBAL VARIABLES */
-/******************************************************************************/
-
-/* the thread object of the current thread */
-/* This is either a thread-local variable defined with __thread, or */
-/* a thread-specific value stored with key threads_current_threadobject_key. */
-#if defined(HAVE___THREAD)
-__thread threadobject *thread_current;
-#else
-pthread_key_t thread_current_key;
-#endif
-
-/* global mutex for stop-the-world */
-static mutex_t stopworldlock;
-
-#if defined(ENABLE_GC_CACAO)
-/* global mutex for the GC */
-static mutex_t mutex_gc;
-#endif
-
-/* global mutex and condition for joining threads on exit */
-static mutex_t mutex_join;
-static pthread_cond_t cond_join;
-
-/* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
-/* being stopped */
-static volatile int stopworldwhere;
-
-#if defined(ENABLE_GC_CACAO)
-
-/* semaphore used for acknowleding thread suspension */
-static sem_t suspend_ack;
-#if defined(__IRIX__)
-static mutex_t suspend_ack_lock = MUTEX_INITIALIZER;
-static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
-#endif
-
-#endif /* ENABLE_GC_CACAO */
-
-/* mutexes used by the fake atomic instructions */
-#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
-mutex_t _cas_lock = MUTEX_INITIALIZER;
-mutex_t _mb_lock = MUTEX_INITIALIZER;
-#endif
-
-
-/* threads_sem_init ************************************************************
-
- Initialize a semaphore. Checks against errors and interruptions.
-
- IN:
- sem..............the semaphore to initialize
- shared...........true if this semaphore will be shared between processes
- value............the initial value for the semaphore
-
-*******************************************************************************/
-
-void threads_sem_init(sem_t *sem, bool shared, int value)
-{
- int r;
-
- assert(sem);
-
- do {
- r = sem_init(sem, shared, value);
- if (r == 0)
- return;
- } while (errno == EINTR);
-
- vm_abort("sem_init failed: %s", strerror(errno));
-}
-
-
-/* threads_sem_wait ************************************************************
-
- Wait for a semaphore, non-interruptible.
-
- IMPORTANT: Always use this function instead of `sem_wait` directly, as
- `sem_wait` may be interrupted by signals!
-
- IN:
- sem..............the semaphore to wait on
-
-*******************************************************************************/
-
-void threads_sem_wait(sem_t *sem)
-{
- int r;
-
- assert(sem);
-
- do {
- r = sem_wait(sem);
- if (r == 0)
- return;
- } while (errno == EINTR);
-
- vm_abort("sem_wait failed: %s", strerror(errno));
-}
-
-
-/* threads_sem_post ************************************************************
-
- Increase the count of a semaphore. Checks for errors.
-
- IN:
- sem..............the semaphore to increase the count of
-
-*******************************************************************************/
-
-void threads_sem_post(sem_t *sem)
-{
- int r;
-
- assert(sem);
-
- /* unlike sem_wait, sem_post is not interruptible */
-
- r = sem_post(sem);
- if (r == 0)
- return;
-
- vm_abort("sem_post failed: %s", strerror(errno));
-}
-
-
-/* lock_stopworld **************************************************************
-
- Enter the stopworld lock, specifying why the world shall be stopped.
-
- IN:
- where........ STOPWORLD_FROM_GC (1) from within GC
- STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
-
-******************************************************************************/
-
-void lock_stopworld(int where)
-{
- mutex_lock(&stopworldlock);
-/* stopworldwhere = where; */
-}
-
-
-/* unlock_stopworld ************************************************************
-
- Release the stopworld lock.
-
-******************************************************************************/
-
-void unlock_stopworld(void)
-{
-/* stopworldwhere = 0; */
- mutex_unlock(&stopworldlock);
-}
-
-/* XXX We disable that whole bunch of code until we have the exact-GC
- running. Some of it may only be needed by the old Boehm-based
- suspension handling. */
-
-#if 0
-
-#if !defined(__DARWIN__)
-/* Caller must hold threadlistlock */
-static s4 threads_cast_sendsignals(s4 sig)
-{
- threadobject *t;
- threadobject *self;
- s4 count;
-
- self = THREADOBJECT;
-
- /* iterate over all started threads */
-
- count = 0;
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- /* don't send the signal to ourself */
-
- if (t == self)
- continue;
-
- /* don't send the signal to NEW threads (because they are not
- completely initialized) */
-
- if (t->state == THREAD_STATE_NEW)
- continue;
-
- /* send the signal */
-
- pthread_kill(t->tid, sig);
-
- /* increase threads count */
-
- count++;
- }
-
- return count;
-}
-
-#else
-
-static void threads_cast_darwinstop(void)
-{
- threadobject *tobj = mainthreadobj;
- threadobject *self = THREADOBJECT;
-
- do {
- if (tobj != self)
- {
- thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
- mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
-#if defined(__I386__)
- i386_thread_state_t thread_state;
-#else
- ppc_thread_state_t thread_state;
-#endif
- mach_port_t thread = tobj->mach_thread;
- kern_return_t r;
-
- r = thread_suspend(thread);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_suspend failed");
-
- r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
- &thread_state_count);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_get_state failed");
-
- md_critical_section_restart((ucontext_t *) &thread_state);
-
- r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
- thread_state_count);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_set_state failed");
- }
-
- tobj = tobj->next;
- } while (tobj != mainthreadobj);
-}
-
-static void threads_cast_darwinresume(void)
-{
- threadobject *tobj = mainthreadobj;
- threadobject *self = THREADOBJECT;
-
- do {
- if (tobj != self)
- {
- mach_port_t thread = tobj->mach_thread;
- kern_return_t r;
-
- r = thread_resume(thread);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_resume failed");
- }
-
- tobj = tobj->next;
- } while (tobj != mainthreadobj);
-}
-
-#endif
-
-#if defined(__IRIX__)
-static void threads_cast_irixresume(void)
-{
- mutex_lock(&suspend_ack_lock);
- pthread_cond_broadcast(&suspend_cond);
- mutex_unlock(&suspend_ack_lock);
-}
-#endif
-
-#if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
-static void threads_sigsuspend_handler(ucontext_t *_uc)
-{
- int sig;
- sigset_t sigs;
-
- /* XXX TWISTI: this is just a quick hack */
-#if defined(ENABLE_JIT)
- md_critical_section_restart(_uc);
-#endif
-
- /* Do as Boehm does. On IRIX a condition variable is used for wake-up
- (not POSIX async-safe). */
-#if defined(__IRIX__)
- mutex_lock(&suspend_ack_lock);
- threads_sem_post(&suspend_ack);
- pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
- mutex_unlock(&suspend_ack_lock);
-#elif defined(__CYGWIN__)
- /* TODO */
- assert(0);
-#else
-
- sig = GC_signum2();
- sigfillset(&sigs);
- sigdelset(&sigs, sig);
- sigsuspend(&sigs);
-#endif
-}
-#endif
-
-
-/* threads_stopworld ***********************************************************
-
- Stops the world from turning. All threads except the calling one
- are suspended. The function returns as soon as all threads have
- acknowledged their suspension.
-
-*******************************************************************************/
-
-void threads_stopworld(void)
-{
-#if !defined(__DARWIN__) && !defined(__CYGWIN__)
- threadobject *t;
- threadobject *self;
- bool result;
- s4 count, i;
-#endif
-
- lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
-
- /* lock the threads lists */
-
- threadlist_lock();
-
-#if defined(__DARWIN__)
- /*threads_cast_darwinstop();*/
- assert(0);
-#elif defined(__CYGWIN__)
- /* TODO */
- assert(0);
-#else
- self = THREADOBJECT;
-
- DEBUGTHREADS("stops World", self);
-
- count = 0;
-
- /* suspend all running threads */
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- /* don't send the signal to ourself */
-
- if (t == self)
- continue;
-
- /* don't send the signal to NEW threads (because they are not
- completely initialized) */
-
- if (t->state == THREAD_STATE_NEW)
- continue;
-
- /* send the signal */
-
- result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
- assert(result);
-
- /* increase threads count */
-
- count++;
- }
-
- /* wait for all threads signaled to suspend */
- for (i = 0; i < count; i++)
- threads_sem_wait(&suspend_ack);
-#endif
-
- /* ATTENTION: Don't unlock the threads-lists here so that
- non-signaled NEW threads can't change their state and execute
- code. */
-}
-
-
-/* threads_startworld **********************************************************
-
- Starts the world again after it has previously been stopped.
-
-*******************************************************************************/
-
-void threads_startworld(void)
-{
-#if !defined(__DARWIN__) && !defined(__CYGWIN__)
- threadobject *t;
- threadobject *self;
- bool result;
- s4 count, i;
-#endif
-
-#if defined(__DARWIN__)
- /*threads_cast_darwinresume();*/
- assert(0);
-#elif defined(__IRIX__)
- threads_cast_irixresume();
-#elif defined(__CYGWIN__)
- /* TODO */
- assert(0);
-#else
- self = THREADOBJECT;
-
- DEBUGTHREADS("starts World", self);
-
- count = 0;
-
- /* resume all thread we haltet */
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- /* don't send the signal to ourself */
-
- if (t == self)
- continue;
-
- /* don't send the signal to NEW threads (because they are not
- completely initialized) */
-
- if (t->state == THREAD_STATE_NEW)
- continue;
-
- /* send the signal */
-
- result = threads_resume_thread(t);
- assert(result);
-
- /* increase threads count */
-
- count++;
- }
-
- /* wait for all threads signaled to suspend */
- for (i = 0; i < count; i++)
- threads_sem_wait(&suspend_ack);
-
-#endif
-
- /* unlock the threads lists */
-
- threadlist_unlock();
-
- unlock_stopworld();
-}
-
-#endif
-
-
-/* threads_impl_thread_init ****************************************************
-
- Initialize OS-level locking constructs in threadobject.
-
- IN:
- t....the threadobject
-
-*******************************************************************************/
-
-void threads_impl_thread_init(threadobject *t)
-{
- int result;
-
- /* initialize the mutex and the condition */
-
- mutex_init(&t->flc_lock);
-
- result = pthread_cond_init(&t->flc_cond, NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
-
- mutex_init(&(t->waitmutex));
-
- result = pthread_cond_init(&(t->waitcond), NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
-
- mutex_init(&(t->suspendmutex));
-
- result = pthread_cond_init(&(t->suspendcond), NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
-}
-
-/* threads_impl_thread_clear ***************************************************
-
- Clears all fields in threadobject the way an MZERO would have
- done. MZERO cannot be used anymore because it would mess up the
- pthread_* bits.
-
- IN:
- t....the threadobject
-
-*******************************************************************************/
-
-void threads_impl_thread_clear(threadobject *t)
-{
- t->object = NULL;
-
- t->thinlock = 0;
-
- t->index = 0;
- t->flags = 0;
- t->state = 0;
-
- t->tid = 0;
-
-#if defined(__DARWIN__)
- t->mach_thread = 0;
-#endif
-
- t->interrupted = false;
- t->signaled = false;
-
- t->suspended = false;
- t->suspend_reason = 0;
-
- t->pc = NULL;
-
- t->_exceptionptr = NULL;
- t->_stackframeinfo = NULL;
- t->_localref_table = NULL;
-
-#if defined(ENABLE_INTRP)
- t->_global_sp = NULL;
-#endif
-
-#if defined(ENABLE_GC_CACAO)
- t->gc_critical = false;
-
- t->ss = NULL;
- t->es = NULL;
-#endif
-
- MZERO(&t->dumpinfo, dumpinfo_t, 1);
-}
-
-/* threads_impl_thread_reuse ***************************************************
-
- Resets some implementation fields in threadobject. This was
- previously done in threads_impl_thread_new.
-
- IN:
- t....the threadobject
-
-*******************************************************************************/
-
-void threads_impl_thread_reuse(threadobject *t)
-{
- /* get the pthread id */
-
- t->tid = pthread_self();
-
-#if defined(ENABLE_DEBUG_FILTER)
- /* Initialize filter counters */
- t->filterverbosecallctr[0] = 0;
- t->filterverbosecallctr[1] = 0;
-#endif
-
-#if !defined(NDEBUG)
- t->tracejavacallindent = 0;
- t->tracejavacallcount = 0;
-#endif
-
- t->flc_bit = false;
- t->flc_next = NULL;
- t->flc_list = NULL;
-
-/* not really needed */
- t->flc_object = NULL;
-}
-
-
-/* threads_impl_thread_free ****************************************************
-
- Cleanup thread stuff.
-
- IN:
- t....the threadobject
-
-*******************************************************************************/
-
-#if 0
-/* never used */
-void threads_impl_thread_free(threadobject *t)
-{
- int result;
-
- /* Destroy the mutex and the condition. */
-
- mutex_destroy(&(t->flc_lock));
-
- result = pthread_cond_destroy(&(t->flc_cond));
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
-
- mutex_destroy(&(t->waitmutex));
-
- result = pthread_cond_destroy(&(t->waitcond));
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
-
- mutex_destroy(&(t->suspendmutex));
-
- result = pthread_cond_destroy(&(t->suspendcond));
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
-}
-#endif
-
-
-/* threads_impl_preinit ********************************************************
-
- Do some early initialization of stuff required.
-
- ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
- is called AFTER this function!
-
-*******************************************************************************/
-
-void threads_impl_preinit(void)
-{
- int result;
-
- mutex_init(&stopworldlock);
-
- /* initialize exit mutex and condition (on exit we join all
- threads) */
-
- mutex_init(&mutex_join);
-
- result = pthread_cond_init(&cond_join, NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_preinit: pthread_cond_init failed");
-
-#if defined(ENABLE_GC_CACAO)
- /* initialize the GC mutex & suspend semaphore */
-
- mutex_init(&mutex_gc);
- threads_sem_init(&suspend_ack, 0, 0);
-#endif
-
-#if !defined(HAVE___THREAD)
- result = pthread_key_create(&thread_current_key, NULL);
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
-#endif
-}
-
-
-/* threads_mutex_gc_lock *******************************************************
-
- Enter the global GC mutex.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void threads_mutex_gc_lock(void)
-{
- mutex_lock(&mutex_gc);
-}
-#endif
-
-
-/* threads_mutex_gc_unlock *****************************************************
-
- Leave the global GC mutex.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void threads_mutex_gc_unlock(void)
-{
- mutex_unlock(&mutex_gc);
-}
-#endif
-
-/* threads_mutex_join_lock *****************************************************
-
- Enter the join mutex.
-
-*******************************************************************************/
-
-void threads_mutex_join_lock(void)
-{
- mutex_lock(&mutex_join);
-}
-
-
-/* threads_mutex_join_unlock ***************************************************
-
- Leave the join mutex.
-
-*******************************************************************************/
-
-void threads_mutex_join_unlock(void)
-{
- mutex_unlock(&mutex_join);
-}
-
-
-/* threads_impl_init ***********************************************************
-
- Initializes the implementation specific bits.
-
-*******************************************************************************/
-
-void threads_impl_init(void)
-{
- pthread_attr_t attr;
- int result;
-
- threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
-
- /* Initialize the thread attribute object. */
-
- result = pthread_attr_init(&attr);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
-
- result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
-}
-
-
-/* threads_startup_thread ******************************************************
-
- Thread startup function called by pthread_create.
-
- Thread which have a startup.function != NULL are marked as internal
- threads. All other threads are threated as normal Java threads.
-
- NOTE: This function is not called directly by pthread_create. The Boehm GC
- inserts its own GC_start_routine in between, which then calls
- threads_startup.
-
- IN:
- arg..........the argument passed to pthread_create, ie. a pointer to
- a startupinfo struct. CAUTION: When the `psem` semaphore
- is posted, the startupinfo struct becomes invalid! (It
- is allocated on the stack of threads_start_thread.)
-
-******************************************************************************/
-
-static void *threads_startup_thread(void *arg)
-{
- startupinfo *startup;
- threadobject *t;
- java_lang_Thread *object;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThread *vmt;
-#endif
- sem_t *psem;
- classinfo *c;
- methodinfo *m;
- java_handle_t *o;
- functionptr function;
-
-#if defined(ENABLE_GC_BOEHM)
-# if !defined(__DARWIN__)
- struct GC_stack_base sb;
- int result;
-# endif
-#endif
-
-#if defined(ENABLE_INTRP)
- u1 *intrp_thread_stack;
-#endif
-
-#if defined(ENABLE_INTRP)
- /* create interpreter stack */
-
- if (opt_intrp) {
- intrp_thread_stack = GCMNEW(u1, opt_stacksize);
- MSET(intrp_thread_stack, 0, u1, opt_stacksize);
- }
- else
- intrp_thread_stack = NULL;
-#endif
-
- /* get passed startupinfo structure and the values in there */
-
- startup = arg;
-
- t = startup->thread;
- function = startup->function;
- psem = startup->psem;
-
- /* Seems like we've encountered a situation where thread->tid was
- not set by pthread_create. We alleviate this problem by waiting
- for pthread_create to return. */
-
- threads_sem_wait(startup->psem_first);
-
-#if defined(__DARWIN__)
- t->mach_thread = mach_thread_self();
-#endif
-
- /* Now that we are in the new thread, we can store the internal
- thread data-structure in the TSD. */
-
- thread_set_current(t);
-
-#if defined(ENABLE_GC_BOEHM)
-# if defined(__DARWIN__)
- // This is currently not implemented in Boehm-GC. Just fail silently.
-# else
- /* Register the thread with Boehm-GC. This must happen before the
- thread allocates any memory from the GC heap.*/
-
- result = GC_get_stack_base(&sb);
-
- if (result != 0)
- vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
-
- GC_register_my_thread(&sb);
-# endif
-#endif
-
- /* get the java.lang.Thread object for this thread */
-
- object = (java_lang_Thread *) thread_get_object(t);
-
- /* set our priority */
-
- threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
-
- /* Thread is completely initialized. */
-
- thread_set_state_runnable(t);
-
- /* tell threads_startup_thread that we registered ourselves */
- /* CAUTION: *startup becomes invalid with this! */
-
- startup = NULL;
- threads_sem_post(psem);
-
-#if defined(ENABLE_INTRP)
- /* set interpreter stack */
-
- if (opt_intrp)
- thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
-#endif
-
-#if defined(ENABLE_JVMTI)
- /* fire thread start event */
-
- if (jvmti)
- jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
-#endif
-
- DEBUGTHREADS("starting", t);
-
- /* find and run the Thread.run()V method if no other function was passed */
-
- if (function == NULL) {
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* We need to start the run method of
- java.lang.VMThread. Since this is a final class, we can use
- the class object directly. */
-
- c = class_java_lang_VMThread;
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- LLNI_class_get(object, c);
-#else
-# error unknown classpath configuration
-#endif
-
- m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
-
- if (m == NULL)
- vm_abort("threads_startup_thread: run() method not found in class");
-
- /* 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;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* we need to start the run method of java.lang.VMThread */
-
- LLNI_field_get_ref(object, vmThread, vmt);
- o = (java_handle_t *) vmt;
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- o = (java_handle_t *) object;
-#else
-# error unknown classpath configuration
-#endif
-
- /* Run the thread. */
-
- (void) vm_call_method(m, o);
- }
- else {
- /* 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;
-
- /* call passed function, e.g. finalizer_thread */
-
- (function)();
- }
-
- DEBUGTHREADS("stopping", t);
-
-#if defined(ENABLE_JVMTI)
- /* fire thread end event */
-
- if (jvmti)
- jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
-#endif
-
- /* We ignore the return value. */
-
- (void) thread_detach_current_thread();
-
- /* set ThreadMXBean variables */
-
- _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
-
- return NULL;
-}
-
-
-/* threads_impl_thread_start ***************************************************
-
- Start a thread in the JVM. Both (vm internal and java) thread
- objects exist.
-
- IN:
- thread....the thread object
- f.........function to run in the new thread. NULL means that the
- "run" method of the object `t` should be called
-
-******************************************************************************/
-
-void threads_impl_thread_start(threadobject *thread, functionptr f)
-{
- sem_t sem;
- sem_t sem_first;
- pthread_attr_t attr;
- startupinfo startup;
- int result;
-
- /* fill startupinfo structure passed by pthread_create to
- * threads_startup_thread */
-
- startup.thread = thread;
- startup.function = f; /* maybe we don't call Thread.run()V */
- startup.psem = &sem;
- startup.psem_first = &sem_first;
-
- threads_sem_init(&sem, 0, 0);
- threads_sem_init(&sem_first, 0, 0);
-
- /* Initialize thread attributes. */
-
- result = pthread_attr_init(&attr);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
-
- result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
-
- /* initialize thread stacksize */
-
- result = pthread_attr_setstacksize(&attr, opt_stacksize);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
-
- /* create the thread */
-
- result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
-
- /* destroy the thread attributes */
-
- result = pthread_attr_destroy(&attr);
-
- if (result != 0)
- vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
-
- /* signal that pthread_create has returned, so thread->tid is valid */
-
- threads_sem_post(&sem_first);
-
- /* wait here until the thread has entered itself into the thread list */
-
- threads_sem_wait(&sem);
-
- /* cleanup */
-
- sem_destroy(&sem);
- sem_destroy(&sem_first);
-}
-
-
-/* threads_set_thread_priority *************************************************
-
- Set the priority of the given thread.
-
- IN:
- tid..........thread id
- priority.....priority to set
-
-******************************************************************************/
-
-void threads_set_thread_priority(pthread_t tid, int priority)
-{
- struct sched_param schedp;
- int policy;
-
- pthread_getschedparam(tid, &policy, &schedp);
- schedp.sched_priority = priority;
- pthread_setschedparam(tid, policy, &schedp);
-}
-
-
-/**
- * Detaches the current thread from the VM.
- *
- * @return true on success, false otherwise
- */
-bool thread_detach_current_thread(void)
-{
- threadobject *t;
- bool result;
- java_lang_Thread *object;
- java_handle_t *o;
-#if defined(ENABLE_JAVASE)
- java_lang_ThreadGroup *group;
- java_handle_t *e;
- void *handler;
- classinfo *c;
- methodinfo *m;
-#endif
-
- t = thread_get_current();
-
- /* Sanity check. */
-
- assert(t != NULL);
-
- /* If the given thread has already been detached, this operation
- is a no-op. */
-
- result = thread_is_attached(t);
-
- if (result == false)
- return true;
-
- DEBUGTHREADS("detaching", t);
-
- object = (java_lang_Thread *) thread_get_object(t);
-
-#if defined(ENABLE_JAVASE)
- LLNI_field_get_ref(object, group, group);
-
- /* If there's an uncaught exception, call uncaughtException on the
- thread's exception handler, or the thread's group if this is
- unset. */
-
- e = exceptions_get_and_clear_exception();
-
- if (e != NULL) {
- /* We use the type void* for handler here, as it's not trivial
- to build the java_lang_Thread_UncaughtExceptionHandler
- header file with cacaoh. */
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- LLNI_field_get_ref(object, exceptionHandler, handler);
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
-# endif
-
- if (handler != NULL) {
- LLNI_class_get(handler, c);
- o = (java_handle_t *) handler;
- }
- else {
- LLNI_class_get(group, c);
- o = (java_handle_t *) group;
- }
-
- m = class_resolveclassmethod(c,
- utf_uncaughtException,
- utf_java_lang_Thread_java_lang_Throwable__V,
- NULL,
- true);
-
- if (m == NULL)
- return false;
-
- (void) vm_call_method(m, o, object, e);
-
- if (exceptions_get_exception())
- return false;
- }
-
- /* XXX TWISTI: should all threads be in a ThreadGroup? */
-
- /* Remove thread from the thread group. */
-
- if (group != NULL) {
- LLNI_class_get(group, c);
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- m = class_resolveclassmethod(c,
- utf_removeThread,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- m = class_resolveclassmethod(c,
- utf_remove,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
-# else
-# error unknown classpath configuration
-# endif
-
- if (m == NULL)
- return false;
-
- o = (java_handle_t *) group;
-
- (void) vm_call_method(m, o, object);
-
- if (exceptions_get_exception())
- return false;
-
- /* Reset the threadgroup in the Java thread object (Mauve
- test: gnu/testlet/java/lang/Thread/getThreadGroup). */
-
- LLNI_field_set_ref(object, group, NULL);
- }
-#endif
-
- /* Thread has terminated. */
-
- thread_set_state_terminated(t);
-
- /* Notify all threads waiting on this thread. These are joining
- this thread. */
-
- o = (java_handle_t *) object;
-
- /* XXX Care about exceptions? */
- (void) lock_monitor_enter(o);
-
- lock_notify_all_object(o);
-
- /* XXX Care about exceptions? */
- (void) lock_monitor_exit(o);
-
- /* Enter the join-mutex before calling thread_free, so
- threads_join_all_threads gets the correct number of non-daemon
- threads. */
-
- threads_mutex_join_lock();
-
- /* Free the internal thread data-structure. */
-
- thread_free(t);
-
- /* Signal that this thread has finished and leave the mutex. */
-
- pthread_cond_signal(&cond_join);
- threads_mutex_join_unlock();
-
- return true;
-}
-
-
-#if defined(ENABLE_GC_CACAO)
-
-/* threads_suspend_thread ******************************************************
-
- Suspend the passed thread. Execution stops until the thread
- is explicitly resumend again.
-
- IN:
- reason.....Reason for suspending this thread.
-
-*******************************************************************************/
-
-bool threads_suspend_thread(threadobject *thread, s4 reason)
-{
- /* acquire the suspendmutex */
- mutex_lock(&(thread->suspendmutex));
-
- if (thread->suspended) {
- mutex_unlock(&(thread->suspendmutex));
- return false;
- }
-
- /* set the reason for the suspension */
- thread->suspend_reason = reason;
-
- /* send the suspend signal to the thread */
- assert(thread != THREADOBJECT);
- if (pthread_kill(thread->tid, SIGUSR1) != 0)
- vm_abort("threads_suspend_thread: pthread_kill failed: %s",
- strerror(errno));
-
- /* REMEMBER: do not release the suspendmutex, this is done
- by the thread itself in threads_suspend_ack(). */
-
- return true;
-}
-
-
-/* threads_suspend_ack *********************************************************
-
- Acknowledges the suspension of the current thread.
-
- IN:
- pc.....The PC where the thread suspended its execution.
- sp.....The SP before the thread suspended its execution.
-
-*******************************************************************************/
-
-void threads_suspend_ack(u1* pc, u1* sp)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- assert(thread->suspend_reason != 0);
-
- /* TODO: remember dump memory size */
-
- /* inform the GC about the suspension */
- if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
-
- /* check if the GC wants to leave the thread running */
- if (!gc_suspend(thread, pc, sp)) {
-
- /* REMEMBER: we do not unlock the suspendmutex because the thread
- will suspend itself again at a later time */
- return;
-
- }
- }
-
- /* mark this thread as suspended and remember the PC */
- thread->pc = pc;
- thread->suspended = true;
-
- /* if we are stopping the world, we should send a global ack */
- if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
- threads_sem_post(&suspend_ack);
- }
-
- DEBUGTHREADS("suspending", thread);
-
- /* release the suspension mutex and wait till we are resumed */
- pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
-
- DEBUGTHREADS("resuming", thread);
-
- /* if we are stopping the world, we should send a global ack */
- if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
- threads_sem_post(&suspend_ack);
- }
-
- /* TODO: free dump memory */
-
- /* release the suspendmutex */
- mutex_unlock(&(thread->suspendmutex));
-}
-
-
-/* threads_resume_thread *******************************************************
-
- Resumes the execution of the passed thread.
-
-*******************************************************************************/
-
-bool threads_resume_thread(threadobject *thread)
-{
- /* acquire the suspendmutex */
- mutex_lock(&(thread->suspendmutex));
-
- if (!thread->suspended) {
- mutex_unlock(&(thread->suspendmutex));
- return false;
- }
-
- thread->suspended = false;
-
- /* tell everyone that the thread should resume */
- assert(thread != THREADOBJECT);
- pthread_cond_broadcast(&(thread->suspendcond));
-
- /* release the suspendmutex */
- mutex_unlock(&(thread->suspendmutex));
-
- return true;
-}
-
-#endif
-
-/* threads_join_all_threads ****************************************************
-
- Join all non-daemon threads.
-
-*******************************************************************************/
-
-void threads_join_all_threads(void)
-{
- threadobject *t;
-
- /* get current thread */
-
- t = THREADOBJECT;
-
- /* This thread is waiting for all non-daemon threads to exit. */
-
- thread_set_state_waiting(t);
-
- /* enter join mutex */
-
- threads_mutex_join_lock();
-
- /* Wait for condition as long as we have non-daemon threads. We
- compare against 1 because the current (main thread) is also a
- non-daemon thread. */
-
- while (threadlist_get_non_daemons() > 1)
- pthread_cond_wait(&cond_join, &mutex_join);
-
- /* leave join mutex */
-
- threads_mutex_join_unlock();
-}
-
-
-/* threads_timespec_earlier ****************************************************
-
- Return true if timespec tv1 is earlier than timespec tv2.
-
- IN:
- tv1..........first timespec
- tv2..........second timespec
-
- RETURN VALUE:
- true, if the first timespec is earlier
-
-*******************************************************************************/
-
-static inline bool threads_timespec_earlier(const struct timespec *tv1,
- const struct timespec *tv2)
-{
- return (tv1->tv_sec < tv2->tv_sec)
- ||
- (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
-}
-
-
-/* threads_current_time_is_earlier_than ****************************************
-
- Check if the current time is earlier than the given timespec.
-
- IN:
- tv...........the timespec to compare against
-
- RETURN VALUE:
- true, if the current time is earlier
-
-*******************************************************************************/
-
-static bool threads_current_time_is_earlier_than(const struct timespec *tv)
-{
- struct timeval tvnow;
- struct timespec tsnow;
-
- /* get current time */
-
- if (gettimeofday(&tvnow, NULL) != 0)
- vm_abort("gettimeofday failed: %s\n", strerror(errno));
-
- /* convert it to a timespec */
-
- tsnow.tv_sec = tvnow.tv_sec;
- tsnow.tv_nsec = tvnow.tv_usec * 1000;
-
- /* compare current time with the given timespec */
-
- return threads_timespec_earlier(&tsnow, tv);
-}
-
-
-/* threads_wait_with_timeout ***************************************************
-
- Wait until the given point in time on a monitor until either
- we are notified, we are interrupted, or the time is up.
-
- IN:
- t............the current thread
- wakeupTime...absolute (latest) wakeup time
- If both tv_sec and tv_nsec are zero, this function
- waits for an unlimited amount of time.
-
-*******************************************************************************/
-
-static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
-{
- /* acquire the waitmutex */
-
- mutex_lock(&t->waitmutex);
-
- /* wait on waitcond */
-
- if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
- /* with timeout */
- while (!t->interrupted && !t->signaled
- && threads_current_time_is_earlier_than(wakeupTime))
- {
- thread_set_state_timed_waiting(t);
-
- pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
- wakeupTime);
-
- thread_set_state_runnable(t);
- }
- }
- else {
- /* no timeout */
- while (!t->interrupted && !t->signaled) {
- thread_set_state_waiting(t);
-
- pthread_cond_wait(&t->waitcond, &t->waitmutex);
-
- thread_set_state_runnable(t);
- }
- }
-
- /* release the waitmutex */
-
- mutex_unlock(&t->waitmutex);
-}
-
-
-/* threads_wait_with_timeout_relative ******************************************
-
- Wait for the given maximum amount of time on a monitor until either
- we are notified, we are interrupted, or the time is up.
-
- IN:
- t............the current thread
- millis.......milliseconds to wait
- nanos........nanoseconds to wait
-
-*******************************************************************************/
-
-void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
- s4 nanos)
-{
- struct timespec wakeupTime;
-
- /* calculate the the (latest) wakeup time */
-
- threads_calc_absolute_time(&wakeupTime, millis, nanos);
-
- /* wait */
-
- threads_wait_with_timeout(thread, &wakeupTime);
-}
-
-
-/* threads_calc_absolute_time **************************************************
-
- Calculate the absolute point in time a given number of ms and ns from now.
-
- IN:
- millis............milliseconds from now
- nanos.............nanoseconds from now
-
- OUT:
- *tm...............receives the timespec of the absolute point in time
-
-*******************************************************************************/
-
-static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
-{
- if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
- struct timeval tv;
- long nsec;
- gettimeofday(&tv, NULL);
- tv.tv_sec += millis / 1000;
- millis %= 1000;
- nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
- tm->tv_sec = tv.tv_sec + nsec / 1000000000;
- tm->tv_nsec = nsec % 1000000000;
- }
- else {
- tm->tv_sec = 0;
- tm->tv_nsec = 0;
- }
-}
-
-
-/* threads_thread_interrupt ****************************************************
-
- Interrupt the given thread.
-
- The thread gets the "waitcond" signal and
- its interrupted flag is set to true.
-
- IN:
- thread............the thread to interrupt
-
-*******************************************************************************/
-
-void threads_thread_interrupt(threadobject *thread)
-{
-#if defined(__LINUX__) && defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* See openjdk/jdk/src/solaris/native/java/net/linux_close.c, "sigWakeup" */
- int sig = (__SIGRTMAX - 2);
-#else
- int sig = SIGHUP;
-#endif
- /* Signal the thread a "waitcond" and tell it that it has been
- interrupted. */
-
- mutex_lock(&thread->waitmutex);
-
- DEBUGTHREADS("interrupted", thread);
-
- /* Interrupt blocking system call using a signal. */
-
- pthread_kill(thread->tid, sig);
-
- pthread_cond_signal(&thread->waitcond);
-
- thread->interrupted = true;
-
- mutex_unlock(&thread->waitmutex);
-}
-
-
-/* threads_sleep ***************************************************************
-
- Sleep the current thread for the specified amount of time.
-
-*******************************************************************************/
-
-void threads_sleep(int64_t millis, int32_t nanos)
-{
- threadobject *t;
- struct timespec wakeupTime;
- bool interrupted;
-
- if (millis < 0) {
-/* exceptions_throw_illegalargumentexception("timeout value is negative"); */
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- t = thread_get_current();
-
- if (thread_is_interrupted(t) && !exceptions_get_exception()) {
- /* Clear interrupted flag (Mauve test:
- gnu/testlet/java/lang/Thread/interrupt). */
-
- thread_set_interrupted(t, false);
-
-/* exceptions_throw_interruptedexception("sleep interrupted"); */
- exceptions_throw_interruptedexception();
- return;
- }
-
- threads_calc_absolute_time(&wakeupTime, millis, nanos);
-
- threads_wait_with_timeout(t, &wakeupTime);
-
- interrupted = thread_is_interrupted(t);
-
- if (interrupted) {
- thread_set_interrupted(t, false);
-
- /* An other exception could have been thrown
- (e.g. ThreadDeathException). */
-
- if (!exceptions_get_exception())
- exceptions_throw_interruptedexception();
- }
-}
-
-
-/* threads_yield ***************************************************************
-
- Yield to the scheduler.
-
-*******************************************************************************/
-
-void threads_yield(void)
-{
- sched_yield();
-}
-
-
-/*
- * 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/threads/posix/thread-posix.cpp - POSIX thread 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"
+
+/* XXX cleanup these includes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include <pthread.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+
+#include "mm/gc.hpp"
+#include "mm/memory.h"
+
+#if defined(ENABLE_GC_CACAO)
+# include "mm/cacao-gc/gc.h"
+#endif
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "threads/condition.hpp"
+#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
+#include "threads/threadlist.h"
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/signallocal.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/jit/asmpart.h"
+
+#if !defined(__DARWIN__)
+# include <semaphore.h>
+#endif
+
+#if defined(__LINUX__)
+# define GC_LINUX_THREADS
+#elif defined(__IRIX__)
+# define GC_IRIX_THREADS
+#elif defined(__DARWIN__)
+# define GC_DARWIN_THREADS
+#endif
+
+#if defined(ENABLE_GC_BOEHM)
+/* We need to include Boehm's gc.h here because it overrides
+ pthread_create and friends. */
+# include "mm/boehm-gc/include/gc.h"
+#endif
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
+
+// FIXME For now we export everything as C functions.
+extern "C" {
+
+#if defined(__DARWIN__)
+/* Darwin has no working semaphore implementation. This one is taken
+ from Boehm-GC. */
+
+/*
+ This is a very simple semaphore implementation for Darwin. It
+ is implemented in terms of pthreads calls so it isn't async signal
+ safe. This isn't a problem because signals aren't used to
+ suspend threads on Darwin.
+*/
+
+static int sem_init(sem_t *sem, int pshared, int value)
+{
+ if (pshared)
+ assert(0);
+
+ sem->mutex = new Mutex();
+ sem->cond = new Condition();
+ sem->value = value;
+
+ return 0;
+}
+
+static int sem_post(sem_t *sem)
+{
+ sem->mutex->lock();
+ sem->value++;
+ sem->cond->signal();
+ sem->mutex->unlock();
+
+ return 0;
+}
+
+static int sem_wait(sem_t *sem)
+{
+ sem->mutex->lock();
+
+ while (sem->value == 0) {
+ sem->cond->wait(sem->mutex);
+ }
+
+ sem->value--;
+ sem->mutex->unlock();
+
+ return 0;
+}
+
+static int sem_destroy(sem_t *sem)
+{
+ delete sem->cond;
+ delete sem->mutex;
+
+ return 0;
+}
+#endif /* defined(__DARWIN__) */
+
+
+/* startupinfo *****************************************************************
+
+ Struct used to pass info from threads_start_thread to
+ threads_startup_thread.
+
+******************************************************************************/
+
+typedef struct {
+ threadobject *thread; /* threadobject for this thread */
+ functionptr function; /* function to run in the new thread */
+ sem_t *psem; /* signals when thread has been entered */
+ /* in the thread list */
+ sem_t *psem_first; /* signals when pthread_create has returned */
+} startupinfo;
+
+
+/* prototypes *****************************************************************/
+
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
+
+
+/******************************************************************************/
+/* GLOBAL VARIABLES */
+/******************************************************************************/
+
+/* the thread object of the current thread */
+/* This is either a thread-local variable defined with __thread, or */
+/* a thread-specific value stored with key threads_current_threadobject_key. */
+#if defined(HAVE___THREAD)
+__thread threadobject *thread_current;
+#else
+pthread_key_t thread_current_key;
+#endif
+
+/* global mutex for stop-the-world */
+static Mutex* stopworldlock;
+
+#if defined(ENABLE_GC_CACAO)
+/* global mutex for the GC */
+static Mutex* mutex_gc;
+#endif
+
+/* global mutex and condition for joining threads on exit */
+static Mutex* mutex_join;
+static Condition* cond_join;
+
+#if defined(ENABLE_GC_CACAO)
+/* semaphore used for acknowleding thread suspension */
+static sem_t suspend_ack;
+#endif
+
+
+/* threads_sem_init ************************************************************
+
+ Initialize a semaphore. Checks against errors and interruptions.
+
+ IN:
+ sem..............the semaphore to initialize
+ shared...........true if this semaphore will be shared between processes
+ value............the initial value for the semaphore
+
+*******************************************************************************/
+
+void threads_sem_init(sem_t *sem, bool shared, int value)
+{
+ int r;
+
+ assert(sem);
+
+ do {
+ r = sem_init(sem, shared, value);
+ if (r == 0)
+ return;
+ } while (errno == EINTR);
+
+ vm_abort("sem_init failed: %s", strerror(errno));
+}
+
+
+/* threads_sem_wait ************************************************************
+
+ Wait for a semaphore, non-interruptible.
+
+ IMPORTANT: Always use this function instead of `sem_wait` directly, as
+ `sem_wait` may be interrupted by signals!
+
+ IN:
+ sem..............the semaphore to wait on
+
+*******************************************************************************/
+
+void threads_sem_wait(sem_t *sem)
+{
+ int r;
+
+ assert(sem);
+
+ do {
+ r = sem_wait(sem);
+ if (r == 0)
+ return;
+ } while (errno == EINTR);
+
+ vm_abort("sem_wait failed: %s", strerror(errno));
+}
+
+
+/* threads_sem_post ************************************************************
+
+ Increase the count of a semaphore. Checks for errors.
+
+ IN:
+ sem..............the semaphore to increase the count of
+
+*******************************************************************************/
+
+void threads_sem_post(sem_t *sem)
+{
+ int r;
+
+ assert(sem);
+
+ /* unlike sem_wait, sem_post is not interruptible */
+
+ r = sem_post(sem);
+ if (r == 0)
+ return;
+
+ vm_abort("sem_post failed: %s", strerror(errno));
+}
+
+
+/* threads_stopworld ***********************************************************
+
+ Stops the world from turning. All threads except the calling one
+ are suspended. The function returns as soon as all threads have
+ acknowledged their suspension.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_stopworld(void)
+{
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
+ threadobject *t;
+ threadobject *self;
+ bool result;
+ s4 count, i;
+#endif
+
+ stopworldlock->lock();
+
+ /* lock the threads lists */
+
+ threadlist_lock();
+
+#if defined(__DARWIN__)
+ /*threads_cast_darwinstop();*/
+ assert(0);
+#elif defined(__CYGWIN__)
+ /* TODO */
+ assert(0);
+#else
+ self = THREADOBJECT;
+
+ DEBUGTHREADS("stops World", self);
+
+ count = 0;
+
+ /* suspend all running threads */
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ /* don't send the signal to ourself */
+
+ if (t == self)
+ continue;
+
+ /* don't send the signal to NEW threads (because they are not
+ completely initialized) */
+
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+ /* send the signal */
+
+ result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
+ assert(result);
+
+ /* increase threads count */
+
+ count++;
+ }
+
+ /* wait for all threads signaled to suspend */
+ for (i = 0; i < count; i++)
+ threads_sem_wait(&suspend_ack);
+#endif
+
+ /* ATTENTION: Don't unlock the threads-lists here so that
+ non-signaled NEW threads can't change their state and execute
+ code. */
+}
+#endif
+
+
+/* threads_startworld **********************************************************
+
+ Starts the world again after it has previously been stopped.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_startworld(void)
+{
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
+ threadobject *t;
+ threadobject *self;
+ bool result;
+ s4 count, i;
+#endif
+
+#if defined(__DARWIN__)
+ /*threads_cast_darwinresume();*/
+ assert(0);
+#elif defined(__IRIX__)
+ threads_cast_irixresume();
+#elif defined(__CYGWIN__)
+ /* TODO */
+ assert(0);
+#else
+ self = THREADOBJECT;
+
+ DEBUGTHREADS("starts World", self);
+
+ count = 0;
+
+ /* resume all thread we haltet */
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ /* don't send the signal to ourself */
+
+ if (t == self)
+ continue;
+
+ /* don't send the signal to NEW threads (because they are not
+ completely initialized) */
+
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+ /* send the signal */
+
+ result = threads_resume_thread(t);
+ assert(result);
+
+ /* increase threads count */
+
+ count++;
+ }
+
+ /* wait for all threads signaled to suspend */
+ for (i = 0; i < count; i++)
+ threads_sem_wait(&suspend_ack);
+
+#endif
+
+ /* unlock the threads lists */
+
+ threadlist_unlock();
+
+ stopworldlock->unlock();
+}
+#endif
+
+
+/* threads_impl_thread_init ****************************************************
+
+ Initialize OS-level locking constructs in threadobject.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+void threads_impl_thread_init(threadobject *t)
+{
+ /* initialize the mutex and the condition */
+
+ t->flc_lock = new Mutex();
+ t->flc_cond = new Condition();
+
+ t->waitmutex = new Mutex();
+ t->waitcond = new Condition();
+
+ t->suspendmutex = new Mutex();
+ t->suspendcond = new Condition();
+
+#if defined(ENABLE_TLH)
+ tlh_init(&(t->tlh));
+#endif
+}
+
+/* threads_impl_thread_clear ***************************************************
+
+ Clears all fields in threadobject the way an MZERO would have
+ done. MZERO cannot be used anymore because it would mess up the
+ pthread_* bits.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+void threads_impl_thread_clear(threadobject *t)
+{
+ t->object = NULL;
+
+ t->thinlock = 0;
+
+ t->index = 0;
+ t->flags = 0;
+ t->state = 0;
+
+ t->tid = 0;
+
+#if defined(__DARWIN__)
+ t->mach_thread = 0;
+#endif
+
+ t->interrupted = false;
+ t->signaled = false;
+
+ t->suspended = false;
+ t->suspend_reason = 0;
+
+ t->pc = NULL;
+
+ t->_exceptionptr = NULL;
+ t->_stackframeinfo = NULL;
+ t->_localref_table = NULL;
+
+#if defined(ENABLE_INTRP)
+ t->_global_sp = NULL;
+#endif
+
+#if defined(ENABLE_GC_CACAO)
+ t->gc_critical = false;
+
+ t->ss = NULL;
+ t->es = NULL;
+#endif
+
+ MZERO(&t->dumpinfo, dumpinfo_t, 1);
+}
+
+/* threads_impl_thread_reuse ***************************************************
+
+ Resets some implementation fields in threadobject. This was
+ previously done in threads_impl_thread_new.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+void threads_impl_thread_reuse(threadobject *t)
+{
+ /* get the pthread id */
+
+ t->tid = pthread_self();
+
+#if defined(ENABLE_DEBUG_FILTER)
+ /* Initialize filter counters */
+ t->filterverbosecallctr[0] = 0;
+ t->filterverbosecallctr[1] = 0;
+#endif
+
+#if !defined(NDEBUG)
+ t->tracejavacallindent = 0;
+ t->tracejavacallcount = 0;
+#endif
+
+ t->flc_bit = false;
+ t->flc_next = NULL;
+ t->flc_list = NULL;
+
+/* not really needed */
+ t->flc_object = NULL;
+
+#if defined(ENABLE_TLH)
+ tlh_destroy(&(t->tlh));
+ tlh_init(&(t->tlh));
+#endif
+}
+
+
+/* threads_impl_thread_free ****************************************************
+
+ Cleanup thread stuff.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+#if 0
+/* never used */
+void threads_impl_thread_free(threadobject *t)
+{
+ int result;
+
+ /* Destroy the mutex and the condition. */
+
+ delete t->flc_lock;
+
+ result = pthread_cond_destroy(&(t->flc_cond));
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+
+ delete t->waitmutex;
+
+ result = pthread_cond_destroy(&(t->waitcond));
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+
+ delete t->suspendmutex;
+
+ result = pthread_cond_destroy(&(t->suspendcond));
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+}
+#endif
+
+
+/* threads_impl_preinit ********************************************************
+
+ Do some early initialization of stuff required.
+
+ ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
+ is called AFTER this function!
+
+*******************************************************************************/
+
+void threads_impl_preinit(void)
+{
+ int result;
+
+ stopworldlock = new Mutex();
+
+ /* initialize exit mutex and condition (on exit we join all
+ threads) */
+
+ mutex_join = new Mutex();
+ cond_join = new Condition();
+
+#if defined(ENABLE_GC_CACAO)
+ /* initialize the GC mutex & suspend semaphore */
+
+ mutex_gc = new Mutex();
+ threads_sem_init(&suspend_ack, 0, 0);
+#endif
+
+#if !defined(HAVE___THREAD)
+ result = pthread_key_create(&thread_current_key, NULL);
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
+#endif
+}
+
+
+/* threads_mutex_gc_lock *******************************************************
+
+ Enter the global GC mutex.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_lock(void)
+{
+ mutex_gc->lock();
+}
+#endif
+
+
+/* threads_mutex_gc_unlock *****************************************************
+
+ Leave the global GC mutex.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_unlock(void)
+{
+ mutex_gc->unlock();
+}
+#endif
+
+/* threads_mutex_join_lock *****************************************************
+
+ Enter the join mutex.
+
+*******************************************************************************/
+
+void threads_mutex_join_lock(void)
+{
+ mutex_join->lock();
+}
+
+
+/* threads_mutex_join_unlock ***************************************************
+
+ Leave the join mutex.
+
+*******************************************************************************/
+
+void threads_mutex_join_unlock(void)
+{
+ mutex_join->unlock();
+}
+
+
+/* threads_impl_init ***********************************************************
+
+ Initializes the implementation specific bits.
+
+*******************************************************************************/
+
+void threads_impl_init(void)
+{
+ pthread_attr_t attr;
+ int result;
+
+ threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
+
+ /* Initialize the thread attribute object. */
+
+ result = pthread_attr_init(&attr);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
+
+ result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
+}
+
+
+/* threads_startup_thread ******************************************************
+
+ Thread startup function called by pthread_create.
+
+ Thread which have a startup.function != NULL are marked as internal
+ threads. All other threads are threated as normal Java threads.
+
+ NOTE: This function is not called directly by pthread_create. The Boehm GC
+ inserts its own GC_start_routine in between, which then calls
+ threads_startup.
+
+ IN:
+ arg..........the argument passed to pthread_create, ie. a pointer to
+ a startupinfo struct. CAUTION: When the `psem` semaphore
+ is posted, the startupinfo struct becomes invalid! (It
+ is allocated on the stack of threads_start_thread.)
+
+******************************************************************************/
+
+static void *threads_startup_thread(void *arg)
+{
+ startupinfo *startup;
+ threadobject *t;
+ sem_t *psem;
+ classinfo *c;
+ methodinfo *m;
+ functionptr function;
+
+#if defined(ENABLE_GC_BOEHM)
+# if !defined(__DARWIN__)
+ struct GC_stack_base sb;
+ int result;
+# endif
+#endif
+
+#if defined(ENABLE_INTRP)
+ u1 *intrp_thread_stack;
+#endif
+
+#if defined(ENABLE_INTRP)
+ /* create interpreter stack */
+
+ if (opt_intrp) {
+ intrp_thread_stack = GCMNEW(u1, opt_stacksize);
+ MSET(intrp_thread_stack, 0, u1, opt_stacksize);
+ }
+ else
+ intrp_thread_stack = NULL;
+#endif
+
+ /* get passed startupinfo structure and the values in there */
+
+ startup = (startupinfo*) arg;
+
+ t = startup->thread;
+ function = startup->function;
+ psem = startup->psem;
+
+ /* Seems like we've encountered a situation where thread->tid was
+ not set by pthread_create. We alleviate this problem by waiting
+ for pthread_create to return. */
+
+ threads_sem_wait(startup->psem_first);
+
+#if defined(__DARWIN__)
+ t->mach_thread = mach_thread_self();
+#endif
+
+ /* Now that we are in the new thread, we can store the internal
+ thread data-structure in the TSD. */
+
+ thread_set_current(t);
+
+#if defined(ENABLE_GC_BOEHM)
+# if defined(__DARWIN__)
+ // This is currently not implemented in Boehm-GC. Just fail silently.
+# else
+ /* Register the thread with Boehm-GC. This must happen before the
+ thread allocates any memory from the GC heap.*/
+
+ result = GC_get_stack_base(&sb);
+
+ if (result != 0)
+ vm_abort("threads_startup_thread: GC_get_stack_base failed: result=%d", result);
+
+ GC_register_my_thread(&sb);
+# endif
+#endif
+
+ // Get the java.lang.Thread object for this thread.
+ java_handle_t* object = thread_get_object(t);
+ java_lang_Thread jlt(object);
+
+ /* set our priority */
+
+ threads_set_thread_priority(t->tid, jlt.get_priority());
+
+ /* Thread is completely initialized. */
+
+ thread_set_state_runnable(t);
+
+ /* tell threads_startup_thread that we registered ourselves */
+ /* CAUTION: *startup becomes invalid with this! */
+
+ startup = NULL;
+ threads_sem_post(psem);
+
+#if defined(ENABLE_INTRP)
+ /* set interpreter stack */
+
+ if (opt_intrp)
+ thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
+#endif
+
+#if defined(ENABLE_JVMTI)
+ /* fire thread start event */
+
+ if (jvmti)
+ jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
+#endif
+
+ DEBUGTHREADS("starting", t);
+
+ /* find and run the Thread.run()V method if no other function was passed */
+
+ if (function == NULL) {
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ /* We need to start the run method of
+ java.lang.VMThread. Since this is a final class, we can use
+ the class object directly. */
+
+ c = class_java_lang_VMThread;
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+ LLNI_class_get(object, c);
+#else
+# error unknown classpath configuration
+#endif
+
+ m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
+
+ if (m == NULL)
+ vm_abort("threads_startup_thread: run() method not found in class");
+
+ /* 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++
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ // We need to start the run method of java.lang.VMThread.
+ java_lang_VMThread jlvmt(jlt.get_vmThread());
+ java_handle_t* h = jlvmt.get_handle();
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ java_handle_t* h = jlt.get_handle();
+
+#else
+# error unknown classpath configuration
+#endif
+
+ /* Run the thread. */
+
+ (void) vm_call_method(m, h);
+ }
+ else {
+ /* 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++
+
+ /* call passed function, e.g. finalizer_thread */
+
+ (function)();
+ }
+
+ DEBUGTHREADS("stopping", t);
+
+#if defined(ENABLE_JVMTI)
+ /* fire thread end event */
+
+ if (jvmti)
+ jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
+
+ /* We ignore the return value. */
+
+ (void) thread_detach_current_thread();
+
+ /* set ThreadMXBean variables */
+
+/* _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
+#warning Move to C++
+
+ return NULL;
+}
+
+
+/* threads_impl_thread_start ***************************************************
+
+ Start a thread in the JVM. Both (vm internal and java) thread
+ objects exist.
+
+ IN:
+ thread....the thread object
+ f.........function to run in the new thread. NULL means that the
+ "run" method of the object `t` should be called
+
+******************************************************************************/
+
+void threads_impl_thread_start(threadobject *thread, functionptr f)
+{
+ sem_t sem;
+ sem_t sem_first;
+ pthread_attr_t attr;
+ startupinfo startup;
+ int result;
+
+ /* fill startupinfo structure passed by pthread_create to
+ * threads_startup_thread */
+
+ startup.thread = thread;
+ startup.function = f; /* maybe we don't call Thread.run()V */
+ startup.psem = &sem;
+ startup.psem_first = &sem_first;
+
+ threads_sem_init(&sem, 0, 0);
+ threads_sem_init(&sem_first, 0, 0);
+
+ /* Initialize thread attributes. */
+
+ result = pthread_attr_init(&attr);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
+
+ result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
+
+ /* initialize thread stacksize */
+
+ result = pthread_attr_setstacksize(&attr, opt_stacksize);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
+
+ /* create the thread */
+
+ result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
+
+ /* destroy the thread attributes */
+
+ result = pthread_attr_destroy(&attr);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
+
+ /* signal that pthread_create has returned, so thread->tid is valid */
+
+ threads_sem_post(&sem_first);
+
+ /* wait here until the thread has entered itself into the thread list */
+
+ threads_sem_wait(&sem);
+
+ /* cleanup */
+
+ sem_destroy(&sem);
+ sem_destroy(&sem_first);
+}
+
+
+/* threads_set_thread_priority *************************************************
+
+ Set the priority of the given thread.
+
+ IN:
+ tid..........thread id
+ priority.....priority to set
+
+******************************************************************************/
+
+void threads_set_thread_priority(pthread_t tid, int priority)
+{
+ struct sched_param schedp;
+ int policy;
+
+ pthread_getschedparam(tid, &policy, &schedp);
+ schedp.sched_priority = priority;
+ pthread_setschedparam(tid, policy, &schedp);
+}
+
+
+/**
+ * Detaches the current thread from the VM.
+ *
+ * @return true on success, false otherwise
+ */
+bool thread_detach_current_thread(void)
+{
+ threadobject* t = thread_get_current();
+
+ /* Sanity check. */
+
+ assert(t != NULL);
+
+ /* If the given thread has already been detached, this operation
+ is a no-op. */
+
+ if (thread_is_attached(t) == false)
+ return true;
+
+ DEBUGTHREADS("detaching", t);
+
+ java_handle_t* object = thread_get_object(t);
+ java_lang_Thread jlt(object);
+
+#if defined(ENABLE_JAVASE)
+ java_handle_t* group = jlt.get_group();
+
+ /* If there's an uncaught exception, call uncaughtException on the
+ thread's exception handler, or the thread's group if this is
+ unset. */
+
+ java_handle_t* e = exceptions_get_and_clear_exception();
+
+ if (e != NULL) {
+ /* We use the type void* for handler here, as it's not trivial
+ to build the java_lang_Thread_UncaughtExceptionHandler
+ header file with cacaoh. */
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ java_handle_t* handler = jlt.get_exceptionHandler();
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ java_handle_t* handler = jlt.get_uncaughtExceptionHandler();
+
+# endif
+
+ classinfo* c;
+ java_handle_t* h;
+
+ if (handler != NULL) {
+ LLNI_class_get(handler, c);
+ h = (java_handle_t *) handler;
+ }
+ else {
+ LLNI_class_get(group, c);
+ h = (java_handle_t *) group;
+ }
+
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_uncaughtException,
+ utf_java_lang_Thread_java_lang_Throwable__V,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return false;
+
+ (void) vm_call_method(m, h, object, e);
+
+ if (exceptions_get_exception())
+ return false;
+ }
+
+ /* XXX TWISTI: should all threads be in a ThreadGroup? */
+
+ /* Remove thread from the thread group. */
+
+ if (group != NULL) {
+ classinfo* c;
+ LLNI_class_get(group, c);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_removeThread,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_remove,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
+# else
+# error unknown classpath configuration
+# endif
+
+ if (m == NULL)
+ return false;
+
+ (void) vm_call_method(m, group, object);
+
+ if (exceptions_get_exception())
+ return false;
+
+ // Clear the ThreadGroup in the Java thread object (Mauve
+ // test: gnu/testlet/java/lang/Thread/getThreadGroup).
+ jlt.set_group(NULL);
+ }
+#endif
+
+ /* Thread has terminated. */
+
+ thread_set_state_terminated(t);
+
+ /* Notify all threads waiting on this thread. These are joining
+ this thread. */
+
+ /* XXX Care about exceptions? */
+ (void) lock_monitor_enter(jlt.get_handle());
+
+ lock_notify_all_object(jlt.get_handle());
+
+ /* XXX Care about exceptions? */
+ (void) lock_monitor_exit(jlt.get_handle());
+
+ /* Enter the join-mutex before calling thread_free, so
+ threads_join_all_threads gets the correct number of non-daemon
+ threads. */
+
+ threads_mutex_join_lock();
+
+ /* Free the internal thread data-structure. */
+
+ thread_free(t);
+
+ /* Signal that this thread has finished and leave the mutex. */
+
+ cond_join->signal();
+ threads_mutex_join_unlock();
+
+ return true;
+}
+
+
+/* threads_suspend_thread ******************************************************
+
+ Suspend the passed thread. Execution stops until the thread
+ is explicitly resumend again.
+
+ IN:
+ reason.....Reason for suspending this thread.
+
+*******************************************************************************/
+
+bool threads_suspend_thread(threadobject *thread, s4 reason)
+{
+ /* acquire the suspendmutex */
+ thread->suspendmutex->lock();
+
+ if (thread->suspended) {
+ thread->suspendmutex->unlock();
+ return false;
+ }
+
+ /* set the reason for the suspension */
+ thread->suspend_reason = reason;
+
+ /* send the suspend signal to the thread */
+ assert(thread != THREADOBJECT);
+ if (pthread_kill(thread->tid, SIGUSR1) != 0)
+ vm_abort("threads_suspend_thread: pthread_kill failed: %s",
+ strerror(errno));
+
+ /* REMEMBER: do not release the suspendmutex, this is done
+ by the thread itself in threads_suspend_ack(). */
+
+ return true;
+}
+
+
+/* threads_suspend_ack *********************************************************
+
+ Acknowledges the suspension of the current thread.
+
+ IN:
+ pc.....The PC where the thread suspended its execution.
+ sp.....The SP before the thread suspended its execution.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_suspend_ack(u1* pc, u1* sp)
+{
+ threadobject *thread;
+
+ thread = THREADOBJECT;
+
+ assert(thread->suspend_reason != 0);
+
+ /* TODO: remember dump memory size */
+
+ /* inform the GC about the suspension */
+ if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
+
+ /* check if the GC wants to leave the thread running */
+ if (!gc_suspend(thread, pc, sp)) {
+
+ /* REMEMBER: we do not unlock the suspendmutex because the thread
+ will suspend itself again at a later time */
+ return;
+
+ }
+ }
+
+ /* mark this thread as suspended and remember the PC */
+ thread->pc = pc;
+ thread->suspended = true;
+
+ /* if we are stopping the world, we should send a global ack */
+ if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+ threads_sem_post(&suspend_ack);
+ }
+
+ DEBUGTHREADS("suspending", thread);
+
+ /* release the suspension mutex and wait till we are resumed */
+ thread->suspendcond->wait(thread->suspendmutex);
+
+ DEBUGTHREADS("resuming", thread);
+
+ /* if we are stopping the world, we should send a global ack */
+ if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+ threads_sem_post(&suspend_ack);
+ }
+
+ /* TODO: free dump memory */
+
+ /* release the suspendmutex */
+ thread->suspendmutex->unlock();
+}
+#endif
+
+
+/* threads_resume_thread *******************************************************
+
+ Resumes the execution of the passed thread.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+bool threads_resume_thread(threadobject *thread)
+{
+ /* acquire the suspendmutex */
+ thread->suspendmutex->lock();
+
+ if (!thread->suspended) {
+ thread->suspendmutex->unlock();
+ return false;
+ }
+
+ thread->suspended = false;
+
+ /* tell everyone that the thread should resume */
+ assert(thread != THREADOBJECT);
+ thread->suspendcond->broadcast();
+
+ /* release the suspendmutex */
+ thread->suspendmutex->unlock();
+
+ return true;
+}
+#endif
+
+
+/* threads_join_all_threads ****************************************************
+
+ Join all non-daemon threads.
+
+*******************************************************************************/
+
+void threads_join_all_threads(void)
+{
+ threadobject *t;
+
+ /* get current thread */
+
+ t = THREADOBJECT;
+
+ /* This thread is waiting for all non-daemon threads to exit. */
+
+ thread_set_state_waiting(t);
+
+ /* enter join mutex */
+
+ threads_mutex_join_lock();
+
+ /* Wait for condition as long as we have non-daemon threads. We
+ compare against 1 because the current (main thread) is also a
+ non-daemon thread. */
+
+ while (threadlist_get_non_daemons() > 1)
+ cond_join->wait(mutex_join);
+
+ /* leave join mutex */
+
+ threads_mutex_join_unlock();
+}
+
+
+/* threads_timespec_earlier ****************************************************
+
+ Return true if timespec tv1 is earlier than timespec tv2.
+
+ IN:
+ tv1..........first timespec
+ tv2..........second timespec
+
+ RETURN VALUE:
+ true, if the first timespec is earlier
+
+*******************************************************************************/
+
+static inline bool threads_timespec_earlier(const struct timespec *tv1,
+ const struct timespec *tv2)
+{
+ return (tv1->tv_sec < tv2->tv_sec)
+ ||
+ (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
+}
+
+
+/* threads_current_time_is_earlier_than ****************************************
+
+ Check if the current time is earlier than the given timespec.
+
+ IN:
+ tv...........the timespec to compare against
+
+ RETURN VALUE:
+ true, if the current time is earlier
+
+*******************************************************************************/
+
+static bool threads_current_time_is_earlier_than(const struct timespec *tv)
+{
+ struct timeval tvnow;
+ struct timespec tsnow;
+
+ /* get current time */
+
+ if (gettimeofday(&tvnow, NULL) != 0)
+ vm_abort("gettimeofday failed: %s\n", strerror(errno));
+
+ /* convert it to a timespec */
+
+ tsnow.tv_sec = tvnow.tv_sec;
+ tsnow.tv_nsec = tvnow.tv_usec * 1000;
+
+ /* compare current time with the given timespec */
+
+ return threads_timespec_earlier(&tsnow, tv);
+}
+
+
+/* threads_wait_with_timeout ***************************************************
+
+ Wait until the given point in time on a monitor until either
+ we are notified, we are interrupted, or the time is up.
+
+ IN:
+ t............the current thread
+ wakeupTime...absolute (latest) wakeup time
+ If both tv_sec and tv_nsec are zero, this function
+ waits for an unlimited amount of time.
+
+*******************************************************************************/
+
+static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
+{
+ // Acquire the waitmutex.
+ t->waitmutex->lock();
+
+ /* wait on waitcond */
+
+ if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
+ /* with timeout */
+ while (!t->interrupted && !t->signaled
+ && threads_current_time_is_earlier_than(wakeupTime))
+ {
+ thread_set_state_timed_waiting(t);
+
+ t->waitcond->timedwait(t->waitmutex, wakeupTime);
+
+ thread_set_state_runnable(t);
+ }
+ }
+ else {
+ /* no timeout */
+ while (!t->interrupted && !t->signaled) {
+ thread_set_state_waiting(t);
+
+ t->waitcond->wait(t->waitmutex);
+
+ thread_set_state_runnable(t);
+ }
+ }
+
+ // Release the waitmutex.
+ t->waitmutex->unlock();
+}
+
+
+/* threads_wait_with_timeout_relative ******************************************
+
+ Wait for the given maximum amount of time on a monitor until either
+ we are notified, we are interrupted, or the time is up.
+
+ IN:
+ t............the current thread
+ millis.......milliseconds to wait
+ nanos........nanoseconds to wait
+
+*******************************************************************************/
+
+void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
+ s4 nanos)
+{
+ struct timespec wakeupTime;
+
+ /* calculate the the (latest) wakeup time */
+
+ threads_calc_absolute_time(&wakeupTime, millis, nanos);
+
+ /* wait */
+
+ threads_wait_with_timeout(thread, &wakeupTime);
+}
+
+
+/* threads_calc_absolute_time **************************************************
+
+ Calculate the absolute point in time a given number of ms and ns from now.
+
+ IN:
+ millis............milliseconds from now
+ nanos.............nanoseconds from now
+
+ OUT:
+ *tm...............receives the timespec of the absolute point in time
+
+*******************************************************************************/
+
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
+{
+ if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
+ struct timeval tv;
+ long nsec;
+ gettimeofday(&tv, NULL);
+ tv.tv_sec += millis / 1000;
+ millis %= 1000;
+ nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
+ tm->tv_sec = tv.tv_sec + nsec / 1000000000;
+ tm->tv_nsec = nsec % 1000000000;
+ }
+ else {
+ tm->tv_sec = 0;
+ tm->tv_nsec = 0;
+ }
+}
+
+
+/* threads_thread_interrupt ****************************************************
+
+ Interrupt the given thread.
+
+ The thread gets the "waitcond" signal and
+ its interrupted flag is set to true.
+
+ IN:
+ thread............the thread to interrupt
+
+*******************************************************************************/
+
+void threads_thread_interrupt(threadobject *t)
+{
+ /* Signal the thread a "waitcond" and tell it that it has been
+ interrupted. */
+
+ t->waitmutex->lock();
+
+ DEBUGTHREADS("interrupted", t);
+
+ /* Interrupt blocking system call using a signal. */
+
+ pthread_kill(t->tid, Signal_INTERRUPT_SYSTEM_CALL);
+
+ t->waitcond->signal();
+
+ t->interrupted = true;
+
+ t->waitmutex->unlock();
+}
+
+
+/**
+ * Sleep the current thread for the specified amount of time.
+ *
+ * @param millis Milliseconds to sleep.
+ * @param nanos Nanoseconds to sleep.
+ */
+void threads_sleep(int64_t millis, int32_t nanos)
+{
+ threadobject *t;
+ struct timespec wakeupTime;
+ bool interrupted;
+
+ if (millis < 0) {
+/* exceptions_throw_illegalargumentexception("timeout value is negative"); */
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ t = thread_get_current();
+
+ if (thread_is_interrupted(t) && !exceptions_get_exception()) {
+ /* Clear interrupted flag (Mauve test:
+ gnu/testlet/java/lang/Thread/interrupt). */
+
+ thread_set_interrupted(t, false);
+
+/* exceptions_throw_interruptedexception("sleep interrupted"); */
+ exceptions_throw_interruptedexception();
+ return;
+ }
+
+ // (Note taken from classpath/vm/reference/java/lang/VMThread.java (sleep))
+ // Note: JDK treats a zero length sleep is like Thread.yield(),
+ // without checking the interrupted status of the thread. It's
+ // unclear if this is a bug in the implementation or the spec.
+ // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203 */
+ if (millis == 0 && nanos == 0) {
+ threads_yield();
+ }
+ else {
+ threads_calc_absolute_time(&wakeupTime, millis, nanos);
+
+ threads_wait_with_timeout(t, &wakeupTime);
+
+ interrupted = thread_is_interrupted(t);
+
+ if (interrupted) {
+ thread_set_interrupted(t, false);
+
+ // An other exception could have been thrown
+ // (e.g. ThreadDeathException).
+ if (!exceptions_get_exception())
+ exceptions_throw_interruptedexception();
+ }
+ }
+}
+
+
+/* threads_yield ***************************************************************
+
+ Yield to the scheduler.
+
+*******************************************************************************/
+
+void threads_yield(void)
+{
+ sched_yield();
+}
+
+#if defined(ENABLE_TLH)
+
+void threads_tlh_add_frame() {
+ tlh_add_frame(&(THREADOBJECT->tlh));
+}
+
+void threads_tlh_remove_frame() {
+ tlh_remove_frame(&(THREADOBJECT->tlh));
+}
+
+#endif
+
+} // extern "C"
+
+
+/*
+ * 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/threads/posix/thread-posix.h - POSIX thread 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.
-
-*/
-
-
-#ifndef _THREAD_POSIX_H
-#define _THREAD_POSIX_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct threadobject threadobject;
-
-
-#include "config.h"
-
-#include <pthread.h>
-#include <ucontext.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/localref.h"
-
-#include "threads/mutex.h"
-
-#include "threads/posix/lock.h"
-
-#include "vm/global.h"
-#include "vm/vm.h"
-
-#if defined(ENABLE_GC_CACAO)
-# include "vm/jit/replace.h"
-#endif
-
-#include "vm/jit/stacktrace.h"
-
-#if defined(ENABLE_INTRP)
-#include "vm/jit/intrp/intrp.h"
-#endif
-
-#if defined(__DARWIN__)
-# include <mach/mach.h>
-
-typedef struct {
- mutex_t mutex;
- pthread_cond_t cond;
- int value;
-} sem_t;
-
-#else
-# include <semaphore.h>
-#endif
-
-
-/* current threadobject *******************************************************/
-
-#if defined(HAVE___THREAD)
-
-#define THREADOBJECT thread_current
-
-extern __thread threadobject *thread_current;
-
-#else /* defined(HAVE___THREAD) */
-
-#define THREADOBJECT \
- ((threadobject *) pthread_getspecific(thread_current_key))
-
-extern pthread_key_t thread_current_key;
-
-#endif /* defined(HAVE___THREAD) */
-
-
-/* threadobject ****************************************************************
-
- Struct holding thread local variables.
-
-*******************************************************************************/
-
-#define THREAD_FLAG_JAVA 0x01 /* a normal Java thread */
-#define THREAD_FLAG_INTERNAL 0x02 /* CACAO internal thread */
-#define THREAD_FLAG_DAEMON 0x04 /* daemon thread */
-#define THREAD_FLAG_IN_NATIVE 0x08 /* currently executing native code */
-
-#define SUSPEND_REASON_JNI 1 /* suspended from JNI */
-#define SUSPEND_REASON_STOPWORLD 2 /* suspended from stop-thw-world */
-
-
-struct threadobject {
- java_object_t *object; /* link to java.lang.Thread object */
-
- ptrint thinlock; /* pre-computed thin lock value */
-
- s4 index; /* thread index, starting with 1 */
- u4 flags; /* flag field */
- u4 state; /* state field */
-
- pthread_t tid; /* pthread id */
-
-#if defined(__DARWIN__)
- mach_port_t mach_thread; /* Darwin thread id */
-#endif
-
- /* for the sable tasuki lock extension */
- bool flc_bit;
- struct threadobject *flc_list; /* FLC list head for this thread */
- struct threadobject *flc_next; /* next pointer for FLC list */
- java_handle_t *flc_object;
- mutex_t flc_lock; /* controlling access to these fields */
- pthread_cond_t flc_cond;
-
- /* these are used for the wait/notify implementation */
- mutex_t waitmutex;
- pthread_cond_t waitcond;
-
- mutex_t suspendmutex; /* lock before suspending this thread */
- pthread_cond_t suspendcond; /* notify to resume this thread */
-
- bool interrupted;
- bool signaled;
-
- bool suspended; /* is this thread suspended? */
- s4 suspend_reason; /* reason for suspending */
-
- u1 *pc; /* current PC (used for profiling) */
-
- java_object_t *_exceptionptr; /* current exception */
- stackframeinfo_t *_stackframeinfo; /* current native stackframeinfo */
- localref_table *_localref_table; /* JNI local references */
-
-#if defined(ENABLE_INTRP)
- Cell *_global_sp; /* stack pointer for interpreter */
-#endif
-
-#if defined(ENABLE_GC_CACAO)
- bool gc_critical; /* indicates a critical section */
-
- sourcestate_t *ss;
- executionstate_t *es;
-#endif
-
- dumpinfo_t dumpinfo; /* dump memory info structure */
-
-#if defined(ENABLE_DEBUG_FILTER)
- u2 filterverbosecallctr[2]; /* counters for verbose call filter */
-#endif
-
-#if !defined(NDEBUG)
- s4 tracejavacallindent;
- u4 tracejavacallcount;
-#endif
-
- listnode_t linkage; /* threads-list */
- listnode_t linkage_free; /* free-list */
-};
-
-
-/* native-world flags *********************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-# define THREAD_NATIVEWORLD_ENTER THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE
-# define THREAD_NATIVEWORLD_EXIT THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE
-#else
-# define THREAD_NATIVEWORLD_ENTER /*nop*/
-# define THREAD_NATIVEWORLD_EXIT /*nop*/
-#endif
-
-
-/* counter for verbose call filter ********************************************/
-
-#if defined(ENABLE_DEBUG_FILTER)
-# define FILTERVERBOSECALLCTR (THREADOBJECT->filterverbosecallctr)
-#endif
-
-/* state for trace java call **************************************************/
-
-#if !defined(NDEBUG)
-# define TRACEJAVACALLINDENT (THREADOBJECT->tracejavacallindent)
-# define TRACEJAVACALLCOUNT (THREADOBJECT->tracejavacallcount)
-#endif
-
-
-/* inline functions ***********************************************************/
-
-/* thread_get_current **********************************************************
-
- Return the threadobject of the current thread.
-
- RETURN:
- the current threadobject *
-
-*******************************************************************************/
-
-inline static threadobject *thread_get_current(void)
-{
- threadobject *t;
-
-#if defined(HAVE___THREAD)
- t = thread_current;
-#else
- t = (threadobject *) pthread_getspecific(thread_current_key);
-#endif
-
- return t;
-}
-
-
-/* thread_set_current **********************************************************
-
- Set the current thread object.
-
- IN:
- t ... the thread object to set
-
-*******************************************************************************/
-
-inline static void thread_set_current(threadobject *t)
-{
-#if defined(HAVE___THREAD)
- thread_current = t;
-#else
- int result;
-
- result = pthread_setspecific(thread_current_key, t);
-
- if (result != 0)
- vm_abort_errnum(result, "thread_set_current: pthread_setspecific failed");
-#endif
-}
-
-
-inline static stackframeinfo_t *threads_get_current_stackframeinfo(void)
-{
- return THREADOBJECT->_stackframeinfo;
-}
-
-inline static void threads_set_current_stackframeinfo(stackframeinfo_t *sfi)
-{
- THREADOBJECT->_stackframeinfo = sfi;
-}
-
-
-/* functions ******************************************************************/
-
-void threads_sem_init(sem_t *sem, bool shared, int value);
-void threads_sem_wait(sem_t *sem);
-void threads_sem_post(sem_t *sem);
-
-void threads_start_thread(threadobject *thread, functionptr function);
-
-void threads_set_thread_priority(pthread_t tid, int priority);
-
-#if defined(ENABLE_GC_CACAO)
-bool threads_suspend_thread(threadobject *thread, s4 reason);
-void threads_suspend_ack(u1* pc, u1* sp);
-bool threads_resume_thread(threadobject *thread);
-#endif
-
-void threads_join_all_threads(void);
-
-void threads_sleep(int64_t millis, int32_t nanos);
-
-void threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
-
-void threads_thread_interrupt(threadobject *thread);
-
-#endif /* _THREAD_POSIX_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:
- */
--- /dev/null
+/* src/threads/posix/thread-posix.hpp - POSIX thread 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.
+
+*/
+
+
+#ifndef _THREAD_POSIX_HPP
+#define _THREAD_POSIX_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct threadobject threadobject;
+
+
+#include "config.h"
+
+#include <pthread.h>
+#include <ucontext.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#if defined(ENABLE_TLH)
+#include "mm/tlh.h"
+#endif
+
+#include "native/localref.h"
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+
+#include "threads/posix/lock.h"
+
+#include "vm/global.h"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_GC_CACAO)
+# include "vm/jit/executionstate.h"
+# include "vm/jit/replace.h"
+#endif
+
+#include "vm/jit/stacktrace.hpp"
+
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
+#if defined(__DARWIN__)
+# include <mach/mach.h>
+
+typedef struct {
+ Mutex* mutex;
+ Condition* cond;
+ int value;
+} sem_t;
+
+#else
+# include <semaphore.h>
+#endif
+
+
+// FIXME
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* current threadobject *******************************************************/
+
+#if defined(HAVE___THREAD)
+
+#define THREADOBJECT thread_current
+
+extern __thread threadobject *thread_current;
+
+#else /* defined(HAVE___THREAD) */
+
+#define THREADOBJECT \
+ ((threadobject *) pthread_getspecific(thread_current_key))
+
+extern pthread_key_t thread_current_key;
+
+#endif /* defined(HAVE___THREAD) */
+
+
+/* threadobject ****************************************************************
+
+ Struct holding thread local variables.
+
+*******************************************************************************/
+
+#define THREAD_FLAG_JAVA 0x01 /* a normal Java thread */
+#define THREAD_FLAG_INTERNAL 0x02 /* CACAO internal thread */
+#define THREAD_FLAG_DAEMON 0x04 /* daemon thread */
+#define THREAD_FLAG_IN_NATIVE 0x08 /* currently executing native code */
+
+#define SUSPEND_REASON_JNI 1 /* suspended from JNI */
+#define SUSPEND_REASON_STOPWORLD 2 /* suspended from stop-thw-world */
+
+
+struct threadobject {
+ java_object_t *object; /* link to java.lang.Thread object */
+
+ ptrint thinlock; /* pre-computed thin lock value */
+
+ s4 index; /* thread index, starting with 1 */
+ u4 flags; /* flag field */
+ u4 state; /* state field */
+
+ pthread_t tid; /* pthread id */
+
+#if defined(__DARWIN__)
+ mach_port_t mach_thread; /* Darwin thread id */
+#endif
+
+ /* for the sable tasuki lock extension */
+ bool flc_bit;
+ struct threadobject *flc_list; /* FLC list head for this thread */
+ struct threadobject *flc_next; /* next pointer for FLC list */
+ java_handle_t *flc_object;
+ Mutex* flc_lock; /* controlling access to these fields */
+ Condition* flc_cond;
+
+ /* these are used for the wait/notify implementation */
+ Mutex* waitmutex;
+ Condition* waitcond;
+
+ Mutex* suspendmutex; /* lock before suspending this thread */
+ Condition* suspendcond; /* notify to resume this thread */
+
+ bool interrupted;
+ bool signaled;
+
+ bool suspended; /* is this thread suspended? */
+ s4 suspend_reason; /* reason for suspending */
+
+ u1 *pc; /* current PC (used for profiling) */
+
+ java_object_t *_exceptionptr; /* current exception */
+ stackframeinfo_t *_stackframeinfo; /* current native stackframeinfo */
+ localref_table *_localref_table; /* JNI local references */
+
+#if defined(ENABLE_INTRP)
+ Cell *_global_sp; /* stack pointer for interpreter */
+#endif
+
+#if defined(ENABLE_GC_CACAO)
+ bool gc_critical; /* indicates a critical section */
+
+ sourcestate_t *ss;
+ executionstate_t *es;
+#endif
+
+ dumpinfo_t dumpinfo; /* dump memory info structure */
+
+#if defined(ENABLE_DEBUG_FILTER)
+ u2 filterverbosecallctr[2]; /* counters for verbose call filter */
+#endif
+
+#if !defined(NDEBUG)
+ s4 tracejavacallindent;
+ u4 tracejavacallcount;
+#endif
+
+#if defined(ENABLE_TLH)
+ tlh_t tlh;
+#endif
+
+#if defined(ENABLE_ESCAPE_REASON)
+ void *escape_reasons;
+#endif
+
+ listnode_t linkage; /* threads-list */
+ listnode_t linkage_free; /* free-list */
+};
+
+
+/* native-world flags *********************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+# define THREAD_NATIVEWORLD_ENTER THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE
+# define THREAD_NATIVEWORLD_EXIT THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE
+#else
+# define THREAD_NATIVEWORLD_ENTER /*nop*/
+# define THREAD_NATIVEWORLD_EXIT /*nop*/
+#endif
+
+
+/* counter for verbose call filter ********************************************/
+
+#if defined(ENABLE_DEBUG_FILTER)
+# define FILTERVERBOSECALLCTR (THREADOBJECT->filterverbosecallctr)
+#endif
+
+/* state for trace java call **************************************************/
+
+#if !defined(NDEBUG)
+# define TRACEJAVACALLINDENT (THREADOBJECT->tracejavacallindent)
+# define TRACEJAVACALLCOUNT (THREADOBJECT->tracejavacallcount)
+#endif
+
+
+/* inline functions ***********************************************************/
+
+/* thread_get_current **********************************************************
+
+ Return the threadobject of the current thread.
+
+ RETURN:
+ the current threadobject *
+
+*******************************************************************************/
+
+inline static threadobject *thread_get_current(void)
+{
+ threadobject *t;
+
+#if defined(HAVE___THREAD)
+ t = thread_current;
+#else
+ t = (threadobject *) pthread_getspecific(thread_current_key);
+#endif
+
+ return t;
+}
+
+
+/* thread_set_current **********************************************************
+
+ Set the current thread object.
+
+ IN:
+ t ... the thread object to set
+
+*******************************************************************************/
+
+inline static void thread_set_current(threadobject *t)
+{
+#if defined(HAVE___THREAD)
+ thread_current = t;
+#else
+ int result;
+
+ result = pthread_setspecific(thread_current_key, t);
+
+ if (result != 0)
+ vm_abort_errnum(result, "thread_set_current: pthread_setspecific failed");
+#endif
+}
+
+
+inline static stackframeinfo_t *threads_get_current_stackframeinfo(void)
+{
+ return THREADOBJECT->_stackframeinfo;
+}
+
+inline static void threads_set_current_stackframeinfo(stackframeinfo_t *sfi)
+{
+ THREADOBJECT->_stackframeinfo = sfi;
+}
+
+
+/* functions ******************************************************************/
+
+void threads_sem_init(sem_t *sem, bool shared, int value);
+void threads_sem_wait(sem_t *sem);
+void threads_sem_post(sem_t *sem);
+
+void threads_start_thread(threadobject *thread, functionptr function);
+
+void threads_set_thread_priority(pthread_t tid, int priority);
+
+#if defined(ENABLE_GC_CACAO)
+bool threads_suspend_thread(threadobject *thread, s4 reason);
+void threads_suspend_ack(u1* pc, u1* sp);
+bool threads_resume_thread(threadobject *thread);
+#endif
+
+void threads_join_all_threads(void);
+
+void threads_sleep(int64_t millis, int32_t nanos);
+
+void threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
+
+void threads_thread_interrupt(threadobject *thread);
+
+#if defined(ENABLE_TLH)
+void threads_tlh_add_frame();
+void threads_tlh_remove_frame();
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _THREAD_POSIX_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
+/* src/threads/removeme.cpp
+
+ Copyright (C) 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.
+
+*/
+
+// XXX Remove me as soon as all using files have been converted to C++!
+
+#include "config.h"
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+
+extern "C" {
+
+Mutex* Mutex_new() { return new Mutex(); }
+void Mutex_delete(Mutex* mutex) { delete mutex; }
+void Mutex_lock(Mutex* mutex) { mutex->lock(); }
+void Mutex_unlock(Mutex* mutex) { mutex->unlock(); }
+
+Condition* Condition_new() { return new Condition(); }
+void Condition_delete(Condition* cond) { delete cond; }
+void Condition_broadcast(Condition* cond) { cond->broadcast(); }
+void Condition_signal(Condition* cond) { cond->signal(); }
+void Condition_timedwait(Condition* cond, Mutex* mutex, const struct timespec* abstime) { cond->timedwait(mutex, abstime); }
+void Condition_wait(Condition* cond, Mutex* mutex) { cond->wait(mutex); }
+
+}
+
+
+/*
+ * 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/threads/thread.c - machine independent thread 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.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#if defined(ENABLE_GC_BOEHM)
-/* We need to include Boehm's gc.h here for GC_register_my_thread and
- friends. */
-# include "mm/boehm-gc/include/gc.h"
-#endif
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Thread.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/java_lang_VMThread.h"
-#endif
-
-#include "threads/critical.h"
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
-#include "threads/thread.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/utf8.h"
-
-
-/* global variables ***********************************************************/
-
-static methodinfo *thread_method_init;
-static java_handle_t *threadgroup_system;
-static java_handle_t *threadgroup_main;
-
-#if defined(__LINUX__)
-/* XXX Remove for exact-GC. */
-bool threads_pthreads_implementation_nptl;
-#endif
-
-
-/* static functions ***********************************************************/
-
-static void thread_create_initial_threadgroups(void);
-static void thread_create_initial_thread(void);
-static threadobject *thread_new(void);
-
-
-/* threads_preinit *************************************************************
-
- Do some early initialization of stuff required.
-
-*******************************************************************************/
-
-void threads_preinit(void)
-{
- threadobject *mainthread;
-#if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
- char *pathbuf;
- size_t len;
-#endif
-
- TRACESUBSYSTEMINITIALIZATION("threads_preinit");
-
-#if defined(__LINUX__)
- /* XXX Remove for exact-GC. */
-
- /* On Linux we need to check the pthread implementation. */
-
- /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
- /* If the glibc is a pre-2.3.2 version, we fall back to
- linuxthreads. */
-
-# if defined(_CS_GNU_LIBPTHREAD_VERSION)
- len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
-
- /* Some systems return as length 0 (maybe cross-compilation
- related). In this case we also fall back to linuxthreads. */
-
- if (len > 0) {
- pathbuf = MNEW(char, len);
-
- (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
-
- if (strstr(pathbuf, "NPTL") != NULL)
- threads_pthreads_implementation_nptl = true;
- else
- threads_pthreads_implementation_nptl = false;
- }
- else
- threads_pthreads_implementation_nptl = false;
-# else
- threads_pthreads_implementation_nptl = false;
-# endif
-#endif
-
- /* Initialize the threads implementation (sets the thinlock on the
- main thread). */
-
- threads_impl_preinit();
-
- /* Create internal thread data-structure for the main thread. */
-
- mainthread = thread_new();
-
- /* The main thread should always have index 1. */
-
- if (mainthread->index != 1)
- vm_abort("threads_preinit: main thread index not 1: %d != 1",
- mainthread->index);
-
- /* thread is a Java thread and running */
-
- mainthread->flags |= THREAD_FLAG_JAVA;
- mainthread->state = THREAD_STATE_RUNNABLE;
-
- /* Store the internal thread data-structure in the TSD. */
-
- thread_set_current(mainthread);
-}
-
-
-/* threads_init ****************************************************************
-
- Initialize the main thread.
-
-*******************************************************************************/
-
-void threads_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("threads_init");
-
- /* Create the system and main thread groups. */
-
- thread_create_initial_threadgroups();
-
- /* Cache the java.lang.Thread initialization method. */
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- thread_method_init =
- class_resolveclassmethod(class_java_lang_Thread,
- utf_init,
- utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
- class_java_lang_Thread,
- true);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- thread_method_init =
- class_resolveclassmethod(class_java_lang_Thread,
- utf_init,
- utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V"),
- class_java_lang_Thread,
- true);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- thread_method_init =
- class_resolveclassmethod(class_java_lang_Thread,
- utf_init,
- utf_java_lang_String__void,
- class_java_lang_Thread,
- true);
-
-#else
-# error unknown classpath configuration
-#endif
-
- if (thread_method_init == NULL)
- vm_abort("threads_init: failed to resolve thread init method");
-
- thread_create_initial_thread();
-}
-
-
-/* thread_create_object ********************************************************
-
- Create a Java thread object for the given thread data-structure,
- initializes it and adds the thread to the threadgroup.
-
- ARGUMENTS:
-
- t ....... thread
- name .... thread name
- group ... threadgroup
-
- RETURN:
-
-*******************************************************************************/
-
-static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
-{
- java_handle_t *o;
- java_lang_Thread *to;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThread *vmto;
- classinfo *c;
- methodinfo *m;
- bool isdaemon;
-#endif
-
- /* Create a java.lang.Thread Java object. */
-
- o = builtin_new(class_java_lang_Thread);
-
- if (o == NULL)
- return false;
-
- to = (java_lang_Thread *) o;
-
- /* Set the Java object in the thread data-structure. This
- indicates that the thread is attached to the VM. */
-
- thread_set_object(t, (java_handle_t *) to);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Create a java.lang.VMThread Java object. */
-
- vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
-
- if (vmto == NULL)
- return false;
-
- /* Set the Java thread object in the Java VM-thread object. */
-
- LLNI_field_set_ref(vmto, thread, to);
-
- /* Set the thread data-structure in the Java VM-thread object. */
-
- LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
-
- /* Call:
- java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
-
- isdaemon = thread_is_daemon(t);
-
- (void) vm_call_method(thread_method_init, o, vmto, name, NORM_PRIORITY,
- isdaemon);
-
- if (exceptions_get_exception())
- return false;
-
- /* Set the threadgroup in the Java thread object. */
-
- LLNI_field_set_ref(to, group, (java_lang_ThreadGroup *) group);
-
- /* Add thread to the threadgroup. */
-
- LLNI_class_get(group, c);
-
- m = class_resolveclassmethod(c,
- utf_addThread,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
-
- if (m == NULL)
- return false;
-
- (void) vm_call_method(m, group, to);
-
- if (exceptions_get_exception())
- return false;
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* OpenJDK's java.lang.Thread does not have a VMThread field in
- the class. Nothing to do here. */
-
- /* Set the priority. java.lang.Thread.<init> requires it because
- it sets the priority of the current thread to the parent's one
- (which is the current thread in this case). */
-
- LLNI_field_set_val(to, priority, NORM_PRIORITY);
-
- /* Call:
- java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V */
-
- (void) vm_call_method(thread_method_init, o, group, name);
-
- if (exceptions_get_exception())
- return false;
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- /* Set the thread data-structure in the Java thread object. */
-
- LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
-
- /* Call: public Thread(Ljava/lang/String;)V */
-
- (void) vm_call_method(thread_method_init, o, name);
-
- if (exceptions_get_exception())
- return false;
-
-#else
-# error unknown classpath configuration
-#endif
-
- return true;
-}
-
-
-/* thread_create_initial_threadgroups ******************************************
-
- Create the initial threadgroups.
-
- GNU Classpath:
- Create the main threadgroup only and set the system
- threadgroup to the main threadgroup.
-
- SUN:
- Create the system and main threadgroup.
-
- CLDC:
- This function is a no-op.
-
-*******************************************************************************/
-
-static void thread_create_initial_threadgroups(void)
-{
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Allocate and initialize the main thread group. */
-
- threadgroup_main = native_new_and_init(class_java_lang_ThreadGroup);
-
- if (threadgroup_main == NULL)
- vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
-
- /* Use the same threadgroup for system as for main. */
-
- threadgroup_system = threadgroup_main;
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- java_handle_t *name;
- methodinfo *m;
-
- /* Allocate and initialize the system thread group. */
-
- threadgroup_system = native_new_and_init(class_java_lang_ThreadGroup);
-
- if (threadgroup_system == NULL)
- vm_abort("thread_create_initial_threadgroups: failed to allocate system threadgroup");
-
- /* Allocate and initialize the main thread group. */
-
- threadgroup_main = builtin_new(class_java_lang_ThreadGroup);
-
- if (threadgroup_main == NULL)
- vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
-
- name = javastring_new(utf_main);
-
- m = class_resolveclassmethod(class_java_lang_ThreadGroup,
- utf_init,
- utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V,
- class_java_lang_ThreadGroup,
- true);
-
- if (m == NULL)
- vm_abort("thread_create_initial_threadgroups: failed to resolve threadgroup init method");
-
- (void) vm_call_method(m, threadgroup_main, threadgroup_system, name);
-
- if (exceptions_get_exception())
- vm_abort("thread_create_initial_threadgroups: exception while initializing main threadgroup");
-
-# else
-# error unknown classpath configuration
-# endif
-#endif
-}
-
-
-/* thread_create_initial_thread ***********************************************
-
- Create the initial thread: main
-
-*******************************************************************************/
-
-static void thread_create_initial_thread(void)
-{
- threadobject *t;
- java_handle_t *name;
-
- /* Get the main-thread (NOTE: The main thread is always the first
- thread in the list). */
-
- t = threadlist_first();
-
- /* The thread name. */
-
- name = javastring_new(utf_main);
-
-#if defined(ENABLE_INTRP)
- /* create interpreter stack */
-
- if (opt_intrp) {
- MSET(intrp_main_stack, 0, u1, opt_stacksize);
- mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
- }
-#endif
-
- /* Create the Java thread object. */
-
- if (!thread_create_object(t, name, threadgroup_main))
- vm_abort("thread_create_initial_thread: failed to create Java object");
-
- /* Initialize the implementation specific bits. */
-
- threads_impl_init();
-
- DEBUGTHREADS("starting (main)", t);
-}
-
-
-/* thread_new ******************************************************************
-
- Allocates and initializes an internal thread data-structure and
- adds it to the threads list.
-
-*******************************************************************************/
-
-static threadobject *thread_new(void)
-{
- int32_t index;
- threadobject *t;
-
- /* Lock the thread lists */
-
- threadlist_lock();
-
- index = threadlist_get_free_index();
-
- /* Allocate a thread data structure. */
-
- /* First, try to get one from the free-list. */
-
- t = threadlist_free_first();
-
- if (t != NULL) {
- /* Remove from free list. */
-
- threadlist_free_remove(t);
-
- /* Equivalent of MZERO on the else path */
-
- threads_impl_thread_clear(t);
- }
- else {
-#if defined(ENABLE_GC_BOEHM)
- t = GCNEW_UNCOLLECTABLE(threadobject, 1);
-#else
- t = NEW(threadobject);
-#endif
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_threadobject += sizeof(threadobject);
-#endif
-
- /* Clear memory. */
-
- MZERO(t, threadobject, 1);
-
-#if defined(ENABLE_GC_CACAO)
- /* Register reference to java.lang.Thread with the GC. */
- /* FIXME is it ok to do this only once? */
-
- gc_reference_register(&(t->object), GC_REFTYPE_THREADOBJECT);
- gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
-#endif
-
- /* Initialize the implementation-specific bits. */
-
- threads_impl_thread_init(t);
- }
-
- /* Pre-compute the thinlock-word. */
-
- assert(index != 0);
-
- t->index = index;
- t->thinlock = lock_pre_compute_thinlock(t->index);
- t->flags = 0;
- t->state = THREAD_STATE_NEW;
-
-#if defined(ENABLE_GC_CACAO)
- t->flags |= THREAD_FLAG_IN_NATIVE;
-#endif
-
- /* Initialize the implementation-specific bits. */
-
- threads_impl_thread_reuse(t);
-
- /* Add the thread to the thread list. */
-
- threadlist_add(t);
-
- /* Unlock the thread lists. */
-
- threadlist_unlock();
-
- return t;
-}
-
-
-/* thread_free *****************************************************************
-
- Remove the thread from the threads-list and free the internal
- thread data structure. The thread index is added to the
- thread-index free-list.
-
- IN:
- t ... thread data structure
-
-*******************************************************************************/
-
-void thread_free(threadobject *t)
-{
- /* Lock the thread lists. */
-
- threadlist_lock();
-
- /* Remove the thread from the thread-list. */
-
- threadlist_remove(t);
-
- /* Add the thread index to the free list. */
-
- threadlist_index_add(t->index);
-
- /* Set the reference to the Java object to NULL. */
-
- thread_set_object(t, NULL);
-
- /* Add the thread data structure to the free list. */
-
- threadlist_free_add(t);
-
- /* Unlock the thread lists. */
-
- threadlist_unlock();
-}
-
-
-/* threads_thread_start_internal ***********************************************
-
- Start an internal thread in the JVM. No Java thread objects exists
- so far.
-
- IN:
- name.......UTF-8 name of the thread
- f..........function pointer to C function to start
-
-*******************************************************************************/
-
-bool threads_thread_start_internal(utf *name, functionptr f)
-{
- threadobject *t;
-
- /* Enter the join-mutex, so if the main-thread is currently
- waiting to join all threads, the number of non-daemon threads
- is correct. */
-
- threads_mutex_join_lock();
-
- /* Create internal thread data-structure. */
-
- t = thread_new();
-
- t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
-
- /* The thread is flagged as (non-)daemon thread, we can leave the
- mutex. */
-
- threads_mutex_join_unlock();
-
- /* Create the Java thread object. */
-
- if (!thread_create_object(t, javastring_new(name), threadgroup_system))
- return false;
-
- /* Start the thread. */
-
- threads_impl_thread_start(t, f);
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* threads_thread_start ********************************************************
-
- Start a Java thread in the JVM. Only the java thread object exists
- so far.
-
- IN:
- object.....the java thread object java.lang.Thread
-
-*******************************************************************************/
-
-void threads_thread_start(java_handle_t *object)
-{
- java_lang_Thread *to;
- threadobject *t;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThread *vmto;
-#endif
-
- to = (java_lang_Thread *) object;
-
- /* Enter the join-mutex, so if the main-thread is currently
- waiting to join all threads, the number of non-daemon threads
- is correct. */
-
- threads_mutex_join_lock();
-
- /* Create internal thread data-structure. */
-
- t = thread_new();
-
- /* this is a normal Java thread */
-
- t->flags |= THREAD_FLAG_JAVA;
-
-#if defined(ENABLE_JAVASE)
- /* Is this a daemon thread? */
-
- if (LLNI_field_direct(to, daemon) == true)
- t->flags |= THREAD_FLAG_DAEMON;
-#endif
-
- /* The thread is flagged and (non-)daemon thread, we can leave the
- mutex. */
-
- threads_mutex_join_unlock();
-
- /* Link the two objects together. */
-
- thread_set_object(t, object);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Get the java.lang.VMThread object and do some sanity checks. */
-
- LLNI_field_get_ref(to, vmThread, vmto);
-
- assert(vmto);
- assert(LLNI_field_direct(vmto, vmdata) == NULL);
-
- LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* Nothing to do. */
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
-
-#else
-# error unknown classpath configuration
-#endif
-
- /* Start the thread. Don't pass a function pointer (NULL) since
- we want Thread.run()V here. */
-
- threads_impl_thread_start(t, NULL);
-}
-
-
-/**
- * Attaches the current thread to the VM.
- *
- * @param vm_aargs Attach arguments.
- * @param isdaemon true if the attached thread should be a daemon
- * thread.
- *
- * @return true on success, false otherwise.
- */
-bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
-{
- bool result;
- threadobject *t;
- utf *u;
- java_handle_t *name;
- java_handle_t *group;
-
- /* If the current thread has already been attached, this operation
- is a no-op. */
-
- result = thread_current_is_attached();
-
- if (result == true)
- return true;
-
- /* Enter the join-mutex, so if the main-thread is currently
- waiting to join all threads, the number of non-daemon threads
- is correct. */
-
- threads_mutex_join_lock();
-
- /* Create internal thread data structure. */
-
- t = thread_new();
-
- /* Thread is a Java thread and running. */
-
- t->flags = THREAD_FLAG_JAVA;
-
- if (isdaemon)
- t->flags |= THREAD_FLAG_DAEMON;
-
- /* Store the internal thread data-structure in the TSD. */
-
- thread_set_current(t);
-
- /* The thread is flagged and (non-)daemon thread, we can leave the
- mutex. */
-
- threads_mutex_join_unlock();
-
- DEBUGTHREADS("attaching", t);
-
- /* Get the thread name. */
-
- if (vm_aargs != NULL) {
- u = utf_new_char(vm_aargs->name);
- }
- else {
- u = utf_null;
- }
-
- name = javastring_new(u);
-
-#if defined(ENABLE_JAVASE)
- /* Get the threadgroup. */
-
- if (vm_aargs != NULL)
- group = (java_handle_t *) vm_aargs->group;
- else
- group = NULL;
-
- /* If no threadgroup was given, use the main threadgroup. */
-
- if (group == NULL)
- group = threadgroup_main;
-#endif
-
-#if defined(ENABLE_INTRP)
- /* create interpreter stack */
-
- if (opt_intrp) {
- MSET(intrp_main_stack, 0, u1, opt_stacksize);
- thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
- }
-#endif
-
- /* Create the Java thread object. */
-
- if (!thread_create_object(t, name, group))
- return false;
-
- /* The thread is completely initialized. */
-
- thread_set_state_runnable(t);
-
- return true;
-}
-
-
-/**
- * Attaches the current external thread to the VM. This function is
- * called by JNI's AttachCurrentThread.
- *
- * @param vm_aargs Attach arguments.
- * @param isdaemon true if the attached thread should be a daemon
- * thread.
- *
- * @return true on success, false otherwise.
- */
-bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
-{
- int result;
-
-#if defined(ENABLE_GC_BOEHM)
- struct GC_stack_base sb;
-#endif
-
-#if defined(ENABLE_GC_BOEHM)
- /* Register the thread with Boehm-GC. This must happen before the
- thread allocates any memory from the GC heap.*/
-
- result = GC_get_stack_base(&sb);
-
- if (result != GC_SUCCESS)
- vm_abort("threads_attach_current_thread: GC_get_stack_base failed");
-
- GC_register_my_thread(&sb);
-#endif
-
- result = thread_attach_current_thread(vm_aargs, isdaemon);
-
- if (result == false) {
-#if defined(ENABLE_GC_BOEHM)
- /* Unregister the thread. */
-
- GC_unregister_my_thread();
-#endif
-
- return false;
- }
-
- return true;
-}
-
-
-/**
- * Detaches the current external thread from the VM. This function is
- * called by JNI's DetachCurrentThread.
- *
- * @return true on success, false otherwise.
- */
-bool thread_detach_current_external_thread(void)
-{
- int result;
-
- result = thread_detach_current_thread();
-
- if (result == false)
- return false;
-
-#if defined(ENABLE_GC_BOEHM)
- /* Unregister the thread with Boehm-GC. This must happen after
- the thread allocates any memory from the GC heap. */
-
- /* Don't detach the main thread. This is a workaround for
- OpenJDK's java binary. */
- if (thread_get_current()->index != 1)
- GC_unregister_my_thread();
-#endif
-
- return true;
-}
-
-
-/* thread_fprint_name **********************************************************
-
- Print the name of the given thread to the given stream.
-
- ARGUMENTS:
- t ........ thread data-structure
- stream ... stream to print to
-
-*******************************************************************************/
-
-void thread_fprint_name(threadobject *t, FILE *stream)
-{
- java_lang_Thread *to;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_String *name;
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- java_chararray_t *name;
-#endif
-
- to = (java_lang_Thread *) thread_get_object(t);
-
- if (to == NULL)
- vm_abort("");
-
- LLNI_field_get_ref(to, name, name);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- javastring_fprint((java_handle_t *) name, stream);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- /* FIXME: In OpenJDK and CLDC the name is a char[]. */
- /* FIXME This prints to stdout. */
- utf_display_printable_ascii(utf_null);
-
-#else
-# error unknown classpath configuration
-#endif
-}
-
-
-/* thread_print_info ***********************************************************
-
- Print information of the passed thread.
-
- ARGUMENTS:
- t ... thread data-structure.
-
-*******************************************************************************/
-
-void thread_print_info(threadobject *t)
-{
- java_lang_Thread *to;
- int state;
-
- /* If the thread is currently in initalization, don't print it. */
-
- to = (java_lang_Thread *) thread_get_object(t);
-
- /* Print as much as we can when we are in state NEW. */
-
- if (to != NULL) {
- /* Print thread name. */
-
- printf("\"");
- thread_fprint_name(t, stdout);
- printf("\"");
- }
- else {
- }
-
- if (thread_is_daemon(t))
- printf(" daemon");
-
- if (to != NULL) {
- printf(" prio=%d", LLNI_field_direct(to, priority));
- }
-
-#if SIZEOF_VOID_P == 8
- printf(" t=0x%016lx tid=0x%016lx (%ld)",
- (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
-#else
- printf(" t=0x%08x tid=0x%08x (%d)",
- (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
-#endif
-
- printf(" index=%d", t->index);
-
- /* Print thread state. */
-
- state = cacaothread_get_state(t);
-
- switch (state) {
- case THREAD_STATE_NEW:
- printf(" new");
- break;
- case THREAD_STATE_RUNNABLE:
- printf(" runnable");
- break;
- case THREAD_STATE_BLOCKED:
- printf(" blocked");
- break;
- case THREAD_STATE_WAITING:
- printf(" waiting");
- break;
- case THREAD_STATE_TIMED_WAITING:
- printf(" waiting on condition");
- break;
- case THREAD_STATE_TERMINATED:
- printf(" terminated");
- break;
- default:
- vm_abort("thread_print_info: unknown thread state %d", state);
- }
-}
-
-
-/* threads_get_current_tid *****************************************************
-
- Return the tid of the current thread.
-
- RETURN VALUE:
- the current tid
-
-*******************************************************************************/
-
-intptr_t threads_get_current_tid(void)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- /* this may happen during bootstrap */
-
- if (thread == NULL)
- return 0;
-
- return (intptr_t) thread->tid;
-}
-
-
-/* thread_set_state_runnable ***************************************************
-
- Set the current state of the given thread to THREAD_STATE_RUNNABLE.
-
- NOTE: If the thread has already terminated, don't set the state.
- This is important for threads_detach_thread.
-
-*******************************************************************************/
-
-void thread_set_state_runnable(threadobject *t)
-{
- /* Set the state inside a lock. */
-
- threadlist_lock();
-
- if (t->state != THREAD_STATE_TERMINATED) {
- t->state = THREAD_STATE_RUNNABLE;
-
- DEBUGTHREADS("is RUNNABLE", t);
- }
-
- threadlist_unlock();
-}
-
-
-/* thread_set_state_waiting ****************************************************
-
- Set the current state of the given thread to THREAD_STATE_WAITING.
-
- NOTE: If the thread has already terminated, don't set the state.
- This is important for threads_detach_thread.
-
-*******************************************************************************/
-
-void thread_set_state_waiting(threadobject *t)
-{
- /* Set the state inside a lock. */
-
- threadlist_lock();
-
- if (t->state != THREAD_STATE_TERMINATED) {
- t->state = THREAD_STATE_WAITING;
-
- DEBUGTHREADS("is WAITING", t);
- }
-
- threadlist_unlock();
-}
-
-
-/* thread_set_state_timed_waiting **********************************************
-
- Set the current state of the given thread to
- THREAD_STATE_TIMED_WAITING.
-
- NOTE: If the thread has already terminated, don't set the state.
- This is important for threads_detach_thread.
-
-*******************************************************************************/
-
-void thread_set_state_timed_waiting(threadobject *t)
-{
- /* Set the state inside a lock. */
-
- threadlist_lock();
-
- if (t->state != THREAD_STATE_TERMINATED) {
- t->state = THREAD_STATE_TIMED_WAITING;
-
- DEBUGTHREADS("is TIMED_WAITING", t);
- }
-
- threadlist_unlock();
-}
-
-
-/* thread_set_state_terminated *************************************************
-
- Set the current state of the given thread to
- THREAD_STATE_TERMINATED.
-
-*******************************************************************************/
-
-void thread_set_state_terminated(threadobject *t)
-{
- /* Set the state inside a lock. */
-
- threadlist_lock();
-
- t->state = THREAD_STATE_TERMINATED;
-
- DEBUGTHREADS("is TERMINATED", t);
-
- threadlist_unlock();
-}
-
-
-/* thread_get_thread **********************************************************
-
- Return the thread data structure of the given Java thread object.
-
- ARGUMENTS:
- h ... java.lang.{VM}Thread object
-
- RETURN VALUE:
- the thread object
-
-*******************************************************************************/
-
-threadobject *thread_get_thread(java_handle_t *h)
-{
- threadobject *t;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThread *vmto;
- java_lang_Object *to;
-#endif
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- bool equal;
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- vmto = (java_lang_VMThread *) h;
-
- LLNI_field_get_val(vmto, vmdata, to);
-
- t = (threadobject *) to;
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* XXX This is just a quick hack. */
-
- threadlist_lock();
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- LLNI_equals(t->object, h, equal);
-
- if (equal == true)
- break;
- }
-
- threadlist_unlock();
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- log_println("threads_get_thread: IMPLEMENT ME!");
-
-#else
-# error unknown classpath configuration
-#endif
-
- return t;
-}
-
-
-/* threads_thread_is_alive *****************************************************
-
- Returns if the give thread is alive.
-
-*******************************************************************************/
-
-bool threads_thread_is_alive(threadobject *t)
-{
- int state;
-
- state = cacaothread_get_state(t);
-
- switch (state) {
- case THREAD_STATE_NEW:
- case THREAD_STATE_TERMINATED:
- return false;
-
- case THREAD_STATE_RUNNABLE:
- case THREAD_STATE_BLOCKED:
- case THREAD_STATE_WAITING:
- case THREAD_STATE_TIMED_WAITING:
- return true;
-
- default:
- vm_abort("threads_thread_is_alive: unknown thread state %d", state);
- }
-
- /* keep compiler happy */
-
- return false;
-}
-
-
-/* threads_dump ****************************************************************
-
- Dumps info for all threads running in the JVM. This function is
- called when SIGQUIT (<ctrl>-\) is sent to CACAO.
-
-*******************************************************************************/
-
-void threads_dump(void)
-{
- threadobject *t;
-
- /* XXX we should stop the world here */
-
- /* Lock the thread lists. */
-
- threadlist_lock();
-
- printf("Full thread dump CACAO "VERSION":\n");
-
- /* iterate over all started threads */
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- /* ignore threads which are in state NEW */
- if (t->state == THREAD_STATE_NEW)
- continue;
-
-#if defined(ENABLE_GC_CACAO)
- /* Suspend the thread. */
- /* XXX Is the suspend reason correct? */
-
- if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
- vm_abort("threads_dump: threads_suspend_thread failed");
-#endif
-
- /* Print thread info. */
-
- printf("\n");
- thread_print_info(t);
- printf("\n");
-
- /* Print trace of thread. */
-
- stacktrace_print_of_thread(t);
-
-#if defined(ENABLE_GC_CACAO)
- /* Resume the thread. */
-
- if (threads_resume_thread(t) == false)
- vm_abort("threads_dump: threads_resume_thread failed");
-#endif
- }
-
- /* Unlock the thread lists. */
-
- threadlist_unlock();
-}
-
-
-/*
- * 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/threads/thread.cpp - machine independent thread 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.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#if defined(ENABLE_GC_BOEHM)
+/* We need to include Boehm's gc.h here for GC_register_my_thread and
+ friends. */
+# include "mm/boehm-gc/include/gc.h"
+#endif
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "threads/lock-common.h"
+#include "threads/threadlist.h"
+#include "threads/thread.hpp"
+
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/jit/stacktrace.hpp"
+
+
+// FIXME
+extern "C" {
+
+/* global variables ***********************************************************/
+
+static methodinfo *thread_method_init;
+static java_handle_t *threadgroup_system;
+static java_handle_t *threadgroup_main;
+
+#if defined(__LINUX__)
+/* XXX Remove for exact-GC. */
+bool threads_pthreads_implementation_nptl;
+#endif
+
+
+/* static functions ***********************************************************/
+
+static void thread_create_initial_threadgroups(void);
+static void thread_create_initial_thread(void);
+static threadobject *thread_new(void);
+
+
+/* threads_preinit *************************************************************
+
+ Do some early initialization of stuff required.
+
+*******************************************************************************/
+
+void threads_preinit(void)
+{
+ threadobject *mainthread;
+#if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
+ char *pathbuf;
+ size_t len;
+#endif
+
+ TRACESUBSYSTEMINITIALIZATION("threads_preinit");
+
+#if defined(__LINUX__)
+ /* XXX Remove for exact-GC. */
+
+ /* On Linux we need to check the pthread implementation. */
+
+ /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
+ /* If the glibc is a pre-2.3.2 version, we fall back to
+ linuxthreads. */
+
+# if defined(_CS_GNU_LIBPTHREAD_VERSION)
+ len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
+
+ /* Some systems return as length 0 (maybe cross-compilation
+ related). In this case we also fall back to linuxthreads. */
+
+ if (len > 0) {
+ pathbuf = MNEW(char, len);
+
+ (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
+
+ if (strstr(pathbuf, "NPTL") != NULL)
+ threads_pthreads_implementation_nptl = true;
+ else
+ threads_pthreads_implementation_nptl = false;
+ }
+ else
+ threads_pthreads_implementation_nptl = false;
+# else
+ threads_pthreads_implementation_nptl = false;
+# endif
+#endif
+
+ /* Initialize the threads implementation (sets the thinlock on the
+ main thread). */
+
+ threads_impl_preinit();
+
+ /* Create internal thread data-structure for the main thread. */
+
+ mainthread = thread_new();
+
+ /* The main thread should always have index 1. */
+
+ if (mainthread->index != 1)
+ vm_abort("threads_preinit: main thread index not 1: %d != 1",
+ mainthread->index);
+
+ /* thread is a Java thread and running */
+
+ mainthread->flags |= THREAD_FLAG_JAVA;
+ mainthread->state = THREAD_STATE_RUNNABLE;
+
+ /* Store the internal thread data-structure in the TSD. */
+
+ thread_set_current(mainthread);
+}
+
+
+/* threads_init ****************************************************************
+
+ Initialize the main thread.
+
+*******************************************************************************/
+
+void threads_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("threads_init");
+
+ /* Create the system and main thread groups. */
+
+ thread_create_initial_threadgroups();
+
+ /* Cache the java.lang.Thread initialization method. */
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ thread_method_init =
+ class_resolveclassmethod(class_java_lang_Thread,
+ utf_init,
+ utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
+ class_java_lang_Thread,
+ true);
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ thread_method_init =
+ class_resolveclassmethod(class_java_lang_Thread,
+ utf_init,
+ utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V"),
+ class_java_lang_Thread,
+ true);
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ thread_method_init =
+ class_resolveclassmethod(class_java_lang_Thread,
+ utf_init,
+ utf_java_lang_String__void,
+ class_java_lang_Thread,
+ true);
+
+#else
+# error unknown classpath configuration
+#endif
+
+ if (thread_method_init == NULL)
+ vm_abort("threads_init: failed to resolve thread init method");
+
+ thread_create_initial_thread();
+}
+
+
+/* thread_create_object ********************************************************
+
+ Create a Java thread object for the given thread data-structure,
+ initializes it and adds the thread to the threadgroup.
+
+ ARGUMENTS:
+
+ t ....... thread
+ name .... thread name
+ group ... threadgroup
+
+ RETURN:
+
+*******************************************************************************/
+
+static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
+{
+ /* Create a java.lang.Thread Java object. */
+
+ java_handle_t* h = builtin_new(class_java_lang_Thread);
+
+ if (h == NULL)
+ return false;
+
+ java_lang_Thread jlt(h);
+
+ // Set the Java object in the thread data-structure. This
+ // indicates that the thread is attached to the VM.
+ thread_set_object(t, jlt.get_handle());
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ h = builtin_new(class_java_lang_VMThread);
+
+ if (h == NULL)
+ return false;
+
+ // Create and initialize a java.lang.VMThread object.
+ java_lang_VMThread jlvmt(h, jlt.get_handle(), t);
+
+ /* Call:
+ java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+
+ bool isdaemon = thread_is_daemon(t);
+
+ (void) vm_call_method(thread_method_init, jlt.get_handle(), jlvmt.get_handle(),
+ name, NORM_PRIORITY, isdaemon);
+
+ if (exceptions_get_exception())
+ return false;
+
+ // Set the ThreadGroup in the Java thread object.
+ jlt.set_group(group);
+
+ /* Add thread to the threadgroup. */
+
+ classinfo* c;
+ LLNI_class_get(group, c);
+
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_addThread,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
+
+ if (m == NULL)
+ return false;
+
+ (void) vm_call_method(m, group, jlt.get_handle());
+
+ if (exceptions_get_exception())
+ return false;
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ /* Set the priority. java.lang.Thread.<init> requires it because
+ it sets the priority of the current thread to the parent's one
+ (which is the current thread in this case). */
+ jlt.set_priority(NORM_PRIORITY);
+
+ // Call: java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V
+
+ (void) vm_call_method(thread_method_init, jlt.get_handle(), group, name);
+
+ if (exceptions_get_exception())
+ return false;
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ // Set the thread data-structure in the Java thread object.
+ jlt.set_vm_thread(t);
+
+ // Call: public Thread(Ljava/lang/String;)V
+ (void) vm_call_method(thread_method_init, jlt.get_handle(), name);
+
+ if (exceptions_get_exception())
+ return false;
+
+#else
+# error unknown classpath configuration
+#endif
+
+ return true;
+}
+
+
+/* thread_create_initial_threadgroups ******************************************
+
+ Create the initial threadgroups.
+
+ GNU Classpath:
+ Create the main threadgroup only and set the system
+ threadgroup to the main threadgroup.
+
+ SUN:
+ Create the system and main threadgroup.
+
+ CLDC:
+ This function is a no-op.
+
+*******************************************************************************/
+
+static void thread_create_initial_threadgroups(void)
+{
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ /* Allocate and initialize the main thread group. */
+
+ threadgroup_main = native_new_and_init(class_java_lang_ThreadGroup);
+
+ if (threadgroup_main == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
+
+ /* Use the same threadgroup for system as for main. */
+
+ threadgroup_system = threadgroup_main;
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ java_handle_t *name;
+ methodinfo *m;
+
+ /* Allocate and initialize the system thread group. */
+
+ threadgroup_system = native_new_and_init(class_java_lang_ThreadGroup);
+
+ if (threadgroup_system == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to allocate system threadgroup");
+
+ /* Allocate and initialize the main thread group. */
+
+ threadgroup_main = builtin_new(class_java_lang_ThreadGroup);
+
+ if (threadgroup_main == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
+
+ name = javastring_new(utf_main);
+
+ m = class_resolveclassmethod(class_java_lang_ThreadGroup,
+ utf_init,
+ utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V,
+ class_java_lang_ThreadGroup,
+ true);
+
+ if (m == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to resolve threadgroup init method");
+
+ (void) vm_call_method(m, threadgroup_main, threadgroup_system, name);
+
+ if (exceptions_get_exception())
+ vm_abort("thread_create_initial_threadgroups: exception while initializing main threadgroup");
+
+# else
+# error unknown classpath configuration
+# endif
+#endif
+}
+
+
+/* thread_create_initial_thread ***********************************************
+
+ Create the initial thread: main
+
+*******************************************************************************/
+
+static void thread_create_initial_thread(void)
+{
+ threadobject *t;
+ java_handle_t *name;
+
+ /* Get the main-thread (NOTE: The main thread is always the first
+ thread in the list). */
+
+ t = threadlist_first();
+
+ /* The thread name. */
+
+ name = javastring_new(utf_main);
+
+#if defined(ENABLE_INTRP)
+ /* create interpreter stack */
+
+ if (opt_intrp) {
+ MSET(intrp_main_stack, 0, u1, opt_stacksize);
+ mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
+ }
+#endif
+
+ /* Create the Java thread object. */
+
+ if (!thread_create_object(t, name, threadgroup_main))
+ vm_abort("thread_create_initial_thread: failed to create Java object");
+
+ /* Initialize the implementation specific bits. */
+
+ threads_impl_init();
+
+ DEBUGTHREADS("starting (main)", t);
+}
+
+
+/* thread_new ******************************************************************
+
+ Allocates and initializes an internal thread data-structure and
+ adds it to the threads list.
+
+*******************************************************************************/
+
+static threadobject *thread_new(void)
+{
+ int32_t index;
+ threadobject *t;
+
+ /* Lock the thread lists */
+
+ threadlist_lock();
+
+ index = threadlist_get_free_index();
+
+ /* Allocate a thread data structure. */
+
+ /* First, try to get one from the free-list. */
+
+ t = threadlist_free_first();
+
+ if (t != NULL) {
+ /* Remove from free list. */
+
+ threadlist_free_remove(t);
+
+ /* Equivalent of MZERO on the else path */
+
+ threads_impl_thread_clear(t);
+ }
+ else {
+#if defined(ENABLE_GC_BOEHM)
+ t = GCNEW_UNCOLLECTABLE(threadobject, 1);
+#else
+ t = NEW(threadobject);
+#endif
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_threadobject += sizeof(threadobject);
+#endif
+
+ /* Clear memory. */
+
+ MZERO(t, threadobject, 1);
+
+#if defined(ENABLE_GC_CACAO)
+ /* Register reference to java.lang.Thread with the GC. */
+ /* FIXME is it ok to do this only once? */
+
+ gc_reference_register(&(t->object), GC_REFTYPE_THREADOBJECT);
+ gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
+#endif
+
+ /* Initialize the implementation-specific bits. */
+
+ threads_impl_thread_init(t);
+ }
+
+ /* Pre-compute the thinlock-word. */
+
+ assert(index != 0);
+
+ t->index = index;
+ t->thinlock = lock_pre_compute_thinlock(t->index);
+ t->flags = 0;
+ t->state = THREAD_STATE_NEW;
+
+#if defined(ENABLE_GC_CACAO)
+ t->flags |= THREAD_FLAG_IN_NATIVE;
+#endif
+
+ /* Initialize the implementation-specific bits. */
+
+ threads_impl_thread_reuse(t);
+
+ /* Add the thread to the thread list. */
+
+ threadlist_add(t);
+
+ /* Unlock the thread lists. */
+
+ threadlist_unlock();
+
+ return t;
+}
+
+
+/* thread_free *****************************************************************
+
+ Remove the thread from the threads-list and free the internal
+ thread data structure. The thread index is added to the
+ thread-index free-list.
+
+ IN:
+ t ... thread data structure
+
+*******************************************************************************/
+
+void thread_free(threadobject *t)
+{
+ /* Lock the thread lists. */
+
+ threadlist_lock();
+
+ /* Remove the thread from the thread-list. */
+
+ threadlist_remove(t);
+
+ /* Add the thread index to the free list. */
+
+ threadlist_index_add(t->index);
+
+ /* Set the reference to the Java object to NULL. */
+
+ thread_set_object(t, NULL);
+
+ /* Add the thread data structure to the free list. */
+
+ threadlist_free_add(t);
+
+ /* Unlock the thread lists. */
+
+ threadlist_unlock();
+}
+
+
+/* threads_thread_start_internal ***********************************************
+
+ Start an internal thread in the JVM. No Java thread objects exists
+ so far.
+
+ IN:
+ name.......UTF-8 name of the thread
+ f..........function pointer to C function to start
+
+*******************************************************************************/
+
+bool threads_thread_start_internal(utf *name, functionptr f)
+{
+ threadobject *t;
+
+ /* Enter the join-mutex, so if the main-thread is currently
+ waiting to join all threads, the number of non-daemon threads
+ is correct. */
+
+ threads_mutex_join_lock();
+
+ /* Create internal thread data-structure. */
+
+ t = thread_new();
+
+ t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
+
+ /* The thread is flagged as (non-)daemon thread, we can leave the
+ mutex. */
+
+ threads_mutex_join_unlock();
+
+ /* Create the Java thread object. */
+
+ if (!thread_create_object(t, javastring_new(name), threadgroup_system))
+ return false;
+
+ /* Start the thread. */
+
+ threads_impl_thread_start(t, f);
+
+ /* everything's ok */
+
+ return true;
+}
+
+
+/* threads_thread_start ********************************************************
+
+ Start a Java thread in the JVM. Only the java thread object exists
+ so far.
+
+ IN:
+ object.....the java thread object java.lang.Thread
+
+*******************************************************************************/
+
+void threads_thread_start(java_handle_t *object)
+{
+ java_lang_Thread jlt(object);
+
+ /* Enter the join-mutex, so if the main-thread is currently
+ waiting to join all threads, the number of non-daemon threads
+ is correct. */
+
+ threads_mutex_join_lock();
+
+ /* Create internal thread data-structure. */
+
+ threadobject* t = thread_new();
+
+ /* this is a normal Java thread */
+
+ t->flags |= THREAD_FLAG_JAVA;
+
+#if defined(ENABLE_JAVASE)
+ /* Is this a daemon thread? */
+
+ if (jlt.get_daemon() == true)
+ t->flags |= THREAD_FLAG_DAEMON;
+#endif
+
+ /* The thread is flagged and (non-)daemon thread, we can leave the
+ mutex. */
+
+ threads_mutex_join_unlock();
+
+ /* Link the two objects together. */
+
+ thread_set_object(t, object);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ /* Get the java.lang.VMThread object and do some sanity checks. */
+ java_lang_VMThread jlvmt(jlt.get_vmThread());
+
+ assert(jlvmt.get_handle() != NULL);
+ assert(jlvmt.get_vmdata() == NULL);
+
+ jlvmt.set_vmdata(t);
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ // Nothing to do.
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ jlt.set_vm_thread(t);
+
+#else
+# error unknown classpath configuration
+#endif
+
+ /* Start the thread. Don't pass a function pointer (NULL) since
+ we want Thread.run()V here. */
+
+ threads_impl_thread_start(t, NULL);
+}
+
+
+/**
+ * Attaches the current thread to the VM.
+ *
+ * @param vm_aargs Attach arguments.
+ * @param isdaemon true if the attached thread should be a daemon
+ * thread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+{
+ bool result;
+ threadobject *t;
+ utf *u;
+ java_handle_t *name;
+ java_handle_t *group;
+
+ /* If the current thread has already been attached, this operation
+ is a no-op. */
+
+ result = thread_current_is_attached();
+
+ if (result == true)
+ return true;
+
+ /* Enter the join-mutex, so if the main-thread is currently
+ waiting to join all threads, the number of non-daemon threads
+ is correct. */
+
+ threads_mutex_join_lock();
+
+ /* Create internal thread data structure. */
+
+ t = thread_new();
+
+ /* Thread is a Java thread and running. */
+
+ t->flags = THREAD_FLAG_JAVA;
+
+ if (isdaemon)
+ t->flags |= THREAD_FLAG_DAEMON;
+
+ /* Store the internal thread data-structure in the TSD. */
+
+ thread_set_current(t);
+
+ /* The thread is flagged and (non-)daemon thread, we can leave the
+ mutex. */
+
+ threads_mutex_join_unlock();
+
+ DEBUGTHREADS("attaching", t);
+
+ /* Get the thread name. */
+
+ if (vm_aargs != NULL) {
+ u = utf_new_char(vm_aargs->name);
+ }
+ else {
+ u = utf_null;
+ }
+
+ name = javastring_new(u);
+
+#if defined(ENABLE_JAVASE)
+ /* Get the threadgroup. */
+
+ if (vm_aargs != NULL)
+ group = (java_handle_t *) vm_aargs->group;
+ else
+ group = NULL;
+
+ /* If no threadgroup was given, use the main threadgroup. */
+
+ if (group == NULL)
+ group = threadgroup_main;
+#endif
+
+#if defined(ENABLE_INTRP)
+ /* create interpreter stack */
+
+ if (opt_intrp) {
+ MSET(intrp_main_stack, 0, u1, opt_stacksize);
+ thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
+ }
+#endif
+
+ /* Create the Java thread object. */
+
+ if (!thread_create_object(t, name, group))
+ return false;
+
+ /* The thread is completely initialized. */
+
+ thread_set_state_runnable(t);
+
+ return true;
+}
+
+
+/**
+ * Attaches the current external thread to the VM. This function is
+ * called by JNI's AttachCurrentThread.
+ *
+ * @param vm_aargs Attach arguments.
+ * @param isdaemon true if the attached thread should be a daemon
+ * thread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+{
+ int result;
+
+#if defined(ENABLE_GC_BOEHM)
+ struct GC_stack_base sb;
+#endif
+
+#if defined(ENABLE_GC_BOEHM)
+ /* Register the thread with Boehm-GC. This must happen before the
+ thread allocates any memory from the GC heap.*/
+
+ result = GC_get_stack_base(&sb);
+
+ if (result != GC_SUCCESS)
+ vm_abort("threads_attach_current_thread: GC_get_stack_base failed");
+
+ GC_register_my_thread(&sb);
+#endif
+
+ result = thread_attach_current_thread(vm_aargs, isdaemon);
+
+ if (result == false) {
+#if defined(ENABLE_GC_BOEHM)
+ /* Unregister the thread. */
+
+ GC_unregister_my_thread();
+#endif
+
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Detaches the current external thread from the VM. This function is
+ * called by JNI's DetachCurrentThread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool thread_detach_current_external_thread(void)
+{
+ int result;
+
+ result = thread_detach_current_thread();
+
+ if (result == false)
+ return false;
+
+#if defined(ENABLE_GC_BOEHM)
+ /* Unregister the thread with Boehm-GC. This must happen after
+ the thread allocates any memory from the GC heap. */
+
+ /* Don't detach the main thread. This is a workaround for
+ OpenJDK's java binary. */
+ if (thread_get_current()->index != 1)
+ GC_unregister_my_thread();
+#endif
+
+ return true;
+}
+
+
+/* thread_fprint_name **********************************************************
+
+ Print the name of the given thread to the given stream.
+
+ ARGUMENTS:
+ t ........ thread data-structure
+ stream ... stream to print to
+
+*******************************************************************************/
+
+void thread_fprint_name(threadobject *t, FILE *stream)
+{
+ if (thread_get_object(t) == NULL)
+ vm_abort("");
+
+ java_lang_Thread jlt(thread_get_object(t));
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ java_handle_t* name = jlt.get_name();
+ javastring_fprint(name, stream);
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ /* FIXME: In OpenJDK and CLDC the name is a char[]. */
+ java_chararray_t *name;
+
+ /* FIXME This prints to stdout. */
+ utf_display_printable_ascii(utf_null);
+
+#else
+# error unknown classpath configuration
+#endif
+}
+
+
+/* thread_print_info ***********************************************************
+
+ Print information of the passed thread.
+
+ ARGUMENTS:
+ t ... thread data-structure.
+
+*******************************************************************************/
+
+void thread_print_info(threadobject *t)
+{
+ java_lang_Thread jlt(thread_get_object(t));
+
+ /* Print as much as we can when we are in state NEW. */
+
+ if (jlt.get_handle() != NULL) {
+ /* Print thread name. */
+
+ printf("\"");
+ thread_fprint_name(t, stdout);
+ printf("\"");
+ }
+ else {
+ }
+
+ if (thread_is_daemon(t))
+ printf(" daemon");
+
+ if (jlt.get_handle() != NULL) {
+ printf(" prio=%d", jlt.get_priority());
+ }
+
+#if SIZEOF_VOID_P == 8
+ printf(" t=0x%016lx tid=0x%016lx (%ld)",
+ (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
+#else
+ printf(" t=0x%08x tid=0x%08x (%d)",
+ (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
+#endif
+
+ printf(" index=%d", t->index);
+
+ /* Print thread state. */
+
+ int state = cacaothread_get_state(t);
+
+ switch (state) {
+ case THREAD_STATE_NEW:
+ printf(" new");
+ break;
+ case THREAD_STATE_RUNNABLE:
+ printf(" runnable");
+ break;
+ case THREAD_STATE_BLOCKED:
+ printf(" blocked");
+ break;
+ case THREAD_STATE_WAITING:
+ printf(" waiting");
+ break;
+ case THREAD_STATE_TIMED_WAITING:
+ printf(" waiting on condition");
+ break;
+ case THREAD_STATE_TERMINATED:
+ printf(" terminated");
+ break;
+ default:
+ vm_abort("thread_print_info: unknown thread state %d", state);
+ }
+}
+
+
+/* threads_get_current_tid *****************************************************
+
+ Return the tid of the current thread.
+
+ RETURN VALUE:
+ the current tid
+
+*******************************************************************************/
+
+intptr_t threads_get_current_tid(void)
+{
+ threadobject *thread;
+
+ thread = THREADOBJECT;
+
+ /* this may happen during bootstrap */
+
+ if (thread == NULL)
+ return 0;
+
+ return (intptr_t) thread->tid;
+}
+
+
+/* thread_set_state_runnable ***************************************************
+
+ Set the current state of the given thread to THREAD_STATE_RUNNABLE.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_runnable(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ t->state = THREAD_STATE_RUNNABLE;
+
+ DEBUGTHREADS("is RUNNABLE", t);
+ }
+
+ threadlist_unlock();
+}
+
+
+/* thread_set_state_waiting ****************************************************
+
+ Set the current state of the given thread to THREAD_STATE_WAITING.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_waiting(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ t->state = THREAD_STATE_WAITING;
+
+ DEBUGTHREADS("is WAITING", t);
+ }
+
+ threadlist_unlock();
+}
+
+
+/* thread_set_state_timed_waiting **********************************************
+
+ Set the current state of the given thread to
+ THREAD_STATE_TIMED_WAITING.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_timed_waiting(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ t->state = THREAD_STATE_TIMED_WAITING;
+
+ DEBUGTHREADS("is TIMED_WAITING", t);
+ }
+
+ threadlist_unlock();
+}
+
+
+/* thread_set_state_terminated *************************************************
+
+ Set the current state of the given thread to
+ THREAD_STATE_TERMINATED.
+
+*******************************************************************************/
+
+void thread_set_state_terminated(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ t->state = THREAD_STATE_TERMINATED;
+
+ DEBUGTHREADS("is TERMINATED", t);
+
+ threadlist_unlock();
+}
+
+
+/* thread_get_thread **********************************************************
+
+ Return the thread data structure of the given Java thread object.
+
+ ARGUMENTS:
+ h ... java.lang.{VM}Thread object
+
+ RETURN VALUE:
+ the thread object
+
+*******************************************************************************/
+
+threadobject *thread_get_thread(java_handle_t *h)
+{
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ java_lang_VMThread jlvmt(h);
+ threadobject* t = jlvmt.get_vmdata();
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ /* XXX This is just a quick hack. */
+ threadobject* t;
+ bool equal;
+
+ threadlist_lock();
+
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ LLNI_equals(t->object, h, equal);
+
+ if (equal == true)
+ break;
+ }
+
+ threadlist_unlock();
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ log_println("threads_get_thread: IMPLEMENT ME!");
+ threadobject* t = NULL;
+
+#else
+# error unknown classpath configuration
+#endif
+
+ return t;
+}
+
+
+/* threads_thread_is_alive *****************************************************
+
+ Returns if the give thread is alive.
+
+*******************************************************************************/
+
+bool threads_thread_is_alive(threadobject *t)
+{
+ int state;
+
+ state = cacaothread_get_state(t);
+
+ switch (state) {
+ case THREAD_STATE_NEW:
+ case THREAD_STATE_TERMINATED:
+ return false;
+
+ case THREAD_STATE_RUNNABLE:
+ case THREAD_STATE_BLOCKED:
+ case THREAD_STATE_WAITING:
+ case THREAD_STATE_TIMED_WAITING:
+ return true;
+
+ default:
+ vm_abort("threads_thread_is_alive: unknown thread state %d", state);
+ }
+
+ /* keep compiler happy */
+
+ return false;
+}
+
+
+/* threads_dump ****************************************************************
+
+ Dumps info for all threads running in the JVM. This function is
+ called when SIGQUIT (<ctrl>-\) is sent to CACAO.
+
+*******************************************************************************/
+
+void threads_dump(void)
+{
+ threadobject *t;
+
+ /* XXX we should stop the world here */
+
+ /* Lock the thread lists. */
+
+ threadlist_lock();
+
+ printf("Full thread dump CACAO "VERSION":\n");
+
+ /* iterate over all started threads */
+
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ /* ignore threads which are in state NEW */
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+#if defined(ENABLE_GC_CACAO)
+ /* Suspend the thread. */
+ /* XXX Is the suspend reason correct? */
+
+ if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
+ vm_abort("threads_dump: threads_suspend_thread failed");
+#endif
+
+ /* Print thread info. */
+
+ printf("\n");
+ thread_print_info(t);
+ printf("\n");
+
+ /* Print trace of thread. */
+
+ stacktrace_print_of_thread(t);
+
+#if defined(ENABLE_GC_CACAO)
+ /* Resume the thread. */
+
+ if (threads_resume_thread(t) == false)
+ vm_abort("threads_dump: threads_resume_thread failed");
+#endif
+ }
+
+ /* Unlock the thread lists. */
+
+ threadlist_unlock();
+}
+
+} // extern "C"
+
+
+/*
+ * 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/threads/thread.h - machine independent thread 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 _THREAD_H
-#define _THREAD_H
-
-#include "config.h"
-
-#include "vmcore/system.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/posix/thread-posix.h"
-#else
-# include "threads/none/thread-none.h"
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "vmcore/utf8.h"
-
-
-/* only define the following stuff with thread enabled ************************/
-
-#if defined(ENABLE_THREADS)
-
-/* thread states **************************************************************/
-
-#define THREAD_STATE_NEW 0
-#define THREAD_STATE_RUNNABLE 1
-#define THREAD_STATE_BLOCKED 2
-#define THREAD_STATE_WAITING 3
-#define THREAD_STATE_TIMED_WAITING 4
-#define THREAD_STATE_TERMINATED 5
-
-
-/* thread priorities **********************************************************/
-
-#define MIN_PRIORITY 1
-#define NORM_PRIORITY 5
-#define MAX_PRIORITY 10
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-# define DEBUGTHREADS(message, thread) \
- do { \
- if (opt_DebugThreads) { \
- printf("[Thread %-16s: ", message); \
- thread_print_info(thread); \
- printf("]\n"); \
- } \
- } while (0)
-#else
-# define DEBUGTHREADS(message, thread)
-#endif
-
-
-/* global variables ***********************************************************/
-
-#if defined(__LINUX__)
-/* XXX Remove for exact-GC. */
-extern bool threads_pthreads_implementation_nptl;
-#endif
-
-
-/* inline functions ***********************************************************/
-
-/* thread_get_object ***********************************************************
-
- Return the Java for the given thread.
-
- ARGUMENTS:
- t ... thread
-
- RETURN:
- the Java object
-
-*******************************************************************************/
-
-inline static java_handle_t *thread_get_object(threadobject *t)
-{
- return LLNI_WRAP(t->object);
-}
-
-
-/* threads_thread_set_object ***************************************************
-
- Set the Java object for the given thread.
-
- ARGUMENTS:
- t ... thread
- o ... Java object
-
-*******************************************************************************/
-
-inline static void thread_set_object(threadobject *t, java_handle_t *o)
-{
- t->object = LLNI_DIRECT(o);
-}
-
-
-/* thread_get_current_object **************************************************
-
- Return the Java object of the current thread.
-
- RETURN VALUE:
- the Java object
-
-*******************************************************************************/
-
-inline static java_handle_t *thread_get_current_object(void)
-{
- threadobject *t;
- java_handle_t *o;
-
- t = THREADOBJECT;
- o = thread_get_object(t);
-
- return o;
-}
-
-
-/* cacaothread_get_state *******************************************************
-
- Returns the current state of the given thread.
-
- ARGUMENTS:
- t ... the thread to check
-
- RETURN:
- thread state
-
-*******************************************************************************/
-
-inline static int cacaothread_get_state(threadobject *t)
-{
- return t->state;
-}
-
-
-/* thread_is_attached **********************************************************
-
- Returns if the given thread is attached to the VM.
-
- ARGUMENTS:
- t ... the thread to check
-
- RETURN:
- true .... the thread is attached to the VM
- false ... the thread is not
-
-*******************************************************************************/
-
-inline static bool thread_is_attached(threadobject *t)
-{
- java_handle_t *o;
-
- o = thread_get_object(t);
-
- if (o != NULL)
- return true;
- else
- return false;
-}
-
-
-/* thread_is_interrupted *******************************************************
-
- Check if the given thread has been interrupted.
-
- ARGUMENTS:
- t ... the thread to check
-
- RETURN VALUE:
- true, if the given thread had been interrupted
-
-*******************************************************************************/
-
-inline static bool thread_is_interrupted(threadobject *t)
-{
- bool interrupted;
-
- /* We need the mutex because classpath will call this function when
- a blocking system call is interrupted. The mutex ensures that it will
- see the correct value for the interrupted flag. */
-
- mutex_lock(&t->waitmutex);
- interrupted = t->interrupted;
- mutex_unlock(&t->waitmutex);
-
- return interrupted;
-}
-
-
-/* thread_set_interrupted ******************************************************
-
- Set the interrupted flag to the given value.
-
- ARGUMENTS:
- interrupted ... value to set
-
-*******************************************************************************/
-
-inline static void thread_set_interrupted(threadobject *t, bool interrupted)
-{
- mutex_lock(&t->waitmutex);
-
- /* Set interrupted flag. */
-
- t->interrupted = interrupted;
-
- mutex_unlock(&t->waitmutex);
-}
-
-
-/* thread_is_daemon ************************************************************
-
- Returns if the given thread is a daemon thread.
-
- ARGUMENTS:
- t ... the thread to check
-
- RETURN:
- true .... the thread is a daemon thread
- false ... the thread is not
-
-*******************************************************************************/
-
-inline static bool thread_is_daemon(threadobject *t)
-{
- if (t->flags & THREAD_FLAG_DAEMON)
- return true;
- else
- return false;
-}
-
-
-/* thread_current_is_attached **************************************************
-
- Returns if the current thread is attached to the VM.
-
- RETURN:
- true .... the thread is attached to the VM
- false ... the thread is not
-
-*******************************************************************************/
-
-inline static bool thread_current_is_attached(void)
-{
- threadobject *t;
- bool result;
-
- t = thread_get_current();
-
- if (t == NULL)
- return false;
-
- result = thread_is_attached(t);
-
- return result;
-}
-
-
-/* function prototypes ********************************************************/
-
-void threads_preinit(void);
-void threads_init(void);
-
-void thread_free(threadobject *t);
-
-bool threads_thread_start_internal(utf *name, functionptr f);
-void threads_thread_start(java_handle_t *object);
-
-bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
-bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
-bool thread_detach_current_thread(void);
-
-bool thread_detach_current_external_thread(void);
-
-void thread_fprint_name(threadobject *t, FILE *stream);
-void thread_print_info(threadobject *t);
-
-intptr_t threads_get_current_tid(void);
-
-void thread_set_state_runnable(threadobject *t);
-void thread_set_state_waiting(threadobject *t);
-void thread_set_state_timed_waiting(threadobject *t);
-void thread_set_state_terminated(threadobject *t);
-
-threadobject *thread_get_thread(java_handle_t *h);
-
-bool threads_thread_is_alive(threadobject *t);
-
-void threads_dump(void);
-
-
-/* implementation specific functions */
-
-void threads_impl_preinit(void);
-void threads_impl_init(void);
-
-#if defined(ENABLE_GC_CACAO)
-void threads_mutex_gc_lock(void);
-void threads_mutex_gc_unlock(void);
-#endif
-
-void threads_mutex_join_lock(void);
-void threads_mutex_join_unlock(void);
-
-void threads_impl_thread_init(threadobject *t);
-void threads_impl_thread_clear(threadobject *t);
-void threads_impl_thread_reuse(threadobject *t);
-void threads_impl_thread_free(threadobject *t);
-void threads_impl_thread_start(threadobject *thread, functionptr f);
-
-void threads_yield(void);
-
-#endif /* ENABLE_THREADS */
-
-#endif /* _THREAD_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:
- */
--- /dev/null
+/* src/threads/thread.hpp - machine independent thread 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 _THREAD_HPP
+#define _THREAD_HPP
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/types.h"
+
+// Include early to get threadobject.
+#if defined(ENABLE_THREADS)
+# include "threads/posix/thread-posix.hpp"
+#else
+# include "threads/none/thread-none.h"
+#endif
+
+#include "vm/os.hpp"
+
+#include "native/jni.h"
+#include "native/llni.h"
+
+#include "threads/mutex.hpp"
+
+#include "vm/global.h"
+#include "vm/utf8.h"
+
+
+/* only define the following stuff with thread enabled ************************/
+
+#if defined(ENABLE_THREADS)
+
+/* thread states **************************************************************/
+
+#define THREAD_STATE_NEW 0
+#define THREAD_STATE_RUNNABLE 1
+#define THREAD_STATE_BLOCKED 2
+#define THREAD_STATE_WAITING 3
+#define THREAD_STATE_TIMED_WAITING 4
+#define THREAD_STATE_TERMINATED 5
+
+
+/* thread priorities **********************************************************/
+
+#define MIN_PRIORITY 1
+#define NORM_PRIORITY 5
+#define MAX_PRIORITY 10
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define DEBUGTHREADS(message, thread) \
+ do { \
+ if (opt_DebugThreads) { \
+ printf("[Thread %-16s: ", message); \
+ thread_print_info(thread); \
+ printf("]\n"); \
+ } \
+ } while (0)
+#else
+# define DEBUGTHREADS(message, thread)
+#endif
+
+
+/* global variables ***********************************************************/
+
+#if defined(__LINUX__)
+/* XXX Remove for exact-GC. */
+extern bool threads_pthreads_implementation_nptl;
+#endif
+
+
+/* inline functions ***********************************************************/
+
+/* thread_get_object ***********************************************************
+
+ Return the Java for the given thread.
+
+ ARGUMENTS:
+ t ... thread
+
+ RETURN:
+ the Java object
+
+*******************************************************************************/
+
+inline static java_handle_t *thread_get_object(threadobject *t)
+{
+ return LLNI_WRAP(t->object);
+}
+
+
+/* threads_thread_set_object ***************************************************
+
+ Set the Java object for the given thread.
+
+ ARGUMENTS:
+ t ... thread
+ o ... Java object
+
+*******************************************************************************/
+
+inline static void thread_set_object(threadobject *t, java_handle_t *o)
+{
+ t->object = LLNI_DIRECT(o);
+}
+
+
+/* thread_get_current_object **************************************************
+
+ Return the Java object of the current thread.
+
+ RETURN VALUE:
+ the Java object
+
+*******************************************************************************/
+
+inline static java_handle_t *thread_get_current_object(void)
+{
+ threadobject *t;
+ java_handle_t *o;
+
+ t = THREADOBJECT;
+ o = thread_get_object(t);
+
+ return o;
+}
+
+
+/* cacaothread_get_state *******************************************************
+
+ Returns the current state of the given thread.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN:
+ thread state
+
+*******************************************************************************/
+
+inline static int cacaothread_get_state(threadobject *t)
+{
+ return t->state;
+}
+
+
+/* thread_is_attached **********************************************************
+
+ Returns if the given thread is attached to the VM.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN:
+ true .... the thread is attached to the VM
+ false ... the thread is not
+
+*******************************************************************************/
+
+inline static bool thread_is_attached(threadobject *t)
+{
+ java_handle_t *o;
+
+ o = thread_get_object(t);
+
+ if (o != NULL)
+ return true;
+ else
+ return false;
+}
+
+
+/* thread_is_interrupted *******************************************************
+
+ Check if the given thread has been interrupted.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN VALUE:
+ true, if the given thread had been interrupted
+
+*******************************************************************************/
+
+inline static bool thread_is_interrupted(threadobject *t)
+{
+ bool interrupted;
+
+ /* We need the mutex because classpath will call this function when
+ a blocking system call is interrupted. The mutex ensures that it will
+ see the correct value for the interrupted flag. */
+
+#ifdef __cplusplus
+ t->waitmutex->lock();
+ interrupted = t->interrupted;
+ t->waitmutex->unlock();
+#else
+ Mutex_lock(t->waitmutex);
+ interrupted = t->interrupted;
+ Mutex_unlock(t->waitmutex);
+#endif
+
+ return interrupted;
+}
+
+
+/* thread_set_interrupted ******************************************************
+
+ Set the interrupted flag to the given value.
+
+ ARGUMENTS:
+ interrupted ... value to set
+
+*******************************************************************************/
+
+inline static void thread_set_interrupted(threadobject *t, bool interrupted)
+{
+#ifdef __cplusplus
+ t->waitmutex->lock();
+ t->interrupted = interrupted;
+ t->waitmutex->unlock();
+#else
+ Mutex_lock(t->waitmutex);
+ t->interrupted = interrupted;
+ Mutex_unlock(t->waitmutex);
+#endif
+}
+
+
+/* thread_is_daemon ************************************************************
+
+ Returns if the given thread is a daemon thread.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN:
+ true .... the thread is a daemon thread
+ false ... the thread is not
+
+*******************************************************************************/
+
+inline static bool thread_is_daemon(threadobject *t)
+{
+ if (t->flags & THREAD_FLAG_DAEMON)
+ return true;
+ else
+ return false;
+}
+
+
+/* thread_current_is_attached **************************************************
+
+ Returns if the current thread is attached to the VM.
+
+ RETURN:
+ true .... the thread is attached to the VM
+ false ... the thread is not
+
+*******************************************************************************/
+
+inline static bool thread_current_is_attached(void)
+{
+ threadobject *t;
+ bool result;
+
+ t = thread_get_current();
+
+ if (t == NULL)
+ return false;
+
+ result = thread_is_attached(t);
+
+ return result;
+}
+
+
+/* function prototypes ********************************************************/
+
+void threads_preinit(void);
+void threads_init(void);
+
+void thread_free(threadobject *t);
+
+bool threads_thread_start_internal(utf *name, functionptr f);
+void threads_thread_start(java_handle_t *object);
+
+bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
+bool thread_attach_current_external_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
+bool thread_detach_current_thread(void);
+
+bool thread_detach_current_external_thread(void);
+
+void thread_fprint_name(threadobject *t, FILE *stream);
+void thread_print_info(threadobject *t);
+
+intptr_t threads_get_current_tid(void);
+
+void thread_set_state_runnable(threadobject *t);
+void thread_set_state_waiting(threadobject *t);
+void thread_set_state_timed_waiting(threadobject *t);
+void thread_set_state_terminated(threadobject *t);
+
+threadobject *thread_get_thread(java_handle_t *h);
+
+bool threads_thread_is_alive(threadobject *t);
+
+void threads_dump(void);
+
+
+/* implementation specific functions */
+
+void threads_impl_preinit(void);
+void threads_impl_init(void);
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_lock(void);
+void threads_mutex_gc_unlock(void);
+#endif
+
+void threads_mutex_join_lock(void);
+void threads_mutex_join_unlock(void);
+
+void threads_impl_thread_init(threadobject *t);
+void threads_impl_thread_clear(threadobject *t);
+void threads_impl_thread_reuse(threadobject *t);
+void threads_impl_thread_free(threadobject *t);
+void threads_impl_thread_start(threadobject *thread, functionptr f);
+
+void threads_yield(void);
+
+#endif /* ENABLE_THREADS */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _THREAD_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:
+ */
#include "mm/memory.h"
-#include "threads/mutex.h"
+#include "threads/mutex.hpp"
#include "threads/threadlist.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/list.h"
-#include "vmcore/options.h"
+#include "vm/options.h"
/* global variables ***********************************************************/
-static mutex_t threadlist_mutex; /* global mutex for the thread list */
+static Mutex* threadlist_mutex; /* global mutex for the thread list */
static list_t *list_thread; /* global threads list */
static list_t *list_thread_free; /* global free threads list */
/* Initialize the thread list mutex. */
- mutex_init(&threadlist_mutex);
+ threadlist_mutex = Mutex_new();
/* Initialize the thread lists. */
void threadlist_lock(void)
{
- mutex_lock(&threadlist_mutex);
+ Mutex_lock(threadlist_mutex);
}
void threadlist_unlock(void)
{
- mutex_unlock(&threadlist_mutex);
+ Mutex_unlock(threadlist_mutex);
}
#include <stdint.h>
-#include "threads/thread.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "threads/thread.hpp"
/* function prototypes ********************************************************/
void threadlist_lock(void);
void threadlist_unlock(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _THREADLIST_H */
/* src/toolbox/avl.c - AVL tree implementation
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
#include "toolbox/avl.h"
#include "toolbox/logging.h"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
/* avl_create ******************************************************************
t = NEW(avl_tree_t);
+ t->mutex = Mutex_new();
t->root = NULL;
t->comparator = comparator;
t->entries = 0;
-#if defined(ENABLE_THREADS)
- /* create lock object for this tree */
-
- t->lock = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(t->lock);
-#endif
-
return t;
}
assert(tree);
assert(data);
- LOCK_MONITOR_ENTER(tree->lock);
+ Mutex_lock(tree->mutex);
/* if we don't have a root node, create one */
tree->entries++;
- LOCK_MONITOR_EXIT(tree->lock);
+ Mutex_unlock(tree->mutex);
/* insertion was ok */
assert(tree);
assert(data);
- LOCK_MONITOR_ENTER(tree->lock);
+ Mutex_lock(tree->mutex);
/* search the tree for the given node */
/* was the entry found? return it */
if (res == 0) {
- LOCK_MONITOR_EXIT(tree->lock);
+ Mutex_unlock(tree->mutex);
return node->data;
}
node = node->childs[(res < 0) ? AVL_LEFT : AVL_RIGHT];
}
- LOCK_MONITOR_EXIT(tree->lock);
+ Mutex_unlock(tree->mutex);
/* entry was not found, returning NULL */
/* src/toolbox/avl.h - AVL tree implementation
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
+#include "threads/mutex.hpp"
+
#include "vm/global.h"
/* avl_tree_t *****************************************************************/
struct avl_tree_t {
-#if defined(ENABLE_THREADS)
- java_object_t *lock; /* threads lock object */
-#endif
- avl_node_t *root; /* pointer to root node */
- avl_comparator *comparator; /* pointer to comparison function */
- s4 entries; /* contains number of entries */
+ Mutex* mutex; ///< Mutex to lock the tree.
+ avl_node_t *root; /* pointer to root node */
+ avl_comparator *comparator; /* pointer to comparison function */
+ s4 entries; /* contains number of entries */
};
/* src/toolbox/hashtable.h - functions for internal hashtables
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Reinhard Grafl
- Christian Thalinger
-
*/
#include "vm/types.h"
#include "vm/global.h"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
/* data structures for hashtables ********************************************
#include "mm/memory.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/logging.h"
#include "toolbox/util.h"
#include "vm/global.h"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
/* src/toolbox/logging.h - contains logging functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdio.h>
#include <stdarg.h>
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/utf8.h"
+#include "vm/class.h"
+#include "vm/method.h"
+#include "vm/utf8.h"
/*500 is to small for eclipse traces, (builtin_trace_args, perhaps the
/* src/toolbox/util.c - contains some utility functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#include "vm/types.h"
#include "mm/memory.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
/* _Jv_getcwd ******************************************************************
/* src/toolbox/util.h - contains some utility functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#ifndef _UTIL_H
#define _UTIL_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "config.h"
#include <stdarg.h>
char *_Jv_getcwd(void);
int get_variable_message_length(const char *fmt, va_list ap);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _UTIL_H */
cycles-stats.h
endif
+if ENABLE_JAVASE
+if ENABLE_ANNOTATIONS
+ANNOTATION_SOURCES = \
+ annotation.c \
+ annotation.h
+endif
+
+STACKMAP_SOURCES = \
+ stackmap.c \
+ stackmap.h
+endif
+
+if ENABLE_RT_TIMING
+RT_TIMING_SOURCES = \
+ rt-timing.c \
+ rt-timing.h
+endif
+
+if ENABLE_STATISTICS
+STATISTICS_SOURCES = \
+ statistics.c \
+ statistics.h
+endif
+
+if ENABLE_ZLIB
+ZLIB_SOURCES = \
+ zip.c \
+ zip.h
+endif
+
noinst_HEADERS = \
global.h \
types.h
libvm.la
libvm_la_SOURCES = \
- $(ASSERTION_SOURCES) \
access.c \
access.h \
+ $(ANNOTATION_SOURCES) \
array.c \
array.h \
+ $(ASSERTION_SOURCES) \
builtin.c \
builtin.h \
builtintable.inc \
+ class.c \
+ class.h \
+ classcache.c \
+ classcache.h \
$(CYCLES_STATS_SOURCES) \
- exceptions.c \
- exceptions.h \
+ descriptor.c \
+ descriptor.h \
+ exceptions.cpp \
+ exceptions.hpp \
+ field.c \
+ field.h \
finalizer.c \
finalizer.h \
+ globals.cpp \
+ globals.hpp \
initialize.c \
initialize.h \
+ javaobjects.cpp \
+ javaobjects.hpp \
jit_interface.h \
+ linker.c \
+ linker.h \
+ loader.c \
+ loader.h \
+ method.c \
+ method.h \
+ options.c \
+ options.h \
+ os.cpp \
+ os.hpp \
package.cpp \
package.hpp \
- primitive.c \
- primitive.h \
+ primitive.cpp \
+ primitive.hpp \
+ primitivecore.c \
properties.c \
properties.h \
+ references.h \
resolve.c \
resolve.h \
+ $(RT_TIMING_SOURCES) \
signal.c \
signallocal.h \
- string.c \
- stringlocal.h \
- vm.c \
- vm.h
+ $(STACKMAP_SOURCES) \
+ $(STATISTICS_SOURCES) \
+ string.cpp \
+ string.hpp \
+ suck.c \
+ suck.h \
+ utf8.c \
+ utf8.h \
+ vm.cpp \
+ vm.hpp \
+ $(ZLIB_SOURCES)
libvm_la_LIBADD = \
jit/libjit.la
#include "vm/access.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.h"
+#include "vm/globals.hpp"
+#include "vm/method.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
+#include "vm/jit/stacktrace.hpp"
/* access_is_accessible_class **************************************************
#include <stdint.h>
-#include "vm/global.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
+#include "vm/class.h"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/method.h"
/* macros *********************************************************************/
bool access_check_method(methodinfo *m, int callerdepth);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _ACCESS_H */
--- /dev/null
+/* src/vm/annotation.c - class annotations
+
+ Copyright (C) 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 <stdint.h>
+
+#include "native/llni.h"
+
+#include "mm/memory.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/annotation.h"
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/loader.h"
+#include "vm/primitive.hpp"
+#include "vm/suck.h"
+#include "vm/types.h"
+
+#if !defined(ENABLE_ANNOTATIONS)
+# error annotation support has to be enabled when compling this file!
+#endif
+
+
+/* annotation_bytearrays_resize ***********************************************
+
+ Resize an array of bytearrays.
+
+ IN:
+ bytearrays.....array of bytearrays
+ size...........new size of the refered array
+
+ RETURN VALUE:
+ The new array if a resize was neccessarry, the old if the given size
+ equals the current size or NULL if an error occured.
+
+*******************************************************************************/
+
+static java_handle_objectarray_t *annotation_bytearrays_resize(
+ java_handle_objectarray_t *bytearrays, uint32_t size)
+{
+ java_handle_objectarray_t *newbas = NULL; /* new array */
+ uint32_t minsize = 0; /* count of object refs to copy */
+ uint32_t oldsize = 0; /* size of old array */
+
+ if (bytearrays != NULL) {
+ oldsize = array_length_get((java_handle_t*)bytearrays);
+
+ /* if the size already fits do nothing */
+ if (size == oldsize) {
+ return bytearrays;
+ }
+ }
+
+ newbas = builtin_anewarray(size,
+ Primitive_get_arrayclass_by_type(PRIMITIVETYPE_BYTE));
+
+ /* is there a old byte array array? */
+ if (newbas != NULL && bytearrays != NULL) {
+ minsize = size < oldsize ? size : oldsize;
+
+ LLNI_CRITICAL_START;
+ MCOPY(
+ LLNI_array_data(newbas), LLNI_array_data(bytearrays),
+ java_object_t*, minsize);
+ LLNI_CRITICAL_END;
+ }
+
+ return newbas;
+}
+
+
+/* annotation_bytearrays_insert ***********************************************
+
+ Insert a bytearray into an array of bytearrays.
+
+ IN:
+ bytearrays........array of bytearrays where 'bytearray' has to be
+ inserted at position 'index'.
+ index.............position where 'ba' has to be inserted into
+ 'bytearrays'.
+ bytearray.........byte array which has to be inserted into
+ 'bytearrays'.
+
+ RETURN VALUE:
+ The new array if a resize was neccessarry, the old if the given size
+ equals the current size or NULL if an error occured.
+
+*******************************************************************************/
+
+static java_handle_t *annotation_bytearrays_insert(
+ java_handle_t *bytearrays, uint32_t index,
+ java_handle_bytearray_t *bytearray)
+{
+ java_handle_objectarray_t *bas; /* bytearrays */
+ uint32_t size = 0; /* current size of the array */
+
+ /* do nothing if NULL is inserted but no array exists */
+ if (bytearray == NULL && bytearrays == NULL) {
+ return NULL;
+ }
+
+ /* get lengths if array exists */
+ if (bytearrays != NULL) {
+ size = array_length_get(bytearrays);
+ }
+
+ bas = (java_handle_objectarray_t*)bytearrays;
+
+ if (bytearray == NULL) {
+ /* insert NULL only if array is big enough */
+ if (size > index) {
+ array_objectarray_element_set(bas, index, NULL);
+ }
+ }
+ else {
+ /* resize array if it's not enough for inserted value */
+ if (size <= index) {
+ bas = annotation_bytearrays_resize(bas, index + 1);
+
+ if (bas == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+ }
+
+ array_objectarray_element_set(bas, index, (java_handle_t*)bytearray);
+ }
+
+ return (java_handle_t*)bas;
+}
+
+
+/* annotation_load_attribute_body *********************************************
+
+ This function loads the body of a generic attribute.
+
+ XXX: Maybe this function should be called loader_load_attribute_body and
+ located in vm/loader.c?
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ errormsg_prefix....prefix for error messages (if any).
+
+ OUT:
+ attribute..........bytearray-pointer which will be set to the read data.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+static bool annotation_load_attribute_body(classbuffer *cb,
+ java_handle_bytearray_t **attribute, const char *errormsg_prefix)
+{
+ uint32_t size = 0; /* size of the attribute */
+ java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */
+
+ assert(cb != NULL);
+ assert(attribute != NULL);
+
+ if (!suck_check_classbuffer_size(cb, 4)) {
+ log_println("%s: size missing", errormsg_prefix);
+ return false;
+ }
+
+ /* load attribute_length */
+ size = suck_u4(cb);
+
+ if (!suck_check_classbuffer_size(cb, size)) {
+ log_println("%s: invalid size", errormsg_prefix);
+ return false;
+ }
+
+ /* if attribute_length == 0 then NULL is
+ * the right value for this attribute */
+ if (size > 0) {
+ ba = builtin_newarray_byte(size);
+
+ if (ba == NULL) {
+ /* out of memory */
+ return false;
+ }
+
+ /* load data */
+ LLNI_CRITICAL_START;
+
+ suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size);
+
+ LLNI_CRITICAL_END;
+
+ /* return data */
+ *attribute = ba;
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_annotationdefault *************************
+
+ Load annotation default value.
+
+ AnnotationDefault_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ element_value default_value;
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the annotation
+ default value is read and into which the value is
+ stored into.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_annotationdefault(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ /* the slot of the method */
+ java_handle_bytearray_t *annotationdefault = NULL;
+ /* unparsed annotation defalut value */
+ java_handle_t *annotationdefaults = NULL;
+ /* array of unparsed annotation default values */
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ LLNI_classinfo_field_get(
+ m->clazz, method_annotationdefaults, annotationdefaults);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotationdefault,
+ "invalid annotation default method attribute")) {
+ return false;
+ }
+
+ if (annotationdefault != NULL) {
+ slot = m - m->clazz->methods;
+ annotationdefaults = annotation_bytearrays_insert(
+ annotationdefaults, slot, annotationdefault);
+
+ if (annotationdefaults == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ m->clazz, method_annotationdefaults, annotationdefaults);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_runtimevisibleparameterannotations ********
+
+ Load runtime visible parameter annotations.
+
+ RuntimeVisibleParameterAnnotations_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 num_parameters;
+ {
+ u2 num_annotations;
+ annotation annotations[num_annotations];
+ } parameter_annotations[num_parameters];
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the parameter
+ annotations are read and into which the parameter
+ annotations are stored into.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimevisibleparameterannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ /* the slot of the method */
+ java_handle_bytearray_t *annotations = NULL;
+ /* unparsed parameter annotations */
+ java_handle_t *parameterannotations = NULL;
+ /* array of unparsed parameter annotations */
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ LLNI_classinfo_field_get(
+ m->clazz, method_parameterannotations, parameterannotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible parameter annotations method attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = m - m->clazz->methods;
+ parameterannotations = annotation_bytearrays_insert(
+ parameterannotations, slot, annotations);
+
+ if (parameterannotations == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ m->clazz, method_parameterannotations, parameterannotations);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
+
+ Load runtime invisible parameter annotations.
+
+ <quote cite="http://jcp.org/en/jsr/detail?id=202">
+ The RuntimeInvisibleParameterAnnotations attribute is similar to the
+ RuntimeVisibleParameterAnnotations attribute, except that the annotations
+ represented by a RuntimeInvisibleParameterAnnotations attribute must not be
+ made available for return by reflective APIs, unless the the JVM has
+ specifically been instructed to retain these annotations via some
+ implementation-specific mechanism such as a command line flag. In the
+ absence of such instructions, the JVM ignores this attribute.
+ </quote>
+
+ Hotspot loads them into the same bytearray as the runtime visible parameter
+ annotations (after the runtime visible parameter annotations). But in J2SE
+ the bytearray will only be parsed as if there is only one annotation
+ structure in it, so the runtime invisible parameter annotatios will be
+ ignored.
+
+ Therefore I do not even bother to read them.
+
+ RuntimeInvisibleParameterAnnotations_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 num_parameters;
+ {
+ u2 num_annotations;
+ annotation annotations[num_annotations];
+ } parameter_annotations[num_parameters];
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the parameter
+ annotations are read and into which the parameter
+ annotations are stored into.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_class_attribute_runtimevisibleannotations ******************
+
+ Load runtime visible annotations of a class.
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_class_attribute_runtimevisibleannotations(
+ classbuffer *cb)
+{
+ java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations class attribute")) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations);
+
+ return true;
+}
+
+
+/* annotation_load_class_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a class (just skip them).
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_class_attribute_runtimeinvisibleannotations(
+ classbuffer *cb)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_method_attribute_runtimevisibleannotations *****************
+
+ Load runtime visible annotations of a method.
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ m.........the method of which the runtime visible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimevisibleannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ /* slot of the method */
+ java_handle_bytearray_t *annotations = NULL;
+ /* unparsed annotations */
+ java_handle_t *method_annotations = NULL;
+ /* array of unparsed method annotations */
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ LLNI_classinfo_field_get(
+ m->clazz, method_annotations, method_annotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations method attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = m - m->clazz->methods;
+ method_annotations = annotation_bytearrays_insert(
+ method_annotations, slot, annotations);
+
+ if (method_annotations == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ m->clazz, method_annotations, method_annotations);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a method (just skip them).
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ m.........the method of which the runtime invisible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_field_attribute_runtimevisibleannotations ******************
+
+ Load runtime visible annotations of a field.
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ f.........the field of which the runtime visible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_field_attribute_runtimevisibleannotations(
+ classbuffer *cb, fieldinfo *f)
+{
+ int slot = 0;
+ /* slot of the field */
+ java_handle_bytearray_t *annotations = NULL;
+ /* unparsed annotations */
+ java_handle_t *field_annotations = NULL;
+ /* array of unparsed field annotations */
+
+ assert(cb != NULL);
+ assert(f != NULL);
+
+ LLNI_classinfo_field_get(
+ f->clazz, field_annotations, field_annotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations field attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = f - f->clazz->fields;
+ field_annotations = annotation_bytearrays_insert(
+ field_annotations, slot, annotations);
+
+ if (field_annotations == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ f->clazz, field_annotations, field_annotations);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_field_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a field (just skip them).
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ f.........the field of which the runtime invisible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_field_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, fieldinfo *f)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/*
+ * 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/annotation.h - class annotations
+
+ Copyright (C) 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 _ANNOTATION_H
+#define _ANNOTATION_H
+
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "vm/class.h"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+
+
+/* function prototypes ********************************************************/
+
+bool annotation_load_class_attribute_runtimevisibleannotations(
+ classbuffer *cb);
+
+bool annotation_load_class_attribute_runtimeinvisibleannotations(
+ classbuffer *cb);
+
+bool annotation_load_method_attribute_runtimevisibleannotations(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_method_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_field_attribute_runtimevisibleannotations(
+ classbuffer *cb, fieldinfo *f);
+
+bool annotation_load_field_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, fieldinfo *f);
+
+bool annotation_load_method_attribute_annotationdefault(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_method_attribute_runtimevisibleparameterannotations(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
+ classbuffer *cb, methodinfo *m);
+
+#endif /* _ANNOTATION_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 "native/llni.h"
#include "vm/array.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/primitive.h"
-#include "vm/vm.h"
+#include "vm/primitive.hpp"
+#include "vm/vm.hpp"
/* array_element_get ***********************************************************
value = array_element_primitive_get(a, index);
- o = primitive_box(type, value);
+ o = Primitive_box(type, value);
return o;
}
{
imm_union value;
- value = primitive_unbox(o);
+ value = Primitive_unbox(o);
array_element_primitive_set(a, index, value);
}
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/global.h"
-#include "vm/primitive.h"
+#include "vm/primitive.hpp"
/* array types ****************************************************************/
int32_t array_length_get(java_handle_t *a);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _VM_ARRAY_H */
#include "vm/assertion.h"
#include "vm/global.h"
-#include "vm/vm.h"
-
-#include "vmcore/system.h"
+#include "vm/os.hpp"
+#include "vm/vm.hpp"
/* -ea/-da options ************************************************************/
}
package = false;
- len = system_strlen(name);
+ len = os_strlen(name);
if (name[len - 1] == '/') {
return;
}
- buf = system_strdup(name);
+ buf = os_strdup(name);
if (buf == NULL) {
vm_abort("assertion_ea_da: strdup failed: %s", strerror(errno));
assertion_class_count += 1;
}
- len = system_strlen(buf);
+ len = os_strlen(buf);
for (i = 0; i < len; i++) {
#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
#define _ASSERTION_H
#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/global.h"
#include "toolbox/list.h"
-#include <stdint.h>
typedef struct assertion_name_t assertion_name_t;
void assertion_ea_da(const char *name, bool enabled);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _ASSERTION_H */
# 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>
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 */
/* 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 */
NULL,
NULL
},
+
+#if defined(ENABLE_TLH)
+ {
+ ICMD_NEW,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_tlh_new,
+ NULL,
+ NULL,
+ "tlh_new",
+ "(Ljava/lang/Class;)Ljava/lang/Object;",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if defined(ENABLE_ESCAPE_REASON)
+ {
+ ICMD_NEW,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_escape_reason_new,
+ NULL,
+ NULL,
+ "escape_reason_new",
+ "(Ljava/lang/Class;)Ljava/lang/Object;",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
{
ICMD_NEW,
0,
--- /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:
+ */
--- /dev/null
+/* src/vm/classcache.c - loaded class cache and loading constraints
+
+ 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 "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/logging.h"
+
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/utf8.h"
+
+
+/*************************************************************************
+
+ Class Cache
+
+ The classcache has two functions:
+
+ 1) caching the resolution of class references
+ 2) storing and checking loading constraints
+
+ We will use the following terms in this description:
+
+ N a class name: a utf string
+ (N,L) a class reference with initiating loader L and class name N
+ C a class (object): the result of resolving a reference (N,L)
+ We will write resultion as
+ C = *(N,L)
+ (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
+ resolve to the same class C. So (N,L1,L2) means
+ *(N,L1) = *(N,L2)
+
+ The functions of the classcache require:
+
+ 1) a mapping (N,L) |--> C for looking up prior resolution results.
+ 2) storing the current set of loading constraints { (N,L1,L2) }
+
+ These functions can be rearranged like that:
+
+ a mapping N |--> (a mapping L |--> C or NULL,
+ a set of constraints {(L1,L2)})
+
+ Thus we can treat the mapping and constraints for each name N
+ separately. The implementation does this by keeping a hash table
+ mapping a name N to a `classcache_name_entry` which contains all
+ info with respect to N.
+
+ For a class name N we can define an equivalence relation ~N~ on
+ class loaders:
+
+ L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
+
+ A loading constraint (N,L1,L2) implies L1 ~N~ L2.
+
+ Also, if two references (N,L1) and (N,L2) resolve to the same class C
+ we have L1 ~N~ L2 because class loaders are required to return
+ consistent resolutions for a name N [XXX].
+
+ A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
+ where
+ Cx...is a class C or NULL
+ IL...is the set of initiating loaders
+ CL...is the set of constrained loaders
+
+ Such a tuple is called `classcache_class_entry` in the source code.
+
+ The following holds for each tuple (Cx,IL,CL):
+
+ . (Cx is NULL) implies IL = {}.
+
+ . If Cx is a class, IL is the set of loaders that have been
+ recorded as initiating loaders for Cx. IL may be the
+ empty set {} in case Cx has already been defined but no
+ initiating loader has been recorded, yet.
+
+ . (IL u CL) is a subset of an equivalence class of ~N~.
+
+ (This means that all loaders in IL and CL must resolve
+ the name N to the same class.)
+
+ The following holds for the set of tuples { (Cx,IL,CL) }:
+
+ . For a given class C there is at most one tuple with Cx = C
+ in the set. (There may be an arbitrary number of tuples
+ with Cx = NULL, however.)
+
+ . For a given loader L there is at most one tuple with
+ L in (IL u CL).
+
+ The implementation stores sets of loaders as linked lists of
+ `classcache_loader_entry`s.
+
+ Comments about manipulating the classcache can be found in the
+ individual functions below.
+
+*************************************************************************/
+
+
+/* initial number of slots in the classcache hash table */
+#define CLASSCACHE_INIT_SIZE 2048
+
+/*============================================================================*/
+/* DEBUG HELPERS */
+/*============================================================================*/
+
+/* #define CLASSCACHE_VERBOSE */
+
+/*============================================================================*/
+/* STATISTICS */
+/*============================================================================*/
+
+/*#define CLASSCACHE_STATS*/
+
+#ifdef CLASSCACHE_STATS
+static int stat_classnames_stored = 0;
+static int stat_classes_stored = 0;
+static int stat_trivial_constraints = 0;
+static int stat_nontriv_constraints = 0;
+static int stat_nontriv_constraints_both = 0;
+static int stat_nontriv_constraints_merged = 0;
+static int stat_nontriv_constraints_one = 0;
+static int stat_nontriv_constraints_none = 0;
+static int stat_new_loader_entry = 0;
+static int stat_merge_class_entries = 0;
+static int stat_merge_loader_entries = 0;
+static int stat_lookup = 0;
+static int stat_lookup_class_entry_checked = 0;
+static int stat_lookup_loader_checked = 0;
+static int stat_lookup_name = 0;
+static int stat_lookup_name_entry = 0;
+static int stat_lookup_name_notfound = 0;
+static int stat_lookup_new_name = 0;
+static int stat_lookup_new_name_entry = 0;
+static int stat_lookup_new_name_collisions = 0;
+static int stat_rehash_names = 0;
+static int stat_rehash_names_collisions = 0;
+
+#define CLASSCACHE_COUNT(cnt) (cnt)++
+#define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
+
+void classcache_print_statistics(FILE *file) {
+ fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
+ fprintf(file,"classes stored : %8d\n",stat_classes_stored);
+ fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
+ fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
+ fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
+ fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
+ fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
+ fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
+ fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
+ fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
+ fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
+ fprintf(file,"lookups : %8d\n",stat_lookup);
+ fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
+ fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
+ fprintf(file,"lookup name : %8d\n",stat_lookup_name);
+ fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
+ fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
+ fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
+ fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
+ fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
+ fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
+ fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
+}
+#else
+#define CLASSCACHE_COUNT(cnt)
+#define CLASSCACHE_COUNTIF(cond,cnt)
+#endif
+
+/*============================================================================*/
+/* THREAD-SAFE LOCKING */
+/*============================================================================*/
+
+ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* CAUTION: The static functions below are */
+ /* NOT synchronized! */
+ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if defined(ENABLE_THREADS)
+# define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
+# define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
+#else
+# define CLASSCACHE_LOCK()
+# define CLASSCACHE_UNLOCK()
+#endif
+
+/*============================================================================*/
+/* GLOBAL VARIABLES */
+/*============================================================================*/
+
+hashtable hashtable_classcache;
+
+#if defined(ENABLE_THREADS)
+static java_object_t *lock_hashtable_classcache;
+#endif
+
+
+/*============================================================================*/
+/* */
+/*============================================================================*/
+
+/* prototypes */
+
+static void classcache_free_class_entry(classcache_class_entry *clsen);
+static void classcache_remove_class_entry(classcache_name_entry *en,
+ classcache_class_entry *clsen);
+
+/* hash function to use */
+
+#define CLASSCACHE_HASH utf_full_hashkey
+
+/* classcache_init *************************************************************
+
+ Initialize the class cache
+
+ Note: NOT synchronized!
+
+*******************************************************************************/
+
+bool classcache_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("classcache_init");
+
+ /* create the hashtable */
+
+ hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
+
+#if defined(ENABLE_THREADS)
+ /* create utf hashtable lock object */
+
+ lock_hashtable_classcache = NEW(java_object_t);
+
+ LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
+#endif
+
+ /* everything's ok */
+
+ return true;
+}
+
+/* classcache_new_loader_entry *************************************************
+
+ Create a new classcache_loader_entry struct
+ (internally used helper function)
+
+ IN:
+ loader...........the ClassLoader object
+ next.............the next classcache_loader_entry
+
+ RETURN VALUE:
+ the new classcache_loader_entry
+
+*******************************************************************************/
+
+static classcache_loader_entry * classcache_new_loader_entry(
+ classloader_t * loader,
+ classcache_loader_entry * next)
+{
+ classcache_loader_entry *lden;
+
+ lden = NEW(classcache_loader_entry);
+ lden->loader = loader;
+ lden->next = next;
+ CLASSCACHE_COUNT(stat_new_loader_entry);
+
+ return lden;
+}
+
+/* classcache_merge_loaders ****************************************************
+
+ Merge two lists of loaders into one
+ (internally used helper function)
+
+ IN:
+ lista............first list (may be NULL)
+ listb............second list (may be NULL)
+
+ RETURN VALUE:
+ the merged list (may be NULL)
+
+ NOTE:
+ The lists given as arguments are destroyed!
+
+*******************************************************************************/
+
+static classcache_loader_entry * classcache_merge_loaders(
+ classcache_loader_entry * lista,
+ classcache_loader_entry * listb)
+{
+ classcache_loader_entry *result;
+ classcache_loader_entry *ldenA;
+ classcache_loader_entry *ldenB;
+ classcache_loader_entry **chain;
+
+ CLASSCACHE_COUNT(stat_merge_loader_entries);
+
+ /* XXX This is a quadratic algorithm. If this ever
+ * becomes a problem, the loader lists should be
+ * stored as sorted lists and merged in linear time. */
+
+ result = NULL;
+ chain = &result;
+
+ for (ldenA = lista; ldenA; ldenA = ldenA->next) {
+
+ for (ldenB = listb; ldenB; ldenB = ldenB->next) {
+ if (ldenB->loader == ldenA->loader)
+ goto common_element;
+ }
+
+ /* this loader is only in lista */
+ *chain = ldenA;
+ chain = &(ldenA->next);
+
+ common_element:
+ /* XXX free the duplicated element */
+ ;
+ }
+
+ /* concat listb to the result */
+ *chain = listb;
+
+ return result;
+}
+
+/* classcache_merge_class_entries **********************************************
+
+ Merge two `classcache_class_entry`s into one.
+ (internally used helper function)
+
+ IN:
+ en...............the classcache_name_entry containing both class entries
+ clsenA...........first class entry, will receive the result
+ clsenB...........second class entry
+
+ PRE-CONDITION:
+ Either both entries must have the same classobj, or one of them has
+ classobj == NULL.
+
+ NOTE:
+ clsenB is freed by this function!
+
+*******************************************************************************/
+
+static void classcache_merge_class_entries(classcache_name_entry *en,
+ classcache_class_entry *clsenA,
+ classcache_class_entry *clsenB)
+{
+#ifdef CLASSCACHE_VERBOSE
+ char logbuffer[1024];
+#endif
+
+ assert(en);
+ assert(clsenA);
+ assert(clsenB);
+ assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
+
+#ifdef CLASSCACHE_VERBOSE
+ sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
+ (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
+ if (clsenA->classobj)
+ utf_cat_classname(logbuffer, clsenA->classobj->name);
+ if (clsenB->classobj)
+ utf_cat_classname(logbuffer, clsenB->classobj->name);
+ log_println(logbuffer);
+#endif
+
+ CLASSCACHE_COUNT(stat_merge_class_entries);
+
+ /* clsenB will be merged into clsenA */
+ clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
+ clsenB->loaders = NULL; /* these have been freed or reused */
+
+ clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
+ clsenB->constraints);
+ clsenB->constraints = NULL; /* these have been freed or reused */
+
+ if (!clsenA->classobj)
+ clsenA->classobj = clsenB->classobj;
+
+ /* remove clsenB from the list of class entries */
+ classcache_remove_class_entry(en, clsenB);
+}
+
+
+/* classcache_lookup_name ******************************************************
+
+ Lookup a name in the first level of the cache
+ (internally used helper function)
+
+ IN:
+ name.............the name to look up
+
+ RETURN VALUE:
+ a pointer to the classcache_name_entry for this name, or
+ null if no entry was found.
+
+*******************************************************************************/
+
+static classcache_name_entry *classcache_lookup_name(utf *name)
+{
+ classcache_name_entry *c; /* hash table element */
+ u4 key; /* hashkey computed from classname */
+ u4 slot; /* slot in hashtable */
+
+ CLASSCACHE_COUNT(stat_lookup_name);
+
+ key = CLASSCACHE_HASH(name->text, (u4) name->blength);
+ slot = key & (hashtable_classcache.size - 1);
+ c = hashtable_classcache.ptr[slot];
+
+ /* search external hash chain for the entry */
+
+ while (c) {
+ /* entry found in hashtable */
+ CLASSCACHE_COUNT(stat_lookup_name_entry);
+
+ if (c->name == name)
+ return c;
+
+ c = c->hashlink; /* next element in external chain */
+ }
+
+ /* not found */
+
+ CLASSCACHE_COUNT(stat_lookup_name_notfound);
+ return NULL;
+}
+
+
+/* classcache_new_name *********************************************************
+
+ Return a classcache_name_entry for the given name. The entry is created
+ if it is not already in the cache.
+ (internally used helper function)
+
+ IN:
+ name.............the name to look up / create an entry for
+
+ RETURN VALUE:
+ a pointer to the classcache_name_entry for this name
+
+*******************************************************************************/
+
+static classcache_name_entry *classcache_new_name(utf *name)
+{
+ classcache_name_entry *c; /* hash table element */
+ u4 key; /* hashkey computed from classname */
+ u4 slot; /* slot in hashtable */
+ u4 i;
+
+ CLASSCACHE_COUNT(stat_lookup_new_name);
+
+ key = CLASSCACHE_HASH(name->text, (u4) name->blength);
+ slot = key & (hashtable_classcache.size - 1);
+ c = hashtable_classcache.ptr[slot];
+
+ /* search external hash chain for the entry */
+
+ while (c) {
+ /* entry found in hashtable */
+ CLASSCACHE_COUNT(stat_lookup_new_name_entry);
+
+ if (c->name == name)
+ return c;
+
+ c = c->hashlink; /* next element in external chain */
+ }
+
+ /* location in hashtable found, create new entry */
+
+ c = NEW(classcache_name_entry);
+
+ c->name = name;
+ c->classes = NULL;
+
+ /* insert entry into hashtable */
+ c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+ CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
+ hashtable_classcache.ptr[slot] = c;
+
+ /* update number of hashtable-entries */
+ hashtable_classcache.entries++;
+ CLASSCACHE_COUNT(stat_classnames_stored);
+
+ if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
+ /* reorganization of hashtable */
+
+ classcache_name_entry *c2;
+ hashtable newhash; /* the new hashtable */
+
+ CLASSCACHE_COUNT(stat_rehash_names);
+
+ /* create new hashtable, double the size */
+
+ hashtable_create(&newhash, hashtable_classcache.size * 2);
+ newhash.entries = hashtable_classcache.entries;
+
+ /* transfer elements to new hashtable */
+
+ for (i = 0; i < hashtable_classcache.size; i++) {
+ c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
+ while (c2) {
+ classcache_name_entry *nextc = c2->hashlink;
+ u4 newslot =
+ (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
+
+ c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
+ CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
+ newhash.ptr[newslot] = c2;
+
+ c2 = nextc;
+ }
+ }
+
+ /* dispose old table */
+
+ MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
+ hashtable_classcache = newhash;
+ }
+
+ return c;
+}
+
+
+/* classcache_lookup ***********************************************************
+
+ Lookup a possibly loaded class
+
+ IN:
+ initloader.......initiating loader for resolving the class name
+ classname........class name to look up
+
+ RETURN VALUE:
+ The return value is a pointer to the cached class object,
+ or NULL, if the class is not in the cache.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+classinfo *classcache_lookup(classloader_t *initloader, utf *classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+ classinfo *cls = NULL;
+
+ CLASSCACHE_LOCK();
+
+ CLASSCACHE_COUNT(stat_lookup);
+ en = classcache_lookup_name(classname);
+
+ if (en) {
+ /* iterate over all class entries */
+
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+ CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
+ /* check if this entry has been loaded by initloader */
+
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ CLASSCACHE_COUNT(stat_lookup_loader_checked);
+ if (lden->loader == initloader) {
+ /* found the loaded class entry */
+
+ assert(clsen->classobj);
+ cls = clsen->classobj;
+ goto found;
+ }
+ }
+ }
+ }
+
+ found:
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+
+/* classcache_lookup_defined ***************************************************
+
+ Lookup a class with the given name and defining loader
+
+ IN:
+ defloader........defining loader
+ classname........class name
+
+ RETURN VALUE:
+ The return value is a pointer to the cached class object,
+ or NULL, if the class is not in the cache.
+
+*******************************************************************************/
+
+classinfo *classcache_lookup_defined(classloader_t *defloader, utf *classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classinfo *cls = NULL;
+
+ CLASSCACHE_LOCK();
+
+ en = classcache_lookup_name(classname);
+
+ if (en) {
+ /* iterate over all class entries */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+ if (!clsen->classobj)
+ continue;
+
+ /* check if this entry has been defined by defloader */
+ if (clsen->classobj->classloader == defloader) {
+ cls = clsen->classobj;
+ goto found;
+ }
+ }
+ }
+
+ found:
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+
+/* classcache_lookup_defined_or_initiated **************************************
+
+ Lookup a class that has been defined or initiated by the given loader
+
+ IN:
+ loader...........defining or initiating loader
+ classname........class name to look up
+
+ RETURN VALUE:
+ The return value is a pointer to the cached class object,
+ or NULL, if the class is not in the cache.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+classinfo *classcache_lookup_defined_or_initiated(classloader_t *loader,
+ utf *classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+ classinfo *cls = NULL;
+
+ CLASSCACHE_LOCK();
+
+ en = classcache_lookup_name(classname);
+
+ if (en) {
+ /* iterate over all class entries */
+
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+
+ /* check if this entry has been defined by loader */
+ if (clsen->classobj && clsen->classobj->classloader == loader) {
+ cls = clsen->classobj;
+ goto found;
+ }
+
+ /* check if this entry has been initiated by loader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == loader) {
+ /* found the loaded class entry */
+
+ assert(clsen->classobj);
+ cls = clsen->classobj;
+ goto found;
+ }
+ }
+ }
+ }
+
+ found:
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+
+/* classcache_store ************************************************************
+
+ Store a loaded class. If a class of the same name has already been stored
+ with the same initiating loader, then the given class CLS is freed (if
+ possible) and the previously stored class is returned.
+
+ IN:
+ initloader.......initiating loader used to load the class
+ (may be NULL indicating the bootstrap loader)
+ cls..............class object to cache
+ mayfree..........true if CLS may be freed in case another class is
+ returned
+
+ RETURN VALUE:
+ cls..............everything ok, the class was stored in the cache,
+ other classinfo..another class with the same (initloader,name) has been
+ stored earlier. CLS has been freed[1] and the earlier
+ stored class is returned.
+ NULL.............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+ [1]...in case MAYFREE is true
+
+*******************************************************************************/
+
+classinfo *classcache_store(classloader_t *initloader, classinfo *cls,
+ bool mayfree)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classcache_class_entry *clsenB;
+ classcache_loader_entry *lden;
+#ifdef CLASSCACHE_VERBOSE
+ char logbuffer[1024];
+#endif
+
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
+
+ CLASSCACHE_LOCK();
+
+#ifdef CLASSCACHE_VERBOSE
+ sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
+ utf_cat_classname(logbuffer, cls->name);
+ strcat(logbuffer,")");
+ log_println(logbuffer);
+#endif
+
+ en = classcache_new_name(cls->name);
+
+ assert(en);
+
+ /* iterate over all class entries */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+
+ /* check if this entry has already been loaded by initloader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == initloader) {
+ if (clsen->classobj != cls) {
+ /* A class with the same (initloader,name) pair has been stored already. */
+ /* We free the given class and return the earlier one. */
+#ifdef CLASSCACHE_VERBOSE
+ log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
+#endif
+ assert(clsen->classobj);
+ if (mayfree)
+ class_free(cls);
+ cls = clsen->classobj;
+ }
+ goto return_success;
+ }
+ }
+
+ /* {This entry has not been resolved with initloader} */
+
+ /* check if initloader is constrained to this entry */
+ for (lden = clsen->constraints; lden; lden = lden->next) {
+ if (lden->loader == initloader) {
+ /* we have to use this entry. check if it has been resolved */
+ if (clsen->classobj) {
+ /* check if is has already been resolved to another class */
+ if (clsen->classobj != cls) {
+ /* a loading constraint is violated */
+ exceptions_throw_linkageerror("loading constraint violated: ", cls);
+ goto return_exception;
+ }
+
+ /* record initloader as initiating loader */
+ clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
+ goto return_success;
+ }
+
+ /* {this is the first resolution for this entry} */
+ /* record initloader as initiating loader */
+ clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
+
+ /* maybe we can merge this entry with another one */
+ for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
+ /* we dont want the entry that we have already */
+ if (clsenB->classobj == cls) {
+ /* this entry has the same classobj. let's merge them */
+ classcache_merge_class_entries(en,clsen,clsenB);
+ goto return_success;
+ }
+ }
+
+ /* record the loaded class object */
+ clsen->classobj = cls;
+ CLASSCACHE_COUNT(stat_classes_stored);
+
+ /* done */
+ goto return_success;
+ }
+ }
+
+ }
+
+ /* {There is no class entry containing initloader as initiating
+ * or constrained loader.} */
+
+ /* we look for a class entry with the same classobj we want to store */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+ if (clsen->classobj == cls) {
+ /* this entry is about the same classobj. let's use it */
+ /* check if this entry has already been loaded by initloader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == initloader)
+ goto return_success;
+ }
+ clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
+ goto return_success;
+ }
+ }
+
+ /* create a new class entry for this class object with */
+ /* initiating loader initloader */
+
+ clsen = NEW(classcache_class_entry);
+ clsen->classobj = cls;
+ clsen->loaders = classcache_new_loader_entry(initloader, NULL);
+ clsen->constraints = NULL;
+
+ clsen->next = en->classes;
+ en->classes = clsen;
+ CLASSCACHE_COUNT(stat_classes_stored);
+
+ return_success:
+#ifdef CLASSCACHE_VERBOSE
+ classcache_debug_dump(stdout,cls->name);
+#endif
+ CLASSCACHE_UNLOCK();
+ return cls;
+
+ return_exception:
+ CLASSCACHE_UNLOCK();
+ return NULL; /* exception */
+}
+
+/* classcache_store_unique *****************************************************
+
+ Store a loaded class as loaded by the bootstrap loader. This is a wrapper
+ aroung classcache_store that throws an exception if a class with the same
+ name has already been loaded by the bootstrap loader.
+
+ This function is used to register a few special classes during startup.
+ It should not be used otherwise.
+
+ IN:
+ cls..............class object to cache
+
+ RETURN VALUE:
+ true.............everything ok, the class was stored.
+ false............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+bool classcache_store_unique(classinfo *cls)
+{
+ classinfo *result;
+
+ result = classcache_store(NULL,cls,false);
+ if (result == NULL)
+ return false;
+
+ if (result != cls) {
+ exceptions_throw_internalerror("class already stored in the class cache");
+ return false;
+ }
+
+ return true;
+}
+
+/* classcache_store_defined ****************************************************
+
+ Store a loaded class after it has been defined. If the class has already
+ been defined by the same defining loader in another thread, free the given
+ class and returned the one which has been defined earlier.
+
+ IN:
+ cls..............class object to store. classloader must be set
+ (classloader may be NULL, for bootloader)
+
+ RETURN VALUE:
+ cls..............everything ok, the class was stored the cache,
+ other classinfo..the class had already been defined, CLS was freed, the
+ class which was defined earlier is returned,
+ NULL.............an exception has been thrown.
+
+*******************************************************************************/
+
+classinfo *classcache_store_defined(classinfo *cls)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+#ifdef CLASSCACHE_VERBOSE
+ char logbuffer[1024];
+#endif
+
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
+
+ CLASSCACHE_LOCK();
+
+#ifdef CLASSCACHE_VERBOSE
+ sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
+ utf_cat_classname(logbuffer, cls->name);
+ strcat(logbuffer,")");
+ log_println(logbuffer);
+#endif
+
+ en = classcache_new_name(cls->name);
+
+ assert(en);
+
+ /* iterate over all class entries */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+
+ /* check if this class has been defined by the same classloader */
+ if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
+ /* we found an earlier definition, delete the newer one */
+ /* (if it is a different classinfo) */
+ if (clsen->classobj != cls) {
+#ifdef CLASSCACHE_VERBOSE
+ log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
+#endif
+ class_free(cls);
+ cls = clsen->classobj;
+ }
+ goto return_success;
+ }
+ }
+
+ /* create a new class entry for this class object */
+ /* the list of initiating loaders is empty at this point */
+
+ clsen = NEW(classcache_class_entry);
+ clsen->classobj = cls;
+ clsen->loaders = NULL;
+ clsen->constraints = NULL;
+
+ clsen->next = en->classes;
+ en->classes = clsen;
+ CLASSCACHE_COUNT(stat_classes_stored);
+
+return_success:
+#ifdef CLASSCACHE_VERBOSE
+ classcache_debug_dump(stdout,cls->name);
+#endif
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+/* classcache_find_loader ******************************************************
+
+ Find the class entry loaded by or constrained to a given loader
+ (internally used helper function)
+
+ IN:
+ entry............the classcache_name_entry
+ loader...........the loader to look for
+
+ RETURN VALUE:
+ the classcache_class_entry for the given loader, or
+ NULL if no entry was found
+
+*******************************************************************************/
+
+static classcache_class_entry * classcache_find_loader(
+ classcache_name_entry * entry,
+ classloader_t * loader)
+{
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+
+ assert(entry);
+
+ /* iterate over all class entries */
+ for (clsen = entry->classes; clsen; clsen = clsen->next) {
+
+ /* check if this entry has already been loaded by initloader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == loader)
+ return clsen; /* found */
+ }
+
+ /* check if loader is constrained to this entry */
+ for (lden = clsen->constraints; lden; lden = lden->next) {
+ if (lden->loader == loader)
+ return clsen; /* found */
+ }
+ }
+
+ /* not found */
+ return NULL;
+}
+
+/* classcache_free_class_entry *************************************************
+
+ Free the memory used by a class entry
+
+ IN:
+ clsen............the classcache_class_entry to free
+
+*******************************************************************************/
+
+static void classcache_free_class_entry(classcache_class_entry * clsen)
+{
+ classcache_loader_entry *lden;
+ classcache_loader_entry *next;
+
+ assert(clsen);
+
+ for (lden = clsen->loaders; lden; lden = next) {
+ next = lden->next;
+ FREE(lden, classcache_loader_entry);
+ }
+ for (lden = clsen->constraints; lden; lden = next) {
+ next = lden->next;
+ FREE(lden, classcache_loader_entry);
+ }
+
+ FREE(clsen, classcache_class_entry);
+}
+
+/* classcache_remove_class_entry ***********************************************
+
+ Remove a classcache_class_entry from the list of possible resolution of
+ a name entry
+ (internally used helper function)
+
+ IN:
+ entry............the classcache_name_entry
+ clsen............the classcache_class_entry to remove
+
+*******************************************************************************/
+
+static void classcache_remove_class_entry(classcache_name_entry * entry,
+ classcache_class_entry * clsen)
+{
+ classcache_class_entry **chain;
+
+ assert(entry);
+ assert(clsen);
+
+ chain = &(entry->classes);
+ while (*chain) {
+ if (*chain == clsen) {
+ *chain = clsen->next;
+ classcache_free_class_entry(clsen);
+ return;
+ }
+ chain = &((*chain)->next);
+ }
+}
+
+/* classcache_free_name_entry **************************************************
+
+ Free the memory used by a name entry
+
+ IN:
+ entry............the classcache_name_entry to free
+
+*******************************************************************************/
+
+static void classcache_free_name_entry(classcache_name_entry * entry)
+{
+ classcache_class_entry *clsen;
+ classcache_class_entry *next;
+
+ assert(entry);
+
+ for (clsen = entry->classes; clsen; clsen = next) {
+ next = clsen->next;
+ classcache_free_class_entry(clsen);
+ }
+
+ FREE(entry, classcache_name_entry);
+}
+
+/* classcache_free *************************************************************
+
+ Free the memory used by the class cache
+
+ NOTE:
+ The class cache may not be used any more after this call, except
+ when it is reinitialized with classcache_init.
+
+ Note: NOT synchronized!
+
+*******************************************************************************/
+
+void classcache_free(void)
+{
+ u4 slot;
+ classcache_name_entry *entry;
+ classcache_name_entry *next;
+
+ for (slot = 0; slot < hashtable_classcache.size; ++slot) {
+ for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
+ next = entry->hashlink;
+ classcache_free_name_entry(entry);
+ }
+ }
+
+ MFREE(hashtable_classcache.ptr, void*, hashtable_classcache.size);
+ hashtable_classcache.size = 0;
+ hashtable_classcache.entries = 0;
+ hashtable_classcache.ptr = NULL;
+}
+
+/* classcache_add_constraint ***************************************************
+
+ Add a loading constraint
+
+ IN:
+ a................first initiating loader
+ b................second initiating loader
+ classname........class name
+
+ RETURN VALUE:
+ true.............everything ok, the constraint has been added,
+ false............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool classcache_add_constraint(classloader_t * a,
+ classloader_t * b,
+ utf * classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsenA;
+ classcache_class_entry *clsenB;
+
+ assert(classname);
+
+#ifdef CLASSCACHE_VERBOSE
+ log_start();
+ log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
+ utf_fprint_printable_ascii_classname(stdout, classname);
+ log_print(")\n");
+ log_finish();
+#endif
+
+ /* a constraint with a == b is trivially satisfied */
+ if (a == b) {
+ CLASSCACHE_COUNT(stat_trivial_constraints);
+ return true;
+ }
+
+ CLASSCACHE_LOCK();
+
+ en = classcache_new_name(classname);
+
+ assert(en);
+ CLASSCACHE_COUNT(stat_nontriv_constraints);
+
+ /* find the entry loaded by / constrained to each loader */
+ clsenA = classcache_find_loader(en, a);
+ clsenB = classcache_find_loader(en, b);
+
+ if (clsenA && clsenB) {
+ /* { both loaders have corresponding entries } */
+ CLASSCACHE_COUNT(stat_nontriv_constraints_both);
+
+ /* if the entries are the same, the constraint is already recorded */
+ if (clsenA == clsenB)
+ goto return_success;
+
+ /* check if the entries can be merged */
+ if (clsenA->classobj && clsenB->classobj
+ && clsenA->classobj != clsenB->classobj) {
+ /* no, the constraint is violated */
+ exceptions_throw_linkageerror("loading constraint violated: ",
+ clsenA->classobj);
+ goto return_exception;
+ }
+
+ /* yes, merge the entries */
+ classcache_merge_class_entries(en,clsenA,clsenB);
+ CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
+ }
+ else {
+ /* { at most one of the loaders has a corresponding entry } */
+
+ /* set clsenA to the single class entry we have */
+ if (!clsenA)
+ clsenA = clsenB;
+
+ if (!clsenA) {
+ /* { no loader has a corresponding entry } */
+ CLASSCACHE_COUNT(stat_nontriv_constraints_none);
+
+ /* create a new class entry with the constraint (a,b,en->name) */
+ clsenA = NEW(classcache_class_entry);
+ clsenA->classobj = NULL;
+ clsenA->loaders = NULL;
+ clsenA->constraints = classcache_new_loader_entry(b, NULL);
+ clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
+
+ clsenA->next = en->classes;
+ en->classes = clsenA;
+ }
+ else {
+ CLASSCACHE_COUNT(stat_nontriv_constraints_one);
+
+ /* make b the loader that has no corresponding entry */
+ if (clsenB)
+ b = a;
+
+ /* loader b must be added to entry clsenA */
+ clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
+ }
+ }
+
+ return_success:
+ CLASSCACHE_UNLOCK();
+ return true;
+
+ return_exception:
+ CLASSCACHE_UNLOCK();
+ return false; /* exception */
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/* classcache_add_constraints_for_params ***************************************
+
+ Add loading constraints for the parameters and return type of
+ the given method.
+
+ IN:
+ a................first initiating loader
+ b................second initiating loader
+ m................methodinfo
+
+ RETURN VALUE:
+ true.............everything ok, the constraints have been added,
+ false............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool classcache_add_constraints_for_params(classloader_t * a,
+ classloader_t * b,
+ methodinfo *m)
+{
+ methoddesc *md;
+ typedesc *td;
+ s4 i;
+
+ /* a constraint with a == b is trivially satisfied */
+
+ if (a == b) {
+ return true;
+ }
+
+ /* get the parsed descriptor */
+
+ assert(m);
+ md = m->parseddesc;
+ assert(md);
+
+ /* constrain the return type */
+
+ if (md->returntype.type == TYPE_ADR) {
+ if (!classcache_add_constraint(a, b, md->returntype.classref->name))
+ return false; /* exception */
+ }
+
+ /* constrain each reference type used in the parameters */
+
+ td = md->paramtypes;
+ i = md->paramcount;
+ for (; i--; td++) {
+ if (td->type != TYPE_ADR)
+ continue;
+
+ if (!classcache_add_constraint(a, b, td->classref->name))
+ return false; /* exception */
+ }
+
+ /* everything ok */
+ return true;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* classcache_number_of_loaded_classes *****************************************
+
+ Counts the number of loaded classes and returns it.
+
+ Note: This function assumes that the CLASSCACHE_LOCK is held by the
+ caller!
+
+*******************************************************************************/
+
+static s4 classcache_number_of_loaded_classes(void)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ s4 number;
+ s4 i;
+
+ /* initialize class counter */
+
+ number = 0;
+
+ for (i = 0; i < hashtable_classcache.size; i++) {
+ /* iterate over hashlink */
+
+ for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
+ /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
+
+ if (en->name->text[0] == '$')
+ continue;
+
+ /* iterate over classes with same name */
+
+ for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
+ /* get only loaded classes */
+
+ if (clsen->classobj != NULL)
+ number++;
+ }
+ }
+ }
+
+ return number;
+}
+
+
+/* classcache_get_loaded_class_count *******************************************
+
+ Counts the number of loaded classes and returns it.
+
+*******************************************************************************/
+
+s4 classcache_get_loaded_class_count(void)
+{
+ s4 count;
+
+ CLASSCACHE_LOCK();
+
+ count = classcache_number_of_loaded_classes();
+
+ CLASSCACHE_UNLOCK();
+
+ return count;
+}
+
+
+/* classcache_get_loaded_classes ***********************************************
+
+ Returns an array of all loaded classes as array. The array is
+ allocaed on the Java heap.
+
+*******************************************************************************/
+
+#if defined(ENABLE_JVMTI)
+void classcache_get_loaded_classes(s4 *class_count_ptr,
+ classinfo ***classes_ptr)
+{
+ classinfo **classes;
+ s4 class_count;
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ s4 i;
+ s4 j;
+
+ CLASSCACHE_LOCK();
+
+ /* get the number of loaded classes and allocate the array */
+
+ class_count = classcache_number_of_loaded_classes();
+
+ classes = GCMNEW(classinfo*, class_count);
+
+ /* look in every slot of the hashtable */
+
+ for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
+ /* iterate over hashlink */
+
+ for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
+ /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
+
+ if (en->name->text[0] == '$')
+ continue;
+
+ /* iterate over classes with same name */
+
+ for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
+ /* get only loaded classes */
+
+ if (clsen->classobj != NULL) {
+ classes[j] = clsen->classobj;
+ j++;
+ }
+ }
+ }
+ }
+
+ /* pass the return values */
+
+ *class_count_ptr = class_count;
+ *classes_ptr = classes;
+
+ CLASSCACHE_UNLOCK();
+}
+#endif /* defined(ENABLE_JVMTI) */
+
+
+/* classcache_foreach_loaded_class *********************************************
+
+ Calls the given function for each loaded class.
+
+*******************************************************************************/
+
+void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
+ void *data)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ s4 i;
+
+ CLASSCACHE_LOCK();
+
+ /* look in every slot of the hashtable */
+
+ for (i = 0; i < hashtable_classcache.size; i++) {
+ /* iterate over hashlink */
+
+ for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
+ /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
+
+ if (en->name->text[0] == '$')
+ continue;
+
+ /* iterate over classes with same name */
+
+ for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
+ /* get only loaded classes */
+
+ if (clsen->classobj != NULL) {
+ (*func)(clsen->classobj, data);
+ }
+ }
+ }
+ }
+
+ CLASSCACHE_UNLOCK();
+}
+
+
+/*============================================================================*/
+/* DEBUG DUMPS */
+/*============================================================================*/
+
+/* classcache_debug_dump *******************************************************
+
+ Print the contents of the loaded class cache to a stream
+
+ IN:
+ file.............output stream
+ only.............if != NULL, only print entries for this name
+ (Currently we print also the rest of the hash chain to
+ get a feel for the average length of hash chains.)
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+#ifndef NDEBUG
+void classcache_debug_dump(FILE * file,utf *only)
+{
+ classcache_name_entry *c;
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+ u4 slot;
+
+ CLASSCACHE_LOCK();
+
+ log_println("=== [loaded class cache] =====================================");
+ log_println("hash size : %d", (int) hashtable_classcache.size);
+ log_println("hash entries: %d", (int) hashtable_classcache.entries);
+ log_println("");
+
+ if (only) {
+ c = classcache_lookup_name(only);
+ slot = 0; /* avoid compiler warning */
+ goto dump_it;
+ }
+
+ for (slot = 0; slot < hashtable_classcache.size; ++slot) {
+ c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+dump_it:
+ for (; c; c = c->hashlink) {
+ utf_fprint_printable_ascii_classname(file, c->name);
+ fprintf(file, "\n");
+
+ /* iterate over all class entries */
+ for (clsen = c->classes; clsen; clsen = clsen->next) {
+ if (clsen->classobj) {
+ log_println(" loaded %p", (void *) clsen->classobj);
+ }
+ else {
+ log_println(" unresolved");
+ }
+
+ log_start();
+ log_print(" loaders: ");
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
+ }
+ log_finish();
+
+ log_start();
+ log_print(" constraints: ");
+ for (lden = clsen->constraints; lden; lden = lden->next) {
+ log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
+ }
+ log_finish();
+ }
+ }
+
+ if (only)
+ break;
+ }
+ fprintf(file, "\n==============================================================\n\n");
+
+ CLASSCACHE_UNLOCK();
+}
+#endif /* 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/classcache.h - loaded class cache and loading constraints
+
+ 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 _CLASSCACHE_H
+#define _CLASSCACHE_H
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/types.h"
+
+#include <stdio.h> /* for FILE */
+
+#if defined(ENABLE_JVMTI)
+# include "native/jni.h"
+#endif
+
+#include "toolbox/hashtable.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/references.h"
+
+
+/* forward declarations *******************************************************/
+
+typedef struct classcache_name_entry classcache_name_entry;
+typedef struct classcache_class_entry classcache_class_entry;
+typedef struct classcache_loader_entry classcache_loader_entry;
+
+/* global variables ***********************************************************/
+
+extern hashtable hashtable_classcache;
+
+
+/* structs ********************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* The Loaded Class Cache */
+/* */
+/* The loaded class cache is implemented as a two-level data structure. */
+/* */
+/* The first level is a hash table indexed by class names. For each class */
+/* name in the cache there is a classcache_name_entry, which collects all */
+/* information about classes with this class name. */
+/* */
+/* Second level: For each classcache_name_entry there is a list of */
+/* classcache_class_entry:s representing the possible different resolutions */
+/* of the class name. */
+/* */
+/* A classcache_class_entry records the following: */
+/* */
+/* - the loaded class object, if this entry has been resolved, otherwise NULL */
+/* - the list of initiating loaders which have resolved the class name to */
+/* this class object */
+/* - the list of initiating loaders which are constrained to resolve this */
+/* class name to this class object in the future */
+/* */
+/* The classcache_class_entry:s approximate the equivalence classes created */
+/* by the loading constraints and the equivalence of loaded classes. */
+/* */
+/* When a loading constraint (loaderA,loaderB,NAME) is added, then the */
+/* classcache_class_entry:s for NAME containing loaderA and loaderB resp. */
+/* must be merged into one entry. If this is impossible, because the entries */
+/* have already been resolved to different class objects, then the constraint */
+/* is violated and an expception must be thrown. */
+/*----------------------------------------------------------------------------*/
+
+
+/* classcache_name_entry
+ *
+ * For each classname a classcache_name_entry struct is created.
+ */
+
+struct classcache_name_entry
+{
+ utf *name; /* class name */
+ classcache_name_entry *hashlink; /* link for external chaining */
+ classcache_class_entry *classes; /* equivalence classes for this name*/
+};
+
+struct classcache_class_entry
+{
+ classinfo *classobj; /* the loaded class object, or NULL */
+ classcache_loader_entry *loaders;
+ classcache_loader_entry *constraints;
+ classcache_class_entry *next; /* next class entry for same name */
+};
+
+struct classcache_loader_entry
+{
+ classloader_t *loader; /* class loader object */
+ classcache_loader_entry *next; /* next loader entry in the list */
+};
+
+
+/* callback function type for classcache_foreach_loaded_class */
+
+typedef void (*classcache_foreach_functionptr_t)(classinfo *, void *);
+
+
+/* function prototypes ********************************************************/
+
+/* initialize the loaded class cache */
+bool classcache_init(void);
+void classcache_free(void);
+
+classinfo * classcache_lookup(classloader_t *initloader,utf *classname);
+classinfo * classcache_lookup_defined(classloader_t *defloader,utf *classname);
+classinfo * classcache_lookup_defined_or_initiated(classloader_t *loader,utf *classname);
+
+bool classcache_store_unique(classinfo *cls);
+classinfo * classcache_store(classloader_t *initloader,classinfo *cls,bool mayfree);
+classinfo * classcache_store_defined(classinfo *cls);
+
+#if defined(ENABLE_VERIFIER)
+bool classcache_add_constraint(classloader_t *a,classloader_t *b,utf *classname);
+bool classcache_add_constraints_for_params(classloader_t *a,classloader_t *b,
+ methodinfo *m);
+#endif
+
+s4 classcache_get_loaded_class_count(void);
+
+void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
+ void *data);
+
+#if defined(ENABLE_JVMTI)
+void classcache_get_loaded_classes(s4 *class_count_ptr,
+ classinfo ***classes_ptr);
+#endif
+
+#ifndef NDEBUG
+void classcache_debug_dump(FILE *file,utf *only);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CLASSCACHE_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:
+ */
+
--- /dev/null
+/* src/vm/descriptor.c - checking and parsing of field / method descriptors
+
+ 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 "vm/types.h"
+
+#include "md-abi.h"
+
+#include "mm/memory.h"
+
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/abi.h"
+
+
+/* constants (private to descriptor.c) ****************************************/
+
+/* initial number of entries for the classrefhash of a descriptor_pool */
+/* (currently the hash is never grown!) */
+#define CLASSREFHASH_INIT_SIZE 64
+
+/* initial number of entries for the descriptorhash of a descriptor_pool */
+/* (currently the hash is never grown!) */
+#define DESCRIPTORHASH_INIT_SIZE 128
+
+/* data structures (private to descriptor.c) **********************************/
+
+typedef struct classref_hash_entry classref_hash_entry;
+typedef struct descriptor_hash_entry descriptor_hash_entry;
+
+/* entry struct for the classrefhash of descriptor_pool */
+struct classref_hash_entry {
+ classref_hash_entry *hashlink; /* for hash chaining */
+ utf *name; /* name of the class refered to */
+ u2 index; /* index into classref table */
+};
+
+/* entry struct for the descriptorhash of descriptor_pool */
+struct descriptor_hash_entry {
+ descriptor_hash_entry *hashlink;
+ utf *desc;
+ parseddesc_t parseddesc;
+ s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
+};
+
+
+/****************************************************************************/
+/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
+/****************************************************************************/
+
+/* SKIP_FIELDDESCRIPTOR:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * CAUTION: This macro does not check for an unexpected end of the
+ * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
+ */
+#define SKIP_FIELDDESCRIPTOR(utf_ptr) \
+ do { while (*(utf_ptr)=='[') (utf_ptr)++; \
+ if (*(utf_ptr)++=='L') \
+ while(*(utf_ptr)++ != ';') /* skip */; } while(0)
+
+/* SKIP_FIELDDESCRIPTOR_SAFE:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * Input:
+ * utf_ptr....points to first char of descriptor
+ * end_ptr....points to first char after the end of the string
+ * errorflag..must be initialized (to false) by the caller!
+ * Output:
+ * utf_ptr....points to first char after the descriptor
+ * errorflag..set to true if the string ended unexpectedly
+ */
+#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
+ do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
+ if ((utf_ptr) == (end_ptr)) \
+ (errorflag) = true; \
+ else \
+ if (*(utf_ptr)++=='L') { \
+ while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
+ /* skip */; \
+ if ((utf_ptr)[-1] != ';') \
+ (errorflag) = true; }} while(0)
+
+
+/****************************************************************************/
+/* DEBUG HELPERS */
+/****************************************************************************/
+
+/*#define DESCRIPTOR_VERBOSE*/
+
+/****************************************************************************/
+/* FUNCTIONS */
+/****************************************************************************/
+
+/* descriptor_to_basic_type ****************************************************
+
+ Return the basic type to use for a value with this descriptor.
+
+ IN:
+ utf..............descriptor utf string
+
+ OUT:
+ A TYPE_* constant.
+
+ PRECONDITIONS:
+ This function assumes that the descriptor has passed
+ descriptor_pool_add checks and that it does not start with '('.
+
+*******************************************************************************/
+
+int descriptor_to_basic_type(utf *descriptor)
+{
+ assert(descriptor->blength >= 1);
+
+ switch (descriptor->text[0]) {
+ case 'Z':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'I':
+ return TYPE_INT;
+
+ case 'J':
+ return TYPE_LNG;
+
+ case 'F':
+ return TYPE_FLT;
+
+ case 'D':
+ return TYPE_DBL;
+
+ case 'L':
+ case '[':
+ return TYPE_ADR;
+
+ default:
+ vm_abort("descriptor_to_basic_type: invalid type %c",
+ descriptor->text[0]);
+ }
+
+ /* keep the compiler happy */
+
+ return 0;
+}
+
+
+/* descriptor_typesize *********************************************************
+
+ Return the size in bytes needed for the given type.
+
+ IN:
+ td..............typedesc describing the type
+
+ OUT:
+ The number of bytes
+
+*******************************************************************************/
+
+int descriptor_typesize(typedesc *td)
+{
+ assert(td);
+
+ switch (td->type) {
+ case TYPE_INT:
+ case TYPE_FLT:
+ return 4;
+
+ case TYPE_LNG:
+ case TYPE_DBL:
+ return 8;
+
+ case TYPE_ADR:
+ return SIZEOF_VOID_P;
+
+ default:
+ vm_abort("descriptor_typesize: invalid type %d", td->type);
+ }
+
+ /* keep the compiler happy */
+
+ return 0;
+}
+
+
+/* name_from_descriptor ********************************************************
+
+ Return the class name indicated by the given descriptor
+ (Internally used helper function)
+
+ IN:
+ c................class containing the descriptor
+ utf_ptr..........first character of descriptor
+ end_ptr..........first character after the end of the string
+ mode.............a combination (binary or) of the following flags:
+
+ (Flags marked with * are the default settings.)
+
+ How to handle "V" descriptors:
+
+ * DESCRIPTOR_VOID.....handle it like other primitive types
+ DESCRIPTOR_NOVOID...treat it as an error
+
+ How to deal with extra characters after the end of the
+ descriptor:
+
+ * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
+ DESCRIPTOR_CHECKEND.....treat them as an error
+
+ OUT:
+ *next............if non-NULL, *next is set to the first character after
+ the descriptor. (Undefined if an error occurs.)
+ *name............set to the utf name of the class
+
+ RETURN VALUE:
+ true.............descriptor parsed successfully
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#define DESCRIPTOR_VOID 0 /* default */
+#define DESCRIPTOR_NOVOID 0x0040
+#define DESCRIPTOR_NOCHECKEND 0 /* default */
+#define DESCRIPTOR_CHECKEND 0x1000
+
+static bool
+name_from_descriptor(classinfo *c,
+ char *utf_ptr, char *end_ptr,
+ char **next, int mode, utf **name)
+{
+ char *start = utf_ptr;
+ bool error = false;
+
+ assert(c);
+ assert(utf_ptr);
+ assert(end_ptr);
+ assert(name);
+
+ *name = NULL;
+ SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
+
+ if (mode & DESCRIPTOR_CHECKEND)
+ error |= (utf_ptr != end_ptr);
+
+ if (!error) {
+ if (next) *next = utf_ptr;
+
+ switch (*start) {
+ case 'V':
+ if (mode & DESCRIPTOR_NOVOID)
+ break;
+ /* FALLTHROUGH! */
+ case 'I':
+ case 'J':
+ case 'F':
+ case 'D':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ return true;
+
+ case 'L':
+ start++;
+ utf_ptr--;
+ /* FALLTHROUGH! */
+ case '[':
+ *name = utf_new(start, utf_ptr - start);
+ return true;
+ }
+ }
+
+ exceptions_throw_classformaterror(c, "Invalid descriptor");
+ return false;
+}
+
+
+/* descriptor_to_typedesc ******************************************************
+
+ Parse the given type descriptor and fill a typedesc struct
+ (Internally used helper function)
+
+ IN:
+ pool.............the descriptor pool
+ utf_ptr..........points to first character of type descriptor
+ end_pos..........points after last character of the whole descriptor
+
+ OUT:
+ *next............set to next character after type descriptor
+ *d...............filled with parsed information
+
+ RETURN VALUE:
+ true.............parsing succeeded
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool
+descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
+ char **next, typedesc *td)
+{
+ utf *name;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
+ return false;
+
+ if (name) {
+ /* a reference type */
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
+ td->arraydim++;
+ td->classref = descriptor_pool_lookup_classref(pool, name);
+
+ } else {
+ /* a primitive type */
+ switch (*utf_ptr) {
+ case 'B':
+ td->primitivetype = PRIMITIVETYPE_BYTE;
+ td->type = TYPE_INT;
+ break;
+ case 'C':
+ td->primitivetype = PRIMITIVETYPE_CHAR;
+ td->type = TYPE_INT;
+ break;
+ case 'S':
+ td->primitivetype = PRIMITIVETYPE_SHORT;
+ td->type = TYPE_INT;
+ break;
+ case 'Z':
+ td->primitivetype = PRIMITIVETYPE_BOOLEAN;
+ td->type = TYPE_INT;
+ break;
+ case 'I':
+ td->primitivetype = PRIMITIVETYPE_INT;
+ td->type = TYPE_INT;
+ break;
+ case 'D':
+ td->primitivetype = PRIMITIVETYPE_DOUBLE;
+ td->type = TYPE_DBL;
+ break;
+ case 'F':
+ td->primitivetype = PRIMITIVETYPE_FLOAT;
+ td->type = TYPE_FLT;
+ break;
+ case 'J':
+ td->primitivetype = PRIMITIVETYPE_LONG;
+ td->type = TYPE_LNG;
+ break;
+ case 'V':
+ td->primitivetype = PRIMITIVETYPE_VOID;
+ td->type = TYPE_VOID;
+ break;
+ default:
+ assert(false);
+ }
+
+ td->arraydim = 0;
+ td->classref = NULL;
+ }
+
+ return true;
+}
+
+
+/* descriptor_pool_new *********************************************************
+
+ Allocate a new descriptor_pool
+
+ IN:
+ referer..........class for which to create the pool
+
+ RETURN VALUE:
+ a pointer to the new descriptor_pool
+
+*******************************************************************************/
+
+descriptor_pool *
+descriptor_pool_new(classinfo *referer)
+{
+ descriptor_pool *pool;
+ u4 hashsize;
+ u4 slot;
+
+ pool = DNEW(descriptor_pool);
+ assert(pool);
+
+ pool->referer = referer;
+ pool->fieldcount = 0;
+ pool->methodcount = 0;
+ pool->paramcount = 0;
+ pool->descriptorsize = 0;
+ pool->descriptors = NULL;
+ pool->descriptors_next = NULL;
+ pool->classrefs = NULL;
+ pool->descriptor_kind = NULL;
+ pool->descriptor_kind_next = NULL;
+
+ hashsize = CLASSREFHASH_INIT_SIZE;
+ pool->classrefhash.size = hashsize;
+ pool->classrefhash.entries = 0;
+ pool->classrefhash.ptr = DMNEW(void*, hashsize);
+ for (slot=0; slot<hashsize; ++slot)
+ pool->classrefhash.ptr[slot] = NULL;
+
+ hashsize = DESCRIPTORHASH_INIT_SIZE;
+ pool->descriptorhash.size = hashsize;
+ pool->descriptorhash.entries = 0;
+ pool->descriptorhash.ptr = DMNEW(void*, hashsize);
+ for (slot=0; slot<hashsize; ++slot)
+ pool->descriptorhash.ptr[slot] = NULL;
+
+ return pool;
+}
+
+
+/* descriptor_pool_add_class ***************************************************
+
+ Add the given class reference to the pool
+
+ IN:
+ pool.............the descriptor_pool
+ name.............the class reference to add
+
+ RETURN VALUE:
+ true.............reference has been added
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
+descriptor_pool_add_class(descriptor_pool *pool, utf *name)
+{
+ u4 key,slot;
+ classref_hash_entry *c;
+
+ assert(pool);
+ assert(name);
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
+ utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
+#endif
+
+ /* find a place in the hashtable */
+
+ key = utf_hashkey(name->text, name->blength);
+ slot = key & (pool->classrefhash.size - 1);
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
+ while (c) {
+ if (c->name == name)
+ return true; /* already stored */
+ c = c->hashlink;
+ }
+
+ /* check if the name is a valid classname */
+
+ if (!is_valid_name(name->text,UTF_END(name))) {
+ exceptions_throw_classformaterror(pool->referer, "Invalid class name");
+ return false; /* exception */
+ }
+
+ /* XXX check maximum array dimension */
+
+ c = DNEW(classref_hash_entry);
+ c->name = name;
+ c->index = pool->classrefhash.entries++;
+ c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ pool->classrefhash.ptr[slot] = c;
+
+ return true;
+}
+
+
+/* descriptor_pool_add *********************************************************
+
+ Check the given descriptor and add it to the pool
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the descriptor to add. Maybe a field or method desc.
+
+ OUT:
+ *paramslots......if non-NULL, set to the number of parameters.
+ LONG and DOUBLE are counted twice
+
+ RETURN VALUE:
+ true.............descriptor has been added
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
+descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
+{
+ u4 key,slot;
+ descriptor_hash_entry *d;
+ char *utf_ptr;
+ char *end_pos;
+ utf *name;
+ s4 argcount = 0;
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
+ utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
+#endif
+
+ assert(pool);
+ assert(desc);
+
+ /* find a place in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ /* Save all method descriptors in the hashtable, since the parsed */
+ /* descriptor may vary between differenf methods (static vs. non-static). */
+
+ utf_ptr = desc->text;
+
+ if (*utf_ptr != '(') {
+ while (d) {
+ if (d->desc == desc) {
+ if (paramslots)
+ *paramslots = d->paramslots;
+ return true; /* already stored */
+ }
+ d = d->hashlink;
+ }
+ }
+
+ /* add the descriptor to the pool */
+
+ d = DNEW(descriptor_hash_entry);
+ d->desc = desc;
+ d->parseddesc.any = NULL;
+ d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+ pool->descriptorhash.ptr[slot] = d;
+
+ /* now check the descriptor */
+
+ end_pos = UTF_END(desc);
+
+ if (*utf_ptr == '(') {
+ /* a method descriptor */
+
+ pool->methodcount++;
+ utf_ptr++;
+
+ /* check arguments */
+
+ while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
+ pool->paramcount++;
+
+ /* We cannot count the `this' argument here because
+ * we don't know if the method is static. */
+
+ if (*utf_ptr == 'J' || *utf_ptr == 'D')
+ argcount += 2;
+ else
+ argcount++;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
+ DESCRIPTOR_NOVOID, &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool, name))
+ return false;
+ }
+
+ if (utf_ptr == end_pos) {
+ exceptions_throw_classformaterror(pool->referer,
+ "Missing ')' in method descriptor");
+ return false;
+ }
+
+ utf_ptr++; /* skip ')' */
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+ DESCRIPTOR_CHECKEND, &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
+
+ if (argcount > 255) {
+ exceptions_throw_classformaterror(pool->referer,
+ "Too many arguments in signature");
+ return false;
+ }
+
+ } else {
+ /* a field descriptor */
+
+ pool->fieldcount++;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+ DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
+ &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
+ }
+
+ d->paramslots = argcount;
+
+ if (paramslots)
+ *paramslots = argcount;
+
+ return true;
+}
+
+
+/* descriptor_pool_create_classrefs ********************************************
+
+ Create a table containing all the classrefs which were added to the pool
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *count...........if count is non-NULL, this is set to the number
+ of classrefs in the table
+
+ RETURN VALUE:
+ a pointer to the constant_classref table
+
+*******************************************************************************/
+
+constant_classref *
+descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
+{
+ u4 nclasses;
+ u4 slot;
+ classref_hash_entry *c;
+ constant_classref *ref;
+
+ assert(pool);
+
+ nclasses = pool->classrefhash.entries;
+ pool->classrefs = MNEW(constant_classref,nclasses);
+
+ /* fill the constant_classref structs */
+
+ for (slot = 0; slot < pool->classrefhash.size; ++slot) {
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ while (c) {
+ ref = pool->classrefs + c->index;
+ CLASSREF_INIT(*ref, pool->referer, c->name);
+ c = c->hashlink;
+ }
+ }
+
+ if (count)
+ *count = nclasses;
+
+ return pool->classrefs;
+}
+
+
+/* descriptor_pool_lookup_classref *********************************************
+
+ Return the constant_classref for the given class name
+
+ IN:
+ pool.............the descriptor_pool
+ classname........name of the class to look up
+
+ RETURN VALUE:
+ a pointer to the constant_classref, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+constant_classref *
+descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
+{
+ u4 key,slot;
+ classref_hash_entry *c;
+
+ assert(pool);
+ assert(pool->classrefs);
+ assert(classname);
+
+ key = utf_hashkey(classname->text, classname->blength);
+ slot = key & (pool->classrefhash.size - 1);
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
+ while (c) {
+ if (c->name == classname)
+ return pool->classrefs + c->index;
+ c = c->hashlink;
+ }
+
+ exceptions_throw_internalerror("Class reference not found in descriptor pool");
+ return NULL;
+}
+
+
+/* descriptor_pool_alloc_parsed_descriptors ************************************
+
+ Allocate space for the parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ NOTE:
+ This function must be called after all descriptors have been added
+ with descriptor_pool_add.
+
+*******************************************************************************/
+
+void
+descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
+{
+ u4 size;
+
+ assert(pool);
+
+ /* TWISTI: paramcount + 1: we don't know if the method is static or */
+ /* not, i have no better solution yet. */
+
+ size =
+ pool->fieldcount * sizeof(typedesc) +
+ pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
+ pool->paramcount * sizeof(typedesc) +
+ pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
+
+ pool->descriptorsize = size;
+ if (size) {
+ pool->descriptors = MNEW(u1, size);
+ pool->descriptors_next = pool->descriptors;
+ }
+
+ size = pool->fieldcount + pool->methodcount;
+ if (size) {
+ pool->descriptor_kind = DMNEW(u1, size);
+ pool->descriptor_kind_next = pool->descriptor_kind;
+ }
+}
+
+
+/* descriptor_pool_parse_field_descriptor **************************************
+
+ Parse the given field descriptor
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the field descriptor
+
+ RETURN VALUE:
+ a pointer to the parsed field descriptor, or
+ NULL if an exception has been thrown
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called (once)
+ before this function is used.
+
+*******************************************************************************/
+
+typedesc *
+descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
+{
+ u4 key,slot;
+ descriptor_hash_entry *d;
+ typedesc *td;
+
+ assert(pool);
+ assert(pool->descriptors);
+ assert(pool->descriptors_next);
+
+ /* lookup the descriptor in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ while (d) {
+ if (d->desc == desc) {
+ /* found */
+ if (d->parseddesc.fd)
+ return d->parseddesc.fd;
+ break;
+ }
+ d = d->hashlink;
+ }
+
+ assert(d);
+
+ if (desc->text[0] == '(') {
+ exceptions_throw_classformaterror(pool->referer,
+ "Method descriptor used in field reference");
+ return NULL;
+ }
+
+ td = (typedesc *) pool->descriptors_next;
+ pool->descriptors_next += sizeof(typedesc);
+
+ if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
+ return NULL;
+
+ *(pool->descriptor_kind_next++) = 'f';
+
+ d->parseddesc.fd = td;
+
+ return td;
+}
+
+
+/* descriptor_pool_parse_method_descriptor *************************************
+
+ Parse the given method descriptor
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the method descriptor
+ mflags...........the method flags
+ thisclass........classref to the class containing the method.
+ This is ignored if mflags contains ACC_STATIC.
+ The classref is stored for inserting the 'this' argument.
+
+ RETURN VALUE:
+ a pointer to the parsed method descriptor, or
+ NULL if an exception has been thrown
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called
+ (once) before this function is used.
+
+*******************************************************************************/
+
+methoddesc *
+descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
+ s4 mflags,constant_classref *thisclass)
+{
+ u4 key, slot;
+ descriptor_hash_entry *d;
+ methoddesc *md;
+ typedesc *td;
+ char *utf_ptr;
+ char *end_pos;
+ s2 paramcount = 0;
+ s2 paramslots = 0;
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
+ (void*)pool,(int)mflags,(void*)thisclass);
+ utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
+#endif
+
+ assert(pool);
+ assert(pool->descriptors);
+ assert(pool->descriptors_next);
+
+ /* check that it is a method descriptor */
+
+ if (desc->text[0] != '(') {
+ exceptions_throw_classformaterror(pool->referer,
+ "Field descriptor used in method reference");
+ return NULL;
+ }
+
+ /* lookup the descriptor in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ /* find an un-parsed descriptor */
+
+ while (d) {
+ if (d->desc == desc)
+ if (!d->parseddesc.md)
+ break;
+ d = d->hashlink;
+ }
+
+ assert(d);
+
+ md = (methoddesc *) pool->descriptors_next;
+ pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
+
+ utf_ptr = desc->text + 1; /* skip '(' */
+ end_pos = UTF_END(desc);
+
+ td = md->paramtypes;
+
+ /* count the `this' pointer */
+
+ if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ td->classref = thisclass;
+
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ paramcount++;
+ paramslots++;
+ }
+
+ while (*utf_ptr != ')') {
+ /* parse a parameter type */
+
+ if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
+ return NULL;
+
+ if (IS_2_WORD_TYPE(td->type))
+ paramslots++;
+
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ paramcount++;
+ paramslots++;
+ }
+ utf_ptr++; /* skip ')' */
+
+ /* Skip possible `this' pointer in paramtypes array to allow a possible */
+ /* memory move later in parse. */
+ /* We store the thisclass reference, so we can later correctly fill in */
+ /* the parameter slot of the 'this' argument. */
+
+ if (mflags == ACC_UNDEF) {
+ td->classref = thisclass;
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ }
+
+ /* parse return type */
+
+ if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
+ &(md->returntype)))
+ return NULL;
+
+ md->paramcount = paramcount;
+ md->paramslots = paramslots;
+
+ /* If mflags != ACC_UNDEF we parse a real loaded method, so do
+ param prealloc. Otherwise we do this in stack analysis. */
+
+ if (mflags != ACC_UNDEF) {
+ if (md->paramcount > 0) {
+ /* allocate memory for params */
+
+ md->params = MNEW(paramdesc, md->paramcount);
+ }
+ else {
+ md->params = METHODDESC_NOPARAMS;
+ }
+
+ /* fill the paramdesc */
+ /* md_param_alloc has to be called if md->paramcount == 0,
+ too, so it can make the reservation for the Linkage Area,
+ Return Register... */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ {
+ /* As builtin-functions are native functions, we have
+ to pre-allocate for the native ABI. */
+
+ if (mflags & ACC_METHOD_BUILTIN)
+ md_param_alloc_native(md);
+ else
+ md_param_alloc(md);
+ }
+#endif
+ }
+ else {
+ /* params will be allocated later by
+ descriptor_params_from_paramtypes if necessary */
+
+ md->params = NULL;
+ }
+
+ *(pool->descriptor_kind_next++) = 'm';
+
+ d->parseddesc.md = md;
+
+ return md;
+}
+
+/* descriptor_params_from_paramtypes *******************************************
+
+ Create the paramdescs for a method descriptor. This function is called
+ when we know whether the method is static or not. This function may only
+ be called once for each methoddesc, and only if md->params == NULL.
+
+ IN:
+ md...............the parsed method descriptor
+ md->params MUST be NULL.
+ mflags...........the ACC_* access flags of the method. Only the
+ ACC_STATIC bit is checked.
+ The value ACC_UNDEF is NOT allowed.
+
+ RETURN VALUE:
+ true.............the paramdescs were created successfully
+ false............an exception has been thrown
+
+ POSTCONDITION:
+ md->parms != NULL
+
+*******************************************************************************/
+
+bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
+{
+ typedesc *td;
+
+ assert(md);
+ assert(md->params == NULL);
+ assert(mflags != ACC_UNDEF);
+
+ td = md->paramtypes;
+
+ /* check for `this' pointer */
+
+ if (!(mflags & ACC_STATIC)) {
+ constant_classref *thisclass;
+
+ /* fetch class reference from reserved param slot */
+ thisclass = td[md->paramcount].classref;
+ assert(thisclass);
+
+ if (md->paramcount > 0) {
+ /* shift param types by 1 argument */
+ MMOVE(td + 1, td, typedesc, md->paramcount);
+ }
+
+ /* fill in first argument `this' */
+
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ td->classref = thisclass;
+
+ md->paramcount++;
+ md->paramslots++;
+ }
+
+ /* if the method has params, process them */
+
+ if (md->paramcount > 0) {
+ /* allocate memory for params */
+
+ md->params = MNEW(paramdesc, md->paramcount);
+
+ } else {
+ md->params = METHODDESC_NOPARAMS;
+ }
+
+ /* fill the paramdesc */
+ /* md_param_alloc has to be called if md->paramcount == 0, too, so
+ it can make the reservation for the Linkage Area, Return
+ Register.. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ {
+ /* As builtin-functions are native functions, we have to
+ pre-allocate for the native ABI. */
+
+ if (mflags & ACC_METHOD_BUILTIN)
+ md_param_alloc_native(md);
+ else
+ md_param_alloc(md);
+ }
+#endif
+
+ return true;
+}
+
+
+/* descriptor_pool_get_parsed_descriptors **************************************
+
+ Return a pointer to the block of parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *size............if size is non-NULL, this is set to the size of the
+ parsed descriptor block (in u1)
+
+ RETURN VALUE:
+ a pointer to the block of parsed descriptors
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called (once)
+ before this function is used.
+
+*******************************************************************************/
+
+void *
+descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
+{
+ assert(pool);
+ assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+
+ if (size)
+ *size = pool->descriptorsize;
+
+ return pool->descriptors;
+}
+
+
+/* descriptor_pool_get_sizes ***************************************************
+
+ Get the sizes of the class reference table and the parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *classrefsize....set to size of the class reference table
+ *descsize........set to size of the parsed descriptors
+
+ NOTE:
+ This function may only be called after both
+ descriptor_pool_create_classrefs, and
+ descriptor_pool_alloc_parsed_descriptors
+ have been called.
+
+*******************************************************************************/
+
+void
+descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
+{
+ assert(pool);
+ assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+ assert(pool->classrefs);
+ assert(classrefsize);
+ assert(descsize);
+
+ *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
+ *descsize = pool->descriptorsize;
+}
+
+
+/****************************************************************************/
+/* DEBUG HELPERS */
+/****************************************************************************/
+
+#ifndef NDEBUG
+/* descriptor_debug_print_typedesc *********************************************
+
+ Print the given typedesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parsed descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_typedesc(FILE *file,typedesc *d)
+{
+ int ch;
+
+ if (!d) {
+ fprintf(file,"(typedesc *)NULL");
+ return;
+ }
+
+ if (d->type == TYPE_ADR) {
+ if (d->classref)
+ utf_fprint_printable_ascii(file,d->classref->name);
+ else
+ fprintf(file,"<class=NULL>");
+ }
+ else {
+ switch (d->primitivetype) {
+ case PRIMITIVETYPE_INT : ch='I'; break;
+ case PRIMITIVETYPE_CHAR : ch='C'; break;
+ case PRIMITIVETYPE_BYTE : ch='B'; break;
+ case PRIMITIVETYPE_SHORT : ch='S'; break;
+ case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
+ case PRIMITIVETYPE_LONG : ch='J'; break;
+ case PRIMITIVETYPE_FLOAT : ch='F'; break;
+ case PRIMITIVETYPE_DOUBLE : ch='D'; break;
+ case PRIMITIVETYPE_VOID : ch='V'; break;
+ default : ch='!';
+ }
+ fputc(ch,file);
+ }
+ if (d->arraydim)
+ fprintf(file,"[%d]",d->arraydim);
+}
+
+/* descriptor_debug_print_paramdesc ********************************************
+
+ Print the given paramdesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parameter descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
+{
+ if (!d) {
+ fprintf(file,"(paramdesc *)NULL");
+ return;
+ }
+
+ if (d->inmemory) {
+ fprintf(file,"<m%d>",d->regoff);
+ }
+ else {
+ fprintf(file,"<r%d>",d->regoff);
+ }
+}
+
+/* descriptor_debug_print_methoddesc *******************************************
+
+ Print the given methoddesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parsed descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
+{
+ int i;
+
+ if (!d) {
+ fprintf(file,"(methoddesc *)NULL");
+ return;
+ }
+
+ fputc('(',file);
+ for (i=0; i<d->paramcount; ++i) {
+ if (i)
+ fputc(',',file);
+ descriptor_debug_print_typedesc(file,d->paramtypes + i);
+ if (d->params) {
+ descriptor_debug_print_paramdesc(file,d->params + i);
+ }
+ }
+ if (d->params == METHODDESC_NOPARAMS)
+ fputs("<NOPARAMS>",file);
+ fputc(')',file);
+ descriptor_debug_print_typedesc(file,&(d->returntype));
+}
+
+/* descriptor_pool_debug_dump **************************************************
+
+ Print the state of the descriptor_pool to the given stream
+
+ IN:
+ pool.............the descriptor_pool
+ file.............stream to print to
+
+*******************************************************************************/
+
+void
+descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
+{
+ u4 slot;
+ u1 *pos;
+ u1 *kind;
+ u4 size;
+
+ fprintf(file,"======[descriptor_pool for ");
+ utf_fprint_printable_ascii(file,pool->referer->name);
+ fprintf(file,"]======\n");
+
+ fprintf(file,"fieldcount: %d\n",pool->fieldcount);
+ fprintf(file,"methodcount: %d\n",pool->methodcount);
+ fprintf(file,"paramcount: %d\n",pool->paramcount);
+ fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
+ fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
+ fprintf(file,"classrefsize: %d bytes\n",
+ (int)(pool->classrefhash.entries * sizeof(constant_classref)));
+
+ fprintf(file,"class references:\n");
+ for (slot=0; slot<pool->classrefhash.size; ++slot) {
+ classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ while (c) {
+ fprintf(file," %4d: ",c->index);
+ utf_fprint_printable_ascii(file,c->name);
+ fprintf(file,"\n");
+ c = c->hashlink;
+ }
+ }
+
+ fprintf(file,"hashed descriptors:\n");
+ for (slot=0; slot<pool->descriptorhash.size; ++slot) {
+ descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+ while (c) {
+ fprintf(file," %p: ",c->parseddesc.any);
+ utf_fprint_printable_ascii(file,c->desc);
+ fprintf(file,"\n");
+ c = c->hashlink;
+ }
+ }
+
+ fprintf(file,"descriptors:\n");
+ if (pool->descriptors) {
+ pos = pool->descriptors;
+ size = pool->descriptors_next - pool->descriptors;
+ fprintf(file," size: %d bytes\n",size);
+
+ if (pool->descriptor_kind) {
+ kind = pool->descriptor_kind;
+
+ while (pos < (pool->descriptors + size)) {
+ fprintf(file," %p: ",pos);
+ switch (*kind++) {
+ case 'f':
+ descriptor_debug_print_typedesc(file,(typedesc*)pos);
+ pos += sizeof(typedesc);
+ break;
+ case 'm':
+ descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
+ pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
+ pos += sizeof(methoddesc) - sizeof(typedesc);
+ break;
+ default:
+ fprintf(file,"INVALID KIND");
+ }
+ fputc('\n',file);
+ }
+ }
+ else {
+ while (size >= sizeof(void*)) {
+ fprintf(file," %p\n",*((void**)pos));
+ pos += sizeof(void*);
+ size -= sizeof(void*);
+ }
+ }
+ }
+
+ fprintf(file,"==========================================================\n");
+}
+#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/descriptor.h - checking and parsing of field / method descriptors
+
+ 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 _DESCRIPTOR_H
+#define _DESCRIPTOR_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct descriptor_pool descriptor_pool;
+typedef struct typedesc typedesc;
+typedef struct paramdesc paramdesc;
+typedef struct methoddesc methoddesc;
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/utf8.h"
+
+#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */
+
+
+/* data structures ************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* Descriptor Pools */
+/* */
+/* A descriptor_pool is a temporary data structure used during loading of */
+/* a class. The descriptor_pool is used to allocate the table of */
+/* constant_classrefs the class uses, and for parsing the field and method */
+/* descriptors which occurr within the class. The inner workings of */
+/* descriptor_pool are not important for outside code. */
+/* */
+/* You use a descriptor_pool as follows: */
+/* */
+/* 1. create one with descriptor_pool_new */
+/* 2. add all explicit class references with descriptor_pool_add_class */
+/* 3. add all field/method descriptors with descriptor_pool_add */
+/* 4. call descriptor_pool_create_classrefs */
+/* You can now lookup classrefs with descriptor_pool_lookup_classref */
+/* 5. call descriptor_pool_alloc_parsed_descriptors */
+/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */
+/* for each method descriptor call descriptor_pool_parse_method_descriptor */
+/* 7. call descriptor_pool_get_parsed_descriptors */
+/* */
+/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */
+/* memory which can be thrown away when the steps above have been */
+/* done. */
+/*----------------------------------------------------------------------------*/
+
+struct descriptor_pool {
+ classinfo *referer;
+ u4 fieldcount;
+ u4 methodcount;
+ u4 paramcount;
+ u4 descriptorsize;
+ u1 *descriptors;
+ u1 *descriptors_next;
+ hashtable descriptorhash;
+ constant_classref *classrefs;
+ hashtable classrefhash;
+ u1 *descriptor_kind; /* useful for debugging */
+ u1 *descriptor_kind_next; /* useful for debugging */
+};
+
+
+/* data structures for parsed field/method descriptors ************************/
+
+struct typedesc {
+ constant_classref *classref; /* class reference for TYPE_ADR types */
+ u1 type; /* TYPE_??? constant [1] */
+ u1 primitivetype; /* (PRIMITIVE)TYPE_??? constant [2] */
+ u1 arraydim; /* array dimension (0 if no array) */
+};
+
+/* [1]...the type field contains the basic type used within the VM. So ints, */
+/* shorts, chars, bytes, booleans all have TYPE_INT. */
+/* [2]...the primitivetype field contains the declared type. */
+/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */
+/* For non-primitive types primitivetype is TYPE_ADR. */
+
+struct paramdesc {
+#if defined(__MIPS__)
+ u1 type; /* TYPE_??? of the register allocated */
+#endif
+ bool inmemory; /* argument in register or on stack */
+ uint32_t index; /* index into argument register array */
+ uint32_t regoff; /* register index or stack offset */
+};
+
+struct methoddesc {
+ s2 paramcount; /* number of parameters */
+ s2 paramslots; /* like above but LONG,DOUBLE count twice */
+ s4 argintreguse; /* number of used integer argument registers */
+ s4 argfltreguse; /* number of used float argument registers */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ s4 argadrreguse; /* number of used address registers */
+#endif
+ s4 memuse; /* number of stack slots used */
+ paramdesc *params; /* allocated parameter descriptions [3] */
+ typedesc returntype; /* parsed descriptor of the return type */
+ typedesc paramtypes[1]; /* parameter types, variable length! */
+};
+
+/* [3]...If params is NULL, the parameter descriptions have not yet been */
+/* allocated. In this case ___the possible 'this' pointer of the method */
+/* is NOT counted in paramcount/paramslots and it is NOT included in */
+/* the paramtypes array___. */
+/* If params != NULL, the parameter descriptions have been */
+/* allocated, and the 'this' pointer of the method, if any, IS included.*/
+/* In case the method has no parameters at all, the special value */
+/* METHODDESC_NO_PARAMS is used (see below). */
+
+/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */
+/* indicating that the method is a static method without any parameters. */
+/* This special value must be != NULL and it may only be set if */
+/* md->paramcount == 0. */
+
+#define METHODDESC_NOPARAMS ((paramdesc*)1)
+
+/* function prototypes ********************************************************/
+
+descriptor_pool * descriptor_pool_new(classinfo *referer);
+
+bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
+bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots);
+
+int descriptor_to_basic_type(utf *desc);
+int descriptor_typesize(typedesc *td);
+
+constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool,
+ s4 *count);
+constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname);
+
+void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool);
+
+typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc);
+methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags,
+ constant_classref *thisclass);
+
+bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags);
+
+void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size);
+void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize,
+ u4 *descsize);
+
+#ifndef NDEBUG
+void descriptor_debug_print_typedesc(FILE *file,typedesc *d);
+void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d);
+void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d);
+void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
+#endif /* !defined(NDEBUG) */
+
+#endif /* _DESCRIPTOR_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:
+ */
+++ /dev/null
-/* src/vm/exceptions.c - exception 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 <string.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-
-#include "vm/types.h"
-
-#include "md-abi.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Thread.h"
-#include "native/include/java_lang_Throwable.h"
-
-#include "threads/lock-common.h"
-#include "threads/thread.h"
-
-#include "toolbox/util.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/methodheader.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/show.h"
-#include "vm/jit/stacktrace.h"
-#include "vm/jit/trace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/system.h"
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-
-/* for raising exceptions from native methods *********************************/
-
-#if !defined(ENABLE_THREADS)
-java_object_t *_no_threads_exceptionptr = NULL;
-#endif
-
-
-/* exceptions_get_exception ****************************************************
-
- Returns the current exception pointer of the current thread.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_get_exception(void)
-{
- java_object_t *o;
- java_handle_t *e;
-#if defined(ENABLE_THREADS)
- threadobject *t;
-
- t = THREADOBJECT;
-#endif
-
- /* Get the exception. */
-
- LLNI_CRITICAL_START;
-
-#if defined(ENABLE_THREADS)
- o = t->_exceptionptr;
-#else
- o = _no_threads_exceptionptr;
-#endif
-
- e = LLNI_WRAP(o);
-
- LLNI_CRITICAL_END;
-
- /* Return the exception. */
-
- return e;
-}
-
-
-/* exceptions_set_exception ****************************************************
-
- Sets the exception pointer of the current thread.
-
-*******************************************************************************/
-
-void exceptions_set_exception(java_handle_t *e)
-{
- threadobject *t;
- java_object_t *o;
-
-#if defined(ENABLE_THREADS)
- t = THREADOBJECT;
-#else
- t = NULL;
-#endif
-
- /* Set the exception. */
-
- LLNI_CRITICAL_START;
-
- o = LLNI_UNWRAP(e);
-
-#if !defined(NDEBUG)
- if (opt_DebugExceptions) {
- printf("[exceptions_set_exception : t=%p, o=%p, class=",
- (void *) t, (void *) o);
- class_print(o->vftbl->clazz);
- printf("]\n");
- }
-#endif
-
-#if defined(ENABLE_THREADS)
- t->_exceptionptr = o;
-#else
- _no_threads_exceptionptr = o;
-#endif
-
- LLNI_CRITICAL_END;
-}
-
-
-/* exceptions_clear_exception **************************************************
-
- Clears the current exception pointer of the current thread.
-
-*******************************************************************************/
-
-void exceptions_clear_exception(void)
-{
- threadobject *t;
-
-#if defined(ENABLE_THREADS)
- t = THREADOBJECT;
-#else
- t = NULL;
-#endif
-
- /* Set the exception. */
-
-#if !defined(NDEBUG)
- if (opt_DebugExceptions) {
- printf("[exceptions_clear_exception: t=%p]\n", (void *) t);
- }
-#endif
-
-#if defined(ENABLE_THREADS)
- t->_exceptionptr = NULL;
-#else
- _no_threads_exceptionptr = NULL;
-#endif
-}
-
-
-/* exceptions_get_and_clear_exception ******************************************
-
- Gets the exception pointer of the current thread and clears it.
- This function may return NULL.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_get_and_clear_exception(void)
-{
- java_handle_t *o;
-
- /* Get the exception... */
-
- o = exceptions_get_exception();
-
- /* ...and clear the exception if it is set. */
-
- if (o != NULL)
- exceptions_clear_exception();
-
- /* return the exception */
-
- return o;
-}
-
-
-/* exceptions_abort ************************************************************
-
- Prints exception to be thrown and aborts.
-
- IN:
- classname....class name
- message......exception message
-
-*******************************************************************************/
-
-static void exceptions_abort(utf *classname, utf *message)
-{
- log_println("exception thrown while VM is initializing: ");
-
- log_start();
- utf_display_printable_ascii_classname(classname);
-
- if (message != NULL) {
- log_print(": ");
- utf_display_printable_ascii_classname(message);
- }
-
- log_finish();
-
- vm_abort("Aborting...");
-}
-
-
-/* exceptions_new_class_utf ****************************************************
-
- Creates an exception object with the given class and initalizes it
- with the given utf message.
-
- IN:
- c ......... exception class
- message ... the message as an utf *
-
- RETURN VALUE:
- an exception pointer (in any case -- either it is the newly
- created exception, or an exception thrown while trying to create
- it).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
-{
- java_handle_t *s;
- java_handle_t *o;
-
- if (vm_initializing) {
- /* This can happen when global class variables are used which
- are not initialized yet. */
-
- if (c == NULL)
- exceptions_abort(NULL, message);
- else
- exceptions_abort(c->name, message);
- }
-
- s = javastring_new(message);
-
- if (s == NULL)
- return exceptions_get_exception();
-
- o = native_new_and_init_string(c, s);
-
- if (o == NULL)
- return exceptions_get_exception();
-
- return o;
-}
-
-
-/* exceptions_new_utf **********************************************************
-
- Creates an exception object with the given name and initalizes it.
-
- IN:
- classname....class name in UTF-8
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf(utf *classname)
-{
- classinfo *c;
- java_handle_t *o;
-
- if (vm_initializing)
- exceptions_abort(classname, NULL);
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return exceptions_get_exception();
-
- o = native_new_and_init(c);
-
- if (o == NULL)
- return exceptions_get_exception();
-
- return o;
-}
-
-
-/* exceptions_new_utf_javastring ***********************************************
-
- Creates an exception object with the given name and initalizes it
- with the given java/lang/String message.
-
- IN:
- classname....class name in UTF-8
- message......the message as a java.lang.String
-
- RETURN VALUE:
- an exception pointer (in any case -- either it is the newly created
- exception, or an exception thrown while trying to create it).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_javastring(utf *classname,
- java_handle_t *message)
-{
- java_handle_t *o;
- classinfo *c;
-
- if (vm_initializing)
- exceptions_abort(classname, NULL);
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return exceptions_get_exception();
-
- o = native_new_and_init_string(c, message);
-
- if (o == NULL)
- return exceptions_get_exception();
-
- return o;
-}
-
-
-/* exceptions_new_utf_utf ******************************************************
-
- Creates an exception object with the given name and initalizes it
- with the given utf message.
-
- IN:
- classname....class name in UTF-8
- message......the message as an utf *
-
- RETURN VALUE:
- an exception pointer (in any case -- either it is the newly created
- exception, or an exception thrown while trying to create it).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
-{
- classinfo *c;
- java_handle_t *o;
-
- if (vm_initializing)
- exceptions_abort(classname, message);
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return exceptions_get_exception();
-
- o = exceptions_new_class_utf(c, message);
-
- return o;
-}
-
-
-/* exceptions_throw_class_utf **************************************************
-
- Creates an exception object with the given class, initalizes and
- throws it with the given utf message.
-
- IN:
- c ......... exception class
- message ... the message as an utf *
-
-*******************************************************************************/
-
-static void exceptions_throw_class_utf(classinfo *c, utf *message)
-{
- java_handle_t *o;
-
- o = exceptions_new_class_utf(c, message);
-
- exceptions_set_exception(o);
-}
-
-
-/* exceptions_throw_utf ********************************************************
-
- Creates an exception object with the given name, initalizes and
- throws it.
-
- IN:
- classname....class name in UTF-8
-
-*******************************************************************************/
-
-static void exceptions_throw_utf(utf *classname)
-{
- java_handle_t *o;
-
- o = exceptions_new_utf(classname);
-
- if (o == NULL)
- return;
-
- exceptions_set_exception(o);
-}
-
-
-/* exceptions_throw_utf_throwable **********************************************
-
- Creates an exception object with the given name and initalizes it
- with the given java/lang/Throwable exception.
-
- IN:
- classname....class name in UTF-8
- cause........the given Throwable
-
-*******************************************************************************/
-
-static void exceptions_throw_utf_throwable(utf *classname,
- java_handle_t *cause)
-{
- classinfo *c;
- java_handle_t *o;
- methodinfo *m;
- java_lang_Throwable *object;
-
- if (vm_initializing)
- exceptions_abort(classname, NULL);
-
- object = (java_lang_Throwable *) cause;
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return;
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return;
-
- /* call initializer */
-
- m = class_resolveclassmethod(c,
- utf_init,
- utf_java_lang_Throwable__void,
- NULL,
- true);
-
- if (m == NULL)
- return;
-
- (void) vm_call_method(m, o, cause);
-
- exceptions_set_exception(o);
-}
-
-
-/* exceptions_throw_utf_exception **********************************************
-
- Creates an exception object with the given name and initalizes it
- with the given java/lang/Exception exception.
-
- IN:
- classname....class name in UTF-8
- exception....the given Exception
-
-*******************************************************************************/
-
-static void exceptions_throw_utf_exception(utf *classname,
- java_handle_t *exception)
-{
- classinfo *c;
- java_handle_t *o;
- methodinfo *m;
-
- if (vm_initializing)
- exceptions_abort(classname, NULL);
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return;
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return;
-
- /* call initializer */
-
- m = class_resolveclassmethod(c,
- utf_init,
- utf_java_lang_Exception__V,
- NULL,
- true);
-
- if (m == NULL)
- return;
-
- (void) vm_call_method(m, o, exception);
-
- exceptions_set_exception(o);
-}
-
-
-/* exceptions_throw_utf_cause **************************************************
-
- Creates an exception object with the given name and initalizes it
- with the given java/lang/Throwable exception with initCause.
-
- IN:
- classname....class name in UTF-8
- cause........the given Throwable
-
-*******************************************************************************/
-
-static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
-{
- classinfo *c;
- java_handle_t *o;
- methodinfo *m;
- java_lang_String *s;
- java_lang_Throwable *object;
-
- if (vm_initializing)
- exceptions_abort(classname, NULL);
-
- object = (java_lang_Throwable *) cause;
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return;
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return;
-
- /* call initializer */
-
- m = class_resolveclassmethod(c,
- utf_init,
- utf_java_lang_String__void,
- NULL,
- true);
-
- if (m == NULL)
- return;
-
- LLNI_field_get_ref(object, detailMessage, s);
-
- (void) vm_call_method(m, o, s);
-
- /* call initCause */
-
- m = class_resolveclassmethod(c,
- utf_initCause,
- utf_java_lang_Throwable__java_lang_Throwable,
- NULL,
- true);
-
- if (m == NULL)
- return;
-
- (void) vm_call_method(m, o, cause);
-
- exceptions_set_exception(o);
-}
-
-
-/* exceptions_throw_utf_utf ****************************************************
-
- Creates an exception object with the given name, initalizes and
- throws it with the given utf message.
-
- IN:
- classname....class name in UTF-8
- message......the message as an utf *
-
-*******************************************************************************/
-
-static void exceptions_throw_utf_utf(utf *classname, utf *message)
-{
- java_handle_t *o;
-
- o = exceptions_new_utf_utf(classname, message);
-
- exceptions_set_exception(o);
-}
-
-
-/* exceptions_new_abstractmethoderror ****************************************
-
- Generates a java.lang.AbstractMethodError for the VM.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_new_abstractmethoderror(void)
-{
- java_handle_t *o;
-
- o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
-
- return o;
-}
-
-
-/* exceptions_new_error ********************************************************
-
- Generates a java.lang.Error for the VM.
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVAME_CLDC1_1)
-static java_handle_t *exceptions_new_error(utf *message)
-{
- java_handle_t *o;
-
- o = exceptions_new_utf_utf(utf_java_lang_Error, message);
-
- return o;
-}
-#endif
-
-
-/* exceptions_asm_new_abstractmethoderror **************************************
-
- Generates a java.lang.AbstractMethodError for
- asm_abstractmethoderror.
-
-*******************************************************************************/
-
-java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
-{
- stackframeinfo_t sfi;
- java_handle_t *e;
- java_object_t *o;
-
- /* Fill and add a stackframeinfo (XPC is equal to RA). */
-
- stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra);
-
- /* create the exception */
-
-#if defined(ENABLE_JAVASE)
- e = exceptions_new_abstractmethoderror();
-#else
- e = exceptions_new_error(utf_java_lang_AbstractMethodError);
-#endif
-
- /* Remove the stackframeinfo. */
-
- stacktrace_stackframeinfo_remove(&sfi);
-
- /* unwrap the exception */
- /* ATTENTION: do the this _after_ the stackframeinfo was removed */
-
- o = LLNI_UNWRAP(e);
-
- return o;
-}
-
-
-/* exceptions_new_arraystoreexception ******************************************
-
- Generates a java.lang.ArrayStoreException for the VM.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_new_arraystoreexception(void)
-{
- java_handle_t *o;
-
- o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
-
- return o;
-}
-
-
-/* exceptions_throw_abstractmethoderror ****************************************
-
- Generates and throws a java.lang.AbstractMethodError for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_abstractmethoderror(void)
-{
- exceptions_throw_utf(utf_java_lang_AbstractMethodError);
-}
-
-
-/* exceptions_throw_classcircularityerror **************************************
-
- Generates and throws a java.lang.ClassCircularityError for the
- classloader.
-
- IN:
- c....the class in which the error was found
-
-*******************************************************************************/
-
-void exceptions_throw_classcircularityerror(classinfo *c)
-{
- exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name);
-}
-
-
-/* exceptions_throw_classformaterror *******************************************
-
- Generates and throws a java.lang.ClassFormatError for the VM.
-
- IN:
- c............the class in which the error was found
- message......UTF-8 format string
-
-*******************************************************************************/
-
-void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
-{
- char *msg;
- s4 msglen;
- va_list ap;
- utf *u;
-
- /* calculate message length */
-
- msglen = 0;
-
- if (c != NULL)
- msglen += utf_bytes(c->name) + strlen(" (");
-
- va_start(ap, message);
- msglen += get_variable_message_length(message, ap);
- va_end(ap);
-
- if (c != NULL)
- msglen += strlen(")");
-
- msglen += strlen("0");
-
- /* allocate a buffer */
-
- msg = MNEW(char, msglen);
-
- /* print message into allocated buffer */
-
- if (c != NULL) {
- utf_copy_classname(msg, c->name);
- strcat(msg, " (");
- }
-
- va_start(ap, message);
- vsprintf(msg + strlen(msg), message, ap);
- va_end(ap);
-
- if (c != NULL)
- strcat(msg, ")");
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
- /* throw exception */
-
- exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u);
-}
-
-
-/* exceptions_throw_classnotfoundexception *************************************
-
- Generates and throws a java.lang.ClassNotFoundException for the
- VM.
-
- IN:
- name.........name of the class not found as a utf *
-
-*******************************************************************************/
-
-void exceptions_throw_classnotfoundexception(utf *name)
-{
- exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
-}
-
-
-/* exceptions_throw_noclassdeffounderror ***************************************
-
- Generates and throws a java.lang.NoClassDefFoundError.
-
- IN:
- name.........name of the class not found as a utf *
-
-*******************************************************************************/
-
-void exceptions_throw_noclassdeffounderror(utf *name)
-{
- exceptions_throw_utf_utf(utf_java_lang_NoClassDefFoundError, name);
-}
-
-
-/* exceptions_throw_noclassdeffounderror_cause *********************************
-
- Generates and throws a java.lang.NoClassDefFoundError with the
- given cause.
-
-*******************************************************************************/
-
-void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause)
-{
- exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause);
-}
-
-
-/* exceptions_throw_noclassdeffounderror_wrong_name ****************************
-
- Generates and throws a java.lang.NoClassDefFoundError with a
- specific message:
-
- IN:
- name.........name of the class not found as a utf *
-
-*******************************************************************************/
-
-void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
-{
- char *msg;
- s4 msglen;
- utf *u;
-
- msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
- utf_bytes(name) + strlen(")") + strlen("0");
-
- msg = MNEW(char, msglen);
-
- utf_copy_classname(msg, c->name);
- strcat(msg, " (wrong name: ");
- utf_cat_classname(msg, name);
- strcat(msg, ")");
-
- u = utf_new_char(msg);
-
- MFREE(msg, char, msglen);
-
- exceptions_throw_noclassdeffounderror(u);
-}
-
-
-/* exceptions_throw_exceptionininitializererror ********************************
-
- Generates and throws a java.lang.ExceptionInInitializerError for
- the VM.
-
- IN:
- cause......cause exception object
-
-*******************************************************************************/
-
-void exceptions_throw_exceptionininitializererror(java_handle_t *cause)
-{
- exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
- cause);
-}
-
-
-/* exceptions_throw_incompatibleclasschangeerror *******************************
-
- Generates and throws a java.lang.IncompatibleClassChangeError for
- the VM.
-
- IN:
- message......UTF-8 message format string
-
-*******************************************************************************/
-
-void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
-{
- char *msg;
- s4 msglen;
- utf *u;
-
- /* calculate exception message length */
-
- msglen = utf_bytes(c->name) + strlen(message) + strlen("0");
-
- /* allocate memory */
-
- msg = MNEW(char, msglen);
-
- utf_copy_classname(msg, c->name);
- strcat(msg, message);
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
- /* throw exception */
-
- exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u);
-}
-
-
-/* exceptions_throw_instantiationerror *****************************************
-
- Generates and throws a java.lang.InstantiationError for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_instantiationerror(classinfo *c)
-{
- exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name);
-}
-
-
-/* exceptions_throw_internalerror **********************************************
-
- Generates and throws a java.lang.InternalError for the VM.
-
- IN:
- message......UTF-8 message format string
-
-*******************************************************************************/
-
-void exceptions_throw_internalerror(const char *message, ...)
-{
- va_list ap;
- char *msg;
- s4 msglen;
- utf *u;
-
- /* calculate exception message length */
-
- va_start(ap, message);
- msglen = get_variable_message_length(message, ap);
- va_end(ap);
-
- /* allocate memory */
-
- msg = MNEW(char, msglen);
-
- /* generate message */
-
- va_start(ap, message);
- vsprintf(msg, message, ap);
- va_end(ap);
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
- /* throw exception */
-
- exceptions_throw_utf_utf(utf_java_lang_InternalError, u);
-}
-
-
-/* exceptions_throw_linkageerror ***********************************************
-
- Generates and throws java.lang.LinkageError with an error message.
-
- IN:
- message......UTF-8 message
- c............class related to the error. If this is != NULL
- the name of c is appended to the error message.
-
-*******************************************************************************/
-
-void exceptions_throw_linkageerror(const char *message, classinfo *c)
-{
- utf *u;
- char *msg;
- int len;
-
- /* calculate exception message length */
-
- len = strlen(message) + 1;
-
- if (c != NULL)
- len += utf_bytes(c->name);
-
- /* allocate memory */
-
- msg = MNEW(char, len);
-
- /* generate message */
-
- strcpy(msg, message);
-
- if (c != NULL)
- utf_cat_classname(msg, c->name);
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, len);
-
- exceptions_throw_utf_utf(utf_java_lang_LinkageError, u);
-}
-
-
-/* exceptions_throw_nosuchfielderror *******************************************
-
- Generates and throws a java.lang.NoSuchFieldError with an error
- message.
-
- IN:
- c............class in which the field was not found
- name.........name of the field
-
-*******************************************************************************/
-
-void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
-{
- char *msg;
- s4 msglen;
- utf *u;
-
- /* calculate exception message length */
-
- msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0");
-
- /* allocate memory */
-
- msg = MNEW(char, msglen);
-
- /* generate message */
-
- utf_copy_classname(msg, c->name);
- strcat(msg, ".");
- utf_cat(msg, name);
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
- exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u);
-}
-
-
-/* exceptions_throw_nosuchmethoderror ******************************************
-
- Generates and throws a java.lang.NoSuchMethodError with an error
- message.
-
- IN:
- c............class in which the method was not found
- name.........name of the method
- desc.........descriptor of the method
-
-*******************************************************************************/
-
-void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
-{
- char *msg;
- s4 msglen;
- utf *u;
-
- /* calculate exception message length */
-
- msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
- utf_bytes(desc) + strlen("0");
-
- /* allocate memory */
-
- msg = MNEW(char, msglen);
-
- /* generate message */
-
- utf_copy_classname(msg, c->name);
- strcat(msg, ".");
- utf_cat(msg, name);
- utf_cat(msg, desc);
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
-#if defined(ENABLE_JAVASE)
- exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
-#else
- exceptions_throw_utf_utf(utf_java_lang_Error, u);
-#endif
-}
-
-
-/* exceptions_throw_outofmemoryerror *******************************************
-
- Generates and throws an java.lang.OutOfMemoryError for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_outofmemoryerror(void)
-{
- exceptions_throw_utf(utf_java_lang_OutOfMemoryError);
-}
-
-
-/* exceptions_throw_unsatisfiedlinkerror ***************************************
-
- Generates and throws a java.lang.UnsatisfiedLinkError for the
- classloader.
-
- IN:
- name......UTF-8 name string
-
-*******************************************************************************/
-
-void exceptions_throw_unsatisfiedlinkerror(utf *name)
-{
-#if defined(ENABLE_JAVASE)
- exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
-#else
- exceptions_throw_utf_utf(utf_java_lang_Error, name);
-#endif
-}
-
-
-/* exceptions_throw_unsupportedclassversionerror *******************************
-
- Generates and throws a java.lang.UnsupportedClassVersionError for
- the classloader.
-
- IN:
- c............class in which the method was not found
- message......UTF-8 format string
-
-*******************************************************************************/
-
-void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
-{
- char *msg;
- s4 msglen;
- utf *u;
-
- /* calculate exception message length */
-
- msglen =
- utf_bytes(c->name) +
- strlen(" (Unsupported major.minor version 00.0)") +
- strlen("0");
-
- /* allocate memory */
-
- msg = MNEW(char, msglen);
-
- /* generate message */
-
- utf_copy_classname(msg, c->name);
- sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
- ma, mi);
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
- /* throw exception */
-
- exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u);
-}
-
-
-/* exceptions_throw_verifyerror ************************************************
-
- Generates and throws a java.lang.VerifyError for the JIT compiler.
-
- IN:
- m............method in which the error was found
- message......UTF-8 format string
-
-*******************************************************************************/
-
-void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
-{
- va_list ap;
- char *msg;
- s4 msglen;
- utf *u;
-
- /* calculate exception message length */
-
- msglen = 0;
-
- if (m != NULL)
- msglen =
- strlen("(class: ") + utf_bytes(m->clazz->name) +
- strlen(", method: ") + utf_bytes(m->name) +
- strlen(" signature: ") + utf_bytes(m->descriptor) +
- strlen(") ") + strlen("0");
-
- va_start(ap, message);
- msglen += get_variable_message_length(message, ap);
- va_end(ap);
-
- /* allocate memory */
-
- msg = MNEW(char, msglen);
-
- /* generate message */
-
- if (m != NULL) {
- strcpy(msg, "(class: ");
- utf_cat_classname(msg, m->clazz->name);
- strcat(msg, ", method: ");
- utf_cat(msg, m->name);
- strcat(msg, " signature: ");
- utf_cat(msg, m->descriptor);
- strcat(msg, ") ");
- }
-
- va_start(ap, message);
- vsprintf(msg + strlen(msg), message, ap);
- va_end(ap);
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
- /* throw exception */
-
- exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
-}
-
-
-/* exceptions_throw_verifyerror_for_stack **************************************
-
- throws a java.lang.VerifyError for an invalid stack slot type
-
- IN:
- m............method in which the error was found
- type.........the expected type
-
- RETURN VALUE:
- an exception pointer (in any case -- either it is the newly created
- exception, or an exception thrown while trying to create it).
-
-*******************************************************************************/
-
-void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
-{
- char *msg;
- s4 msglen;
- char *typename;
- utf *u;
-
- /* calculate exception message length */
-
- msglen = 0;
-
- if (m != NULL)
- msglen = strlen("(class: ") + utf_bytes(m->clazz->name) +
- strlen(", method: ") + utf_bytes(m->name) +
- strlen(" signature: ") + utf_bytes(m->descriptor) +
- strlen(") Expecting to find longest-------typename on stack")
- + strlen("0");
-
- /* allocate memory */
-
- msg = MNEW(char, msglen);
-
- /* generate message */
-
- if (m != NULL) {
- strcpy(msg, "(class: ");
- utf_cat_classname(msg, m->clazz->name);
- strcat(msg, ", method: ");
- utf_cat(msg, m->name);
- strcat(msg, " signature: ");
- utf_cat(msg, m->descriptor);
- strcat(msg, ") ");
- }
- else {
- msg[0] = 0;
- }
-
- strcat(msg, "Expecting to find ");
-
- switch (type) {
- case TYPE_INT: typename = "integer"; break;
- case TYPE_LNG: typename = "long"; break;
- case TYPE_FLT: typename = "float"; break;
- case TYPE_DBL: typename = "double"; break;
- case TYPE_ADR: typename = "object/array"; break;
- case TYPE_RET: typename = "returnAddress"; break;
- default: typename = "<INVALID>"; assert(0); break;
- }
-
- strcat(msg, typename);
- strcat(msg, " on stack");
-
- u = utf_new_char(msg);
-
- /* free memory */
-
- MFREE(msg, char, msglen);
-
- /* throw exception */
-
- exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
-}
-
-
-/* exceptions_new_arithmeticexception ******************************************
-
- Generates a java.lang.ArithmeticException for the JIT compiler.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_new_arithmeticexception(void)
-{
- java_handle_t *o;
-
- o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
- utf_division_by_zero);
-
- return o;
-}
-
-
-/* exceptions_new_arrayindexoutofboundsexception *******************************
-
- Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
- system.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index)
-{
- java_handle_t *o;
- methodinfo *m;
- java_handle_t *s;
-
- /* convert the index into a String, like Sun does */
-
- m = class_resolveclassmethod(class_java_lang_String,
- utf_new_char("valueOf"),
- utf_new_char("(I)Ljava/lang/String;"),
- class_java_lang_Object,
- true);
-
- if (m == NULL)
- return exceptions_get_exception();
-
- s = vm_call_method(m, NULL, index);
-
- if (s == NULL)
- return exceptions_get_exception();
-
- o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
- s);
-
- if (o == NULL)
- return exceptions_get_exception();
-
- return o;
-}
-
-
-/* exceptions_throw_arrayindexoutofboundsexception *****************************
-
- Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
- the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_arrayindexoutofboundsexception(void)
-{
- exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException);
-}
-
-
-/* exceptions_throw_arraystoreexception ****************************************
-
- Generates and throws a java.lang.ArrayStoreException for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_arraystoreexception(void)
-{
- exceptions_throw_utf(utf_java_lang_ArrayStoreException);
-}
-
-
-/* exceptions_new_classcastexception *******************************************
-
- Generates a java.lang.ClassCastException for the JIT compiler.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_new_classcastexception(java_handle_t *o)
-{
- java_handle_t *e;
- classinfo *c;
- utf *classname;
-
- LLNI_class_get(o, c);
-
- classname = c->name;
-
- e = exceptions_new_utf_utf(utf_java_lang_ClassCastException, classname);
-
- return e;
-}
-
-
-/* exceptions_throw_clonenotsupportedexception *********************************
-
- Generates and throws a java.lang.CloneNotSupportedException for the
- VM.
-
-*******************************************************************************/
-
-void exceptions_throw_clonenotsupportedexception(void)
-{
- exceptions_throw_utf(utf_java_lang_CloneNotSupportedException);
-}
-
-
-/* exceptions_throw_illegalaccessexception *************************************
-
- Generates and throws a java.lang.IllegalAccessException for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_illegalaccessexception(utf *message)
-{
- exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message);
-}
-
-
-/* exceptions_throw_illegalargumentexception ***********************************
-
- Generates and throws a java.lang.IllegalArgumentException for the
- VM.
-
-*******************************************************************************/
-
-void exceptions_throw_illegalargumentexception(void)
-{
- exceptions_throw_utf(utf_java_lang_IllegalArgumentException);
-}
-
-
-/* exceptions_throw_illegalmonitorstateexception *******************************
-
- Generates and throws a java.lang.IllegalMonitorStateException for
- the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_illegalmonitorstateexception(void)
-{
- exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException);
-}
-
-
-/* exceptions_throw_instantiationexception *************************************
-
- Generates and throws a java.lang.InstantiationException for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_instantiationexception(classinfo *c)
-{
- exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name);
-}
-
-
-/* exceptions_throw_interruptedexception ***************************************
-
- Generates and throws a java.lang.InterruptedException for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_interruptedexception(void)
-{
- exceptions_throw_utf(utf_java_lang_InterruptedException);
-}
-
-
-/* exceptions_throw_invocationtargetexception **********************************
-
- Generates and throws a java.lang.reflect.InvocationTargetException
- for the VM.
-
- IN:
- cause......cause exception object
-
-*******************************************************************************/
-
-void exceptions_throw_invocationtargetexception(java_handle_t *cause)
-{
- exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
- cause);
-}
-
-
-/* exceptions_throw_negativearraysizeexception *********************************
-
- Generates and throws a java.lang.NegativeArraySizeException for the
- VM.
-
-*******************************************************************************/
-
-void exceptions_throw_negativearraysizeexception(void)
-{
- exceptions_throw_utf(utf_java_lang_NegativeArraySizeException);
-}
-
-
-/* exceptions_new_nullpointerexception *****************************************
-
- Generates a java.lang.NullPointerException for the VM system.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_new_nullpointerexception(void)
-{
- java_handle_t *o;
-
- o = exceptions_new_utf(utf_java_lang_NullPointerException);
-
- return o;
-}
-
-
-/* exceptions_throw_nullpointerexception ***************************************
-
- Generates a java.lang.NullPointerException for the VM system and
- throw it in the VM system.
-
-*******************************************************************************/
-
-void exceptions_throw_nullpointerexception(void)
-{
- exceptions_throw_utf(utf_java_lang_NullPointerException);
-}
-
-
-/* exceptions_throw_privilegedactionexception **********************************
-
- Generates and throws a java.security.PrivilegedActionException.
-
-*******************************************************************************/
-
-void exceptions_throw_privilegedactionexception(java_handle_t *exception)
-{
- exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
- exception);
-}
-
-
-/* exceptions_throw_stringindexoutofboundsexception ****************************
-
- Generates and throws a java.lang.StringIndexOutOfBoundsException
- for the VM.
-
-*******************************************************************************/
-
-void exceptions_throw_stringindexoutofboundsexception(void)
-{
- exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException);
-}
-
-
-/* exceptions_fillinstacktrace *************************************************
-
- Calls the fillInStackTrace-method of the currently thrown
- exception.
-
-*******************************************************************************/
-
-java_handle_t *exceptions_fillinstacktrace(void)
-{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
-
- /* get exception */
-
- o = exceptions_get_and_clear_exception();
-
- assert(o);
-
- /* resolve methodinfo pointer from exception object */
-
- LLNI_class_get(o, c);
-
-#if defined(ENABLE_JAVASE)
- m = class_resolvemethod(c,
- utf_fillInStackTrace,
- utf_void__java_lang_Throwable);
-#elif defined(ENABLE_JAVAME_CLDC1_1)
- m = class_resolvemethod(c,
- utf_fillInStackTrace,
- utf_void__void);
-#else
-#error IMPLEMENT ME!
-#endif
-
- /* call function */
-
- (void) vm_call_method(m, o);
-
- /* return exception object */
-
- return o;
-}
-
-
-/* exceptions_handle_exception *************************************************
-
- Try to find an exception handler for the given exception and return it.
- If no handler is found, exit the monitor of the method (if any)
- and return NULL.
-
- IN:
- xptr.........the exception object
- xpc..........PC of where the exception was thrown
- pv...........Procedure Value of the current method
- sp...........current stack pointer
-
- RETURN VALUE:
- the address of the first matching exception handler, or
- NULL if no handler was found
-
-*******************************************************************************/
-
-#if defined(ENABLE_JIT)
-void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp)
-{
- stackframeinfo_t sfi;
- java_handle_t *xptr;
- methodinfo *m;
- codeinfo *code;
- exceptiontable_t *et;
- exceptiontable_entry_t *ete;
- s4 i;
- classref_or_classinfo cr;
- classinfo *c;
-#if defined(ENABLE_THREADS)
- java_object_t *o;
-#endif
- void *result;
-
-#ifdef __S390__
- /* Addresses are 31 bit integers */
-# define ADDR_MASK(x) (void *) ((uintptr_t) (x) & 0x7FFFFFFF)
-#else
-# define ADDR_MASK(x) (x)
-#endif
-
- xptr = LLNI_WRAP(xptro);
- xpc = ADDR_MASK(xpc);
-
- /* Fill and add a stackframeinfo (XPC is equal to RA). */
-
- stacktrace_stackframeinfo_add(&sfi, pv, sp, xpc, xpc);
-
- result = NULL;
-
- /* Get the codeinfo for the current method. */
-
- code = code_get_codeinfo_for_pv(pv);
-
- /* Get the methodinfo pointer from the codeinfo pointer. For
- asm_vm_call_method the codeinfo pointer is NULL and we simply
- can return the proper exception handler. */
-
- if (code == NULL) {
- result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler;
- goto exceptions_handle_exception_return;
- }
-
- m = code->m;
-
-#if !defined(NDEBUG)
- /* print exception trace */
-
- if (opt_TraceExceptions)
- trace_exception(LLNI_DIRECT(xptr), m, xpc);
-
-# if defined(ENABLE_VMLOG)
- vmlog_cacao_throw(xptr);
-# endif
-#endif
-
- /* Get the exception table. */
-
- et = code->exceptiontable;
-
- if (et != NULL) {
- /* Iterate over all exception table entries. */
-
- ete = et->entries;
-
- for (i = 0; i < et->length; i++, ete++) {
- /* is the xpc is the current catch range */
-
- if ((ADDR_MASK(ete->startpc) <= xpc) && (xpc < ADDR_MASK(ete->endpc))) {
- cr = ete->catchtype;
-
- /* NULL catches everything */
-
- if (cr.any == NULL) {
-#if !defined(NDEBUG)
- /* Print stacktrace of exception when caught. */
-
-# if defined(ENABLE_VMLOG)
- vmlog_cacao_catch(xptr);
-# endif
-
- if (opt_TraceExceptions) {
- exceptions_print_exception(xptr);
- stacktrace_print_exception(xptr);
- }
-#endif
-
- result = ete->handlerpc;
- goto exceptions_handle_exception_return;
- }
-
- /* resolve or load/link the exception class */
-
- if (IS_CLASSREF(cr)) {
- /* The exception class reference is unresolved. */
- /* We have to do _eager_ resolving here. While the
- class of the exception object is guaranteed to be
- loaded, it may well have been loaded by a different
- loader than the defining loader of m's class, which
- is the one we must use to resolve the catch
- class. Thus lazy resolving might fail, even if the
- result of the resolution would be an already loaded
- class. */
-
- c = resolve_classref_eager(cr.ref);
-
- if (c == NULL) {
- /* Exception resolving the exception class, argh! */
- goto exceptions_handle_exception_return;
- }
-
- /* Ok, we resolved it. Enter it in the table, so we
- don't have to do this again. */
- /* XXX this write should be atomic. Is it? */
-
- ete->catchtype.cls = c;
- }
- else {
- c = cr.cls;
-
- /* XXX I don't think this case can ever happen. -Edwin */
- if (!(c->state & CLASS_LOADED))
- /* use the methods' classloader */
- if (!load_class_from_classloader(c->name,
- m->clazz->classloader))
- goto exceptions_handle_exception_return;
-
- /* XXX I think, if it is not linked, we can be sure
- that the exception object is no (indirect) instance
- of it, no? -Edwin */
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- goto exceptions_handle_exception_return;
- }
-
- /* is the thrown exception an instance of the catch class? */
-
- if (builtin_instanceof(xptr, c)) {
-#if !defined(NDEBUG)
- /* Print stacktrace of exception when caught. */
-
-# if defined(ENABLE_VMLOG)
- vmlog_cacao_catch(xptr);
-# endif
-
- if (opt_TraceExceptions) {
- exceptions_print_exception(xptr);
- stacktrace_print_exception(xptr);
- }
-#endif
-
- result = ete->handlerpc;
- goto exceptions_handle_exception_return;
- }
- }
- }
- }
-
-#if defined(ENABLE_THREADS)
- /* Is this method realization synchronized? */
-
- if (code_is_synchronized(code)) {
- /* Get synchronization object. */
-
- o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset));
-
- assert(o != NULL);
-
- lock_monitor_exit(LLNI_QUICKWRAP(o));
- }
-#endif
-
- /* none of the exceptions catch this one */
-
-#if !defined(NDEBUG)
-# if defined(ENABLE_VMLOG)
- vmlog_cacao_unwnd_method(m);
-# endif
-
-# if defined(ENABLE_DEBUG_FILTER)
- if (show_filters_test_verbosecall_exit(m)) {
-# endif
-
- /* outdent the log message */
-
- if (opt_verbosecall) {
- if (TRACEJAVACALLINDENT)
- TRACEJAVACALLINDENT--;
- else
- log_text("exceptions_handle_exception: WARNING: unmatched unindent");
- }
-
-# if defined(ENABLE_DEBUG_FILTER)
- }
-# endif
-#endif /* !defined(NDEBUG) */
-
- result = NULL;
-
-exceptions_handle_exception_return:
-
- /* Remove the stackframeinfo. */
-
- stacktrace_stackframeinfo_remove(&sfi);
-
- return result;
-}
-#endif /* defined(ENABLE_JIT) */
-
-
-/* exceptions_print_exception **************************************************
-
- Prints an exception, the detail message and the cause, if
- available, with CACAO internal functions to stdout.
-
-*******************************************************************************/
-
-void exceptions_print_exception(java_handle_t *xptr)
-{
- java_lang_Throwable *t;
-#if defined(ENABLE_JAVASE)
- java_lang_Throwable *cause;
-#endif
- java_lang_String *s;
- classinfo *c;
- utf *u;
-
- t = (java_lang_Throwable *) xptr;
-
- if (t == NULL) {
- puts("NULL\n");
- return;
- }
-
-#if defined(ENABLE_JAVASE)
- LLNI_field_get_ref(t, cause, cause);
-#endif
-
- /* print the root exception */
-
- LLNI_class_get(t, c);
- utf_display_printable_ascii_classname(c->name);
-
- LLNI_field_get_ref(t, detailMessage, s);
-
- if (s != NULL) {
- u = javastring_toutf((java_handle_t *) s, false);
-
- printf(": ");
- utf_display_printable_ascii(u);
- }
-
- putc('\n', stdout);
-
-#if defined(ENABLE_JAVASE)
- /* print the cause if available */
-
- if ((cause != NULL) && (cause != t)) {
- printf("Caused by: ");
-
- LLNI_class_get(cause, c);
- utf_display_printable_ascii_classname(c->name);
-
- LLNI_field_get_ref(cause, detailMessage, s);
-
- if (s != NULL) {
- u = javastring_toutf((java_handle_t *) s, false);
-
- printf(": ");
- utf_display_printable_ascii(u);
- }
-
- putc('\n', stdout);
- }
-#endif
-}
-
-
-/* exceptions_print_current_exception ******************************************
-
- Prints the current pending exception, the detail message and the
- cause, if available, with CACAO internal functions to stdout.
-
-*******************************************************************************/
-
-void exceptions_print_current_exception(void)
-{
- java_handle_t *o;
-
- o = exceptions_get_exception();
-
- exceptions_print_exception(o);
-}
-
-
-/* exceptions_print_stacktrace *************************************************
-
- Prints a pending exception with Throwable.printStackTrace(). If
- there happens an exception during printStackTrace(), we print the
- thrown exception and the original one.
-
- NOTE: This function calls Java code.
-
-*******************************************************************************/
-
-void exceptions_print_stacktrace(void)
-{
- java_handle_t *e;
- java_handle_t *ne;
- classinfo *c;
- methodinfo *m;
-
-#if defined(ENABLE_THREADS)
- threadobject *t;
- java_lang_Thread *to;
-#endif
-
- /* Get and clear exception because we are calling Java code
- again. */
-
- e = exceptions_get_and_clear_exception();
-
- if (e == NULL)
- return;
-
-#if 0
- /* FIXME Enable me. */
- if (builtin_instanceof(e, class_java_lang_ThreadDeath)) {
- /* Don't print anything if we are being killed. */
- }
- else
-#endif
- {
- /* Get the exception class. */
-
- LLNI_class_get(e, c);
-
- /* Find the printStackTrace() method. */
-
- m = class_resolveclassmethod(c,
- utf_printStackTrace,
- utf_void__void,
- class_java_lang_Object,
- false);
-
- if (m == NULL)
- vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
-
- /* Print message. */
-
- fprintf(stderr, "Exception ");
-
-#if defined(ENABLE_THREADS)
- /* Print thread name. We get the thread here explicitly as we
- need it afterwards. */
-
- t = thread_get_current();
- to = (java_lang_Thread *) thread_get_object(t);
-
- if (to != NULL) {
- fprintf(stderr, "in thread \"");
- thread_fprint_name(t, stderr);
- fprintf(stderr, "\" ");
- }
-#endif
-
- /* Print the stacktrace. */
-
- if (builtin_instanceof(e, class_java_lang_Throwable)) {
- (void) vm_call_method(m, e);
-
- /* If this happens we are EXTREMLY out of memory or have a
- serious problem while printStackTrace. But may be
- another exception, so print it. */
-
- ne = exceptions_get_exception();
-
- if (ne != NULL) {
- fprintf(stderr, "Exception while printStackTrace(): ");
-
- /* Print the current exception. */
-
- exceptions_print_exception(ne);
- stacktrace_print_exception(ne);
-
- /* Now print the original exception. */
-
- fprintf(stderr, "Original exception was: ");
- exceptions_print_exception(e);
- stacktrace_print_exception(e);
- }
- }
- else {
- fprintf(stderr, ". Uncaught exception of type ");
-#if !defined(NDEBUG)
- /* FIXME This prints to stdout. */
- class_print(c);
-#else
- fprintf(stderr, "UNKNOWN");
-#endif
- fprintf(stderr, ".");
- }
-
- fflush(stderr);
- }
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * 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/exceptions.cpp - exception 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 <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "threads/lock-common.h"
+#include "threads/thread.hpp"
+
+#include "toolbox/util.h"
+
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.h"
+#include "vm/jit/show.h"
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trace.hpp"
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+
+// FIXME
+extern "C" {
+
+/* for raising exceptions from native methods *********************************/
+
+#if !defined(ENABLE_THREADS)
+java_object_t *_no_threads_exceptionptr = NULL;
+#endif
+
+
+/* exceptions_get_exception ****************************************************
+
+ Returns the current exception pointer of the current thread.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_get_exception(void)
+{
+ java_object_t *o;
+ java_handle_t *e;
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+
+ t = THREADOBJECT;
+#endif
+
+ /* Get the exception. */
+
+ LLNI_CRITICAL_START;
+
+#if defined(ENABLE_THREADS)
+ o = t->_exceptionptr;
+#else
+ o = _no_threads_exceptionptr;
+#endif
+
+ e = LLNI_WRAP(o);
+
+ LLNI_CRITICAL_END;
+
+ /* Return the exception. */
+
+ return e;
+}
+
+
+/* exceptions_set_exception ****************************************************
+
+ Sets the exception pointer of the current thread.
+
+*******************************************************************************/
+
+void exceptions_set_exception(java_handle_t *e)
+{
+ threadobject *t;
+ java_object_t *o;
+
+#if defined(ENABLE_THREADS)
+ t = THREADOBJECT;
+#else
+ t = NULL;
+#endif
+
+ /* Set the exception. */
+
+ LLNI_CRITICAL_START;
+
+ o = LLNI_UNWRAP(e);
+
+#if !defined(NDEBUG)
+ if (opt_DebugExceptions) {
+ printf("[exceptions_set_exception : t=%p, o=%p, class=",
+ (void *) t, (void *) o);
+ class_print(o->vftbl->clazz);
+ printf("]\n");
+ }
+#endif
+
+#if defined(ENABLE_THREADS)
+ t->_exceptionptr = o;
+#else
+ _no_threads_exceptionptr = o;
+#endif
+
+ LLNI_CRITICAL_END;
+}
+
+
+/* exceptions_clear_exception **************************************************
+
+ Clears the current exception pointer of the current thread.
+
+*******************************************************************************/
+
+void exceptions_clear_exception(void)
+{
+ threadobject *t;
+
+#if defined(ENABLE_THREADS)
+ t = THREADOBJECT;
+#else
+ t = NULL;
+#endif
+
+ /* Set the exception. */
+
+#if !defined(NDEBUG)
+ if (opt_DebugExceptions) {
+ printf("[exceptions_clear_exception: t=%p]\n", (void *) t);
+ }
+#endif
+
+#if defined(ENABLE_THREADS)
+ t->_exceptionptr = NULL;
+#else
+ _no_threads_exceptionptr = NULL;
+#endif
+}
+
+
+/* exceptions_get_and_clear_exception ******************************************
+
+ Gets the exception pointer of the current thread and clears it.
+ This function may return NULL.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_get_and_clear_exception(void)
+{
+ java_handle_t *o;
+
+ /* Get the exception... */
+
+ o = exceptions_get_exception();
+
+ /* ...and clear the exception if it is set. */
+
+ if (o != NULL)
+ exceptions_clear_exception();
+
+ /* return the exception */
+
+ return o;
+}
+
+
+/* exceptions_abort ************************************************************
+
+ Prints exception to be thrown and aborts.
+
+ IN:
+ classname....class name
+ message......exception message
+
+*******************************************************************************/
+
+static void exceptions_abort(utf *classname, utf *message)
+{
+ log_println("exception thrown while VM is initializing: ");
+
+ log_start();
+ utf_display_printable_ascii_classname(classname);
+
+ if (message != NULL) {
+ log_print(": ");
+ utf_display_printable_ascii_classname(message);
+ }
+
+ log_finish();
+
+ vm_abort("Aborting...");
+}
+
+
+/* exceptions_new_class_utf ****************************************************
+
+ Creates an exception object with the given class and initalizes it
+ with the given utf message.
+
+ IN:
+ c ......... exception class
+ message ... the message as an utf *
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly
+ created exception, or an exception thrown while trying to create
+ it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
+{
+ java_handle_t *s;
+ java_handle_t *o;
+
+ if (vm->is_initializing()) {
+ /* This can happen when global class variables are used which
+ are not initialized yet. */
+
+ if (c == NULL)
+ exceptions_abort(NULL, message);
+ else
+ exceptions_abort(c->name, message);
+ }
+
+ s = javastring_new(message);
+
+ if (s == NULL)
+ return exceptions_get_exception();
+
+ o = native_new_and_init_string(c, s);
+
+ if (o == NULL)
+ return exceptions_get_exception();
+
+ return o;
+}
+
+
+/* exceptions_new_utf **********************************************************
+
+ Creates an exception object with the given name and initalizes it.
+
+ IN:
+ classname....class name in UTF-8
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf(utf *classname)
+{
+ classinfo *c;
+ java_handle_t *o;
+
+ if (vm->is_initializing())
+ exceptions_abort(classname, NULL);
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return exceptions_get_exception();
+
+ o = native_new_and_init(c);
+
+ if (o == NULL)
+ return exceptions_get_exception();
+
+ return o;
+}
+
+
+/* exceptions_new_utf_javastring ***********************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/String message.
+
+ IN:
+ classname....class name in UTF-8
+ message......the message as a java.lang.String
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly created
+ exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_javastring(utf *classname,
+ java_handle_t *message)
+{
+ java_handle_t *o;
+ classinfo *c;
+
+ if (vm->is_initializing())
+ exceptions_abort(classname, NULL);
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return exceptions_get_exception();
+
+ o = native_new_and_init_string(c, message);
+
+ if (o == NULL)
+ return exceptions_get_exception();
+
+ return o;
+}
+
+
+/* exceptions_new_utf_utf ******************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given utf message.
+
+ IN:
+ classname....class name in UTF-8
+ message......the message as an utf *
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly created
+ exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
+{
+ classinfo *c;
+ java_handle_t *o;
+
+ if (vm->is_initializing())
+ exceptions_abort(classname, message);
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return exceptions_get_exception();
+
+ o = exceptions_new_class_utf(c, message);
+
+ return o;
+}
+
+
+/* exceptions_throw_class_utf **************************************************
+
+ Creates an exception object with the given class, initalizes and
+ throws it with the given utf message.
+
+ IN:
+ c ......... exception class
+ message ... the message as an utf *
+
+*******************************************************************************/
+
+static void exceptions_throw_class_utf(classinfo *c, utf *message)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_class_utf(c, message);
+
+ exceptions_set_exception(o);
+}
+
+
+/* exceptions_throw_utf ********************************************************
+
+ Creates an exception object with the given name, initalizes and
+ throws it.
+
+ IN:
+ classname....class name in UTF-8
+
+*******************************************************************************/
+
+static void exceptions_throw_utf(utf *classname)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf(classname);
+
+ if (o == NULL)
+ return;
+
+ exceptions_set_exception(o);
+}
+
+
+/* exceptions_throw_utf_throwable **********************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/Throwable exception.
+
+ IN:
+ classname....class name in UTF-8
+ cause........the given Throwable
+
+*******************************************************************************/
+
+static void exceptions_throw_utf_throwable(utf *classname,
+ java_handle_t *cause)
+{
+ classinfo *c;
+ methodinfo *m;
+
+ if (vm->is_initializing())
+ exceptions_abort(classname, NULL);
+
+ java_lang_Throwable jlt(cause);
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return;
+
+ /* create object */
+
+ java_handle_t* h = builtin_new(c);
+
+ if (h == NULL)
+ return;
+
+ /* call initializer */
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_Throwable__void,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, h, jlt.get_handle());
+
+ exceptions_set_exception(h);
+}
+
+
+/* exceptions_throw_utf_exception **********************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/Exception exception.
+
+ IN:
+ classname....class name in UTF-8
+ exception....the given Exception
+
+*******************************************************************************/
+
+static void exceptions_throw_utf_exception(utf *classname,
+ java_handle_t *exception)
+{
+ classinfo *c;
+ java_handle_t *o;
+ methodinfo *m;
+
+ if (vm->is_initializing())
+ exceptions_abort(classname, NULL);
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return;
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return;
+
+ /* call initializer */
+
+ m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_Exception__V,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, o, exception);
+
+ exceptions_set_exception(o);
+}
+
+
+/* exceptions_throw_utf_cause **************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/Throwable exception with initCause.
+
+ IN:
+ classname....class name in UTF-8
+ cause........the given Throwable
+
+*******************************************************************************/
+
+static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
+{
+ if (vm->is_initializing())
+ exceptions_abort(classname, NULL);
+
+ java_lang_Throwable jltcause(cause);
+
+ classinfo* c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return;
+
+ /* create object */
+
+ java_handle_t* h = builtin_new(c);
+
+ if (h == NULL)
+ return;
+
+ /* call initializer */
+
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_init,
+ utf_java_lang_String__void,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, h, jltcause.get_detailMessage());
+
+ /* call initCause */
+
+ m = class_resolveclassmethod(c,
+ utf_initCause,
+ utf_java_lang_Throwable__java_lang_Throwable,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ (void) vm_call_method(m, h, jltcause.get_handle());
+
+ exceptions_set_exception(h);
+}
+
+
+/* exceptions_throw_utf_utf ****************************************************
+
+ Creates an exception object with the given name, initalizes and
+ throws it with the given utf message.
+
+ IN:
+ classname....class name in UTF-8
+ message......the message as an utf *
+
+*******************************************************************************/
+
+static void exceptions_throw_utf_utf(utf *classname, utf *message)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf_utf(classname, message);
+
+ exceptions_set_exception(o);
+}
+
+
+/* exceptions_new_abstractmethoderror ****************************************
+
+ Generates a java.lang.AbstractMethodError for the VM.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_new_abstractmethoderror(void)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf(utf_java_lang_AbstractMethodError);
+
+ return o;
+}
+
+
+/* exceptions_new_error ********************************************************
+
+ Generates a java.lang.Error for the VM.
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVAME_CLDC1_1)
+static java_handle_t *exceptions_new_error(utf *message)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf_utf(utf_java_lang_Error, message);
+
+ return o;
+}
+#endif
+
+
+/* exceptions_asm_new_abstractmethoderror **************************************
+
+ Generates a java.lang.AbstractMethodError for
+ asm_abstractmethoderror.
+
+*******************************************************************************/
+
+java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra)
+{
+ stackframeinfo_t sfi;
+ java_handle_t *e;
+ java_object_t *o;
+
+ /* Fill and add a stackframeinfo (XPC is equal to RA). */
+
+ stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra);
+
+ /* create the exception */
+
+#if defined(ENABLE_JAVASE)
+ e = exceptions_new_abstractmethoderror();
+#else
+ e = exceptions_new_error(utf_java_lang_AbstractMethodError);
+#endif
+
+ /* Remove the stackframeinfo. */
+
+ stacktrace_stackframeinfo_remove(&sfi);
+
+ /* unwrap the exception */
+ /* ATTENTION: do the this _after_ the stackframeinfo was removed */
+
+ o = LLNI_UNWRAP(e);
+
+ return o;
+}
+
+
+/* exceptions_new_arraystoreexception ******************************************
+
+ Generates a java.lang.ArrayStoreException for the VM.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_new_arraystoreexception(void)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf(utf_java_lang_ArrayStoreException);
+
+ return o;
+}
+
+
+/* exceptions_throw_abstractmethoderror ****************************************
+
+ Generates and throws a java.lang.AbstractMethodError for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_abstractmethoderror(void)
+{
+ exceptions_throw_utf(utf_java_lang_AbstractMethodError);
+}
+
+
+/* exceptions_throw_classcircularityerror **************************************
+
+ Generates and throws a java.lang.ClassCircularityError for the
+ classloader.
+
+ IN:
+ c....the class in which the error was found
+
+*******************************************************************************/
+
+void exceptions_throw_classcircularityerror(classinfo *c)
+{
+ exceptions_throw_utf_utf(utf_java_lang_ClassCircularityError, c->name);
+}
+
+
+/* exceptions_throw_classformaterror *******************************************
+
+ Generates and throws a java.lang.ClassFormatError for the VM.
+
+ IN:
+ c............the class in which the error was found
+ message......UTF-8 format string
+
+*******************************************************************************/
+
+void exceptions_throw_classformaterror(classinfo *c, const char *message, ...)
+{
+ char *msg;
+ s4 msglen;
+ va_list ap;
+ utf *u;
+
+ /* calculate message length */
+
+ msglen = 0;
+
+ if (c != NULL)
+ msglen += utf_bytes(c->name) + strlen(" (");
+
+ va_start(ap, message);
+ msglen += get_variable_message_length(message, ap);
+ va_end(ap);
+
+ if (c != NULL)
+ msglen += strlen(")");
+
+ msglen += strlen("0");
+
+ /* allocate a buffer */
+
+ msg = MNEW(char, msglen);
+
+ /* print message into allocated buffer */
+
+ if (c != NULL) {
+ utf_copy_classname(msg, c->name);
+ strcat(msg, " (");
+ }
+
+ va_start(ap, message);
+ vsprintf(msg + strlen(msg), message, ap);
+ va_end(ap);
+
+ if (c != NULL)
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_ClassFormatError, u);
+}
+
+
+/* exceptions_throw_classnotfoundexception *************************************
+
+ Generates and throws a java.lang.ClassNotFoundException for the
+ VM.
+
+ IN:
+ name.........name of the class not found as a utf *
+
+*******************************************************************************/
+
+void exceptions_throw_classnotfoundexception(utf *name)
+{
+ exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
+}
+
+
+/* exceptions_throw_noclassdeffounderror ***************************************
+
+ Generates and throws a java.lang.NoClassDefFoundError.
+
+ IN:
+ name.........name of the class not found as a utf *
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror(utf *name)
+{
+ exceptions_throw_utf_utf(utf_java_lang_NoClassDefFoundError, name);
+}
+
+
+/* exceptions_throw_noclassdeffounderror_cause *********************************
+
+ Generates and throws a java.lang.NoClassDefFoundError with the
+ given cause.
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause)
+{
+ exceptions_throw_utf_cause(utf_java_lang_NoClassDefFoundError, cause);
+}
+
+
+/* exceptions_throw_noclassdeffounderror_wrong_name ****************************
+
+ Generates and throws a java.lang.NoClassDefFoundError with a
+ specific message:
+
+ IN:
+ name.........name of the class not found as a utf *
+
+*******************************************************************************/
+
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ msglen = utf_bytes(c->name) + strlen(" (wrong name: ") +
+ utf_bytes(name) + strlen(")") + strlen("0");
+
+ msg = MNEW(char, msglen);
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, " (wrong name: ");
+ utf_cat_classname(msg, name);
+ strcat(msg, ")");
+
+ u = utf_new_char(msg);
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_noclassdeffounderror(u);
+}
+
+
+/* exceptions_throw_exceptionininitializererror ********************************
+
+ Generates and throws a java.lang.ExceptionInInitializerError for
+ the VM.
+
+ IN:
+ cause......cause exception object
+
+*******************************************************************************/
+
+void exceptions_throw_exceptionininitializererror(java_handle_t *cause)
+{
+ exceptions_throw_utf_throwable(utf_java_lang_ExceptionInInitializerError,
+ cause);
+}
+
+
+/* exceptions_throw_incompatibleclasschangeerror *******************************
+
+ Generates and throws a java.lang.IncompatibleClassChangeError for
+ the VM.
+
+ IN:
+ message......UTF-8 message format string
+
+*******************************************************************************/
+
+void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = utf_bytes(c->name) + strlen(message) + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, message);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_IncompatibleClassChangeError, u);
+}
+
+
+/* exceptions_throw_instantiationerror *****************************************
+
+ Generates and throws a java.lang.InstantiationError for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_instantiationerror(classinfo *c)
+{
+ exceptions_throw_utf_utf(utf_java_lang_InstantiationError, c->name);
+}
+
+
+/* exceptions_throw_internalerror **********************************************
+
+ Generates and throws a java.lang.InternalError for the VM.
+
+ IN:
+ message......UTF-8 message format string
+
+*******************************************************************************/
+
+void exceptions_throw_internalerror(const char *message, ...)
+{
+ va_list ap;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ va_start(ap, message);
+ msglen = get_variable_message_length(message, ap);
+ va_end(ap);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ va_start(ap, message);
+ vsprintf(msg, message, ap);
+ va_end(ap);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_InternalError, u);
+}
+
+
+/* exceptions_throw_linkageerror ***********************************************
+
+ Generates and throws java.lang.LinkageError with an error message.
+
+ IN:
+ message......UTF-8 message
+ c............class related to the error. If this is != NULL
+ the name of c is appended to the error message.
+
+*******************************************************************************/
+
+void exceptions_throw_linkageerror(const char *message, classinfo *c)
+{
+ utf *u;
+ char *msg;
+ int len;
+
+ /* calculate exception message length */
+
+ len = strlen(message) + 1;
+
+ if (c != NULL)
+ len += utf_bytes(c->name);
+
+ /* allocate memory */
+
+ msg = MNEW(char, len);
+
+ /* generate message */
+
+ strcpy(msg, message);
+
+ if (c != NULL)
+ utf_cat_classname(msg, c->name);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, len);
+
+ exceptions_throw_utf_utf(utf_java_lang_LinkageError, u);
+}
+
+
+/* exceptions_throw_nosuchfielderror *******************************************
+
+ Generates and throws a java.lang.NoSuchFieldError with an error
+ message.
+
+ IN:
+ c............class in which the field was not found
+ name.........name of the field
+
+*******************************************************************************/
+
+void exceptions_throw_nosuchfielderror(classinfo *c, utf *name)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, ".");
+ utf_cat(msg, name);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ exceptions_throw_utf_utf(utf_java_lang_NoSuchFieldError, u);
+}
+
+
+/* exceptions_throw_nosuchmethoderror ******************************************
+
+ Generates and throws a java.lang.NoSuchMethodError with an error
+ message.
+
+ IN:
+ c............class in which the method was not found
+ name.........name of the method
+ desc.........descriptor of the method
+
+*******************************************************************************/
+
+void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = utf_bytes(c->name) + strlen(".") + utf_bytes(name) +
+ utf_bytes(desc) + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ utf_copy_classname(msg, c->name);
+ strcat(msg, ".");
+ utf_cat(msg, name);
+ utf_cat(msg, desc);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+#if defined(ENABLE_JAVASE)
+ exceptions_throw_utf_utf(utf_java_lang_NoSuchMethodError, u);
+#else
+ exceptions_throw_utf_utf(utf_java_lang_Error, u);
+#endif
+}
+
+
+/* exceptions_throw_outofmemoryerror *******************************************
+
+ Generates and throws an java.lang.OutOfMemoryError for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_outofmemoryerror(void)
+{
+ exceptions_throw_utf(utf_java_lang_OutOfMemoryError);
+}
+
+
+/* exceptions_throw_unsatisfiedlinkerror ***************************************
+
+ Generates and throws a java.lang.UnsatisfiedLinkError for the
+ classloader.
+
+ IN:
+ name......UTF-8 name string
+
+*******************************************************************************/
+
+void exceptions_throw_unsatisfiedlinkerror(utf *name)
+{
+#if defined(ENABLE_JAVASE)
+ exceptions_throw_utf_utf(utf_java_lang_UnsatisfiedLinkError, name);
+#else
+ exceptions_throw_utf_utf(utf_java_lang_Error, name);
+#endif
+}
+
+
+/* exceptions_throw_unsupportedclassversionerror *******************************
+
+ Generates and throws a java.lang.UnsupportedClassVersionError for
+ the classloader.
+
+ IN:
+ c............class in which the method was not found
+ message......UTF-8 format string
+
+*******************************************************************************/
+
+void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen =
+ utf_bytes(c->name) +
+ strlen(" (Unsupported major.minor version 00.0)") +
+ strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ utf_copy_classname(msg, c->name);
+ sprintf(msg + strlen(msg), " (Unsupported major.minor version %d.%d)",
+ ma, mi);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_UnsupportedClassVersionError, u);
+}
+
+
+/* exceptions_throw_verifyerror ************************************************
+
+ Generates and throws a java.lang.VerifyError for the JIT compiler.
+
+ IN:
+ m............method in which the error was found
+ message......UTF-8 format string
+
+*******************************************************************************/
+
+void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
+{
+ va_list ap;
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = 0;
+
+ if (m != NULL)
+ msglen =
+ strlen("(class: ") + utf_bytes(m->clazz->name) +
+ strlen(", method: ") + utf_bytes(m->name) +
+ strlen(" signature: ") + utf_bytes(m->descriptor) +
+ strlen(") ") + strlen("0");
+
+ va_start(ap, message);
+ msglen += get_variable_message_length(message, ap);
+ va_end(ap);
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ if (m != NULL) {
+ strcpy(msg, "(class: ");
+ utf_cat_classname(msg, m->clazz->name);
+ strcat(msg, ", method: ");
+ utf_cat(msg, m->name);
+ strcat(msg, " signature: ");
+ utf_cat(msg, m->descriptor);
+ strcat(msg, ") ");
+ }
+
+ va_start(ap, message);
+ vsprintf(msg + strlen(msg), message, ap);
+ va_end(ap);
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
+}
+
+
+/* exceptions_throw_verifyerror_for_stack **************************************
+
+ throws a java.lang.VerifyError for an invalid stack slot type
+
+ IN:
+ m............method in which the error was found
+ type.........the expected type
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly created
+ exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type)
+{
+ char *msg;
+ s4 msglen;
+ utf *u;
+
+ /* calculate exception message length */
+
+ msglen = 0;
+
+ if (m != NULL)
+ msglen = strlen("(class: ") + utf_bytes(m->clazz->name) +
+ strlen(", method: ") + utf_bytes(m->name) +
+ strlen(" signature: ") + utf_bytes(m->descriptor) +
+ strlen(") Expecting to find longest-------typename on stack")
+ + strlen("0");
+
+ /* allocate memory */
+
+ msg = MNEW(char, msglen);
+
+ /* generate message */
+
+ if (m != NULL) {
+ strcpy(msg, "(class: ");
+ utf_cat_classname(msg, m->clazz->name);
+ strcat(msg, ", method: ");
+ utf_cat(msg, m->name);
+ strcat(msg, " signature: ");
+ utf_cat(msg, m->descriptor);
+ strcat(msg, ") ");
+ }
+ else {
+ msg[0] = 0;
+ }
+
+ strcat(msg, "Expecting to find ");
+
+ const char *name;
+
+ switch (type) {
+ case TYPE_INT: name = "integer"; break;
+ case TYPE_LNG: name = "long"; break;
+ case TYPE_FLT: name = "float"; break;
+ case TYPE_DBL: name = "double"; break;
+ case TYPE_ADR: name = "object/array"; break;
+ case TYPE_RET: name = "returnAddress"; break;
+ default: name = "<INVALID>"; assert(0); break;
+ }
+
+ strcat(msg, name);
+ strcat(msg, " on stack");
+
+ u = utf_new_char(msg);
+
+ /* free memory */
+
+ MFREE(msg, char, msglen);
+
+ /* throw exception */
+
+ exceptions_throw_utf_utf(utf_java_lang_VerifyError, u);
+}
+
+
+/* exceptions_new_arithmeticexception ******************************************
+
+ Generates a java.lang.ArithmeticException for the JIT compiler.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_new_arithmeticexception(void)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf_utf(utf_java_lang_ArithmeticException,
+ utf_division_by_zero);
+
+ return o;
+}
+
+
+/* exceptions_new_arrayindexoutofboundsexception *******************************
+
+ Generates a java.lang.ArrayIndexOutOfBoundsException for the VM
+ system.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index)
+{
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *s;
+
+ /* convert the index into a String, like Sun does */
+
+ m = class_resolveclassmethod(class_java_lang_String,
+ utf_new_char("valueOf"),
+ utf_new_char("(I)Ljava/lang/String;"),
+ class_java_lang_Object,
+ true);
+
+ if (m == NULL)
+ return exceptions_get_exception();
+
+ s = vm_call_method(m, NULL, index);
+
+ if (s == NULL)
+ return exceptions_get_exception();
+
+ o = exceptions_new_utf_javastring(utf_java_lang_ArrayIndexOutOfBoundsException,
+ s);
+
+ if (o == NULL)
+ return exceptions_get_exception();
+
+ return o;
+}
+
+
+/* exceptions_throw_arrayindexoutofboundsexception *****************************
+
+ Generates and throws a java.lang.ArrayIndexOutOfBoundsException for
+ the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_arrayindexoutofboundsexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_ArrayIndexOutOfBoundsException);
+}
+
+
+/* exceptions_throw_arraystoreexception ****************************************
+
+ Generates and throws a java.lang.ArrayStoreException for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_arraystoreexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_ArrayStoreException);
+}
+
+
+/* exceptions_new_classcastexception *******************************************
+
+ Generates a java.lang.ClassCastException for the JIT compiler.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_new_classcastexception(java_handle_t *o)
+{
+ java_handle_t *e;
+ classinfo *c;
+ utf *classname;
+
+ LLNI_class_get(o, c);
+
+ classname = c->name;
+
+ e = exceptions_new_utf_utf(utf_java_lang_ClassCastException, classname);
+
+ return e;
+}
+
+
+/* exceptions_throw_clonenotsupportedexception *********************************
+
+ Generates and throws a java.lang.CloneNotSupportedException for the
+ VM.
+
+*******************************************************************************/
+
+void exceptions_throw_clonenotsupportedexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_CloneNotSupportedException);
+}
+
+
+/* exceptions_throw_illegalaccessexception *************************************
+
+ Generates and throws a java.lang.IllegalAccessException for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_illegalaccessexception(utf *message)
+{
+ exceptions_throw_utf_utf(utf_java_lang_IllegalAccessException, message);
+}
+
+
+/* exceptions_throw_illegalargumentexception ***********************************
+
+ Generates and throws a java.lang.IllegalArgumentException for the
+ VM.
+
+*******************************************************************************/
+
+void exceptions_throw_illegalargumentexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_IllegalArgumentException);
+}
+
+
+/* exceptions_throw_illegalmonitorstateexception *******************************
+
+ Generates and throws a java.lang.IllegalMonitorStateException for
+ the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_illegalmonitorstateexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_IllegalMonitorStateException);
+}
+
+
+/* exceptions_throw_instantiationexception *************************************
+
+ Generates and throws a java.lang.InstantiationException for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_instantiationexception(classinfo *c)
+{
+ exceptions_throw_utf_utf(utf_java_lang_InstantiationException, c->name);
+}
+
+
+/* exceptions_throw_interruptedexception ***************************************
+
+ Generates and throws a java.lang.InterruptedException for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_interruptedexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_InterruptedException);
+}
+
+
+/* exceptions_throw_invocationtargetexception **********************************
+
+ Generates and throws a java.lang.reflect.InvocationTargetException
+ for the VM.
+
+ IN:
+ cause......cause exception object
+
+*******************************************************************************/
+
+void exceptions_throw_invocationtargetexception(java_handle_t *cause)
+{
+ exceptions_throw_utf_throwable(utf_java_lang_reflect_InvocationTargetException,
+ cause);
+}
+
+
+/* exceptions_throw_negativearraysizeexception *********************************
+
+ Generates and throws a java.lang.NegativeArraySizeException for the
+ VM.
+
+*******************************************************************************/
+
+void exceptions_throw_negativearraysizeexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_NegativeArraySizeException);
+}
+
+
+/* exceptions_new_nullpointerexception *****************************************
+
+ Generates a java.lang.NullPointerException for the VM system.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_new_nullpointerexception(void)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_utf(utf_java_lang_NullPointerException);
+
+ return o;
+}
+
+
+/* exceptions_throw_nullpointerexception ***************************************
+
+ Generates a java.lang.NullPointerException for the VM system and
+ throw it in the VM system.
+
+*******************************************************************************/
+
+void exceptions_throw_nullpointerexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_NullPointerException);
+}
+
+
+/* exceptions_throw_privilegedactionexception **********************************
+
+ Generates and throws a java.security.PrivilegedActionException.
+
+*******************************************************************************/
+
+void exceptions_throw_privilegedactionexception(java_handle_t *exception)
+{
+ exceptions_throw_utf_exception(utf_java_security_PrivilegedActionException,
+ exception);
+}
+
+
+/* exceptions_throw_stringindexoutofboundsexception ****************************
+
+ Generates and throws a java.lang.StringIndexOutOfBoundsException
+ for the VM.
+
+*******************************************************************************/
+
+void exceptions_throw_stringindexoutofboundsexception(void)
+{
+ exceptions_throw_utf(utf_java_lang_StringIndexOutOfBoundsException);
+}
+
+
+/* exceptions_fillinstacktrace *************************************************
+
+ Calls the fillInStackTrace-method of the currently thrown
+ exception.
+
+*******************************************************************************/
+
+java_handle_t *exceptions_fillinstacktrace(void)
+{
+ java_handle_t *o;
+ classinfo *c;
+ methodinfo *m;
+
+ /* get exception */
+
+ o = exceptions_get_and_clear_exception();
+
+ assert(o);
+
+ /* resolve methodinfo pointer from exception object */
+
+ LLNI_class_get(o, c);
+
+#if defined(ENABLE_JAVASE)
+ m = class_resolvemethod(c,
+ utf_fillInStackTrace,
+ utf_void__java_lang_Throwable);
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+ m = class_resolvemethod(c,
+ utf_fillInStackTrace,
+ utf_void__void);
+#else
+#error IMPLEMENT ME!
+#endif
+
+ /* call function */
+
+ (void) vm_call_method(m, o);
+
+ /* return exception object */
+
+ return o;
+}
+
+
+/* exceptions_handle_exception *************************************************
+
+ Try to find an exception handler for the given exception and return it.
+ If no handler is found, exit the monitor of the method (if any)
+ and return NULL.
+
+ IN:
+ xptr.........the exception object
+ xpc..........PC of where the exception was thrown
+ pv...........Procedure Value of the current method
+ sp...........current stack pointer
+
+ RETURN VALUE:
+ the address of the first matching exception handler, or
+ NULL if no handler was found
+
+*******************************************************************************/
+
+#if defined(ENABLE_JIT)
+void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp)
+{
+ stackframeinfo_t sfi;
+ java_handle_t *xptr;
+ methodinfo *m;
+ codeinfo *code;
+ exceptiontable_t *et;
+ exceptiontable_entry_t *ete;
+ s4 i;
+ classref_or_classinfo cr;
+ classinfo *c;
+#if defined(ENABLE_THREADS)
+ java_object_t *o;
+#endif
+ void *result;
+
+#ifdef __S390__
+ /* Addresses are 31 bit integers */
+# define ADDR_MASK(x) (void *) ((uintptr_t) (x) & 0x7FFFFFFF)
+#else
+# define ADDR_MASK(x) (x)
+#endif
+
+ xptr = LLNI_WRAP(xptro);
+ xpc = ADDR_MASK(xpc);
+
+ /* Fill and add a stackframeinfo (XPC is equal to RA). */
+
+ stacktrace_stackframeinfo_add(&sfi, pv, sp, xpc, xpc);
+
+ result = NULL;
+
+ /* Get the codeinfo for the current method. */
+
+ code = code_get_codeinfo_for_pv(pv);
+
+ /* Get the methodinfo pointer from the codeinfo pointer. For
+ asm_vm_call_method the codeinfo pointer is NULL and we simply
+ can return the proper exception handler. */
+
+ if (code == NULL) {
+ result = (void *) (uintptr_t) &asm_vm_call_method_exception_handler;
+ goto exceptions_handle_exception_return;
+ }
+
+ m = code->m;
+
+#if !defined(NDEBUG)
+ /* print exception trace */
+
+ if (opt_TraceExceptions)
+ trace_exception(LLNI_DIRECT(xptr), m, xpc);
+
+# if defined(ENABLE_VMLOG)
+ vmlog_cacao_throw(xptr);
+# endif
+#endif
+
+ /* Get the exception table. */
+
+ et = code->exceptiontable;
+
+ if (et != NULL) {
+ /* Iterate over all exception table entries. */
+
+ ete = et->entries;
+
+ for (i = 0; i < et->length; i++, ete++) {
+ /* is the xpc is the current catch range */
+
+ if ((ADDR_MASK(ete->startpc) <= xpc) && (xpc < ADDR_MASK(ete->endpc))) {
+ cr = ete->catchtype;
+
+ /* NULL catches everything */
+
+ if (cr.any == NULL) {
+#if !defined(NDEBUG)
+ /* Print stacktrace of exception when caught. */
+
+# if defined(ENABLE_VMLOG)
+ vmlog_cacao_catch(xptr);
+# endif
+
+ if (opt_TraceExceptions) {
+ exceptions_print_exception(xptr);
+ stacktrace_print_exception(xptr);
+ }
+#endif
+
+ result = ete->handlerpc;
+ goto exceptions_handle_exception_return;
+ }
+
+ /* resolve or load/link the exception class */
+
+ if (IS_CLASSREF(cr)) {
+ /* The exception class reference is unresolved. */
+ /* We have to do _eager_ resolving here. While the
+ class of the exception object is guaranteed to be
+ loaded, it may well have been loaded by a different
+ loader than the defining loader of m's class, which
+ is the one we must use to resolve the catch
+ class. Thus lazy resolving might fail, even if the
+ result of the resolution would be an already loaded
+ class. */
+
+ c = resolve_classref_eager(cr.ref);
+
+ if (c == NULL) {
+ /* Exception resolving the exception class, argh! */
+ goto exceptions_handle_exception_return;
+ }
+
+ /* Ok, we resolved it. Enter it in the table, so we
+ don't have to do this again. */
+ /* XXX this write should be atomic. Is it? */
+
+ ete->catchtype.cls = c;
+ }
+ else {
+ c = cr.cls;
+
+ /* XXX I don't think this case can ever happen. -Edwin */
+ if (!(c->state & CLASS_LOADED))
+ /* use the methods' classloader */
+ if (!load_class_from_classloader(c->name,
+ m->clazz->classloader))
+ goto exceptions_handle_exception_return;
+
+ /* XXX I think, if it is not linked, we can be sure
+ that the exception object is no (indirect) instance
+ of it, no? -Edwin */
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ goto exceptions_handle_exception_return;
+ }
+
+ /* is the thrown exception an instance of the catch class? */
+
+ if (builtin_instanceof(xptr, c)) {
+#if !defined(NDEBUG)
+ /* Print stacktrace of exception when caught. */
+
+# if defined(ENABLE_VMLOG)
+ vmlog_cacao_catch(xptr);
+# endif
+
+ if (opt_TraceExceptions) {
+ exceptions_print_exception(xptr);
+ stacktrace_print_exception(xptr);
+ }
+#endif
+
+ result = ete->handlerpc;
+ goto exceptions_handle_exception_return;
+ }
+ }
+ }
+ }
+
+#if defined(ENABLE_THREADS)
+ /* Is this method realization synchronized? */
+
+ if (code_is_synchronized(code)) {
+ /* Get synchronization object. */
+
+ o = *((java_object_t **) (((uintptr_t) sp) + code->synchronizedoffset));
+
+ assert(o != NULL);
+
+ lock_monitor_exit(LLNI_QUICKWRAP(o));
+ }
+#endif
+
+ /* none of the exceptions catch this one */
+
+#if !defined(NDEBUG)
+# if defined(ENABLE_VMLOG)
+ vmlog_cacao_unwnd_method(m);
+# endif
+
+# if defined(ENABLE_DEBUG_FILTER)
+ if (show_filters_test_verbosecall_exit(m)) {
+# endif
+
+ /* outdent the log message */
+
+ if (opt_verbosecall) {
+ if (TRACEJAVACALLINDENT)
+ TRACEJAVACALLINDENT--;
+ else
+ log_text("exceptions_handle_exception: WARNING: unmatched unindent");
+ }
+
+# if defined(ENABLE_DEBUG_FILTER)
+ }
+# endif
+#endif /* !defined(NDEBUG) */
+
+ result = NULL;
+
+exceptions_handle_exception_return:
+
+ /* Remove the stackframeinfo. */
+
+ stacktrace_stackframeinfo_remove(&sfi);
+
+ return result;
+}
+#endif /* defined(ENABLE_JIT) */
+
+
+/* exceptions_print_exception **************************************************
+
+ Prints an exception, the detail message and the cause, if
+ available, with CACAO internal functions to stdout.
+
+*******************************************************************************/
+
+void exceptions_print_exception(java_handle_t *xptr)
+{
+ java_lang_Throwable jlt(xptr);
+
+ if (jlt.is_null()) {
+ puts("NULL\n");
+ return;
+ }
+
+#if defined(ENABLE_JAVASE)
+ java_lang_Throwable jltcause(jlt.get_cause());
+#endif
+
+ /* print the root exception */
+
+ classinfo* c = jlt.get_Class();
+ utf_display_printable_ascii_classname(c->name);
+
+ java_lang_String jls(jlt.get_detailMessage());
+
+ if (!jls.is_null()) {
+ utf* u = javastring_toutf(jls.get_handle(), false);
+
+ printf(": ");
+ utf_display_printable_ascii(u);
+ }
+
+ putc('\n', stdout);
+
+#if defined(ENABLE_JAVASE)
+ /* print the cause if available */
+
+ // FIXME cause != t compare with operator override.
+ if ((!jltcause.is_null()) && (jltcause.get_handle() != jlt.get_handle())) {
+ printf("Caused by: ");
+
+ c = jltcause.get_Class();
+ utf_display_printable_ascii_classname(c->name);
+
+ java_lang_String jlscause(jlt.get_detailMessage());
+
+ if (jlscause.get_handle() != NULL) {
+ utf* u = javastring_toutf(jlscause.get_handle(), false);
+
+ printf(": ");
+ utf_display_printable_ascii(u);
+ }
+
+ putc('\n', stdout);
+ }
+#endif
+}
+
+
+/* exceptions_print_current_exception ******************************************
+
+ Prints the current pending exception, the detail message and the
+ cause, if available, with CACAO internal functions to stdout.
+
+*******************************************************************************/
+
+void exceptions_print_current_exception(void)
+{
+ java_handle_t *o;
+
+ o = exceptions_get_exception();
+
+ exceptions_print_exception(o);
+}
+
+
+/* exceptions_print_stacktrace *************************************************
+
+ Prints a pending exception with Throwable.printStackTrace(). If
+ there happens an exception during printStackTrace(), we print the
+ thrown exception and the original one.
+
+ NOTE: This function calls Java code.
+
+*******************************************************************************/
+
+void exceptions_print_stacktrace(void)
+{
+ java_handle_t *e;
+ java_handle_t *ne;
+ classinfo *c;
+ methodinfo *m;
+
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+ java_lang_Thread *to;
+#endif
+
+ /* Get and clear exception because we are calling Java code
+ again. */
+
+ e = exceptions_get_and_clear_exception();
+
+ if (e == NULL)
+ return;
+
+#if 0
+ /* FIXME Enable me. */
+ if (builtin_instanceof(e, class_java_lang_ThreadDeath)) {
+ /* Don't print anything if we are being killed. */
+ }
+ else
+#endif
+ {
+ /* Get the exception class. */
+
+ LLNI_class_get(e, c);
+
+ /* Find the printStackTrace() method. */
+
+ m = class_resolveclassmethod(c,
+ utf_printStackTrace,
+ utf_void__void,
+ class_java_lang_Object,
+ false);
+
+ if (m == NULL)
+ vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+
+ /* Print message. */
+
+ fprintf(stderr, "Exception ");
+
+#if defined(ENABLE_THREADS)
+ /* Print thread name. We get the thread here explicitly as we
+ need it afterwards. */
+
+ t = thread_get_current();
+ to = (java_lang_Thread *) thread_get_object(t);
+
+ if (to != NULL) {
+ fprintf(stderr, "in thread \"");
+ thread_fprint_name(t, stderr);
+ fprintf(stderr, "\" ");
+ }
+#endif
+
+ /* Print the stacktrace. */
+
+ if (builtin_instanceof(e, class_java_lang_Throwable)) {
+ (void) vm_call_method(m, e);
+
+ /* If this happens we are EXTREMLY out of memory or have a
+ serious problem while printStackTrace. But may be
+ another exception, so print it. */
+
+ ne = exceptions_get_exception();
+
+ if (ne != NULL) {
+ fprintf(stderr, "Exception while printStackTrace(): ");
+
+ /* Print the current exception. */
+
+ exceptions_print_exception(ne);
+ stacktrace_print_exception(ne);
+
+ /* Now print the original exception. */
+
+ fprintf(stderr, "Original exception was: ");
+ exceptions_print_exception(e);
+ stacktrace_print_exception(e);
+ }
+ }
+ else {
+ fprintf(stderr, ". Uncaught exception of type ");
+#if !defined(NDEBUG)
+ /* FIXME This prints to stdout. */
+ class_print(c);
+#else
+ fprintf(stderr, "UNKNOWN");
+#endif
+ fprintf(stderr, ".");
+ }
+
+ fflush(stderr);
+ }
+}
+
+} // extern "C"
+
+
+/*
+ * 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/exceptions.h - exception related functions prototypes
-
- 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 _EXCEPTIONS_H
-#define _EXCEPTIONS_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/references.h"
-#include "vmcore/method.h"
-
-
-/* function prototypes ********************************************************/
-
-java_handle_t *exceptions_get_exception(void);
-void exceptions_set_exception(java_handle_t *o);
-void exceptions_clear_exception(void);
-java_handle_t *exceptions_get_and_clear_exception(void);
-
-
-/* functions to generate compiler exceptions */
-
-java_handle_t *exceptions_new_abstractmethoderror(void);
-java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra);
-java_handle_t *exceptions_new_arraystoreexception(void);
-
-void exceptions_throw_abstractmethoderror(void);
-void exceptions_throw_classcircularityerror(classinfo *c);
-void exceptions_throw_classformaterror(classinfo *c, const char *message, ...);
-void exceptions_throw_classnotfoundexception(utf *name);
-void exceptions_throw_noclassdeffounderror(utf *name);
-void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause);
-void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name);
-void exceptions_throw_linkageerror(const char *message, classinfo *c);
-void exceptions_throw_nosuchfielderror(classinfo *c, utf *name);
-void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc);
-void exceptions_throw_exceptionininitializererror(java_handle_t *cause);
-void exceptions_throw_incompatibleclasschangeerror(classinfo *c,
- const char *message);
-void exceptions_throw_instantiationerror(classinfo *c);
-void exceptions_throw_internalerror(const char *message, ...);
-void exceptions_throw_outofmemoryerror(void);
-void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...);
-void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type);
-void exceptions_throw_unsatisfiedlinkerror(utf *name);
-void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi);
-
-java_handle_t *exceptions_new_arithmeticexception(void);
-
-java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index);
-void exceptions_throw_arrayindexoutofboundsexception(void);
-void exceptions_throw_arraystoreexception(void);
-
-java_handle_t *exceptions_new_classcastexception(java_handle_t *o);
-
-void exceptions_throw_clonenotsupportedexception(void);
-void exceptions_throw_illegalaccessexception(utf *message);
-void exceptions_throw_illegalargumentexception(void);
-void exceptions_throw_illegalmonitorstateexception(void);
-void exceptions_throw_interruptedexception(void);
-void exceptions_throw_instantiationexception(classinfo *c);
-void exceptions_throw_invocationtargetexception(java_handle_t *cause);
-void exceptions_throw_negativearraysizeexception(void);
-
-java_handle_t *exceptions_new_nullpointerexception(void);
-void exceptions_throw_nullpointerexception(void);
-void exceptions_throw_privilegedactionexception(java_handle_t *cause);
-void exceptions_throw_stringindexoutofboundsexception(void);
-
-java_handle_t *exceptions_fillinstacktrace(void);
-
-void exceptions_print_exception(java_handle_t *xptr);
-void exceptions_print_current_exception(void);
-void exceptions_print_stacktrace(void);
-
-#endif /* _EXCEPTIONS_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:
- */
--- /dev/null
+/* src/vm/exceptions.hpp - exception related functions prototypes
+
+ 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 _EXCEPTIONS_HPP
+#define _EXCEPTIONS_HPP
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/references.h"
+#include "vm/method.h"
+
+
+/* function prototypes ********************************************************/
+
+java_handle_t *exceptions_get_exception(void);
+void exceptions_set_exception(java_handle_t *o);
+void exceptions_clear_exception(void);
+java_handle_t *exceptions_get_and_clear_exception(void);
+
+
+/* functions to generate compiler exceptions */
+
+java_handle_t *exceptions_new_abstractmethoderror(void);
+java_object_t *exceptions_asm_new_abstractmethoderror(u1 *sp, u1 *ra);
+java_handle_t *exceptions_new_arraystoreexception(void);
+
+void exceptions_throw_abstractmethoderror(void);
+void exceptions_throw_classcircularityerror(classinfo *c);
+void exceptions_throw_classformaterror(classinfo *c, const char *message, ...);
+void exceptions_throw_classnotfoundexception(utf *name);
+void exceptions_throw_noclassdeffounderror(utf *name);
+void exceptions_throw_noclassdeffounderror_cause(java_handle_t *cause);
+void exceptions_throw_noclassdeffounderror_wrong_name(classinfo *c, utf *name);
+void exceptions_throw_linkageerror(const char *message, classinfo *c);
+void exceptions_throw_nosuchfielderror(classinfo *c, utf *name);
+void exceptions_throw_nosuchmethoderror(classinfo *c, utf *name, utf *desc);
+void exceptions_throw_exceptionininitializererror(java_handle_t *cause);
+void exceptions_throw_incompatibleclasschangeerror(classinfo *c,
+ const char *message);
+void exceptions_throw_instantiationerror(classinfo *c);
+void exceptions_throw_internalerror(const char *message, ...);
+void exceptions_throw_outofmemoryerror(void);
+void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...);
+void exceptions_throw_verifyerror_for_stack(methodinfo *m, int type);
+void exceptions_throw_unsatisfiedlinkerror(utf *name);
+void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi);
+
+java_handle_t *exceptions_new_arithmeticexception(void);
+
+java_handle_t *exceptions_new_arrayindexoutofboundsexception(s4 index);
+void exceptions_throw_arrayindexoutofboundsexception(void);
+void exceptions_throw_arraystoreexception(void);
+
+java_handle_t *exceptions_new_classcastexception(java_handle_t *o);
+
+void exceptions_throw_clonenotsupportedexception(void);
+void exceptions_throw_illegalaccessexception(utf *message);
+void exceptions_throw_illegalargumentexception(void);
+void exceptions_throw_illegalmonitorstateexception(void);
+void exceptions_throw_interruptedexception(void);
+void exceptions_throw_instantiationexception(classinfo *c);
+void exceptions_throw_invocationtargetexception(java_handle_t *cause);
+void exceptions_throw_negativearraysizeexception(void);
+
+java_handle_t *exceptions_new_nullpointerexception(void);
+void exceptions_throw_nullpointerexception(void);
+void exceptions_throw_privilegedactionexception(java_handle_t *cause);
+void exceptions_throw_stringindexoutofboundsexception(void);
+
+java_handle_t *exceptions_fillinstacktrace(void);
+
+void exceptions_print_exception(java_handle_t *xptr);
+void exceptions_print_current_exception(void);
+void exceptions_print_stacktrace(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _EXCEPTIONS_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
+/* src/vm/field.c - field 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 <stdint.h>
+#include <stdio.h>
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "vm/types.h"
+
+#include "vm/annotation.h"
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/references.h"
+#include "vm/string.hpp"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/* field_load ******************************************************************
+
+ Load everything about a class field from the class file and fill a
+ fieldinfo structure.
+
+*******************************************************************************/
+
+#define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
+
+bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
+{
+ classinfo *c;
+ u4 attrnum, i;
+ u4 pindex = field_load_NOVALUE; /* constantvalue_index */
+ utf *u;
+
+ /* Get class. */
+
+ c = cb->clazz;
+
+ f->clazz = c;
+
+ /* Get access flags. */
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
+ return false;
+
+ f->flags = suck_u2(cb);
+
+ /* Get name. */
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ f->name = u;
+
+ /* Get descriptor. */
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ f->descriptor = u;
+ f->parseddesc = NULL;
+
+ if (!descriptor_pool_add(descpool, u, NULL))
+ return false;
+
+ /* descriptor_pool_add accepts method descriptors, so we have to
+ check against them here before the call of
+ descriptor_to_basic_type below. */
+
+ if (u->text[0] == '(') {
+ exceptions_throw_classformaterror(c, "Method descriptor used for field");
+ return false;
+ }
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ /* check name */
+ if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
+ exceptions_throw_classformaterror(c,
+ "Illegal Field name \"%s\"",
+ f->name->text);
+ return false;
+ }
+
+ /* check flag consistency */
+ i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
+
+ if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
+ ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
+ exceptions_throw_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
+ return false;
+ }
+
+ if (c->flags & ACC_INTERFACE) {
+ if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
+ != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
+ f->flags & ACC_TRANSIENT) {
+ exceptions_throw_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
+ return false;
+ }
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* data type */
+
+ f->type = descriptor_to_basic_type(f->descriptor);
+
+ /* For static-fields allocate memory for the value and set the
+ value to 0. */
+
+ if (f->flags & ACC_STATIC) {
+ switch (f->type) {
+ case TYPE_INT:
+ case TYPE_LNG:
+ case TYPE_FLT:
+ case TYPE_DBL:
+ f->value = NEW(imm_union);
+ break;
+
+ case TYPE_ADR:
+#if !defined(ENABLE_GC_BOEHM)
+ f->value = NEW(imm_union);
+#else
+ f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
+#endif
+ break;
+
+ default:
+ vm_abort("field_load: invalid field type %d", f->type);
+ }
+
+ /* Set the field to zero, for float and double fields set the
+ correct 0.0 value. */
+
+ switch (f->type) {
+ case TYPE_INT:
+ case TYPE_LNG:
+ case TYPE_ADR:
+ f->value->l = 0;
+ break;
+
+ case TYPE_FLT:
+ f->value->f = 0.0;
+ break;
+
+ case TYPE_DBL:
+ f->value->d = 0.0;
+ break;
+ }
+ }
+ else {
+ /* For instance-fields set the offset to 0. */
+
+ f->offset = 0;
+
+ /* For final fields, which are not static, we need a value
+ structure. */
+
+ if (f->flags & ACC_FINAL) {
+ f->value = NEW(imm_union);
+ /* XXX hack */
+ f->value->l = 0;
+ }
+
+ switch (f->type) {
+ case TYPE_ADR:
+ c->flags |= ACC_CLASS_HAS_POINTERS;
+ break;
+ }
+ }
+
+ /* read attributes */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attrnum = suck_u2(cb);
+
+ for (i = 0; i < attrnum; i++) {
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ if (u == utf_ConstantValue) {
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* check attribute length */
+
+ if (suck_u4(cb) != 2) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* constant value attribute */
+
+ if (pindex != field_load_NOVALUE) {
+ exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
+ return false;
+ }
+
+ /* index of value in constantpool */
+
+ pindex = suck_u2(cb);
+
+ /* initialize field with value from constantpool */
+
+ switch (f->type) {
+ case TYPE_INT: {
+ constant_integer *ci;
+
+ if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
+ return false;
+
+ f->value->i = ci->value;
+ }
+ break;
+
+ case TYPE_LNG: {
+ constant_long *cl;
+
+ if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
+ return false;
+
+ f->value->l = cl->value;
+ }
+ break;
+
+ case TYPE_FLT: {
+ constant_float *cf;
+
+ if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
+ return false;
+
+ f->value->f = cf->value;
+ }
+ break;
+
+ case TYPE_DBL: {
+ constant_double *cd;
+
+ if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
+ return false;
+
+ f->value->d = cd->value;
+ }
+ break;
+
+ case TYPE_ADR:
+ if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
+ return false;
+
+ /* Create Java-string from compressed UTF8-string. */
+
+ f->value->a = literalstring_new(u);
+ break;
+
+ default:
+ vm_abort("field_load: invalid field type %d", f->type);
+ }
+ }
+#if defined(ENABLE_JAVASE)
+ else if (u == utf_Signature) {
+ /* Signature */
+
+ if (!loader_load_attribute_signature(cb, &(f->signature)))
+ return false;
+ }
+
+#if defined(ENABLE_ANNOTATIONS)
+ else if (u == utf_RuntimeVisibleAnnotations) {
+ /* RuntimeVisibleAnnotations */
+ if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
+ return false;
+ }
+ else if (u == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
+ return false;
+ }
+#endif
+#endif
+ else {
+ /* unknown attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+
+ /* everything was ok */
+
+ return true;
+}
+
+
+/* field_get_type **************************************************************
+
+ Returns the type of the field as class.
+
+*******************************************************************************/
+
+classinfo *field_get_type(fieldinfo *f)
+{
+ typedesc *td;
+ utf *u;
+ classinfo *c;
+
+ td = f->parseddesc;
+
+ if (td->type == TYPE_ADR) {
+ assert(td->classref);
+
+ u = td->classref->name;
+
+ /* load the class of the field-type with the field's
+ classloader */
+
+ c = load_class_from_classloader(u, f->clazz->classloader);
+ }
+ else {
+ c = Primitive_get_class_by_type(td->primitivetype);
+ }
+
+ return c;
+}
+
+
+/* field_free ******************************************************************
+
+ Frees a fields' resources.
+
+*******************************************************************************/
+
+void field_free(fieldinfo *f)
+{
+ /* free memory for fields which have a value */
+
+ if (f->value)
+#if defined(ENABLE_GC_BOEHM)
+ if (f->type != TYPE_ADR)
+#endif
+ FREE(f->value, imm_union);
+}
+
+
+/* field_get_annotations ******************************************************
+
+ Get a fields' unparsed annotations in a byte array.
+
+ IN:
+ f........the field of which the annotations should be returned
+
+ RETURN VALUE:
+ The unparsed annotations in a byte array (or NULL if there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* declaring class */
+ int slot; /* slot of this field */
+ java_handle_bytearray_t *annotations; /* unparsed annotations */
+ java_handle_t *field_annotations; /* array of unparsed */
+ /* annotations of all fields of the declaring class */
+
+ c = f->clazz;
+ slot = f - c->fields;
+ annotations = NULL;
+
+ LLNI_classinfo_field_get(c, field_annotations, field_annotations);
+
+ /* the field_annotations array might be shorter then the field
+ * count if the fields above a certain index have no annotations.
+ */
+ if (field_annotations != NULL &&
+ array_length_get(field_annotations) > slot) {
+ annotations = (java_handle_bytearray_t*)array_objectarray_element_get(
+ (java_handle_objectarray_t*)field_annotations, slot);
+ }
+
+ return annotations;
+#else
+ return NULL;
+#endif
+}
+
+
+/* field_printflags ************************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_printflags(fieldinfo *f)
+{
+ if (f == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
+ if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
+ if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
+ if (f->flags & ACC_STATIC) printf(" STATIC");
+ if (f->flags & ACC_FINAL) printf(" FINAL");
+ if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (f->flags & ACC_NATIVE) printf(" NATIVE");
+ if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (f->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+}
+#endif
+
+
+/* field_print *****************************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_print(fieldinfo *f)
+{
+ if (f == NULL) {
+ printf("(fieldinfo*)NULL");
+ return;
+ }
+
+ utf_display_printable_ascii_classname(f->clazz->name);
+ printf(".");
+ utf_display_printable_ascii(f->name);
+ printf(" ");
+ utf_display_printable_ascii(f->descriptor);
+
+ field_printflags(f);
+
+ if (!(f->flags & ACC_STATIC)) {
+ printf(", offset: %d", f->offset);
+ }
+}
+#endif
+
+
+/* field_println ***************************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_println(fieldinfo *f)
+{
+ field_print(f);
+ printf("\n");
+}
+#endif
+
+/* field_fieldref_print ********************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_fieldref_print(constant_FMIref *fr)
+{
+ if (fr == NULL) {
+ printf("(constant_FMIref *)NULL");
+ return;
+ }
+
+ if (IS_FMIREF_RESOLVED(fr)) {
+ printf("<field> ");
+ field_print(fr->p.field);
+ }
+ else {
+ printf("<fieldref> ");
+ utf_display_printable_ascii_classname(fr->p.classref->name);
+ printf(".");
+ utf_display_printable_ascii(fr->name);
+ printf(" ");
+ utf_display_printable_ascii(fr->descriptor);
+ }
+}
+#endif
+
+/* field_fieldref_println ******************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_fieldref_println(constant_FMIref *fr)
+{
+ field_fieldref_print(fr);
+ printf("\n");
+}
+#endif
+
+/*
+ * 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/field.h - field 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 _FIELD_H
+#define _FIELD_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct fieldinfo fieldinfo;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/descriptor.h"
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/references.h"
+#include "vm/utf8.h"
+
+
+/* fieldinfo ******************************************************************/
+
+struct fieldinfo { /* field of a class */
+
+ /* CAUTION: The first field must be a pointer that is never the same */
+ /* value as CLASSREF_PSEUDO_VFTBL! This is used to check whether */
+ /* a constant_FMIref has been resolved. */
+
+ classinfo *clazz; /* needed by typechecker. Could be optimized */
+ /* away by using constant_FMIref instead of */
+ /* fieldinfo throughout the compiler. */
+
+ s4 flags; /* ACC flags */
+ s4 type; /* basic data type */
+ utf *name; /* name of field */
+ utf *descriptor;/* JavaVM descriptor string of field */
+ utf *signature; /* Signature attribute string */
+ typedesc *parseddesc;/* parsed descriptor */
+
+ int32_t offset; /* offset from start of object (instance variables) */
+ imm_union *value; /* storage for static values (class variables) */
+};
+
+
+/* function prototypes ********************************************************/
+
+bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool);
+classinfo *field_get_type(fieldinfo *f);
+void field_free(fieldinfo *f);
+
+java_handle_bytearray_t *field_get_annotations(fieldinfo *f);
+
+#if !defined(NDEBUG)
+void field_printflags(fieldinfo *f);
+void field_print(fieldinfo *f);
+void field_println(fieldinfo *f);
+void field_fieldref_print(constant_FMIref *fr);
+void field_fieldref_println(constant_FMIref *fr);
+#endif
+
+#endif /* _FIELD_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:
+ */
#include "mm/memory.h"
#include "threads/lock-common.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vmcore/options.h"
-
/* global variables ***********************************************************/
/* src/vm/finalizer.h - finalizer linked list and thread header
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#define _FINALIZER_H
#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/types.h"
#include "vm/global.h"
void finalizer_notify(void);
void finalizer_run(void *o, void *p);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _FINALIZER_H */
/* additional data types ******************************************************/
-typedef void *voidptr; /* generic pointer */
typedef void (*functionptr) (void); /* generic function pointer */
typedef u1* methodptr;
#define ACC_METHOD_IMPLEMENTED 0x00020000 /* there is an implementation */
#define ACC_METHOD_MONOMORPHIC 0x00040000 /* currently monomorphic method */
#define ACC_METHOD_EA 0x00080000 /* method being escape analyzed */
+#define ACC_METHOD_MONOMORPHY_USED \
+ 0x00100000
+#define ACC_METHOD_PARENT_MONOMORPHY_USED \
+ 0x00200000
/* data structures of the runtime system **************************************/
--- /dev/null
+/* src/vm/globals.cpp - global variables
+
+ Copyright (C) 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 "vm/class.h"
+
+
+// Classes.
+
+/* Important system classes. */
+
+classinfo *class_java_lang_Object;
+classinfo *class_java_lang_Class;
+classinfo *class_java_lang_ClassLoader;
+classinfo *class_java_lang_Cloneable;
+classinfo *class_java_lang_SecurityManager;
+classinfo *class_java_lang_String;
+classinfo *class_java_lang_System;
+classinfo *class_java_lang_Thread;
+classinfo *class_java_lang_ThreadGroup;
+classinfo *class_java_lang_Throwable;
+classinfo *class_java_io_Serializable;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_java_lang_VMSystem;
+classinfo *class_java_lang_VMThread;
+classinfo *class_java_lang_VMThrowable;
+#endif
+
+/* Important system exceptions. */
+
+classinfo *class_java_lang_Exception;
+classinfo *class_java_lang_ClassNotFoundException;
+classinfo *class_java_lang_RuntimeException;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+classinfo *class_sun_misc_Signal;
+classinfo *class_sun_reflect_MagicAccessorImpl;
+#endif
+
+#if defined(ENABLE_JAVASE)
+classinfo *class_java_lang_Void;
+#endif
+classinfo *class_java_lang_Boolean;
+classinfo *class_java_lang_Byte;
+classinfo *class_java_lang_Character;
+classinfo *class_java_lang_Short;
+classinfo *class_java_lang_Integer;
+classinfo *class_java_lang_Long;
+classinfo *class_java_lang_Float;
+classinfo *class_java_lang_Double;
+
+/* some classes which may be used more often */
+
+#if defined(ENABLE_JAVASE)
+classinfo *class_java_lang_StackTraceElement;
+classinfo *class_java_lang_reflect_Constructor;
+classinfo *class_java_lang_reflect_Field;
+classinfo *class_java_lang_reflect_Method;
+classinfo *class_java_security_PrivilegedAction;
+classinfo *class_java_util_Vector;
+classinfo *class_java_util_HashMap;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_java_lang_reflect_VMConstructor;
+classinfo *class_java_lang_reflect_VMField;
+classinfo *class_java_lang_reflect_VMMethod;
+# endif
+
+classinfo *arrayclass_java_lang_Object;
+
+# if defined(ENABLE_ANNOTATIONS)
+classinfo *class_sun_reflect_ConstantPool;
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_sun_reflect_annotation_AnnotationParser;
+# endif
+# endif
+#endif
+
+/* pseudo classes for the typechecker */
+
+classinfo *pseudo_class_Arraystub;
+classinfo *pseudo_class_Null;
+classinfo *pseudo_class_New;
+
+
+/*
+ * 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/globals.hpp - global variables
+
+ Copyright (C) 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 _GLOBALS_HPP
+#define _GLOBALS_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/class.h"
+
+
+// FIXME For now we export them a C symbols.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Classes.
+
+/* Important system classes. */
+
+extern classinfo *class_java_lang_Object;
+extern classinfo *class_java_lang_Class;
+extern classinfo *class_java_lang_ClassLoader;
+extern classinfo *class_java_lang_Cloneable;
+extern classinfo *class_java_lang_SecurityManager;
+extern classinfo *class_java_lang_String;
+extern classinfo *class_java_lang_System;
+extern classinfo *class_java_lang_Thread;
+extern classinfo *class_java_lang_ThreadGroup;
+extern classinfo *class_java_lang_Throwable;
+extern classinfo *class_java_io_Serializable;
+
+/* Important system exceptions. */
+
+extern classinfo *class_java_lang_Exception;
+extern classinfo *class_java_lang_ClassNotFoundException;
+extern classinfo *class_java_lang_RuntimeException;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern classinfo *class_java_lang_VMSystem;
+extern classinfo *class_java_lang_VMThread;
+extern classinfo *class_java_lang_VMThrowable;
+#endif
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+extern classinfo *class_sun_misc_Signal;
+extern classinfo *class_sun_reflect_MagicAccessorImpl;
+#endif
+
+#if defined(ENABLE_JAVASE)
+extern classinfo *class_java_lang_Void;
+#endif
+
+extern classinfo *class_java_lang_Boolean;
+extern classinfo *class_java_lang_Byte;
+extern classinfo *class_java_lang_Character;
+extern classinfo *class_java_lang_Short;
+extern classinfo *class_java_lang_Integer;
+extern classinfo *class_java_lang_Long;
+extern classinfo *class_java_lang_Float;
+extern classinfo *class_java_lang_Double;
+
+/* some classes which may be used more often */
+
+#if defined(ENABLE_JAVASE)
+extern classinfo *class_java_lang_StackTraceElement;
+extern classinfo *class_java_lang_reflect_Constructor;
+extern classinfo *class_java_lang_reflect_Field;
+extern classinfo *class_java_lang_reflect_Method;
+extern classinfo *class_java_security_PrivilegedAction;
+extern classinfo *class_java_util_Vector;
+extern classinfo *class_java_util_HashMap;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern classinfo *class_java_lang_reflect_VMConstructor;
+extern classinfo *class_java_lang_reflect_VMField;
+extern classinfo *class_java_lang_reflect_VMMethod;
+# endif
+
+extern classinfo *arrayclass_java_lang_Object;
+
+# if defined(ENABLE_ANNOTATIONS)
+extern classinfo *class_sun_reflect_ConstantPool;
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern classinfo *class_sun_reflect_annotation_AnnotationParser;
+# endif
+# endif
+#endif
+
+
+/* pseudo classes for the type checker ****************************************/
+
+/*
+ * pseudo_class_Arraystub
+ * (extends Object implements Cloneable, java.io.Serializable)
+ *
+ * If two arrays of incompatible component types are merged,
+ * the resulting reference has no accessible components.
+ * The result does, however, implement the interfaces Cloneable
+ * and java.io.Serializable. This pseudo class is used internally
+ * to represent such results. (They are *not* considered arrays!)
+ *
+ * pseudo_class_Null
+ *
+ * This pseudo class is used internally to represent the
+ * null type.
+ *
+ * pseudo_class_New
+ *
+ * This pseudo class is used internally to represent the
+ * the 'uninitialized object' type.
+ */
+
+extern classinfo *pseudo_class_Arraystub;
+extern classinfo *pseudo_class_Null;
+extern classinfo *pseudo_class_New;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CLASS_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:
+ */
#include "threads/lock-common.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/asmpart.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
+#include "vm/jit/asmpart.h"
+
/* private functions **********************************************************/
#include "config.h"
-#include "vm/global.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
-#include "vmcore/class.h"
+#include "vm/class.h"
+#include "vm/global.h"
/* function prototypes ********************************************************/
void initialize_init(void);
bool initialize_class(classinfo *c);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _INITIALIZE_H */
--- /dev/null
+/* src/vm/javaobjects.cpp - functions to create and access Java objects
+
+ Copyright (C) 2008 Theobroma Systems Ltd.
+
+ 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 "native/vm/reflection.hpp"
+
+#include "vm/access.h"
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+
+
+#if defined(ENABLE_JAVASE)
+
+/**
+ * Constructs a Java object with the given
+ * java.lang.reflect.Constructor.
+ *
+ * @param args Constructor arguments.
+ *
+ * @return Handle to Java object.
+ */
+java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarray_t* args)
+{
+ methodinfo* m = get_method();
+
+ // Should we bypass security the checks (AccessibleObject)?
+ if (get_override() == false) {
+ /* This method is always called like this:
+ [0] java.lang.reflect.Constructor.constructNative (Native Method)
+ [1] java.lang.reflect.Constructor.newInstance
+ [2] <caller>
+ */
+
+ if (!access_check_method(m, 2))
+ return NULL;
+ }
+
+ // Create a Java object.
+ java_handle_t* h = builtin_new(m->clazz);
+
+ if (h == NULL)
+ return NULL;
+
+ // Call initializer.
+ (void) Reflection::invoke(m, h, args);
+
+ return h;
+}
+
+
+/**
+ * Invokes the given method.
+ *
+ * @param args Method arguments.
+ *
+ * @return return value of the method
+ */
+java_handle_t* java_lang_reflect_Method::invoke(java_handle_t* o, java_handle_objectarray_t* args)
+{
+ methodinfo* m = get_method();
+
+ // Should we bypass security the checks (AccessibleObject)?
+ if (get_override() == false) {
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ /* This method is always called like this:
+ [0] java.lang.reflect.Method.invokeNative (Native Method)
+ [1] java.lang.reflect.Method.invoke (Method.java:329)
+ [2] <caller>
+ */
+
+ if (!access_check_method(m, 2))
+ return NULL;
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* We only pass 1 here as stacktrace_get_caller_class, which
+ is called from access_check_method, skips
+ java.lang.reflect.Method.invoke(). */
+
+ if (!access_check_method(m, 1))
+ return NULL;
+#else
+# error unknown classpath configuration
+#endif
+ }
+
+ // Check if method class is initialized.
+ if (!(m->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(m->clazz))
+ return NULL;
+
+ // Call the Java method.
+ java_handle_t* result = Reflection::invoke(m, o, args);
+
+ return result;
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+ java_handle_t* java_lang_reflect_Constructor_create(methodinfo* m) { return java_lang_reflect_Constructor(m).get_handle(); }
+ java_handle_t* java_lang_reflect_Field_create(fieldinfo* f) { return java_lang_reflect_Field(f).get_handle(); }
+ java_handle_t* java_lang_reflect_Method_create(methodinfo* m) { return java_lang_reflect_Method(m).get_handle(); }
+}
+
+#endif // ENABLE_JAVASE
+
+
+/*
+ * 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/javaobjects.hpp - functions to create and access Java objects
+
+ Copyright (C) 2008 Theobroma Systems Ltd.
+
+ 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 _JAVAOBJECTS_HPP
+#define _JAVAOBJECTS_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "vm/class.h"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/method.h"
+
+
+#ifdef __cplusplus
+
+/**
+ * This class provides low-level functions to access Java object
+ * instance fields.
+ *
+ * These functions do NOT take care about the GC critical section!
+ * Please use FieldAccess wherever possible.
+ */
+class RawFieldAccess {
+protected:
+ template<class T> static inline T raw_get(void* address, const off_t offset);
+ template<class T> static inline void raw_set(void* address, const off_t offset, T value);
+};
+
+
+template<class T> inline T RawFieldAccess::raw_get(void* address, const off_t offset)
+{
+ T* p = (T*) (((uintptr_t) address) + offset);
+ return *p;
+}
+
+
+template<class T> inline void RawFieldAccess::raw_set(void* address, const off_t offset, T value)
+{
+ T* p = (T*) (((uintptr_t) address) + offset);
+ *p = value;
+}
+
+
+/**
+ * This classes provides functions to access Java object instance
+ * fields. These functions enter a critical GC section before
+ * accessing the Java object throught the handle and leave it
+ * afterwards.
+ */
+class FieldAccess : private RawFieldAccess {
+protected:
+ template<class T> static inline T get(java_handle_t* h, const off_t offset);
+ template<class T> static inline void set(java_handle_t* h, const off_t offset, T value);
+};
+
+template<class T> inline T FieldAccess::get(java_handle_t* h, const off_t offset)
+{
+ java_object_t* o;
+ T result;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be _handle->get_object();
+ o = LLNI_UNWRAP(h);
+
+ result = raw_get<T>(o, offset);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+
+ return result;
+}
+
+template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
+{
+ java_object_t* o;
+ java_object_t* result;
+ java_handle_t* hresult;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be _handle->get_object();
+ o = LLNI_UNWRAP(h);
+
+ result = raw_get<java_object_t*>(o, offset);
+
+ hresult = LLNI_WRAP(result);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+
+ return result;
+}
+
+
+template<class T> inline void FieldAccess::set(java_handle_t* h, const off_t offset, T value)
+{
+ java_object_t* o;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be h->get_object();
+ o = LLNI_UNWRAP(h);
+
+ raw_set(o, offset, value);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+}
+
+template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
+{
+ java_object_t* o;
+ java_object_t* ovalue;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be h->get_object();
+ o = LLNI_UNWRAP(h);
+ ovalue = LLNI_UNWRAP(value);
+
+ raw_set(o, offset, ovalue);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+}
+
+
+/**
+ * java/lang/Object
+ *
+ * Object layout:
+ *
+ * 0. object header
+ */
+class java_lang_Object {
+protected:
+ // Handle of Java object.
+ java_handle_t* _handle;
+
+protected:
+ java_lang_Object() : _handle(NULL) {}
+ java_lang_Object(java_handle_t* h) : _handle(h) {}
+ java_lang_Object(jobject h) : _handle((java_handle_t*) h) {}
+ virtual ~java_lang_Object() {}
+
+public:
+ // Getters.
+ virtual inline java_handle_t* get_handle() const { return _handle; }
+ inline vftbl_t* get_vftbl () const;
+ inline classinfo* get_Class () const;
+
+ inline bool is_null () const;
+ inline bool is_non_null() const;
+};
+
+
+inline vftbl_t* java_lang_Object::get_vftbl() const
+{
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be h->get_object();
+ java_object_t* o = LLNI_UNWRAP(_handle);
+ vftbl_t* vftbl = o->vftbl;
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+
+ return vftbl;
+}
+
+inline classinfo* java_lang_Object::get_Class() const
+{
+ return get_vftbl()->clazz;
+}
+
+
+inline bool java_lang_Object::is_null() const
+{
+ return (_handle == NULL);
+}
+
+inline bool java_lang_Object::is_non_null() const
+{
+ return (_handle != NULL);
+}
+
+
+/**
+ * java/lang/Boolean
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean value;
+ */
+class java_lang_Boolean : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Boolean(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline uint8_t get_value();
+ inline void set_value(uint8_t value);
+};
+
+inline uint8_t java_lang_Boolean::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Boolean::set_value(uint8_t value)
+{
+ set(_handle, offset_value, (uint32_t) value);
+}
+
+
+/**
+ * java/lang/Byte
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. byte value;
+ */
+class java_lang_Byte : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Byte(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int8_t get_value();
+ inline void set_value(int8_t value);
+};
+
+inline int8_t java_lang_Byte::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Byte::set_value(int8_t value)
+{
+ set(_handle, offset_value, (int32_t) value);
+}
+
+
+/**
+ * java/lang/Character
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char value;
+ */
+class java_lang_Character : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Character(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline uint16_t get_value();
+ inline void set_value(uint16_t value);
+};
+
+inline uint16_t java_lang_Character::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Character::set_value(uint16_t value)
+{
+ set(_handle, offset_value, (uint32_t) value);
+}
+
+
+/**
+ * java/lang/Short
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. short value;
+ */
+class java_lang_Short : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Short(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int16_t get_value();
+ inline void set_value(int16_t value);
+};
+
+inline int16_t java_lang_Short::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Short::set_value(int16_t value)
+{
+ set(_handle, offset_value, (int32_t) value);
+}
+
+
+/**
+ * java/lang/Integer
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int value;
+ */
+class java_lang_Integer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Integer(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int32_t get_value();
+ inline void set_value(int32_t value);
+};
+
+inline int32_t java_lang_Integer::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Integer::set_value(int32_t value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+/**
+ * java/lang/Long
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. long value;
+ */
+class java_lang_Long : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int64_t));
+
+public:
+ java_lang_Long(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int64_t get_value();
+ inline void set_value(int64_t value);
+};
+
+inline int64_t java_lang_Long::get_value()
+{
+ return get<int64_t>(_handle, offset_value);
+}
+
+inline void java_lang_Long::set_value(int64_t value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+/**
+ * java/lang/Float
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. float value;
+ */
+class java_lang_Float : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(float));
+
+public:
+ java_lang_Float(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline float get_value();
+ inline void set_value(float value);
+};
+
+inline float java_lang_Float::get_value()
+{
+ return get<float>(_handle, offset_value);
+}
+
+inline void java_lang_Float::set_value(float value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+/**
+ * java/lang/Double
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. double value;
+ */
+class java_lang_Double : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(double));
+
+public:
+ java_lang_Double(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline double get_value();
+ inline void set_value(double value);
+};
+
+inline double java_lang_Double::get_value()
+{
+ return get<double>(_handle, offset_value);
+}
+
+inline void java_lang_Double::set_value(double value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+#if defined(ENABLE_JAVASE)
+
+# if defined(ENABLE_ANNOTATIONS)
+/**
+ * OpenJDK sun/reflect/ConstantPool
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object constantPoolOop;
+ */
+class sun_reflect_ConstantPool : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_constantPoolOop = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+
+public:
+ sun_reflect_ConstantPool(java_handle_t* h) : java_lang_Object(h) {}
+ sun_reflect_ConstantPool(java_handle_t* h, jclass constantPoolOop);
+
+ // Setters.
+ inline void set_constantPoolOop(classinfo* value);
+ inline void set_constantPoolOop(jclass value);
+};
+
+
+inline sun_reflect_ConstantPool::sun_reflect_ConstantPool(java_handle_t* h, jclass constantPoolOop) : java_lang_Object(h)
+{
+ set_constantPoolOop(constantPoolOop);
+}
+
+
+inline void sun_reflect_ConstantPool::set_constantPoolOop(classinfo* value)
+{
+ set(_handle, offset_constantPoolOop, value);
+}
+
+inline void sun_reflect_ConstantPool::set_constantPoolOop(jclass value)
+{
+ // XXX jclass is a boxed object.
+ set_constantPoolOop(LLNI_classinfo_unwrap(value));
+}
+# endif // ENABLE_ANNOTATIONS
+
+#endif // ENABLE_JAVASE
+
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+/**
+ * GNU Classpath java/lang/Class
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object[] signers;
+ * 2. java.security.ProtectionDomain pd;
+ * 3. java.lang.Object vmdata;
+ * 4. java.lang.reflect.Constructor constructor;
+ */
+class java_lang_Class : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_signers = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_pd = MEMORY_ALIGN(offset_signers + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_vmdata = MEMORY_ALIGN(offset_pd + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_constructor = MEMORY_ALIGN(offset_vmdata + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Class(java_handle_t* h) : java_lang_Object(h) {}
+
+ // Setters.
+ inline void set_pd(java_handle_t* value);
+ inline void set_pd(jobject value);
+};
+
+inline void java_lang_Class::set_pd(java_handle_t* value)
+{
+ set(_handle, offset_pd, value);
+}
+
+inline void java_lang_Class::set_pd(jobject value)
+{
+ set_pd((java_handle_t*) value);
+}
+
+
+/**
+ * GNU Classpath java/lang/StackTraceElement
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String fileName;
+ * 2. int lineNumber;
+ * 3. java.lang.String declaringClass;
+ * 4. java.lang.String methodName;
+ * 5. boolean isNative;
+ */
+class java_lang_StackTraceElement : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_fileName = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_lineNumber = MEMORY_ALIGN(offset_fileName + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_declaringClass = MEMORY_ALIGN(offset_lineNumber + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_methodName = MEMORY_ALIGN(offset_declaringClass + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_isNative = MEMORY_ALIGN(offset_methodName + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_StackTraceElement(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_StackTraceElement(java_handle_t* h, java_handle_t* fileName, int32_t lineNumber, java_handle_t* declaringClass, java_handle_t* methodName, uint8_t isNative);
+};
+
+inline java_lang_StackTraceElement::java_lang_StackTraceElement(java_handle_t* h, java_handle_t* fileName, int32_t lineNumber, java_handle_t* declaringClass, java_handle_t* methodName, uint8_t isNative) : java_lang_Object(h)
+{
+ java_lang_StackTraceElement((java_handle_t*) h);
+
+ set(_handle, offset_fileName, fileName);
+ set(_handle, offset_lineNumber, lineNumber);
+ set(_handle, offset_declaringClass, declaringClass);
+ set(_handle, offset_methodName, methodName);
+ set(_handle, offset_isNative, isNative);
+}
+
+
+/**
+ * GNU Classpath java/lang/String
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] value;
+ * 2. int count;
+ * 3. int cachedHashCode;
+ * 4. int offset;
+ */
+class java_lang_String : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_count = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_cachedHashCode = MEMORY_ALIGN(offset_count + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_offset = MEMORY_ALIGN(offset_cachedHashCode + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_String(jstring h);
+ java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
+
+ // Getters.
+ inline java_handle_chararray_t* get_value () const;
+ inline int32_t get_count () const;
+ inline int32_t get_offset() const;
+
+ // Setters.
+ inline void set_value (java_handle_chararray_t* value);
+ inline void set_count (int32_t value);
+ inline void set_offset(int32_t value);
+};
+
+inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
+{
+ java_lang_String((java_handle_t*) h);
+}
+
+inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
+{
+ set_value(value);
+ set_count(count);
+ set_offset(offset);
+}
+
+inline java_handle_chararray_t* java_lang_String::get_value() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_value);
+}
+
+inline int32_t java_lang_String::get_count() const
+{
+ return get<int32_t>(_handle, offset_count);
+}
+
+inline int32_t java_lang_String::get_offset() const
+{
+ return get<int32_t>(_handle, offset_offset);
+}
+
+inline void java_lang_String::set_value(java_handle_chararray_t* value)
+{
+ set(_handle, offset_value, value);
+}
+
+inline void java_lang_String::set_count(int32_t value)
+{
+ set(_handle, offset_count, value);
+}
+
+inline void java_lang_String::set_offset(int32_t value)
+{
+ set(_handle, offset_offset, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/Thread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.VMThread vmThread;
+ * 2. java.lang.ThreadGroup group;
+ * 3. java.lang.Runnable runnable;
+ * 4. java.lang.String name;
+ * 5. boolean daemon;
+ * 6. int priority;
+ * 7. long stacksize;
+ * 8. java.lang.Throwable stillborn;
+ * 9. java.lang.ClassLoader contextClassLoader;
+ * 10. boolean contextClassLoaderIsSystemClassLoader;
+ * 11. long threadId;
+ * 12. java.lang.Object parkBlocker;
+ * 13. gnu.java.util.WeakIdentityHashMap locals;
+ * 14. java_lang_Thread_UncaughtExceptionHandler exceptionHandler;
+ */
+class java_lang_Thread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_vmThread = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_group = MEMORY_ALIGN(offset_vmThread + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_runnable = MEMORY_ALIGN(offset_group + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_name = MEMORY_ALIGN(offset_runnable + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_daemon = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_priority = MEMORY_ALIGN(offset_daemon + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_stacksize = MEMORY_ALIGN(offset_priority + sizeof(int32_t), sizeof(int64_t));
+ static const off_t offset_stillborn = MEMORY_ALIGN(offset_stacksize + sizeof(int64_t), SIZEOF_VOID_P);
+ static const off_t offset_contextClassLoader = MEMORY_ALIGN(offset_stillborn + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_contextClassLoaderIsSystemClassLoader = MEMORY_ALIGN(offset_contextClassLoader + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_threadId = MEMORY_ALIGN(offset_contextClassLoaderIsSystemClassLoader + sizeof(int32_t), sizeof(int64_t));
+ static const off_t offset_parkBlocker = MEMORY_ALIGN(offset_threadId + sizeof(int64_t), SIZEOF_VOID_P);
+ static const off_t offset_locals = MEMORY_ALIGN(offset_parkBlocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_exceptionHandler = MEMORY_ALIGN(offset_locals + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
+// java_lang_Thread(threadobject* t);
+
+ // Getters.
+ inline java_handle_t* get_vmThread () const;
+ inline java_handle_t* get_group () const;
+ inline java_handle_t* get_name () const;
+ inline int32_t get_daemon () const;
+ inline int32_t get_priority () const;
+ inline java_handle_t* get_exceptionHandler() const;
+
+ // Setters.
+ inline void set_group(java_handle_t* value);
+};
+
+
+// inline java_lang_Thread::java_lang_Thread(threadobject* t) : java_lang_Object(h)
+// {
+// java_lang_Thread(thread_get_object(t));
+// }
+
+
+inline java_handle_t* java_lang_Thread::get_vmThread() const
+{
+ return get<java_handle_t*>(_handle, offset_vmThread);
+}
+
+inline java_handle_t* java_lang_Thread::get_group() const
+{
+ return get<java_handle_t*>(_handle, offset_group);
+}
+
+inline java_handle_t* java_lang_Thread::get_name() const
+{
+ return get<java_handle_t*>(_handle, offset_name);
+}
+
+inline int32_t java_lang_Thread::get_daemon() const
+{
+ return get<int32_t>(_handle, offset_daemon);
+}
+
+inline int32_t java_lang_Thread::get_priority() const
+{
+ return get<int32_t>(_handle, offset_priority);
+}
+
+inline java_handle_t* java_lang_Thread::get_exceptionHandler() const
+{
+ return get<java_handle_t*>(_handle, offset_exceptionHandler);
+}
+
+
+inline void java_lang_Thread::set_group(java_handle_t* value)
+{
+ set(_handle, offset_group, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/VMThread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Thread thread;
+ * 2. boolean running;
+ * 3. java.lang.VMThread vmdata;
+ */
+class java_lang_VMThread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_thread = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_running = MEMORY_ALIGN(offset_thread + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_vmdata = MEMORY_ALIGN(offset_running + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_lang_VMThread(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_VMThread(jobject h);
+ java_lang_VMThread(java_handle_t* h, java_handle_t* thread, threadobject* vmdata);
+
+ // Getters.
+ inline java_handle_t* get_thread() const;
+ inline threadobject* get_vmdata() const;
+
+ // Setters.
+ inline void set_thread(java_handle_t* value);
+ inline void set_vmdata(threadobject* value);
+};
+
+
+inline java_lang_VMThread::java_lang_VMThread(jobject h) : java_lang_Object(h)
+{
+ java_lang_VMThread((java_handle_t*) h);
+}
+
+inline java_lang_VMThread::java_lang_VMThread(java_handle_t* h, java_handle_t* thread, threadobject* vmdata) : java_lang_Object(h)
+{
+ set_thread(thread);
+ set_vmdata(vmdata);
+}
+
+
+inline java_handle_t* java_lang_VMThread::get_thread() const
+{
+ return get<java_handle_t*>(_handle, offset_thread);
+}
+
+inline threadobject* java_lang_VMThread::get_vmdata() const
+{
+ return get<threadobject*>(_handle, offset_vmdata);
+}
+
+
+inline void java_lang_VMThread::set_thread(java_handle_t* value)
+{
+ set(_handle, offset_thread, value);
+}
+
+inline void java_lang_VMThread::set_vmdata(threadobject* value)
+{
+ set(_handle, offset_vmdata, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/Throwable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String detailMessage;
+ * 2. java.lang.Throwable cause;
+ * 3. java.lang.StackTraceElement[] stackTrace;
+ * 4. java.lang.VMThrowable vmState;
+ */
+class java_lang_Throwable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_detailMessage = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_cause = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stackTrace = MEMORY_ALIGN(offset_cause + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_vmState = MEMORY_ALIGN(offset_stackTrace + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
+
+ // Getters.
+ inline java_handle_t* get_detailMessage() const;
+ inline java_handle_t* get_cause () const;
+ inline java_handle_t* get_vmState () const;
+};
+
+
+inline java_handle_t* java_lang_Throwable::get_detailMessage() const
+{
+ return get<java_handle_t*>(_handle, offset_detailMessage);
+}
+
+inline java_handle_t* java_lang_Throwable::get_cause() const
+{
+ return get<java_handle_t*>(_handle, offset_cause);
+}
+
+inline java_handle_t* java_lang_Throwable::get_vmState() const
+{
+ return get<java_handle_t*>(_handle, offset_vmState);
+}
+
+
+/**
+ * GNU Classpath java/lang/VMThrowable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object vmdata;
+ */
+class java_lang_VMThrowable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_vmdata = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+
+public:
+ java_lang_VMThrowable(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_VMThrowable(jobject h);
+
+ inline java_handle_bytearray_t* get_vmdata() const;
+ inline void set_vmdata(java_handle_bytearray_t* value);
+};
+
+inline java_lang_VMThrowable::java_lang_VMThrowable(jobject h) : java_lang_Object(h)
+{
+ java_lang_VMThrowable((java_handle_t*) h);
+}
+
+inline java_handle_bytearray_t* java_lang_VMThrowable::get_vmdata() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_vmdata);
+}
+
+inline void java_lang_VMThrowable::set_vmdata(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_vmdata, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/VMConstructor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Class clazz;
+ * 2. int slot;
+ * 3. byte[] annotations;
+ * 4. byte[] parameterAnnotations;
+ * 5. java.util.Map declaredAnnotations;
+ * 6. java.lang.reflect.Constructor cons;
+ */
+class java_lang_reflect_VMConstructor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_cons = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_VMConstructor(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_VMConstructor(jobject h);
+ java_lang_reflect_VMConstructor(methodinfo* m);
+
+ // Getters.
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_bytearray_t* get_parameterAnnotations() const;
+ inline java_handle_t* get_declaredAnnotations () const;
+ inline java_handle_t* get_cons () const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_slot (int32_t value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_parameterAnnotations(java_handle_bytearray_t* value);
+ inline void set_declaredAnnotations (java_handle_t* value);
+ inline void set_cons (java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method();
+};
+
+
+inline java_lang_reflect_VMConstructor::java_lang_reflect_VMConstructor(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_VMConstructor((java_handle_t*) h);
+}
+
+inline java_lang_reflect_VMConstructor::java_lang_reflect_VMConstructor(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_VMConstructor);
+
+ if (is_null())
+ return;
+
+ int slot = m - m->clazz->methods;
+ java_handle_bytearray_t* annotations = method_get_annotations(m);
+ java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
+
+ set_clazz(m->clazz);
+ set_slot(slot);
+ set_annotations(annotations);
+ set_parameterAnnotations(parameterAnnotations);
+}
+
+
+inline classinfo* java_lang_reflect_VMConstructor::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_VMConstructor::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMConstructor::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMConstructor::get_parameterAnnotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMConstructor::get_declaredAnnotations() const
+{
+ return get<java_handle_t*>(_handle, offset_declaredAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMConstructor::get_cons() const
+{
+ return get<java_handle_t*>(_handle, offset_cons);
+}
+
+inline void java_lang_reflect_VMConstructor::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_parameterAnnotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_parameterAnnotations, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_declaredAnnotations(java_handle_t* value)
+{
+ set(_handle, offset_declaredAnnotations, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_cons(java_handle_t* value)
+{
+ set(_handle, offset_cons, value);
+}
+
+inline methodinfo* java_lang_reflect_VMConstructor::get_method()
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/Constructor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean flag;
+ * 2. gnu.java.lang.reflect.MethodSignatureParser p;
+ * 3. java.lang.reflect.VMConstructor cons;
+ */
+class java_lang_reflect_Constructor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_cons = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Constructor(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Constructor(jobject h);
+ java_lang_reflect_Constructor(methodinfo* m);
+
+ java_handle_t* new_instance(java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_flag() const;
+ inline java_handle_t* get_cons() const;
+
+ // Setters.
+ inline void set_cons(java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method () const;
+ inline int32_t get_override() const;
+};
+
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Constructor((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(methodinfo* m)
+{
+ java_lang_reflect_VMConstructor jlrvmc(m);
+
+ if (jlrvmc.is_null())
+ return;
+
+ _handle = builtin_new(class_java_lang_reflect_Constructor);
+
+ if (is_null())
+ return;
+
+ // Link the two Java objects.
+ set_cons(jlrvmc.get_handle());
+ jlrvmc.set_cons(get_handle());
+}
+
+
+inline int32_t java_lang_reflect_Constructor::get_flag() const
+{
+ return get<int32_t>(_handle, offset_flag);
+}
+
+inline java_handle_t* java_lang_reflect_Constructor::get_cons() const
+{
+ return get<java_handle_t*>(_handle, offset_cons);
+}
+
+
+inline void java_lang_reflect_Constructor::set_cons(java_handle_t* value)
+{
+ set(_handle, offset_cons, value);
+}
+
+
+inline methodinfo* java_lang_reflect_Constructor::get_method() const
+{
+ java_lang_reflect_VMConstructor jlrvmc(get_cons());
+ return jlrvmc.get_method();
+}
+
+inline int32_t java_lang_reflect_Constructor::get_override() const
+{
+ return get_flag();
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/VMField
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Class clazz;
+ * 2. java.lang.String name;
+ * 3. int slot;
+ * 4. byte[] annotations;
+ * 5. java.lang.Map declaredAnnotations;
+ * 6. java.lang.reflect.Field f;
+ */
+class java_lang_reflect_VMField : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_name = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_f = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_VMField(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_VMField(jobject h);
+ java_lang_reflect_VMField(fieldinfo* f);
+
+ // Getters.
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_t* get_declaredAnnotations() const;
+ inline java_handle_t* get_f () const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_name (java_handle_t* value);
+ inline void set_slot (int32_t value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_declaredAnnotations(java_handle_t* value);
+ inline void set_f (java_handle_t* value);
+
+ // Convenience functions.
+ inline fieldinfo* get_field() const;
+};
+
+
+inline java_lang_reflect_VMField::java_lang_reflect_VMField(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_VMField((java_handle_t*) h);
+}
+
+inline java_lang_reflect_VMField::java_lang_reflect_VMField(fieldinfo* f)
+{
+ _handle = builtin_new(class_java_lang_reflect_VMField);
+
+ if (is_null())
+ return;
+
+ java_handle_t* name = javastring_intern(javastring_new(f->name));
+ int slot = f - f->clazz->fields;
+ java_handle_bytearray_t* annotations = field_get_annotations(f);
+
+ set_clazz(f->clazz);
+ set_name(name);
+ set_slot(slot);
+ set_annotations(annotations);
+}
+
+
+inline classinfo* java_lang_reflect_VMField::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_VMField::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMField::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMField::get_declaredAnnotations() const
+{
+ return get<java_handle_t*>(_handle, offset_declaredAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMField::get_f() const
+{
+ return get<java_handle_t*>(_handle, offset_f);
+}
+
+
+inline void java_lang_reflect_VMField::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_VMField::set_name(java_handle_t* value)
+{
+ set(_handle, offset_name, value);
+}
+
+inline void java_lang_reflect_VMField::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_VMField::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_VMField::set_declaredAnnotations(java_handle_t* value)
+{
+ set(_handle, offset_declaredAnnotations, value);
+}
+
+inline void java_lang_reflect_VMField::set_f(java_handle_t* value)
+{
+ set(_handle, offset_f, value);
+}
+
+inline fieldinfo* java_lang_reflect_VMField::get_field() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ fieldinfo* f = &(c->fields[slot]);
+ return f;
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/Field
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean flag;
+ * 2. gnu.java.lang.reflect.FieldSignatureParser p;
+ * 3. java.lang.reflect.VMField f;
+ */
+class java_lang_reflect_Field : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_f = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Field(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Field(jobject h);
+ java_lang_reflect_Field(fieldinfo* f);
+
+ // Getters.
+ inline int32_t get_flag() const;
+ inline java_handle_t* get_f() const;
+
+ // Setters.
+ inline void set_f(java_handle_t* value);
+
+ // Convenience functions.
+ inline fieldinfo* get_field() const;
+};
+
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Field((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(fieldinfo* f)
+{
+ java_lang_reflect_VMField jlrvmf(f);
+
+ if (jlrvmf.is_null())
+ return;
+
+ _handle = builtin_new(class_java_lang_reflect_Field);
+
+ if (is_null())
+ return;
+
+ // Link the two Java objects.
+ set_f(jlrvmf.get_handle());
+ jlrvmf.set_f(get_handle());
+}
+
+
+inline int32_t java_lang_reflect_Field::get_flag() const
+{
+ return get<int32_t>(_handle, offset_flag);
+}
+
+inline java_handle_t* java_lang_reflect_Field::get_f() const
+{
+ return get<java_handle_t*>(_handle, offset_f);
+}
+
+
+inline void java_lang_reflect_Field::set_f(java_handle_t* value)
+{
+ set(_handle, offset_f, value);
+}
+
+
+inline fieldinfo* java_lang_reflect_Field::get_field() const
+{
+ java_lang_reflect_VMField jlrvmf(get_f());
+ return jlrvmf.get_field();
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/VMMethod
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Class clazz;
+ * 2. java.lang.String name;
+ * 3. int slot;
+ * 4. byte[] annotations;
+ * 5. byte[] parameterAnnotations;
+ * 6. byte[] annotationDefault;
+ * 7. java.lang.Map declaredAnnotations;
+ * 8. java.lang.reflect.Method m;
+ */
+class java_lang_reflect_VMMethod : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_name = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotationDefault = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_annotationDefault + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_m = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_VMMethod(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_VMMethod(jobject h);
+ java_lang_reflect_VMMethod(methodinfo* m);
+
+ // Getters.
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_bytearray_t* get_parameterAnnotations() const;
+ inline java_handle_bytearray_t* get_annotationDefault () const;
+ inline java_handle_t* get_declaredAnnotations () const;
+ inline java_handle_t* get_m () const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_name (java_handle_t* value);
+ inline void set_slot (int32_t value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_parameterAnnotations(java_handle_bytearray_t* value);
+ inline void set_annotationDefault (java_handle_bytearray_t* value);
+ inline void set_declaredAnnotations (java_handle_t* value);
+ inline void set_m (java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method() const;
+};
+
+inline java_lang_reflect_VMMethod::java_lang_reflect_VMMethod(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_VMMethod((java_handle_t*) h);
+}
+
+inline java_lang_reflect_VMMethod::java_lang_reflect_VMMethod(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_VMMethod);
+
+ if (is_null())
+ return;
+
+ java_handle_t* name = javastring_intern(javastring_new(m->name));
+ int slot = m - m->clazz->methods;
+ java_handle_bytearray_t* annotations = method_get_annotations(m);
+ java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
+ java_handle_bytearray_t* annotationDefault = method_get_annotationdefault(m);
+
+ set_clazz(m->clazz);
+ set_name(name);
+ set_slot(slot);
+ set_annotations(annotations);
+ set_parameterAnnotations(parameterAnnotations);
+ set_annotationDefault(annotationDefault);
+}
+
+inline classinfo* java_lang_reflect_VMMethod::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_VMMethod::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_parameterAnnotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_annotationDefault() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotationDefault);
+}
+
+inline java_handle_t* java_lang_reflect_VMMethod::get_declaredAnnotations() const
+{
+ return get<java_handle_t*>(_handle, offset_declaredAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMMethod::get_m() const
+{
+ return get<java_handle_t*>(_handle, offset_m);
+}
+
+inline void java_lang_reflect_VMMethod::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_name(java_handle_t* value)
+{
+ set(_handle, offset_name, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_parameterAnnotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_parameterAnnotations, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_annotationDefault(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotationDefault, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_declaredAnnotations(java_handle_t* value)
+{
+ set(_handle, offset_declaredAnnotations, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_m(java_handle_t* value)
+{
+ set(_handle, offset_m, value);
+}
+
+inline methodinfo* java_lang_reflect_VMMethod::get_method() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/Method
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean flag;
+ * 2. gnu.java.lang.reflect.MethodSignatureParser p;
+ * 3. java.lang.reflect.VMMethod m;
+ */
+class java_lang_reflect_Method : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_m = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Method(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Method(jobject h);
+ java_lang_reflect_Method(methodinfo* m);
+
+ java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_flag() const;
+ inline java_handle_t* get_m() const;
+
+ // Setters.
+ inline void set_m(java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method () const;
+ inline int32_t get_override() const;
+};
+
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Method((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(methodinfo* m)
+{
+ java_lang_reflect_VMMethod jlrvmm(m);
+
+ if (jlrvmm.is_null())
+ return;
+
+ _handle = builtin_new(class_java_lang_reflect_Method);
+
+ if (is_null())
+ return;
+
+ // Link the two Java objects.
+ set_m(jlrvmm.get_handle());
+ jlrvmm.set_m(get_handle());
+}
+
+
+inline int32_t java_lang_reflect_Method::get_flag() const
+{
+ return get<int32_t>(_handle, offset_flag);
+}
+
+inline java_handle_t* java_lang_reflect_Method::get_m() const
+{
+ return get<java_handle_t*>(_handle, offset_m);
+}
+
+
+inline void java_lang_reflect_Method::set_m(java_handle_t* value)
+{
+ set(_handle, offset_m, value);
+}
+
+
+inline methodinfo* java_lang_reflect_Method::get_method() const
+{
+ java_lang_reflect_VMMethod jlrvmm(get_m());
+ return jlrvmm.get_method();
+}
+
+inline int32_t java_lang_reflect_Method::get_override() const
+{
+ return get_flag();
+}
+
+
+/**
+ * GNU Classpath java/nio/Buffer
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int cap;
+ * 2. int limit;
+ * 3. int pos;
+ * 4. int mark;
+ * 5. gnu.classpath.Pointer address;
+ */
+class java_nio_Buffer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_cap = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_limit = MEMORY_ALIGN(offset_cap + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_pos = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_mark = MEMORY_ALIGN(offset_pos + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_address = MEMORY_ALIGN(offset_mark + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
+
+ // Getters.
+ inline int32_t get_cap() const;
+};
+
+inline int32_t java_nio_Buffer::get_cap() const
+{
+ return get<int32_t>(_handle, offset_cap);
+}
+
+
+/**
+ * GNU Classpath java/nio/DirectByteBufferImpl
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int cap;
+ * 2. int limit;
+ * 3. int pos;
+ * 4. int mark;
+ * 5. gnu.classpath.Pointer address;
+ * 6. java.nio.ByteOrder endian;
+ * 7. byte[] backing_buffer;
+ * 8. int array_offset;
+ * 9. java.lang.Object owner;
+ */
+class java_nio_DirectByteBufferImpl : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_cap = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_limit = MEMORY_ALIGN(offset_cap + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_pos = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_mark = MEMORY_ALIGN(offset_pos + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_address = MEMORY_ALIGN(offset_mark + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_endian = MEMORY_ALIGN(offset_address + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_backing_buffer = MEMORY_ALIGN(offset_endian + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_array_offset = MEMORY_ALIGN(offset_backing_buffer + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_owner = MEMORY_ALIGN(offset_array_offset + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_nio_DirectByteBufferImpl(java_handle_t* h) : java_lang_Object(h) {}
+ java_nio_DirectByteBufferImpl(jobject h);
+
+ // Getters.
+ inline java_handle_t* get_address() const;
+};
+
+inline java_nio_DirectByteBufferImpl::java_nio_DirectByteBufferImpl(jobject h) : java_lang_Object(h)
+{
+ java_nio_DirectByteBufferImpl((java_handle_t*) h);
+}
+
+inline java_handle_t* java_nio_DirectByteBufferImpl::get_address() const
+{
+ return get<java_handle_t*>(_handle, offset_address);
+}
+
+
+/**
+ * GNU Classpath gnu/classpath/Pointer
+ *
+ * Actually there are two classes, gnu.classpath.Pointer32 and
+ * gnu.classpath.Pointer64, but we only define the abstract super
+ * class and use the int/long field as void* type.
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int/long data;
+ */
+class gnu_classpath_Pointer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_data = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+
+public:
+ gnu_classpath_Pointer(java_handle_t* h) : java_lang_Object(h) {}
+ gnu_classpath_Pointer(java_handle_t* h, void* data);
+
+ // Setters.
+ inline void* get_data() const;
+
+ // Setters.
+ inline void set_data(void* value);
+};
+
+inline gnu_classpath_Pointer::gnu_classpath_Pointer(java_handle_t* h, void* data) : java_lang_Object(h)
+{
+ set_data(data);
+}
+
+inline void* gnu_classpath_Pointer::get_data() const
+{
+ return get<void*>(_handle, offset_data);
+}
+
+inline void gnu_classpath_Pointer::set_data(void* value)
+{
+ set(_handle, offset_data, value);
+}
+
+#endif // WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH
+
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+/**
+ * OpenJDK java/lang/AssertionStatusDirectives
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String[] classes;
+ * 2. boolean[] classEnabled;
+ * 3. java.lang.String[] packages;
+ * 4. boolean[] packageEnabled;
+ * 5. boolean deflt;
+ */
+class java_lang_AssertionStatusDirectives : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_classes = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_classEnabled = MEMORY_ALIGN(offset_classes + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_packages = MEMORY_ALIGN(offset_classEnabled + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_packageEnabled = MEMORY_ALIGN(offset_packages + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_deflt = MEMORY_ALIGN(offset_packageEnabled + SIZEOF_VOID_P, sizeof(int32_t));
+
+public:
+ java_lang_AssertionStatusDirectives(java_handle_objectarray_t* classes, java_handle_booleanarray_t* classEnabled, java_handle_objectarray_t* packages, java_handle_booleanarray_t* packageEnabled);
+};
+
+inline java_lang_AssertionStatusDirectives::java_lang_AssertionStatusDirectives(java_handle_objectarray_t* classes, java_handle_booleanarray_t* classEnabled, java_handle_objectarray_t* packages, java_handle_booleanarray_t* packageEnabled)
+{
+ classinfo* c = load_class_bootstrap(utf_new_char("java/lang/AssertionStatusDirectives"));
+
+ // FIXME Load the class at VM startup.
+ if (c == NULL)
+ return;
+
+ _handle = builtin_new(c);
+
+ if (is_null())
+ return;
+
+ set(_handle, offset_classes, classes);
+ set(_handle, offset_classEnabled, classEnabled);
+ set(_handle, offset_packages, packages);
+ set(_handle, offset_packageEnabled, packageEnabled);
+}
+
+
+/**
+ * OpenJDK java/lang/StackTraceElement
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String declaringClass;
+ * 2. java.lang.String methodName;
+ * 3. java.lang.String fileName;
+ * 4. int lineNumber;
+ */
+class java_lang_StackTraceElement : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_declaringClass = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_methodName = MEMORY_ALIGN(offset_declaringClass + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_fileName = MEMORY_ALIGN(offset_methodName + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_lineNumber = MEMORY_ALIGN(offset_fileName + SIZEOF_VOID_P, sizeof(int32_t));
+
+public:
+ java_lang_StackTraceElement(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_StackTraceElement(java_handle_t* declaringClass, java_handle_t* methodName, java_handle_t* fileName, int32_t lineNumber);
+};
+
+inline java_lang_StackTraceElement::java_lang_StackTraceElement(java_handle_t* declaringClass, java_handle_t* methodName, java_handle_t* fileName, int32_t lineNumber)
+{
+ _handle = builtin_new(class_java_lang_StackTraceElement);
+
+ if (is_null())
+ return;
+
+ set(_handle, offset_declaringClass, declaringClass);
+ set(_handle, offset_methodName, methodName);
+ set(_handle, offset_fileName, fileName);
+ set(_handle, offset_lineNumber, lineNumber);
+}
+
+
+/**
+ * OpenJDK java/lang/String
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] value;
+ * 2. int offset;
+ * 3. int count;
+ * 4. int hash;
+ */
+class java_lang_String : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_offset = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_count = MEMORY_ALIGN(offset_offset + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_hash = MEMORY_ALIGN(offset_count + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_String(jstring h);
+ java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
+
+ // Getters.
+ inline java_handle_chararray_t* get_value () const;
+ inline int32_t get_offset() const;
+ inline int32_t get_count () const;
+
+ // Setters.
+ inline void set_value (java_handle_chararray_t* value);
+ inline void set_offset(int32_t value);
+ inline void set_count (int32_t value);
+};
+
+inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
+{
+ java_lang_String((java_handle_t*) h);
+}
+
+inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
+{
+ set_value(value);
+ set_offset(offset);
+ set_count(count);
+}
+
+inline java_handle_chararray_t* java_lang_String::get_value() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_value);
+}
+
+inline int32_t java_lang_String::get_offset() const
+{
+ return get<int32_t>(_handle, offset_offset);
+}
+
+inline int32_t java_lang_String::get_count() const
+{
+ return get<int32_t>(_handle, offset_count);
+}
+
+inline void java_lang_String::set_value(java_handle_chararray_t* value)
+{
+ set(_handle, offset_value, value);
+}
+
+inline void java_lang_String::set_offset(int32_t value)
+{
+ set(_handle, offset_offset, value);
+}
+
+inline void java_lang_String::set_count(int32_t value)
+{
+ set(_handle, offset_count, value);
+}
+
+
+/**
+ * OpenJDK java/lang/Thread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] name;
+ * 2. int priority;
+ * 3. java_lang_Thread threadQ;
+ * 4. long eetop;
+ * 5. boolean single_step;
+ * 6. boolean daemon;
+ * 7. boolean stillborn;
+ * 8. java_lang_Runnable target;
+ * 9. java_lang_ThreadGroup group;
+ * 10. java_lang_ClassLoader contextClassLoader;
+ * 11. java_security_AccessControlContext inheritedAccessControlContext;
+ * 12. java_lang_ThreadLocal_ThreadLocalMap threadLocals;
+ * 13. java_lang_ThreadLocal_ThreadLocalMap inheritableThreadLocals;
+ * 14. long stackSize;
+ * 15. long nativeParkEventPointer;
+ * 16. long tid;
+ * 17. int threadStatus;
+ * 18. java_lang_Object parkBlocker;
+ * 19. sun_nio_ch_Interruptible blocker;
+ * 20. java_lang_Object blockerLock;
+ * 21. boolean stopBeforeStart;
+ * 22. java_lang_Throwable throwableFromStop;
+ * 23. java.lang.Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
+ */
+class java_lang_Thread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_name = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_priority = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_threadQ = MEMORY_ALIGN(offset_priority + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_eetop = MEMORY_ALIGN(offset_threadQ + SIZEOF_VOID_P, sizeof(int64_t));
+ static const off_t offset_single_step = MEMORY_ALIGN(offset_eetop + sizeof(int64_t), sizeof(int32_t));
+ static const off_t offset_daemon = MEMORY_ALIGN(offset_single_step + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_stillborn = MEMORY_ALIGN(offset_daemon + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_target = MEMORY_ALIGN(offset_stillborn + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_group = MEMORY_ALIGN(offset_target + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_contextClassLoader = MEMORY_ALIGN(offset_group + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_inheritedAccessControlContext = MEMORY_ALIGN(offset_contextClassLoader + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_threadLocals = MEMORY_ALIGN(offset_inheritedAccessControlContext + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_inheritableThreadLocals = MEMORY_ALIGN(offset_threadLocals + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stackSize = MEMORY_ALIGN(offset_inheritableThreadLocals + SIZEOF_VOID_P, sizeof(int64_t));
+ static const off_t offset_nativeParkEventPointer = MEMORY_ALIGN(offset_stackSize + sizeof(int64_t), sizeof(int64_t));
+ static const off_t offset_tid = MEMORY_ALIGN(offset_nativeParkEventPointer + sizeof(int64_t), sizeof(int64_t));
+ static const off_t offset_threadStatus = MEMORY_ALIGN(offset_tid + sizeof(int64_t), sizeof(int32_t));
+ static const off_t offset_parkBlocker = MEMORY_ALIGN(offset_threadStatus + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_blocker = MEMORY_ALIGN(offset_parkBlocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_blockerLock = MEMORY_ALIGN(offset_blocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stopBeforeStart = MEMORY_ALIGN(offset_blockerLock + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_throwableFromStop = MEMORY_ALIGN(offset_stopBeforeStart + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_uncaughtExceptionHandler = MEMORY_ALIGN(offset_throwableFromStop + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
+// java_lang_Thread(threadobject* t);
+
+ // Getters.
+ inline int32_t get_priority () const;
+ inline int32_t get_daemon () const;
+ inline java_handle_t* get_group () const;
+ inline java_handle_t* get_uncaughtExceptionHandler() const;
+
+ // Setters.
+ inline void set_priority(int32_t value);
+ inline void set_group (java_handle_t* value);
+};
+
+
+inline int32_t java_lang_Thread::get_priority() const
+{
+ return get<int32_t>(_handle, offset_priority);
+}
+
+inline int32_t java_lang_Thread::get_daemon() const
+{
+ return get<int32_t>(_handle, offset_daemon);
+}
+
+inline java_handle_t* java_lang_Thread::get_group() const
+{
+ return get<java_handle_t*>(_handle, offset_group);
+}
+
+inline java_handle_t* java_lang_Thread::get_uncaughtExceptionHandler() const
+{
+ return get<java_handle_t*>(_handle, offset_uncaughtExceptionHandler);
+}
+
+
+inline void java_lang_Thread::set_priority(int32_t value)
+{
+ set(_handle, offset_priority, value);
+}
+
+inline void java_lang_Thread::set_group(java_handle_t* value)
+{
+ set(_handle, offset_group, value);
+}
+
+
+
+/**
+ * OpenJDK java/lang/Throwable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object backtrace;
+ * 2. java.lang.String detailMessage;
+ * 3. java.lang.Throwable cause;
+ * 4. java.lang.StackTraceElement[] stackTrace;
+ */
+class java_lang_Throwable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_backtrace = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_detailMessage = MEMORY_ALIGN(offset_backtrace + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_cause = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stackTrace = MEMORY_ALIGN(offset_cause + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_Throwable(jobject h);
+ java_lang_Throwable(jobject h, java_handle_bytearray_t* backtrace);
+
+ // Getters.
+ inline java_handle_bytearray_t* get_backtrace () const;
+ inline java_handle_t* get_detailMessage() const;
+ inline java_handle_t* get_cause () const;
+
+ // Setters.
+ inline void set_backtrace(java_handle_bytearray_t* value);
+};
+
+
+inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
+{
+ java_lang_Throwable((java_handle_t*) h);
+}
+
+inline java_lang_Throwable::java_lang_Throwable(jobject h, java_handle_bytearray_t* backtrace) : java_lang_Object(h)
+{
+ java_lang_Throwable((java_handle_t*) h);
+ set_backtrace(backtrace);
+}
+
+
+inline java_handle_bytearray_t* java_lang_Throwable::get_backtrace() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_backtrace);
+}
+
+inline java_handle_t* java_lang_Throwable::get_detailMessage() const
+{
+ return get<java_handle_t*>(_handle, offset_detailMessage);
+}
+
+inline java_handle_t* java_lang_Throwable::get_cause() const
+{
+ return get<java_handle_t*>(_handle, offset_cause);
+}
+
+
+inline void java_lang_Throwable::set_backtrace(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_backtrace, value);
+}
+
+
+/**
+ * OpenJDK java/lang/reflect/Constructor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean override;
+ * 2. java.lang.Class clazz;
+ * 3. int slot;
+ * 4. java.lang.Class[] parameterTypes;
+ * 5. java.lang.Class[] exceptionTypes;
+ * 6. int modifiers;
+ * 7. java.lang.String signature;
+ * 8. sun.reflect.generics.repository.ConstructorRepository genericInfo;
+ * 9. byte[] annotations;
+ * 10. byte[] parameterAnnotations;
+ * 11. java.lang.Class securityCheckCache;
+ * 12. sun.reflect.ConstructorAccessor constructorAccessor;
+ * 13. java.lang.reflect.Constructor root;
+ * 14. java.util.Map declaredAnnotations;
+ */
+class java_lang_reflect_Constructor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_parameterTypes = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_exceptionTypes = MEMORY_ALIGN(offset_parameterTypes + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_modifiers = MEMORY_ALIGN(offset_exceptionTypes + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_constructorAccessor = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_root = MEMORY_ALIGN(offset_constructorAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Constructor(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Constructor(jobject h);
+ java_lang_reflect_Constructor(methodinfo* m);
+
+ java_handle_t* new_instance(java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_override () const;
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations() const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_slot (int32_t value);
+ inline void set_parameterTypes (java_handle_objectarray_t* value);
+ inline void set_exceptionTypes (java_handle_objectarray_t* value);
+ inline void set_modifiers (int32_t value);
+ inline void set_signature (java_handle_t* value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_parameterAnnotations(java_handle_bytearray_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method();
+};
+
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Constructor((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_Constructor);
+
+ if (is_null())
+ return;
+
+ int slot = m - m->clazz->methods;
+ java_handle_objectarray_t* parameterTypes = method_get_parametertypearray(m);
+ java_handle_objectarray_t* exceptionTypes = method_get_exceptionarray(m);
+ java_handle_bytearray_t* annotations = method_get_annotations(m);
+ java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
+
+ set_clazz(m->clazz);
+ set_slot(slot);
+ set_parameterTypes(parameterTypes);
+ set_exceptionTypes(exceptionTypes);
+ set_modifiers(m->flags & ACC_CLASS_REFLECT_MASK);
+ set_signature(m->signature ? javastring_new(m->signature) : NULL);
+ set_annotations(annotations);
+ set_parameterAnnotations(parameterAnnotations);
+}
+
+
+inline int32_t java_lang_reflect_Constructor::get_override() const
+{
+ return get<int32_t>(_handle, offset_override);
+}
+
+inline classinfo* java_lang_reflect_Constructor::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_Constructor::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Constructor::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+
+inline void java_lang_reflect_Constructor::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_Constructor::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_Constructor::set_parameterTypes(java_handle_objectarray_t* value)
+{
+ set(_handle, offset_parameterTypes, value);
+}
+
+inline void java_lang_reflect_Constructor::set_exceptionTypes(java_handle_objectarray_t* value)
+{
+ set(_handle, offset_exceptionTypes, value);
+}
+
+inline void java_lang_reflect_Constructor::set_modifiers(int32_t value)
+{
+ set(_handle, offset_modifiers, value);
+}
+
+inline void java_lang_reflect_Constructor::set_signature(java_handle_t* value)
+{
+ set(_handle, offset_signature, value);
+}
+
+inline void java_lang_reflect_Constructor::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_Constructor::set_parameterAnnotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_parameterAnnotations, value);
+}
+
+
+inline methodinfo* java_lang_reflect_Constructor::get_method()
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * OpenJDK java/lang/reflect/Field
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean override;
+ * 2. java.lang.Class clazz;
+ * 3. int slot;
+ * 4. java.lang.String name;
+ * 5. java.lang.Class type;
+ * 6. int modifiers;
+ * 7. java.lang.String signature;
+ * 8. sun.reflect.generics.repository.FieldRepository genericInfo;
+ * 9. byte[] annotations;
+ * 10. sun.reflect.FieldAccessor fieldAccessor;
+ * 11. sun.reflect.FieldAccessor overrideFieldAccessor;
+ * 12. java.lang.reflect.Field root;
+ * 13. java.lang.Class securityCheckCache;
+ * 14. java.lang.Class securityCheckTargetClassCache;
+ * 15. java.util.Map declaredAnnotations;
+ */
+class java_lang_reflect_Field : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_name = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_type = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_modifiers = MEMORY_ALIGN(offset_type + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_fieldAccessor = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_overrideFieldAccessor = MEMORY_ALIGN(offset_fieldAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_root = MEMORY_ALIGN(offset_overrideFieldAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckTargetClassCache = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_securityCheckTargetClassCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Field(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Field(jobject h);
+ java_lang_reflect_Field(fieldinfo* f);
+
+ // Getters.
+ inline int32_t get_override () const;
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations() const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_slot (int32_t value);
+ inline void set_name (java_handle_t* value);
+ inline void set_type (classinfo* value);
+ inline void set_modifiers (int32_t value);
+ inline void set_signature (java_handle_t* value);
+ inline void set_annotations(java_handle_bytearray_t* value);
+
+ // Convenience functions.
+ inline fieldinfo* get_field() const;
+};
+
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Field((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(fieldinfo* f)
+{
+ _handle = builtin_new(class_java_lang_reflect_Field);
+
+ // OOME.
+ if (is_null())
+ return;
+
+ set_clazz(f->clazz);
+ set_slot(f - f->clazz->fields);
+ set_name(javastring_intern(javastring_new(f->name)));
+ set_type(field_get_type(f));
+ set_modifiers(f->flags);
+ set_signature(f->signature ? javastring_new(f->signature) : NULL);
+ set_annotations(field_get_annotations(f));
+}
+
+
+inline int32_t java_lang_reflect_Field::get_override() const
+{
+ return get<int32_t>(_handle, offset_override);
+}
+
+inline classinfo* java_lang_reflect_Field::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_Field::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Field::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+
+inline void java_lang_reflect_Field::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_Field::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_Field::set_name(java_handle_t* value)
+{
+ set(_handle, offset_name, value);
+}
+
+inline void java_lang_reflect_Field::set_type(classinfo* value)
+{
+ set(_handle, offset_type, value);
+}
+
+inline void java_lang_reflect_Field::set_modifiers(int32_t value)
+{
+ set(_handle, offset_modifiers, value);
+}
+
+inline void java_lang_reflect_Field::set_signature(java_handle_t* value)
+{
+ set(_handle, offset_signature, value);
+}
+
+inline void java_lang_reflect_Field::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+
+inline fieldinfo* java_lang_reflect_Field::get_field() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ fieldinfo* f = &(c->fields[slot]);
+ return f;
+}
+
+
+/**
+ * OpenJDK java/lang/reflect/Method
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean override;
+ * 2. java.lang.Class clazz;
+ * 3. int slot;
+ * 4. java.lang.String name;
+ * 5. java.lang.Class returnType;
+ * 6. java.lang.Class[] parameterTypes;
+ * 7. java.lang.Class[] exceptionTypes;
+ * 8. int modifiers;
+ * 9. java.lang.String signature;
+ * 10 sun.reflect.generics.repository.ConstructorRepository genericInfo;
+ * 11. byte[] annotations;
+ * 12. byte[] parameterAnnotations;
+ * 13. byte[] annotationDefault;
+ * 14. sun.reflect.MethodAccessor methodAccessor;
+ * 15. java.lang.reflect.Method root;
+ * 16. java.lang.Class securityCheckCache;
+ * 17. java.lang.Class securityCheckTargetClassCache;
+ * 18. java.util.Map declaredAnnotations;
+ */
+class java_lang_reflect_Method : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_name = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_returnType = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_parameterTypes = MEMORY_ALIGN(offset_returnType + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_exceptionTypes = MEMORY_ALIGN(offset_parameterTypes + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_modifiers = MEMORY_ALIGN(offset_exceptionTypes + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotationDefault = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_methodAccessor = MEMORY_ALIGN(offset_annotationDefault + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_root = MEMORY_ALIGN(offset_methodAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckTargetClassCache = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_securityCheckTargetClassCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Method(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Method(jobject h);
+ java_lang_reflect_Method(methodinfo* m);
+
+ java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_override () const;
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_bytearray_t* get_parameterAnnotations() const;
+ inline java_handle_bytearray_t* get_annotationDefault () const;
+
+ // Setters.
+
+ // Convenience functions.
+ inline methodinfo* get_method() const;
+};
+
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Method((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_Method);
+
+ if (is_null())
+ return;
+
+ set(_handle, offset_clazz, m->clazz);
+ set(_handle, offset_slot, m - m->clazz->methods);
+ set(_handle, offset_name, javastring_intern(javastring_new(m->name)));
+ set(_handle, offset_returnType, method_returntype_get(m));
+ set(_handle, offset_parameterTypes, method_get_parametertypearray(m));
+ set(_handle, offset_exceptionTypes, method_get_exceptionarray(m));
+ set(_handle, offset_modifiers, m->flags & ACC_CLASS_REFLECT_MASK);
+ set(_handle, offset_signature, m->signature ? javastring_new(m->signature) : NULL);
+ set(_handle, offset_annotations, method_get_annotations(m));
+ set(_handle, offset_parameterAnnotations, method_get_parameterannotations(m));
+ set(_handle, offset_annotationDefault, method_get_annotationdefault(m));
+}
+
+
+inline int32_t java_lang_reflect_Method::get_override() const
+{
+ return get<int32_t>(_handle, offset_override);
+}
+
+inline classinfo* java_lang_reflect_Method::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_Method::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Method::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Method::get_parameterAnnotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Method::get_annotationDefault() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotationDefault);
+}
+
+
+inline methodinfo* java_lang_reflect_Method::get_method() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * OpenJDK java/nio/Buffer
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int mark;
+ * 2. int position;
+ * 3. int limit;
+ * 4. int capacity;
+ * 5. long address;
+ */
+class java_nio_Buffer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_mark = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_position = MEMORY_ALIGN(offset_mark + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_limit = MEMORY_ALIGN(offset_position + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_capacity = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_address = MEMORY_ALIGN(offset_capacity + sizeof(int32_t), sizeof(int64_t));
+
+public:
+ java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
+ java_nio_Buffer(jobject h) : java_lang_Object(h) {}
+
+ // Getters.
+ inline void* get_address() const;
+};
+
+
+inline void* java_nio_Buffer::get_address() const
+{
+ return get<void*>(_handle, offset_address);
+}
+
+#endif // WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
+
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+/**
+ * CLDC 1.1 com/sun/cldchi/jvm/FileDescriptor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. long pointer;
+ * 2. int position;
+ * 3. int length;
+ */
+class com_sun_cldchi_jvm_FileDescriptor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_pointer = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int64_t));
+ static const off_t offset_position = MEMORY_ALIGN(offset_pointer + sizeof(int64_t), sizeof(int32_t));
+ static const off_t offset_length = MEMORY_ALIGN(offset_position + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h) : java_lang_Object(h) {}
+ com_sun_cldchi_jvm_FileDescriptor(jobject h);
+ com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, int64_t pointer, int32_t position, int32_t length);
+ com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, com_sun_cldchi_jvm_FileDescriptor& fd);
+
+ // Getters.
+ inline int64_t get_pointer () const;
+ inline int32_t get_position() const;
+ inline int32_t get_length () const;
+
+ // Setters.
+ inline void set_pointer (int64_t value);
+ inline void set_position(int32_t value);
+ inline void set_length (int32_t value);
+};
+
+
+inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(jobject h) : java_lang_Object(h)
+{
+ com_sun_cldchi_jvm_FileDescriptor((java_handle_t*) h);
+}
+
+inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, int64_t pointer, int32_t position, int32_t length) : java_lang_Object(h)
+{
+ set_pointer(pointer);
+ set_position(position);
+ set_length(length);
+}
+
+inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, com_sun_cldchi_jvm_FileDescriptor& fd) : java_lang_Object(h)
+{
+ com_sun_cldchi_jvm_FileDescriptor(h, fd.get_pointer(), fd.get_position(), fd.get_length());
+}
+
+
+inline int64_t com_sun_cldchi_jvm_FileDescriptor::get_pointer() const
+{
+ return get<int64_t>(_handle, offset_pointer);
+}
+
+inline int32_t com_sun_cldchi_jvm_FileDescriptor::get_position() const
+{
+ return get<int32_t>(_handle, offset_position);
+}
+
+inline int32_t com_sun_cldchi_jvm_FileDescriptor::get_length() const
+{
+ return get<int32_t>(_handle, offset_length);
+}
+
+
+inline void com_sun_cldchi_jvm_FileDescriptor::set_pointer(int64_t value)
+{
+ set(_handle, offset_pointer, value);
+}
+
+inline void com_sun_cldchi_jvm_FileDescriptor::set_position(int32_t value)
+{
+ set(_handle, offset_position, value);
+}
+
+inline void com_sun_cldchi_jvm_FileDescriptor::set_length(int32_t value)
+{
+ set(_handle, offset_length, value);
+}
+
+
+/**
+ * CLDC 1.1 java/lang/String
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] value;
+ * 2. int offset;
+ * 3. int count;
+ */
+class java_lang_String : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_offset = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_count = MEMORY_ALIGN(offset_offset + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_String(jstring h);
+ java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
+
+ // Getters.
+ inline java_handle_chararray_t* get_value () const;
+ inline int32_t get_offset() const;
+ inline int32_t get_count () const;
+
+ // Setters.
+ inline void set_value (java_handle_chararray_t* value);
+ inline void set_offset(int32_t value);
+ inline void set_count (int32_t value);
+};
+
+inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
+{
+ java_lang_String((java_handle_t*) h);
+}
+
+inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
+{
+ set_value(value);
+ set_offset(offset);
+ set_count(count);
+}
+
+inline java_handle_chararray_t* java_lang_String::get_value() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_value);
+}
+
+inline int32_t java_lang_String::get_offset() const
+{
+ return get<int32_t>(_handle, offset_offset);
+}
+
+inline int32_t java_lang_String::get_count() const
+{
+ return get<int32_t>(_handle, offset_count);
+}
+
+inline void java_lang_String::set_value(java_handle_chararray_t* value)
+{
+ set(_handle, offset_value, value);
+}
+
+inline void java_lang_String::set_offset(int32_t value)
+{
+ set(_handle, offset_offset, value);
+}
+
+inline void java_lang_String::set_count(int32_t value)
+{
+ set(_handle, offset_count, value);
+}
+
+
+/**
+ * CLDC 1.1 java/lang/Thread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int priority;
+ * 2. java.lang.Runnable runnable;
+ * 3. java.lang.Object vm_thread;
+ * 4. int is_terminated;
+ * 5. int is_stillborn;
+ * 6. char[] name;
+ */
+class java_lang_Thread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_priority = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_runnable = MEMORY_ALIGN(offset_priority + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_vm_thread = MEMORY_ALIGN(offset_runnable + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_is_terminated = MEMORY_ALIGN(offset_vm_thread + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_is_stillborn = MEMORY_ALIGN(offset_is_terminated + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_name = MEMORY_ALIGN(offset_is_stillborn + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_Thread(jobject h);
+// java_lang_Thread(threadobject* t);
+
+ // Getters.
+ inline int32_t get_priority () const;
+ inline threadobject* get_vm_thread() const;
+ inline java_handle_chararray_t* get_name () const;
+
+ // Setters.
+ inline void set_vm_thread(threadobject* value);
+};
+
+
+inline java_lang_Thread::java_lang_Thread(jobject h) : java_lang_Object(h)
+{
+ java_lang_Thread((java_handle_t*) h);
+}
+
+// inline java_lang_Thread::java_lang_Thread(threadobject* t) : java_lang_Object(h)
+// {
+// java_lang_Thread(thread_get_object(t));
+// }
+
+
+inline int32_t java_lang_Thread::get_priority() const
+{
+ return get<int32_t>(_handle, offset_priority);
+}
+
+inline threadobject* java_lang_Thread::get_vm_thread() const
+{
+ return get<threadobject*>(_handle, offset_vm_thread);
+}
+
+inline java_handle_chararray_t* java_lang_Thread::get_name() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_name);
+}
+
+
+inline void java_lang_Thread::set_vm_thread(threadobject* value)
+{
+ set(_handle, offset_vm_thread, value);
+}
+
+
+/**
+ * CLDC 1.1 java/lang/Throwable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String detailMessage;
+ * 2. java.lang.Object backtrace;
+ */
+class java_lang_Throwable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_detailMessage = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_backtrace = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_Throwable(jobject h);
+
+ // Getters.
+ inline java_handle_t* get_detailMessage() const;
+ inline java_handle_bytearray_t* get_backtrace () const;
+
+ // Setters.
+ inline void set_backtrace(java_handle_bytearray_t* value);
+};
+
+
+inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
+{
+ java_lang_Throwable((java_handle_t*) h);
+}
+
+
+inline java_handle_t* java_lang_Throwable::get_detailMessage() const
+{
+ return get<java_handle_t*>(_handle, offset_detailMessage);
+}
+
+inline java_handle_bytearray_t* java_lang_Throwable::get_backtrace() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_backtrace);
+}
+
+
+inline void java_lang_Throwable::set_backtrace(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_backtrace, value);
+}
+
+#endif // WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1
+
+#else
+
+// Legacy C interface.
+java_handle_t* java_lang_reflect_Constructor_create(methodinfo* m);
+java_handle_t* java_lang_reflect_Field_create(fieldinfo* f);
+java_handle_t* java_lang_reflect_Method_create(methodinfo* m);
+
+#endif
+
+#endif // _JAVAOBJECTS_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:
+ */
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
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 "toolbox/worklist.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/resolve.h"
#include "vm/types.h"
#include "mm/memory.h"
+
#include "toolbox/logging.h"
+
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/resolve.h"
#include "vm/options.h"
#include "vm/statistics.h"
-#include "vm/stringlocal.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
+
#include "vm/jit/allocator/liveness.h"
#include "vm/jit/allocator/lsra.h"
#include "mm/memory.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
#include "vm/resolve.h"
-#include "vm/stringlocal.h"
+#include "vm/string.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
#include "vm/jit/show.h"
#include "vm/jit/allocator/simplereg.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
#if 0
# define LOG(args) printf args
noinst_HEADERS = \
arch.h \
- machine-instr.h \
\
- md-asm.h
+ md-asm.h \
+ md-atomic.hpp
noinst_LTLIBRARIES = libarch.la
.globl asm_abstractmethoderror
- .globl asm_compare_and_swap
- .globl asm_memory_barrier
-
.globl asm_md_init
.globl asm_cacheflush
.end asm_abstractmethoderror
-/* asm_compare_and_swap ********************************************************
-
- Does an atomic compare and swap. Required for the lock
- implementation.
-
- Atomically do the following: Check if the location still contains
- `oldval`. If so, replace it by `newval` and return `oldval`.
-
- RETURN VALUE:
- the old value at *p
-
- long compare_and_swap(volatile long *p, long oldval, long newval);
-
-*******************************************************************************/
-
- .ent asm_compare_and_swap
-
-asm_compare_and_swap:
-1:
- ldq_l v0,0(a0)
- cmpeq v0,a1,t0
- beq t0,2f
- mov a2,t0
- stq_c t0,0(a0)
- beq t0,1b
-2:
- jmp zero,(ra)
-
- .end asm_compare_and_swap
-
-
-/* asm_memory_barrier **********************************************************
-
- A memory barrier for the Java Memory Model.
-
-*******************************************************************************/
-
- .ent asm_memory_barrier
-
-asm_memory_barrier:
- mb
- jmp zero,(ra)
-
- .end asm_memory_barrier
-
-
/* asm_md_init *****************************************************************
Initialize machine dependent stuff.
#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/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.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"
-
/* codegen_emit ****************************************************************
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 */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP3, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
/* if (s1 != REG_ITMP1) { */
/* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
M_ALD(REG_ITMP3, REG_PV, disp);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
/* } */
M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3);
emit_classcast_check(cd, iptr, BRANCH_EQ, REG_ITMP3, s1);
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);
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMPULE(REG_ITMP1, REG_ITMP2, d);
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_ALD(REG_A0, REG_PV, disp);
}
#include "threads/lock-common.h"
+#include "vm/options.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
-/* src/vm/jit/alpha/freebsd/md.c - machine dependent Alpha FreeBSD functions
+/* src/vm/jit/alpha/freebsd/md-os.c - machine dependent Alpha FreeBSD functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#include "vm/jit/alpha/md-abi.h"
-#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
}
-#if defined(ENABLE_THREADS)
-void thread_restartcriticalsection(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- void *critical;
-
- _mc = &_uc->uc_mcontext;
-
- critical = critical_find_restart_point((void *) _mc->mc_regs[R_PC]);
-
- if (critical)
- _mc->mc_regs[R_PC] = (ptrint) critical;
-}
-#endif
-
-
/*
* 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
#include "vm/jit/alpha/md.h"
#include "vm/jit/alpha/md-abi.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
#include "vm/signallocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
-#include "vm/jit/stacktrace.h"
#include "vm/jit/trap.h"
-#include "vmcore/system.h"
-
/* md_signal_handler_sigsegv ***************************************************
* the _mc->sc_fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
- system_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
+ os_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
}
* the _mc->sc_fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
- system_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
+ os_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
/* write special registers */
_mc->sc_pc = (ptrint) es->pc;
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- u1 *pc;
- u1 *npc;
-
- _mc = &_uc->uc_mcontext;
-
- pc = (u1 *) _mc->sc_pc;
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL)
- _mc->sc_pc = (ptrint) npc;
-}
-#endif
-
-
/*
* 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
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-static inline long
-__attribute__ ((unused))
-compare_and_swap (volatile long *p, long oldval, long newval)
-{
- long ret, temp;
-
- __asm__ __volatile__ (
- "1:\t"
- "ldq_l %0,%5\n\t"
- "cmpeq %0,%3,%2\n\t"
- "beq %2,2f\n\t"
- "mov %4,%2\n\t"
- "stq_c %2,%1\n\t"
- "beq %2,1b\n\t"
- "2:\t"
- : "=&r"(ret), "=m"(*p), "=&r"(temp)
- : "r"(oldval), "r"(newval), "m"(*p));
-
- return ret;
-}
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("wmb" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
-#define MEMORY_BARRIER() __asm__ __volatile__ ( \
- "mb" : : : "memory" );
-
-#endif
#include "vm/jit/alpha/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
-#include "vmcore/descriptor.h"
-
/* register descripton array **************************************************/
--- /dev/null
+/* src/vm/jit/alpha/atomic.hpp - Alpha atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t temp;
+ uint32_t result;
+
+ __asm__ __volatile__ (
+ "1: \n"
+ " ldl_l %0,%5 \n"
+ " cmpeq %0,%3,%2 \n"
+ " beq %2,2f \n"
+ " mov %4,%2 \n"
+ " stl_c %2,%1 \n"
+ " beq %2,1b \n"
+ "2: \n"
+ : "=&r" (result), "=m" (*p), "=&r" (temp)
+ : "r" (oldval), "r" (newval), "m" (*p));
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ uint64_t temp;
+ uint64_t result;
+
+ __asm__ __volatile__ (
+ "1: \n"
+ " ldq_l %0,%5 \n"
+ " cmpeq %0,%3,%2 \n"
+ " beq %2,2f \n"
+ " mov %4,%2 \n"
+ " stq_c %2,%1 \n"
+ " beq %2,1b \n"
+ "2: \n"
+ : "=&r" (result), "=m" (*p), "=&r" (temp)
+ : "r" (oldval), "r" (newval), "m" (*p));
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("mb" : : : "memory");
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("wmb" : : : "memory");
+}
+
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ __asm__ __volatile__ ("mb" : : : "memory");
+}
+
+#endif // _MD_ATOMIC_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:
+ */
/* Don't use 8 (could be a normal load offset). */
TRAP_COMPILER = 9,
+ TRAP_COUNTDOWN = 10,
TRAP_END
};
/* src/vm/jit/alpha/md.h - machine dependent Alpha functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/alpha/codegen.h"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#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 "vm/jit/methodheader.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
#define PATCH_BACK_ORIGINAL_MCODE \
/* src/vm/jit/argument.c - argument passing from and to JIT methods
- 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 "native/llni.h"
#include "vm/array.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
-#include "vm/primitive.h"
+#include "vm/method.h"
+#include "vm/primitive.hpp"
#include "vm/resolve.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/abi-asm.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/method.h"
-
/* argument_jitarray_load ******************************************************
}
for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
- switch (td->decltype) {
+ switch (td->primitivetype) {
case TYPE_INT:
argument_vmarray_store_int(array, pd, args[j].i);
break;
/* convert the value according to its declared type */
LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
+ type = Primitive_get_type_by_wrapperclass(c);
- switch (td->decltype) {
+ switch (td->primitivetype) {
case PRIMITIVETYPE_BOOLEAN:
switch (type) {
case PRIMITIVETYPE_BOOLEAN:
default:
vm_abort("argument_vmarray_from_objectarray: invalid type %d",
- td->decltype);
+ td->primitivetype);
}
- value = primitive_unbox(param);
+ value = Primitive_unbox(param);
argument_vmarray_store_int(array, pd, value.i);
break;
return NULL;
LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
+ type = Primitive_get_type_by_wrapperclass(c);
- assert(td->decltype == PRIMITIVETYPE_LONG);
+ assert(td->primitivetype == PRIMITIVETYPE_LONG);
switch (type) {
case PRIMITIVETYPE_BYTE:
return NULL;
}
- value = primitive_unbox(param);
+ value = Primitive_unbox(param);
argument_vmarray_store_lng(array, pd, value.l);
break;
return NULL;
LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
+ type = Primitive_get_type_by_wrapperclass(c);
- assert(td->decltype == PRIMITIVETYPE_FLOAT);
+ assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
switch (type) {
case PRIMITIVETYPE_FLOAT:
return NULL;
}
- value = primitive_unbox(param);
+ value = Primitive_unbox(param);
argument_vmarray_store_flt(array, pd, value.l);
break;
return NULL;
LLNI_class_get(param, c);
- type = primitive_type_get_by_wrapperclass(c);
+ type = Primitive_get_type_by_wrapperclass(c);
- assert(td->decltype == PRIMITIVETYPE_DOUBLE);
+ assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
switch (type) {
case PRIMITIVETYPE_FLOAT:
return NULL;
}
- value = primitive_unbox(param);
+ value = Primitive_unbox(param);
argument_vmarray_store_dbl(array, pd, value.l);
break;
/* src/vm/jit/argument.h - argument passing from and to JIT methods
- 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 <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/global.h"
uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
java_handle_objectarray_t *params);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _VM_JIT_ARGUMENT_H */
noinst_HEADERS = \
arch.h \
- machine-instr.h \
- md-asm.h
+ md-asm.h \
+ md-atomic.hpp
noinst_LTLIBRARIES = libarch.la
asm_vm_call_method:
asm_vm_call_method_int:
asm_vm_call_method_long:
-/* asm_vm_call_method_float:
-asm_vm_call_method_double: */
+asm_vm_call_method_float:
+asm_vm_call_method_double:
SAVE_SCRATCH_REGISTERS /* save our personal scratch regs */
stmfd sp!, {v1} /* V1 is used to remember SP */
str a0, [sp, #-4]! /* store methods entrypoint */
ldmfd sp!, {v1}
RESTORE_SCRATCH_REGS_AND_RETURN /* return to caller, restore regs */
-asm_vm_call_method_float:
- mov a0,#0x51
- b asm_debug
-asm_vm_call_method_double:
- mov a0,#0x52
- b asm_debug
-
asm_vm_call_method_end:
#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/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/* codegen_emit ****************************************************************
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 */
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);
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);
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 */
/* 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 "threads/lock-common.h"
-#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
#include "toolbox/logging.h" /* XXX for debugging only */
#define scontext_t struct sigcontext
-#include "threads/thread.h"
+#include "threads/thread.hpp"
-#include "vm/exceptions.h"
+#include "vm/os.hpp"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
-#include "vm/jit/stacktrace.h"
#include "vm/jit/trap.h"
* the _mc->sc_fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
- system_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
+ os_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
#endif
}
* the _mc->sc_fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
- system_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
+ os_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
/* write special registers */
_mc->sc_pc = (ptrint) es->pc;
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- scontext_t *_sc;
- u1 *pc;
- u1 *npc;
-
- _sc = &_uc->uc_mcontext;
-
- pc = (u1 *) _sc->arm_pc;
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL)
- _sc->arm_pc = (ptrint) npc;
-}
-#endif
-
-
/*
* 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
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-static inline long compare_and_swap(long *p, long oldval, long newval)
-{
- long ret, temp;
- /*dolog("compare_and_swap(%p [%d], %d, %d)", p, *p, oldval, newval);*/
-
- /* TODO: improve this one! */
- __asm__ __volatile__ (
- "1:\t"
- "ldr %0,[%2]\n\t"
- "cmp %0,%4\n\t"
- "bne 2f\n\t"
- "swp %1,%3,[%2]\n\t"
- "cmp %1,%0\n\t"
- "swpne %0,%1,[%2]\n\t"
- "bne 1b\n\t"
- "2:"
- : "=&r" (ret), "=&r" (temp)
- : "r" (p), "r" (newval), "r" (oldval)
- : "cc", "memory"
- );
-
- /*dolog("compare_and_swap() return=%d mem=%d", ret, *p);*/
- return ret;
-}
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER() __asm__ __volatile__ ("" : : : "memory" );
-
-#endif
#include "vm/jit/arm/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
-#include "vmcore/descriptor.h"
-
/* register descripton array **************************************************/
--- /dev/null
+/* src/vm/jit/arm/atomic.hpp - ARM atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t result;
+ uint32_t temp;
+
+ /* TODO: improve this one! */
+ __asm__ __volatile__ (
+ "1:\t"
+ "ldr %0,[%2]\n\t"
+ "cmp %0,%4\n\t"
+ "bne 2f\n\t"
+ "swp %1,%3,[%2]\n\t"
+ "cmp %1,%0\n\t"
+ "swpne %0,%1,[%2]\n\t"
+ "bne 1b\n\t"
+ "2:"
+ : "=&r" (result), "=&r" (temp)
+ : "r" (p), "r" (newval), "r" (oldval)
+ : "cc", "memory"
+ );
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ return generic_compare_and_swap(p, oldval, newval);
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+#endif // _MD_ATOMIC_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:
+ */
TRAP_ClassCastException = 5,
TRAP_CHECK_EXCEPTION = 6,
TRAP_PATCHER = 7,
- TRAP_COMPILER = 8
+ TRAP_COMPILER = 8,
+ TRAP_COUNTDOWN = 9
};
#endif /* _MD_TRAP_H */
-/* src/vm/jit/arm/md.c - machine dependent Arm functions
+/* src/vm/jit/arm/md.c - machine dependent ARM functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
}
+/**
+ * Patch the given replacement point.
+ */
+#if defined(ENABLE_REPLACEMENT)
+void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
+{
+ vm_abort("md_patch_replacement_point: IMPLEMENT ME!");
+}
+#endif
+
+
/*
* 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
/* src/vm/jit/arm/md.h - machine dependent Arm functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
*******************************************************************************/
-inline static u1 *md_codegen_get_pv_from_pc(u1 *ra)
+inline static void* md_codegen_get_pv_from_pc(void* ra)
{
- u1 *pv;
- u4 mcode1, mcode2, mcode3;
+ uint32_t* pc;
+ uintptr_t pv;
+ uint32_t mcode1, mcode2, mcode3;
- pv = ra;
+ pc = (uint32_t*) ra;
+ pv = (uintptr_t) ra;
/* this can either be a RECOMPUTE_IP in JIT code or a fake in asm_calljavafunction */
- mcode1 = *((u4*) ra);
+ mcode1 = pc[0];
if ((mcode1 & 0xffffff00) == 0xe24fcf00 /*sub ip,pc,#__*/)
- pv -= (s4) ((mcode1 & 0x000000ff) << 2);
+ pv -= (uintptr_t) ((mcode1 & 0x000000ff) << 2);
else if ((mcode1 & 0xffffff00) == 0xe24fc000 /*sub ip,pc,#__*/)
- pv -= (s4) (mcode1 & 0x000000ff);
+ pv -= (uintptr_t) (mcode1 & 0x000000ff);
else {
/* if this happens, we got an unexpected instruction at (*ra) */
vm_abort("Unable to find method: %p (instr=%x)", ra, mcode1);
}
/* if we have a RECOMPUTE_IP there can be more than one instruction */
- mcode2 = *((u4*) (ra + 4));
- mcode3 = *((u4*) (ra + 8));
+ mcode2 = pc[1];
+ mcode3 = pc[2];
if ((mcode2 & 0xffffff00) == 0xe24ccb00 /*sub ip,ip,#__*/)
- pv -= (s4) ((mcode2 & 0x000000ff) << 10);
+ pv -= (uintptr_t) ((mcode2 & 0x000000ff) << 10);
if ((mcode3 & 0xffffff00) == 0xe24cc700 /*sub ip,ip,#__*/)
- pv -= (s4) ((mcode3 & 0x000000ff) << 18);
+ pv -= (uintptr_t) ((mcode3 & 0x000000ff) << 18);
/* we used PC-relative adressing; but now it is LR-relative */
pv += 8;
/* we check this by looking up the IsLeaf field, which has to be boolean */
/* assert( *((s4*)pv-8) == (s4)true || *((s4*)pv-8) == (s4)false ); */
- return pv;
+ return (void*) pv;
}
#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; \
/* src/vm/jit/asmpart.h - prototypes for machine specfic functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
-#include "vm/types.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/critical.h"
+#ifdef __cplusplus
+extern "C" {
#endif
-#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/types.h"
-#include "vmcore/linker.h"
+#include "vm/global.h"
+#include "vm/vm.hpp"
/* function prototypes ********************************************************/
/* wrapper for code patching functions */
void asm_patcher_wrapper(void);
-long asm_compare_and_swap(volatile long *p, long oldval, long newval);
-void asm_memory_barrier(void);
-
/* cache flush function */
-void asm_cacheflush(u1 *addr, s4 nbytes);
+void asm_cacheflush(void* addr, int nbytes);
u8 asm_get_cycle_count(void);
void asm_escape_check(java_object_t *obj);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _ASMPART_H */
}
}
+void cfg_remove_root(jitdata *jd) {
+ basicblock *root, *zero, *it;
+
+ root = jd->basicblocks;
+ zero = root->next;
+
+ zero->predecessorcount -= 1;
+
+ jd->basicblocks = zero;
+
+ for (it = zero; it; it = it->next) {
+ it->nr -= 1;
+ }
+}
+
#if defined(ENABLE_SSA)
static void cfg_eliminate_edges_to_unreachable(jitdata *jd);
#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/methodtree.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/options.h"
-
/* code_init *******************************************************************
#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 *******************************************************************
#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.
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);
/* src/vm/jit/codegen-common.h - architecture independent code generator stuff
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
typedef struct codegendata codegendata;
typedef struct branchref branchref;
typedef struct branch_label_ref_t branch_label_ref_t;
-typedef struct critical_section_ref_t critical_section_ref_t;
typedef struct jumpref jumpref;
typedef struct dataref dataref;
typedef struct exceptionref exceptionref;
#include "vm/types.h"
#include "vm/builtin.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
#include "vm/jit/code.h"
#include "vm/jit/replace.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-
#define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
#define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
#endif
list_t *brancheslabel;
- list_t *listcritical; /* list of critical sections */
list_t *linenumbers; /* list of line numbers */
methodinfo *method;
};
-/* critical_section_ref_t *****************************************************/
-
-struct critical_section_ref_t {
- s4 start; /* relative offset to method entry-point */
- s4 end;
- s4 restart;
- listnode_t linkage;
-};
-
-
/* jumpref ********************************************************************/
struct jumpref {
s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum);
s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum);
-#if defined(ENABLE_THREADS)
-void codegen_critical_section_new(codegendata *cd);
-void codegen_critical_section_start(codegendata *cd);
-void codegen_critical_section_end(codegendata *cd);
-
-# define CODEGEN_CRITICAL_SECTION_NEW codegen_critical_section_new(cd)
-# define CODEGEN_CRITICAL_SECTION_START codegen_critical_section_start(cd)
-# define CODEGEN_CRITICAL_SECTION_END codegen_critical_section_end(cd)
-#else
-# define CODEGEN_CRITICAL_SECTION_NEW /* no-op */
-# define CODEGEN_CRITICAL_SECTION_START /* no-op */
-# define CODEGEN_CRITICAL_SECTION_END /* no-op */
-#endif
-
#if defined(ENABLE_SSA)
void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr);
#endif
/* src/vm/jit/disass.h - disassembler header
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#ifndef _DISASS_H
#define _DISASS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "config.h"
#if defined(WITH_BINUTILS_DISASSEMBLER)
#endif /* defined(ENABLE_DISASSEMBLER) */
-#endif /* _DISASS_H */
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DISASS_H
/*
/* src/vm/jit/dseg.c - data segment handling stuff
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
+#include "vm/options.h"
+
#include "vm/jit/codegen-common.h"
#include "vm/jit/methodheader.h"
-#include "vmcore/options.h"
-
/* dseg_finish *****************************************************************
/* src/vm/jit/dseg.c - data segment handling stuff
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "toolbox/list.h"
+#include "vm/references.h"
+
#include "vm/jit/jit.h"
#include "vm/jit/codegen-common.h"
-#include "vmcore/references.h"
-
/* convenience macros *********************************************************/
#include "arch.h"
#include "codegen.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* emit_load_s1 ****************************************************************
void emit_exception_check(codegendata *cd, instruction *iptr);
void emit_trap_compiler(codegendata *cd);
+void emit_trap_countdown(codegendata *cd, s4 *counter);
uint32_t emit_trap(codegendata *cd);
void emit_patcher_traps(jitdata *jd);
#include "md-abi.h"
+#include "vm/descriptor.h"
+#include "vm/os.hpp"
+
#include "vm/jit/abi.h"
#include "vm/jit/executionstate.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/system.h"
-
/* executionstate_sanity_check *************************************************
/* keep a copy of (a prefix of) the context for reference */
- system_memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
+ os_memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
/* different poisons */
- system_memset(&es1, 0xc9, sizeof(executionstate_t));
- system_memset(&es2, 0xb5, sizeof(executionstate_t));
- system_memset(&es3, 0x6f, sizeof(executionstate_t));
+ os_memset(&es1, 0xc9, sizeof(executionstate_t));
+ os_memset(&es2, 0xb5, sizeof(executionstate_t));
+ os_memset(&es3, 0x6f, sizeof(executionstate_t));
md_executionstate_read(&es1, context);
cygwin \
darwin \
freebsd \
- linux
+ linux \
+ solaris
SUBDIRS = $(OS_DIR)
noinst_HEADERS = \
arch.h \
- machine-instr.h
+ md-atomic.hpp
noinst_LTLIBRARIES = \
libarch.la
#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 ****************************************************************
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
break;
case ICMD_PUTSTATIC: /* ..., value ==> ... */
-
+
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
uf = iptr->sx.s23.s3.uf;
fieldtype = uf->fieldref->parseddesc.fd->type;
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 ...]] ==> ... */
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 */
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) { */
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);
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);
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);
/* 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;
/* src/vm/jit/i386/cygwin/md-os.c - machine dependent i386 Windows functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Michael Starzinger
-
- Changes:
-
*/
#include "vm/types.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/stacktrace.h"
/* md_signal_handler_sigsegv ***************************************************
}
-#if defined(ENABLE_THREADS)
-void thread_restartcriticalsection(ucontext_t *uc)
-{
- assert(0);
-}
-#endif
-
-
/*
* 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
#include "vm/jit/i386/codegen.h"
#include "vm/jit/i386/md.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
#include "vm/global.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
#include "vm/jit/i386/codegen.h"
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void thread_restartcriticalsection(ucontext_t *_uc)
-{
- mcontext_t _mc;
- i386_thread_state_t *_ss;
- u1 *pc;
- void *rpc;
-
- _mc = _uc->uc_mcontext;
- _ss = &_mc->__ss;
-
- pc = (u1 *) _ss->__eip;
-
- rpc = critical_find_restart_point(pc);
-
- if (rpc != NULL)
- _ss->__eip = (ptrint) rpc;
-}
-#endif
-
-
/*
* 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
#include "threads/lock-common.h"
-#include "vm/exceptions.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* emit_load ******************************************************************
M_ALD_MEM(REG_METHODPTR, TRAP_COMPILER);
}
+/* emit_trap_countdown *********************************************************
+
+ Emit a countdown trap.
+
+ counter....absolute address of the counter variable
+
+*******************************************************************************/
+
+void emit_trap_countdown(codegendata *cd, s4 *counter)
+{
+ M_ISUB_IMM_MEMABS(1, (s4) counter);
+ M_BNS(6);
+ M_ALD_MEM(REG_METHODPTR, TRAP_COUNTDOWN);
+}
/* emit_trap *******************************************************************
/* src/vm/jit/i386/freebsd/md-os.c - machine dependent i386 FreeBSD functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#include "vm/jit/i386/md-abi.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
/* md_signal_handler_sigsegv ***************************************************
}
-#if defined(ENABLE_THREADS)
-void thread_restartcriticalsection(ucontext_t *uc)
-{
- void *critical;
-
- critical = critical_find_restart_point((void *) uc->uc_mcontext.mc_eip);
-
- if (critical)
- uc->uc_mcontext.mc_eip = (ptrint) critical;
-}
-#endif
-
-
/*
* 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
#include "vm/jit/i386/codegen.h"
#include "vm/jit/i386/md.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
_mc->gregs[REG_EIP] = (uintptr_t) p;
}
}
+#if defined(ENABLE_REPLACEMENT)
+ else if (type == TRAP_COUNTDOWN) {
+ /* context has been written by md_replace_executionstate_write */
+ }
+#endif
else {
_mc->gregs[REG_EAX] = (uintptr_t) p;
_mc->gregs[REG_ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- u1 *pc;
- u1 *npc;
-
- _mc = &_uc->uc_mcontext;
-
- pc = (u1 *) _mc->gregs[REG_EIP];
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL)
- _mc->gregs[REG_EIP] = (ptrint) npc;
-}
-#endif
-
-
/*
* 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
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-static inline long
-__attribute__ ((unused))
-compare_and_swap (volatile long *p, long oldval, long newval)
-{
- long ret;
-
- __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
- : "=a" (ret), "=m" (*p)
- : "r" (newval), "m" (*p), "0" (oldval));
- return ret;
-}
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() /* nothing */
-#define MEMORY_BARRIER() __asm__ __volatile__ ( \
- "lock; add $0, 0(%%esp)" : : : "memory" );
-
-#endif
#include "vm/jit/i386/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
-#include "vmcore/descriptor.h"
-
/* register descripton - array ************************************************/
--- /dev/null
+/* src/vm/jit/i386/atomic.hpp - i386 atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t result;
+
+ __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
+ : "=a" (result), "=m" (*p)
+ : "r" (newval), "m" (*p), "0" (oldval));
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+#warning Should we use cmpxchg8b or a generic version?
+ return generic_compare_and_swap(p, oldval, newval);
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("lock; add $0, 0(%%esp)" : : : "memory" );
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ // Nothing.
+}
+
+#endif // _MD_ATOMIC_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:
+ */
-/* src/vm/jit/x86_64/md-trap.h - i386 hardware traps
+/* src/vm/jit/i386/md-trap.h - i386 hardware traps
Copyright (C) 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
/* Don't use 8 (could be a normal load offset). */
TRAP_COMPILER = 9,
+ TRAP_COUNTDOWN = 10,
TRAP_END
};
/* src/vm/jit/i386/md.c - machine dependent i386 functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
#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
--- /dev/null
+## src/vm/jit/i386/solaris/Makefile.am
+##
+## Copyright (C) 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.
+
+
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_builddir)/src
+
+LIBS =
+
+noinst_HEADERS = \
+ md-asm.h
+
+noinst_LTLIBRARIES = \
+ libmd.la
+
+libmd_la_SOURCES = \
+ md-os.c
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+/* src/vm/jit/i386/solaris/md-asm.h - assembler defines for i386 ABI
+
+ Copyright (C) 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 _MD_ASM_H
+#define _MD_ASM_H
+
+/* register defines ***********************************************************/
+
+#define v0 %eax
+#define itmp1 v0
+
+#define itmp2 %ecx
+#define itmp3 %edx
+
+#define t0 %ebx
+
+#define sp %esp
+#define s0 %ebp
+#define s1 %esi
+#define s2 %edi
+
+#define bp s0
+
+#define itmp1b %al
+
+#define xptr itmp1
+#define xpc itmp2
+#define mptr itmp2
+
+
+/* save and restore macros ****************************************************/
+
+#define SAVE_ARGUMENT_REGISTERS(off) \
+ /* no argument registers */
+
+#define SAVE_TEMPORARY_REGISTERS(off) \
+ mov t0,(0+(off))*4(sp) ;
+
+
+#define RESTORE_ARGUMENT_REGISTERS(off) \
+ /* no argument registers */
+
+#define RESTORE_TEMPORARY_REGISTERS(off) \
+ mov (0+(off))*4(sp),t0 ;
+
+#endif /* _MD_ASM_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/jit/i386/solaris/md-os.c - machine dependent i386 Solaris functions
+
+ Copyright (C) 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 <ucontext.h>
+
+#include "vm/types.h"
+
+#include "vm/jit/i386/codegen.h"
+#include "vm/jit/i386/md.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/builtin.h"
+#include "vm/signallocal.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trap.h"
+
+
+/* md_signal_handler_sigsegv ***************************************************
+
+ Signal handler for hardware exceptions.
+
+*******************************************************************************/
+
+void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ u1 opc;
+ u1 mod;
+ u1 rm;
+ s4 d;
+ s4 disp;
+ ptrint val;
+ s4 type;
+ void *p;
+ java_object_t *o;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ pv = NULL; /* is resolved during stackframeinfo creation */
+ sp = (u1 *) _mc->gregs[ESP];
+ xpc = (u1 *) _mc->gregs[EIP];
+ ra = xpc; /* return address is equal to XPC */
+
+ /* get exception-throwing instruction */
+
+ opc = M_ALD_MEM_GET_OPC(xpc);
+ mod = M_ALD_MEM_GET_MOD(xpc);
+ rm = M_ALD_MEM_GET_RM(xpc);
+
+ /* for values see emit_mov_mem_reg and emit_mem */
+
+ if ((opc == 0x8b) && (mod == 0) && (rm == 5)) {
+ /* this was a hardware-exception */
+
+ d = M_ALD_MEM_GET_REG(xpc);
+ disp = M_ALD_MEM_GET_DISP(xpc);
+
+ /* we use the exception type as load displacement */
+
+ type = disp;
+
+ /* ATTENTION: The _mc->gregs layout is completely crazy! The
+ registers are reversed starting with number 4 for REG_EDI
+ (see /usr/include/sys/ucontext.h). We have to convert that
+ here. */
+
+ val = _mc->gregs[EAX - d];
+
+ if (type == TRAP_COMPILER) {
+ /* The PV from the compiler stub is equal to the XPC. */
+
+ pv = xpc;
+
+ /* We use a framesize of zero here because the call pushed
+ the return addres onto the stack. */
+
+ ra = md_stacktrace_get_returnaddress(sp, 0);
+
+ /* Skip the RA on the stack. */
+
+ sp = sp + 1 * SIZEOF_VOID_P;
+
+ /* The XPC is the RA minus 2, because the RA points to the
+ instruction after the call. */
+
+ xpc = ra - 2;
+ }
+ }
+ else {
+ /* this was a normal NPE */
+
+ type = TRAP_NullPointerException;
+ val = 0;
+ }
+
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* Set registers. */
+
+ if (type == TRAP_COMPILER) {
+ if (p == NULL) {
+ o = builtin_retrieve_exception();
+
+ _mc->gregs[ESP] = (uintptr_t) sp; /* Remove RA from stack. */
+
+ _mc->gregs[EAX] = (uintptr_t) o;
+ _mc->gregs[ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
+ }
+ else {
+ _mc->gregs[EIP] = (uintptr_t) p;
+ }
+ }
+ else {
+ _mc->gregs[EAX] = (uintptr_t) p;
+ _mc->gregs[ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
+ }
+}
+
+
+/* md_signal_handler_sigfpe ****************************************************
+
+ ArithmeticException signal handler for hardware divide by zero
+ check.
+
+*******************************************************************************/
+
+void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ s4 type;
+ ptrint val;
+ void *p;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ pv = NULL; /* is resolved during stackframeinfo creation */
+ sp = (u1 *) _mc->gregs[ESP];
+ xpc = (u1 *) _mc->gregs[EIP];
+ ra = xpc; /* return address is equal to xpc */
+
+ /* This is an ArithmeticException. */
+
+ type = TRAP_ArithmeticException;
+ val = 0;
+
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* Set registers. */
+
+ _mc->gregs[EAX] = (uintptr_t) p;
+ _mc->gregs[ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
+}
+
+
+/* md_signal_handler_sigill ****************************************************
+
+ Signal handler for hardware patcher traps (ud2).
+
+*******************************************************************************/
+
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ s4 type;
+ ptrint val;
+ void *p;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ pv = NULL; /* is resolved during stackframeinfo creation */
+ sp = (u1 *) _mc->gregs[ESP];
+ xpc = (u1 *) _mc->gregs[EIP];
+ ra = xpc; /* return address is equal to xpc */
+
+ type = TRAP_PATCHER;
+ val = 0;
+
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* Set registers. */
+
+ if (p != NULL) {
+ _mc->gregs[EAX] = (uintptr_t) p;
+ _mc->gregs[ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[EIP] = (uintptr_t) asm_handle_exception;
+ }
+}
+
+
+/* md_signal_handler_sigusr1 ***************************************************
+
+ Signal handler for suspending threads.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pc;
+ u1 *sp;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ /* get the PC and SP for this thread */
+ pc = (u1 *) _mc->gregs[EIP];
+ sp = (u1 *) _mc->gregs[ESP];
+
+ /* now suspend the current thread */
+ threads_suspend_ack(pc, sp);
+}
+#endif
+
+
+/* md_signal_handler_sigusr2 ***************************************************
+
+ Signal handler for profiling sampling.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
+{
+ threadobject *t;
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pc;
+
+ t = THREADOBJECT;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ pc = (u1 *) _mc->gregs[EIP];
+
+ t->pc = pc;
+}
+#endif
+
+
+/* md_executionstate_read ******************************************************
+
+ Read the given context into an executionstate for Replacement.
+
+*******************************************************************************/
+
+void md_executionstate_read(executionstate_t *es, void *context)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ s4 i;
+
+ _uc = (ucontext_t *) context;
+ _mc = &_uc->uc_mcontext;
+
+ /* read special registers */
+ es->pc = (u1 *) _mc->gregs[EIP];
+ es->sp = (u1 *) _mc->gregs[ESP];
+ es->pv = NULL; /* pv must be looked up via AVL tree */
+
+ /* read integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ es->intregs[i] = _mc->gregs[EAX - i];
+
+ /* read float registers */
+ for (i = 0; i < FLT_REG_CNT; i++)
+ es->fltregs[i] = 0xdeadbeefdeadbeefULL;
+}
+
+
+/* md_executionstate_write *****************************************************
+
+ Write the given executionstate back to the context for Replacement.
+
+*******************************************************************************/
+
+void md_executionstate_write(executionstate_t *es, void *context)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ s4 i;
+
+ _uc = (ucontext_t *) context;
+ _mc = &_uc->uc_mcontext;
+
+ /* write integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ _mc->gregs[EAX - i] = es->intregs[i];
+
+ /* write special registers */
+ _mc->gregs[EIP] = (ptrint) es->pc;
+ _mc->gregs[ESP] = (ptrint) es->sp;
+}
+
+
+/*
+ * 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:
+ */
#include "mm/memory.h"
#include "threads/lock-common.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/logging.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/global.h"
#include "vm/initialize.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
#include "vm/jit/jit.h"
#include "vm/jit/parse.h"
#include "vm/jit/verify/typecheck.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* algorithm tuning constants *************************************************/
#include "arch.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/class.h"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/intrp/intrp.h"
-#include "vmcore/class.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
#endif
#include "native/native.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
#include "vm/jit/stack.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/options.h"
+#include "vm/jit/stacktrace.hpp"
#define gen_branch(_inst) { \
assert(false);
}
- av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
+ av_ptr(alist, _Jv_JNIEnv *, VM_get_jnienv());
if (m->flags & ACC_STATIC)
av_ptr(alist, classinfo *, m->clazz);
/* pass env pointer */
- penv = (_Jv_JNIEnv *) _Jv_env;
+ penv = (_Jv_JNIEnv *) VM_get_jnienv();
*pvalues++ = &penv;
/* for static methods, pass class pointer */
Copyright (C) 1995,1996,1997,1998,2000,2003,2004 Free Software Foundation, Inc.
Taken from Gforth.
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
+
*/
#include "toolbox/hashtable.h"
#include "toolbox/logging.h"
+#include "vm/options.h"
+
#include "vm/jit/disass.h"
#include "vm/jit/intrp/intrp.h"
-#include "vmcore/options.h"
-
s4 no_super=0; /* option: just use replication, but no dynamic superinsts */
#include "mm/memory.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/patcher.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
+#include "vm/jit/stacktrace.hpp"
#if defined(ENABLE_THREADS)
-# ifndef USE_FAKE_ATOMIC_INSTRUCTIONS
-# include "machine-instr.h"
-# else
-# include "threads/posix/generic-primitives.h"
-# endif
+# include "threads/atomic.hpp"
#endif
#if !defined(STORE_ORDER_BARRIER) && !defined(ENABLE_THREADS)
/* src/vm/jit/intrp/intrp.h - definitions for Interpreter
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
typedef s4 Cell;
#endif
+#include "vm/class.h"
#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/codegen-common.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
-#include "vmcore/linker.h"
-
typedef void *Label;
typedef void *Inst;
#include "native/native.h"
#include "vm/builtin.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.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-#include "vmcore/references.h"
-
/* patcher_get_putstatic *******************************************************
#include "vm/jit/intrp/intrp.h"
-#include "vmcore/options.h"
+#include "vm/options.h"
/* the numbers in this struct are primitive indices */
#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/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
}
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)
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/chain.h"
#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
#include "vm/resolve.h"
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
#include "vm/jit/codegen-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stack.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#if defined(ENABLE_INLINING)
# include "vm/jit/inline/inline.h"
#include "vm/jit/verify/typeinfo.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
/* common jit/codegen macros **************************************************/
#if SIZEOF_VOID_P == 4
flags_operand_t flags; /* 4 bytes */
#endif
+#if defined(ENABLE_ESCAPE_REASON)
+ void *escape_reasons;
+#endif
};
#define FOR_EACH_INSTRUCTION(bptr, it) \
for ((it) = (bptr)->iinstr; (it) != (bptr)->iinstr + (bptr)->icount; ++(it))
+#define FOR_EACH_INSTRUCTION_REV(bptr, it) \
+ for ((it) = (bptr)->iinstr + (bptr)->icount - 1; (it) != (bptr)->iinstr - 1; --(it))
+
#if defined(ENABLE_SSA)
#define FOR_EACH_EXHANDLER(bptr, it) \
#include "mm/memory.h"
+#if defined(ENABLE_STATISTICS)
+# include "vm/options.h"
+# include "vm/statistics.h"
+#endif
+
#include "vm/jit/code.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/linenumbertable.h"
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/options.h"
-# include "vmcore/statistics.h"
-#endif
#if defined(__S390__)
# define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
/* src/vm/jit/linenumbertable.h - linenumber table
- Copyright (C) 2007
+ Copyright (C) 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#ifndef _LINENUMBERTABLE_H
#define _LINENUMBERTABLE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* forward typedefs ***********************************************************/
typedef struct linenumbertable_t linenumbertable_t;
#include "toolbox/list.h"
+#include "vm/method.h"
+
#include "vm/jit/jit.h"
#include "vm/jit/code.h"
#include "vm/jit/codegen-common.h"
-#include "vmcore/method.h"
-
/* linenumbertable_t **********************************************************/
int32_t linenumbertable_linenumber_for_pc(methodinfo **pm, codeinfo *code, void *pc);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _LINENUMBERTABLE_H */
/* src/vm/jit/loop/graph.h - control flow graph header
Copyright (C) 1996-2005, 2006, 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
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include "vm/types.h"
-#include "vm/jit/loop/loop.h"
+#include "vm/method.h"
-#include "vmcore/method.h"
+#include "vm/jit/loop/loop.h"
/* function prototypes ********************************************************/
/* src/vm/jit/loop/loop.h - array bound removal header
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
#include "vm/global.h"
+#include "vm/method.h"
#include "vm/jit/jit.h"
-#include "vmcore/method.h"
-
/* Different types for struct Trace */
#define TRACE_UNKNOWN 0 /* unknown */
noinst_HEADERS = \
arch.h \
- machine-instr.h
+ md-atomic.hpp
noinst_LTLIBRARIES = \
libarch.la
#include "threads/lock-common.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/parse.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
bool codegen_emit(jitdata *jd)
{
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ATMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
M_ALD(REG_ATMP1, s1, OFFSET(java_object_t, vftbl));
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ATMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ATMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP3, REG_ITMP1);
M_ICMP(REG_ITMP2, REG_ITMP1);
M_BHI(4);
superindex = super->index;
}
- if ((super == NULL) || !(super->flags & ACC_INTERFACE))
- CODEGEN_CRITICAL_SECTION_NEW;
-
s1 = emit_load_s1(jd, iptr, REG_ATMP1);
assert(VAROP(iptr->s1)->type == TYPE_ADR);
M_ALD(REG_ATMP2, s1, OFFSET(java_object_t, vftbl));
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP3, REG_ATMP2, OFFSET(vftbl_t, baseval)); /* REG_ITMP3 == sub->vftbl->baseval */
M_ILD(REG_ITMP1, REG_ATMP3, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ATMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP1, REG_ITMP3);
M_ICMP(REG_ITMP2, REG_ITMP3); /* XXX was CMPU */
M_AST(REG_ATMP3, REG_SP, 1 * 4);
/* env ist first argument */
- M_AMOV_IMM(_Jv_env, REG_ATMP1);
+ M_AMOV_IMM(VM_get_jnienv(), REG_ATMP1);
M_AST(REG_ATMP1, REG_SP, 0 * 4);
}
/* src/vm/jit/m68k/emit.c
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/emit-common.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
#include "config.h"
#include "vm/types.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/codegen-common.h"
void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg);
#include "vm/jit/m68k/md.h"
#include "vm/jit/m68k/linux/md-abi.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/trap.h"
+++ /dev/null
-/* src/vm/jit/m68k/machine-instr.h
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-static inline long compare_and_swap(long *p, long oldval, long newval)
-{
- /* XXX, coldifre has no atomic compare and swap instrcution */
- #warning "compare_and_swap is not atmically"
- if (*p == oldval) {
- *p = newval;
- return oldval;
- }
- return *p;
-}
-
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER() __asm__ __volatile__ ( "" : : : "memory" );
-
-#endif
-
-
-/*
- * 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/jit/m68k/md-atomic.hpp - m68k atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ return generic_compare_and_swap(p, oldval, newval);
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ return generic_compare_and_swap(p, oldval, newval);
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return generic_compare_and_swap(p, oldval, newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ generic_memory_barrier();
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+#endif // _MD_ATOMIC_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:
+ */
TRAP_ClassCastException = 5,
TRAP_CHECK_EXCEPTION = 6,
TRAP_PATCHER = 7,
- TRAP_COMPILER = 8
+ TRAP_COMPILER = 8,
+ TRAP_COUNTDOWN = 9
};
#endif /* _MD_TRAP_H */
#include "vm/types.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
/*
#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 "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
#include "codegen.h"
#include "mm/memory.h"
-#include "threads/thread.h"
-
#include "toolbox/avl.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodtree.h"
+#include "vm/jit/stacktrace.hpp"
/* methodtree_element *********************************************************/
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "toolbox/avl.h"
void *methodtree_find(void *pc);
void *methodtree_find_nocheck(void *pc);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _METHODTREE_H */
noinst_HEADERS = \
arch.h \
- machine-instr.h \
\
- md-asm.h
+ md-asm.h \
+ md-atomic.hpp
noinst_LTLIBRARIES = \
libarch.la
.globl asm_abstractmethoderror
- .globl compare_and_swap
-
/* asm_vm_call_method **********************************************************
* *
l.d fs1,-3*8(t1)
l.d fs2,-2*8(t1)
l.d fs3,-1*8(t1)
-#else /* SIZEOF_VOID_P == 8 */
+#else
# if !defined(ENABLE_SOFT_FLOAT)
- l.d fs0,-4*8(t1)
- l.d fs1,-3*8(t1)
- l.d fs2,-2*8(t1)
- l.d fs3,-1*8(t1)
- l.d fs4,-1*8(t1)
+ l.d fs0,-6*8(t1)
+ l.d fs1,-5*8(t1)
+ l.d fs2,-4*8(t1)
+ l.d fs3,-3*8(t1)
+ l.d fs4,-2*8(t1)
l.d fs5,-1*8(t1)
-# endif /* !defined(ENABLE_SOFT_FLOAT) */
-#endif /* SIZEOF_VOID_P == 8 */
+# endif
+#endif
ex_flt2:
lw t1,FrameSize(pv) /* get frame size */
.end asm_abstractmethoderror
- .ent compare_and_swap
-
-compare_and_swap:
-1:
-#if defined(__GNUC__)
- .set mips2
-#endif
- all v0,0(a0)
-#if defined(__GNUC__)
- .set mips0
-#endif
- bne v0,a1,2f
- move t0,a2
-#if defined(__GNUC__)
- .set mips2
-#endif
- asc t0,0(a0)
-#if defined(__GNUC__)
- .set mips0
-#endif
- beqz t0,1b
-2:
-#if defined(__GNUC__)
- .set mips2
-#endif
- sync
-#if defined(__GNUC__)
- .set mips0
-#endif
- j ra
-
- .end compare_and_swap
-
-
/* disable exec-stacks ********************************************************/
#if defined(__linux__) && defined(__ELF__)
#include "threads/lock-common.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/vm.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/class.h"
-#include "vmcore/options.h"
-
/* codegen_emit ****************************************************************
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 */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP3, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
/* if (s1 != REG_ITMP1) { */
/* M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
M_ALD(REG_ITMP3, REG_PV, disp);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
/* } */
M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
emit_classcast_check(cd, iptr, ICMD_IFNE, REG_ITMP3, s1);
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);
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMPULT(REG_ITMP2, REG_ITMP1, d);
M_XOR_IMM(d, 1, d);
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_ALD(REG_A0, REG_PV, disp);
}
#include "threads/lock-common.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h" /* XXX for gen_resolvebranch */
+#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/replace.h"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
/* src/vm/jit/mips/irix/md-os.c - machine dependent MIPS IRIX functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/mips/codegen.h"
#include "vm/jit/mips/md-abi.h"
-#include "mm/gc-common.h"
+#include "mm/gc.hpp"
#include "vm/global.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
-#include "vm/jit/stacktrace.h"
/* md_init *********************************************************************
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- u1 *pc;
- u1 *npc;
-
- _mc = &_uc->uc_mcontext;
-
- pc = (u1 *) _mc->gregs[CTX_EPC];
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL) {
- log_println("md_critical_section_restart: pc=%p, npc=%p", pc, npc);
- _mc->gregs[CTX_EPC] = (ptrint) npc;
- }
-}
-#endif
-
-
/*
* 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
#include "vm/jit/mips/md.h"
#include "vm/jit/mips/md-abi.h"
-#include "mm/gc-common.h"
+#include "mm/gc.hpp"
#include "mm/memory.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
-#include "vm/jit/stacktrace.h"
#include "vm/jit/trap.h"
_mc->fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->fpregs.fp_r) == sizeof(es->fltregs));
- system_memcpy(&es->fltregs, &_mc->fpregs.fp_r, sizeof(_mc->fpregs.fp_r));
+ os_memcpy(&es->fltregs, &_mc->fpregs.fp_r, sizeof(_mc->fpregs.fp_r));
}
_mc->fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->fpregs.fp_r) == sizeof(es->fltregs));
- system_memcpy(&_mc->fpregs.fp_r, &es->fltregs, sizeof(_mc->fpregs.fp_r));
+ os_memcpy(&_mc->fpregs.fp_r, &es->fltregs, sizeof(_mc->fpregs.fp_r));
/* Write special registers. */
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- u1 *pc;
- u1 *npc;
-
- _mc = &_uc->uc_mcontext;
-
-#if defined(__UCLIBC__)
- pc = (u1 *) (ptrint) _mc->gpregs[CTX_EPC];
-#else
- pc = (u1 *) (ptrint) _mc->pc;
-#endif
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL) {
-#if defined(__UCLIBC__)
- _mc->gpregs[CTX_EPC] = (ptrint) npc;
-#else
- _mc->pc = (ptrint) npc;
-#endif
- }
-}
-#endif
-
-
/*
* 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
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-#if 0
-
-/* If anyone wants to compile with gcc, use this section.
- * It is not usable with the MIPSPro compiler.
- *
- * It is outdated, too.
- */
-
-static inline int
-__attribute__ ((unused))
-compare_and_swap (volatile long *p, long oldval, long newval)
-{
- long ret, temp;
-
- __asm__ __volatile__
- ("1:\n\t"
- ".set push\n\t"
- ".set mips2\n\t"
- "lld %1,%5\n\t"
- "move %0,$0\n\t"
- "bne %1,%3,2f\n\t"
- "move %0,%4\n\t"
- "scd %0,%2\n\t"
- ".set pop\n\t"
- "beqz %0,1b\n"
- "2:\n\t"
- : "=&r" (ret), "=&r" (temp), "=m" (*p)
- : "r" (oldval), "r" (newval), "m" (*p)
- : "memory");
-
- return ret;
-}
-
-#else
-
-long compare_and_swap (long *p, long oldval, long newval);
-
-#define STORE_ORDER_BARRIER()
-#define MEMORY_BARRIER_AFTER_ATOMIC()
-#define MEMORY_BARRIER()
-
-#endif
-#endif
#include "mm/memory.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
+#include "vm/method.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/method.h"
-
/* register descripton array **************************************************/
--- /dev/null
+/* src/vm/jit/mips/atomic.hpp - MIPS atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t result;
+ uint32_t temp;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set mips2 \n"
+ "1: \n"
+ " ll %0,%5 \n"
+ " bne %0,%3,2f \n"
+ " move %1,%4 \n"
+ " sc %1,%2 \n"
+ " .set pop \n"
+ " beqz %1,1b \n"
+ "2: \n"
+ : "=&r" (result), "=&r" (temp), "=m" (*p)
+ : "r" (oldval), "r" (newval), "m" (*p)
+ : "memory");
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+#if SIZEOF_VOID_P == 8
+ uint64_t result;
+ uint64_t temp;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set mips2 \n"
+ "1: \n"
+ " lld %0,%5 \n"
+ " bne %0,%3,2f \n"
+ " move %1,%4 \n"
+ " scd %1,%2 \n"
+ " .set pop \n"
+ " beqz %1,1b \n"
+ "2: \n"
+ : "=&r" (result), "=&r" (temp), "=m" (*p)
+ : "r" (oldval), "r" (newval), "m" (*p)
+ : "memory");
+
+ return result;
+#else
+ return generic_compare_and_swap(p, oldval, newval);
+#endif
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+#if SIZEOF_VOID_P == 8
+ return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
+#else
+ return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+#endif
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+#endif // _MD_ATOMIC_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:
+ */
/* Don't use 8 (could be a normal load offset). */
TRAP_COMPILER = 9,
+ TRAP_COUNTDOWN = 10,
TRAP_END
};
#include "vm/jit/mips/md.h"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/jit.h"
/* src/vm/jit/mips/md.h - machine dependent MIPS functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
/* md_stacktrace_get_returnaddress *********************************************
*******************************************************************************/
-inline static u1 *md_codegen_get_pv_from_pc(u1 *ra)
+inline static void* md_codegen_get_pv_from_pc(void* ra)
{
- u1 *pv;
- u4 mcode;
- s4 offset;
+ int32_t offset;
+
+ uint32_t* pc = (uint32_t*) ra;
/* get the offset of the instructions */
/* get first instruction word after jump */
- mcode = *((u4 *) ra);
+ uint32_t mcode = pc[0];
/* check if we have 2 instructions (lui, daddiu) */
if ((mcode >> 16) == 0x3c19) {
/* get displacement of first instruction (lui) */
- offset = (s4) (mcode << 16);
+ offset = (int32_t) (mcode << 16);
/* get displacement of second instruction (daddiu) */
- mcode = *((u4 *) (ra + 1 * 4));
+ mcode = pc[1];
#if SIZEOF_VOID_P == 8
assert((mcode >> 16) == 0x6739);
assert((mcode >> 16) == 0x2739);
#endif
- offset += (s2) (mcode & 0x0000ffff);
+ offset += (int16_t) (mcode & 0x0000ffff);
}
else {
/* get offset of first instruction (daddiu) */
- mcode = *((u4 *) ra);
-
#if SIZEOF_VOID_P == 8
assert((mcode >> 16) == 0x67fe);
#else
assert((mcode >> 16) == 0x27fe);
#endif
- offset = (s2) (mcode & 0x0000ffff);
+ offset = (int16_t) (mcode & 0x0000ffff);
}
/* calculate PV via RA + offset */
- pv = ra + offset;
+ void* pv = (void*) (((uintptr_t) ra) + offset);
return pv;
}
#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/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-#include "vmcore/references.h"
-
#define PATCH_BACK_ORIGINAL_MCODE \
*((u4 *) pr->mpc) = (u4) pr->mcode; \
/* src/vm/jit/mips/uclinux/md-os.c - machine dependent MIPS uClinux functions
- 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/types.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
/* md_init *********************************************************************
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- vm_abort("md_critical_section_restart: IMPLEMENT ME!");
-}
-#endif
-
-
/*
* 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
--- /dev/null
+/* src/vm/jit/oprofile-agent.cpp - oprofile agent implementation
+
+ Copyright (C) 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 "mm/memory.h"
+
+#include "vm/jit/code.h"
+#include "vm/jit/oprofile-agent.hpp"
+
+#include <string.h>
+
+/* static fields **************************************************************/
+op_agent_t OprofileAgent::_handle = 0;
+
+/**
+ * Initializes the OprofileAgent system.
+ *
+ */
+/* void OprofileAgent_initialize() */
+void OprofileAgent::initialize(void)
+{
+ _handle = op_open_agent();
+ if (!_handle)
+ vm_abort_errno("unable to open opagent handle:");
+}
+
+/**
+ * Reports the given method to oprofile.
+ *
+ * This has to be done once per JIT compilation step for a specific method.
+ *
+ * @param m Method to register.
+ */
+/* void OprofileAgent_newmethod(methodinfo *m) */
+void OprofileAgent::newmethod(methodinfo *m)
+{
+ unsigned int real_length = (unsigned int) m->code->mcodelength -
+ (unsigned int) (m->code->entrypoint - m->code->mcode);
+
+ char *buf;
+ s4 len;
+
+ len = utf_bytes(m->clazz->name) + strlen(".") +
+ utf_bytes(m->name) + utf_bytes(m->descriptor) + strlen("0");
+
+ buf = MNEW(char, len);
+
+ utf_copy_classname(buf, m->clazz->name);
+ strcat(buf, ".");
+ utf_cat(buf, m->name);
+ utf_cat(buf, m->descriptor);
+
+ if (_handle)
+ op_write_native_code(_handle, buf,
+ (uint64_t) (ptrint) m->code->entrypoint,
+ (const void *) m->code->entrypoint,
+ real_length);
+
+ MFREE(buf, char, len);
+}
+
+/**
+ * Shuts down the OprofileAgent system.
+ *
+ */
+/* void OprofileAgent_close() */
+void OprofileAgent::close()
+{
+ if (_handle)
+ op_close_agent(_handle);
+
+ _handle = 0;
+}
+/* Legacy C interface *********************************************************/
+
+extern "C" {
+
+void OprofileAgent_initialize() { OprofileAgent::initialize(); }
+void OprofileAgent_newmethod(methodinfo *m) { OprofileAgent::newmethod(m); }
+void OprofileAgent_close() { OprofileAgent::close(); }
+
+}
+
+/*
+ * 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/jit/oprofile-agent.hpp - oprofile agent implementation
+
+ Copyright (C) 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 _OPROFILE_AGENT_HPP
+#define _OPROFILE_AGENT_HPP
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/method.h"
+
+#include <opagent.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+
+class OprofileAgent
+{
+ static op_agent_t _handle;
+
+public:
+ static void initialize();
+
+ static void newmethod(methodinfo *);
+
+ static void close();
+};
+
+#else
+
+/* Legacy C interface *********************************************************/
+
+typedef struct OprofileAgent OprofileAgent;
+
+void OprofileAgent_initialize(void);
+void OprofileAgent_newmethod(methodinfo *);
+void OprofileAgent_close();
+
+#endif
+
+#endif /* _OPROFILE_AGENT_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:
+ */
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 "mm/dumpmemory.h"
#include "mm/memory.h"
#include "toolbox/bitvector.h"
+#include "vm/class.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
-#include "vm/jit/ir/bytecode.h"
-#include "vm/jit/optimizing/escape.h"
+#include "vm/references.h"
#include "vm/resolve.h"
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/references.h"
+#include "vm/jit/ir/bytecode.h"
+#include "vm/jit/optimizing/escape.h"
#include <assert.h>
#include <stdarg.h>
op_stack_slot_t *ptr;
op_stack_slot_t *bottom;
unsigned max;
+ bool *perror_flag;
} op_stack_t;
-#define stack_assert_position(stack, pos) \
- do { \
- assert((stack)->elements <= (pos)); \
- assert((pos) < (stack)->end); \
- } while (0)
-
-static void op_stack_init(op_stack_t *stack, unsigned max) {
+static void op_stack_init(op_stack_t *stack, unsigned max, bool *perror_flag) {
op_stack_slot_t *it;
stack->elements = DMNEW(op_stack_slot_t, max * 2);
stack->ptr = stack->start;
stack->bottom = stack->start;
+
+ stack->perror_flag = perror_flag;
+}
+
+static void op_stack_set_error(op_stack_t *stack) {
+ *(stack->perror_flag) = true;
+#if BC_ESCAPE_VERBOSE
+ printf("%s: error.\n", __FUNCTION__);
+#endif
+}
+
+static bool op_stack_test_position(op_stack_t *stack, op_stack_slot_t *pos) {
+ if (!(stack->elements <= pos)) {
+ op_stack_set_error(stack);
+ return false;
+ } else if (!(pos < stack->end)) {
+ op_stack_set_error(stack);
+ return false;
+ } else {
+ return true;
+ }
}
static void op_stack_reset(op_stack_t *stack) {
static op_stack_slot_t op_stack_pop(op_stack_t *stack) {
op_stack_slot_t ret;
stack->ptr -= 1;
- stack_assert_position(stack, stack->ptr);
+ if (! op_stack_test_position(stack, stack->ptr)) {
+ return OP_STACK_SLOT_UNKNOWN;
+ }
ret = *(stack->ptr);
if (stack->ptr < stack->bottom) {
stack->bottom = stack->ptr;
}
static void op_stack_push(op_stack_t *stack, op_stack_slot_t element) {
- stack_assert_position(stack, stack->ptr);
- *(stack->ptr) = element;
- stack->ptr += 1;
+ if (op_stack_test_position(stack, stack->ptr)) {
+ *(stack->ptr) = element;
+ stack->ptr += 1;
+ }
}
static op_stack_slot_t op_stack_get(const op_stack_t *stack, int offset) {
- stack_assert_position(stack, stack->ptr - offset);
- return *(stack->ptr - offset);
+ if (op_stack_test_position(stack, stack->ptr - offset)) {
+ return *(stack->ptr - offset);
+ } else {
+ return OP_STACK_SLOT_UNKNOWN;
+ }
}
static void op_stack_set(op_stack_t *stack, int offset, op_stack_slot_t value) {
- stack_assert_position(stack, stack->ptr - offset);
- *(stack->ptr - offset) = value;
+ if (op_stack_test_position(stack, stack->ptr - offset)) {
+ *(stack->ptr - offset) = value;
+ }
}
static inline void op_stack_push_unknown(op_stack_t *stack) {
u1 *pos;
u1 *instruction_start;
s4 offset;
+ bool *perror_flag;
} jcode_t;
-static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset) {
+static void jcode_init(jcode_t *jc, u1 *start, s4 length, s4 offset, bool *perror_flag) {
jc->start = start;
jc->end = jc->start + length;
jc->pos = jc->start;
jc->offset = offset;
+ jc->perror_flag = perror_flag;
+}
+
+static void jcode_set_error(jcode_t *jc) {
+ *(jc->perror_flag) = true;
+#if BC_ESCAPE_VERBOSE
+ printf("%s: error.\n", __FUNCTION__);
+#endif
}
static void jcode_move_to_index(jcode_t *jc, s4 index) {
return jc->offset + (jc->pos - jc->start);
}
-#define jcode_assert_has_bytes(jc, n) \
- assert((jc->pos + n) <= jc->end)
+bool jcode_test_has_bytes(jcode_t *jc, s4 n) {
+ if ((jc->pos + n) <= jc->end) {
+ return true;
+ } else {
+ jcode_set_error(jc);
+ return false;
+ }
+}
static u1 jcode_get_u1(jcode_t *jc) {
u1 ret;
- jcode_assert_has_bytes(jc, 1);
- ret = jc->pos[0];
- jc->pos += 1;
+ if (jcode_test_has_bytes(jc, 1)) {
+ ret = jc->pos[0];
+ jc->pos += 1;
+ } else {
+ ret = 0;
+ }
return ret;
}
static s2 jcode_get_s2(jcode_t *jc) {
s2 ret;
- jcode_assert_has_bytes(jc, 2);
- ret = (jc->pos[0] << 8) | (jc->pos[1]);
- jc->pos += 2;
+ if (jcode_test_has_bytes(jc, 2)) {
+ ret = (jc->pos[0] << 8) | (jc->pos[1]);
+ jc->pos += 2;
+ } else {
+ ret = 0;
+ }
return ret;
}
static u2 jcode_get_u2(jcode_t *jc) {
u2 ret;
- jcode_assert_has_bytes(jc, 2);
- ret = (jc->pos[0] << 8) | (jc->pos[1]);
- jc->pos += 2;
+ if (jcode_test_has_bytes(jc, 2)) {
+ ret = (jc->pos[0] << 8) | (jc->pos[1]);
+ jc->pos += 2;
+ } else {
+ ret = 0;
+ }
return ret;
}
static s4 jcode_get_s4(jcode_t *jc) {
s4 ret;
- jcode_assert_has_bytes(jc, 4);
- ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
- jc->pos += 4;
+ if (jcode_test_has_bytes(jc, 4)) {
+ ret = (jc->pos[0] << 24) | (jc->pos[1] << 16) | (jc->pos[2] << 8) | (jc->pos[3]);
+ jc->pos += 4;
+ } else {
+ ret = 0;
+ }
return ret;
}
static s4 jcode_get_fall_through_target(jcode_t *jc) {
int length = bytecode[*jc->instruction_start].length;
- assert(length > 0);
+ if (length <= 0) {
+ jcode_set_error(jc);
+ }
return jc->offset + (jc->instruction_start - jc->start) + length;
}
bool verbose;
#endif
int depth;
+
+ bool fatal_error;
} bc_escape_analysis_t;
static void bc_escape_analysis_perform_intern(methodinfo *m, int depth);
int a;
u1 *ite;
u1 t;
- int ret_adr;
unsigned n;
+ int ret_val_is_adr;
be->method = m;
be->stack = DNEW(op_stack_t);
- op_stack_init(be->stack, m->maxstack);
+ op_stack_init(be->stack, m->maxstack, &(be->fatal_error));
be->basicblocks = DNEW(basicblock_work_list_t);
basicblock_work_list_init(be->basicblocks);
assert(l == be->local_to_adr_param_size);
- /* Determine whether return type is address */
-
- ret_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
+ ret_val_is_adr = m->parseddesc->returntype.type == TYPE_ADR ? 1 : 0;
/* Allocate param_escape on heap. */
be->param_escape_size = a;
- n = a + ret_adr;
+ n = a + ret_val_is_adr;
if (n == 0) {
/* Use some non-NULL value. */
be->param_escape = (u1 *)1;
} else {
be->param_escape = MNEW(u1, n);
+ be->param_escape += ret_val_is_adr;
}
for (ite = be->param_escape; ite != be->param_escape + n; ++ite) {
- *ite = (u1)ESCAPE_NONE;
+ *ite = escape_state_to_u1(ESCAPE_NONE);
}
- be->param_escape += ret_adr;
+ if (ret_val_is_adr) {
+ be->param_escape[-1] = escape_state_to_u1(ESCAPE_NONE);
+ }
be->adr_param_dirty = DNEW(bit_vector_t);
bit_vector_init(be->adr_param_dirty, a);
#endif
be->depth = depth;
+
+ be->fatal_error = false;
}
static void bc_escape_analysis_branch_target(bc_escape_analysis_t *be, s4 branch_target) {
parameters. */
if (
- old < ESCAPE_GLOBAL_THROUGH_METHOD &&
- escape_state >= ESCAPE_GLOBAL_THROUGH_METHOD
+ old < ESCAPE_GLOBAL &&
+ escape_state >= ESCAPE_GLOBAL
) {
be->non_escaping_adr_params -= 1;
}
bc_escape_analysis_dirty(be, local + 1);
}
-static void bc_escape_analyisis_returned(bc_escape_analysis_t *be, op_stack_slot_t value) {
+static void bc_escape_analysis_returned(bc_escape_analysis_t *be, op_stack_slot_t value) {
if (op_stack_slot_is_param(value)) {
/* A parameter is returned, mark it as being returned. */
bit_vector_set(be->adr_param_returned, value.index);
- } else if (op_stack_slot_is_unknown(value)) {
- /* An untracked value is returned.
- Conservatively asume a globally escaping value is returned. */
+ /* The escape state of the return value will be adjusted later. */
+ } else {
+ /* Adjust escape state of return value. */
if (be->method->parseddesc->returntype.type == TYPE_ADR) {
- be->param_escape[-1] = (u1)ESCAPE_GLOBAL;
+ be->param_escape[-1] = escape_state_to_u1(ESCAPE_GLOBAL);
}
+ bc_escape_analysis_adjust_state(be, value, ESCAPE_GLOBAL);
}
}
}
}
+static void bc_escape_analysis_push_return_value(
+ bc_escape_analysis_t *be,
+ methoddesc *md
+) {
+ switch (md->returntype.type) {
+ case TYPE_LNG:
+ case TYPE_DBL:
+ op_stack_push_unknown(be->stack);
+ op_stack_push_unknown(be->stack);
+ break;
+ case TYPE_VOID:
+ /* Do nothing */
+ break;
+ default:
+ op_stack_push_unknown(be->stack);
+ break;
+ }
+}
+
static void bc_escape_analysis_adjust_invoke_parameters(
bc_escape_analysis_t *be,
methodinfo *mi
methoddesc *md = mi->parseddesc;
u1 *paramescape = mi->paramescape;
s4 stack_depth = md->paramslots;
+ unsigned num_params_returned = 0;
+ op_stack_slot_t param_returned;
/* Process parameters.
* The first parameter is at the highest depth on the stack.
for (i = 0; i < md->paramcount; ++i) {
switch (md->paramtypes[i].type) {
case TYPE_ADR:
+ if (*paramescape & 0x80) {
+ num_params_returned += 1;
+ param_returned = op_stack_get(be->stack, stack_depth);
+ }
bc_escape_analysis_adjust_state(
be,
op_stack_get(be->stack, stack_depth),
- (escape_state_t)*(paramescape++)
+ escape_state_from_u1(*paramescape++)
);
stack_depth -= 1;
break;
for (i = 0; i < md->paramslots; ++i) {
op_stack_pop(be->stack);
}
+
+ /* Push return value. */
+ if (md->returntype.type == TYPE_ADR) {
+ if ((num_params_returned == 1) && (mi->paramescape[-1] < ESCAPE_GLOBAL)) {
+ /* Only a single argument can be returned by the method,
+ and the retun value does not escape otherwise. */
+ op_stack_push(be->stack, param_returned);
+ } else {
+ op_stack_push_unknown(be->stack);
+ }
+ } else {
+ bc_escape_analysis_push_return_value(be, md);
+ }
}
static void bc_escape_analysis_escape_invoke_parameters(
for (i = 0; i < md->paramslots; ++i) {
bc_escape_analysis_adjust_state(be, op_stack_pop(be->stack), ESCAPE_GLOBAL);
}
+
+ bc_escape_analysis_push_return_value(be, md);
}
static void bc_escape_analysis_parse_invoke(bc_escape_analysis_t *be, jcode_t *jc) {
or recurse into callee.
Otherwise we must assume, that all parameters escape. */
- if (mi != NULL) {
+ if (mi != NULL && escape_is_monomorphic(be->method, mi)) {
if (mi->paramescape == NULL) {
bc_escape_analysis_perform_intern(mi, be->depth + 1);
} else {
bc_escape_analysis_escape_invoke_parameters(be, md);
}
-
- switch (md->returntype.type) {
- case TYPE_LNG:
- case TYPE_DBL:
- op_stack_push_unknown(be->stack);
- op_stack_push_unknown(be->stack);
- break;
- case TYPE_VOID:
- /* Do nothing */
- break;
- default:
- op_stack_push_unknown(be->stack);
- break;
- }
}
static void bc_escape_analysis_parse_tableswitch(
/* TODO end if all parameters escape */
/* TODO move code into process_instruction or the like */
- while ((! jcode_end(jc)) && (! bb_end)) {
+ while ((! jcode_end(jc)) && (! bb_end) && (! be->fatal_error)) {
jcode_record_instruction_start(jc);
case BC_areturn:
/* FIXME */
- bc_escape_analyisis_returned(be, op_stack_pop(be->stack));
+ bc_escape_analysis_returned(be, op_stack_pop(be->stack));
bb_end = true;
break;
}
#endif
- while (! op_stack_is_empty(be->stack)) {
+ while ((! op_stack_is_empty(be->stack)) && (! be->fatal_error)) {
#if BC_ESCAPE_VERBOSE
if (be->verbose) {
dprintf(be->depth, "Stack element: ");
}
#endif
}
+
+ if (be->fatal_error) {
+#if BC_ESCAPE_VERBOSE
+ if (be->verbose) {
+ printf("Fatal error while processing basic block. Aborting.\n");
+ }
+#endif
+ assert(0);
+ }
}
static void bc_escape_analysis_adjust_return_value(bc_escape_analysis_t *be) {
- escape_state_t e, pe;
+ escape_state_t re, pe;
int i;
/* Only calculate, if return value is of type address. */
return ;
}
- /* Get current escape state of return value. */
-
- e = (escape_state_t)be->param_escape[-1];
-
/* If a parameter can be returned, adjust to its escape state. */
for (i = 0; i < be->param_escape_size; ++i) {
if (bit_vector_get(be->adr_param_returned, i)) {
- pe = (escape_state_t)be->param_escape[i];
- if (pe > e) {
- e = pe;
+ be->param_escape[i] |= 0x80;
+
+ pe = escape_state_from_u1(be->param_escape[i]);
+ re = escape_state_from_u1(be->param_escape[-1]);
+
+ if (pe > re) {
+ be->param_escape[-1] = escape_state_to_u1(pe);
}
}
}
-
- be->param_escape[-1] = (u1)e;
}
static void bc_escape_analysis_analyze(bc_escape_analysis_t *be) {
&jc,
be->method->jcode,
be->method->jcodelength,
- 0
+ 0,
+ &(be->fatal_error)
);
/* Process basicblock by basicblock. */
}
#endif
+ if (depth >= 3) {
+ return;
+ }
+
if (m->paramescape != NULL) {
#if BC_ESCAPE_VERBOSE
if (verbose) {
return;
}
- /* TODO threshold */
+ if (m->jcodelength > 250) {
+#if BC_ESCAPE_VERBOSE
+ if (verbose) {
+ dprintf(depth, "Bytecode too long: %d.\n", m->jcodelength);
+ }
+#endif
+ return;
+ }
be = DNEW(bc_escape_analysis_t);
bc_escape_analysis_init(be, m, verbose, depth);
-/* src/vm/optimizing/escape.c
+/* src/vm/jit/optimizing/escape.c
Copyright (C) 2008
CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
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 "vm/class.h"
+#include "vm/classcache.h"
+
#include "vm/jit/jit.h"
-#include "vmcore/class.h"
#include "vm/jit/optimizing/escape.h"
+#include <stdarg.h>
+
+#if defined(ENABLE_ESCAPE_REASON)
+#define ENABLE_REASON
+#endif
+
+#if defined(ENABLE_REASON)
+#define I2(why, tov, es) escape_analysis_record_reason(e, why, iptr, tov, es);
+#else
+#define I2(why, tov, es)
+#endif
+#define I(why, to, from) I2(why, instruction_ ## to (iptr), escape_analysis_get_state(e, instruction_ ## from (iptr)))
+#define E2(why, var) I2(why, var, ESCAPE_GLOBAL)
+#define E(why, which) E2(why, instruction_ ## which (iptr))
+
+typedef enum {
+ RED = 31,
+ GREEN,
+ YELLOW,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ WHITE,
+ COLOR_END
+} color_t;
+
+#define ENABLE_COLOR
+
+static void color_start(color_t color) {
+#if defined(ENABLE_COLOR)
+ if (RED <= color && color < COLOR_END) {
+ printf("\033[%dm", color);
+ }
+#endif
+}
+
+static void color_end() {
+#if defined(ENABLE_COLOR)
+ printf("\033[m");
+ fflush(stdout);
+#endif
+}
+
+static void color_printf(color_t color, const char *fmt, ...) {
+ va_list ap;
+ color_start(color);
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+ color_end();
+}
+
+
/*** escape_state *************************************************************/
const char *escape_state_to_string(escape_state_t escape_state) {
str(ESCAPE_UNKNOWN)
str(ESCAPE_NONE)
str(ESCAPE_METHOD)
- str(ESCAPE_GLOBAL_THROUGH_METHOD)
+ str(ESCAPE_METHOD_RETURN)
str(ESCAPE_GLOBAL)
default: return "???";
}
instruction_list_t *allocations;
instruction_list_t *getfields;
+ instruction_list_t *monitors;
+ instruction_list_t *returns;
struct var_extra **var;
/*** var_extra ***************************************************************/
+#if defined(ENABLE_REASON)
+typedef struct reason {
+ const char *why;
+ instruction *iptr;
+ struct reason *next;
+} reason_t;
+#endif
+
typedef struct var_extra {
instruction *allocation;
escape_state_t escape_state;
s4 representant;
dependency_list_t *dependency_list;
- bool is_arg; /* TODO optimize */
+ unsigned contains_arg:1;
+ unsigned contains_only_args:1;
+ /*signed adr_arg_num:30;*/
+#if defined(ENABLE_REASON)
+ reason_t *reasons;
+#endif
} var_extra_t;
static void var_extra_init(var_extra_t *ve) {
ve->escape_state = ESCAPE_NONE;
ve->representant = -1;
ve->dependency_list = NULL;
- ve->is_arg = false;
+ ve->contains_arg = false;
+ ve->contains_only_args = false;
+ /*ve->adr_arg_num = -1;*/
+#if defined(ENABLE_REASON)
+ ve->reasons = NULL;
+#endif
}
static inline var_extra_t *var_extra_get_no_alloc(const escape_analysis_t *e, s4 var) {
e->getfields = DNEW(instruction_list_t);
instruction_list_init(e->getfields);
+ e->monitors = DNEW(instruction_list_t);
+ instruction_list_init(e->monitors);
+
+ e->returns = DNEW(instruction_list_t);
+ instruction_list_init(e->returns);
+
e->var = DMNEW(var_extra_t *, jd->vartop);
MZERO(e->var, var_extra_t *, jd->vartop);
e->adr_args_count = 0;
- e->verbose = (
- strcmp(e->jd->m->clazz->name->text, "gnu/java/util/regex/RESyntax") == 0
- && strcmp(e->jd->m->name->text, "<clinit>") == 0
- );
e->verbose = 1;
+ e->verbose = strcmp(jd->m->name->text, "<init>") == 0;
+ e->verbose = getenv("EV") != NULL;
}
+#if defined(ENABLE_REASON)
+static void escape_analysis_record_reason(escape_analysis_t *e, const char *why, instruction *iptr, s4 var, escape_state_t es) {
+ var_extra_t *ve;
+ reason_t *re;
+ if (es == ESCAPE_GLOBAL || es == ESCAPE_METHOD_RETURN) {
+ var = var_extra_get_representant(e, var);
+ ve = var_extra_get(e, var);
+ re = NEW(reason_t);
+ re->why = why;
+ re->iptr= iptr;
+ re->next = ve->reasons;
+ ve->reasons = re;
+ if (e->verbose) {
+ printf("%d escapes because %s\n", var, why);
+ }
+ }
+}
+#endif
+
static void escape_analysis_set_allocation(escape_analysis_t *e, s4 var, instruction *iptr) {
var_extra_get(e, var)->allocation = iptr;
}
return ve->allocation;
}
-static void escape_analysis_set_is_argument(escape_analysis_t *e, s4 var) {
- var_extra_get(e, var)->is_arg = true;
+static void escape_analysis_set_contains_argument(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
+ var_extra_get(e, var)->contains_arg = true;
+}
+
+static bool escape_analysis_get_contains_argument(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
+ return var_extra_get(e, var)->contains_arg;
+}
+
+static void escape_analysis_set_contains_only_arguments(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
+ var_extra_get(e, var)->contains_only_args = true;
+}
+
+static bool escape_analysis_get_contains_only_arguments(escape_analysis_t *e, s4 var) {
+ var = var_extra_get_representant(e, var);
+ return var_extra_get(e, var)->contains_only_args;
+}
+
+/*
+static void escape_analysis_set_adr_arg_num(escape_analysis_t *e, s4 var, s4 num) {
+ var_extra_get(e, var)->adr_arg_num = num;
+}
+
+static s4 escape_analysis_get_adr_arg_num(escape_analysis_t *e, s4 var) {
+ return var_extra_get(e, var)->adr_arg_num;
}
+*/
-static bool escape_analysis_get_is_argument(escape_analysis_t *e, s4 var) {
- return var_extra_get(e, var)->is_arg;
+static bool escape_analysis_in_same_set(escape_analysis_t *e, s4 var1, s4 var2) {
+ return var_extra_get_representant(e, var1) == var_extra_get_representant(e, var2);
}
static void escape_analysis_ensure_state(escape_analysis_t *e, s4 var, escape_state_t escape_state) {
dependency_list_item_get_dependency(it),
escape_state
);
+ {
+ instruction *iptr = NULL;
+ I2("propagated by dependency", dependency_list_item_get_dependency(it), escape_state);
+ }
}
}
}
return var_extra_get_escape_state(e, var);
}
-#define escape_analysis_assert_has_escape(e, var) \
- assert( \
- var_extra_get_no_alloc(e, var) && \
- (var_extra_get_no_alloc(e, var)->escape_state > ESCAPE_UNKNOWN) \
- )
-
static classinfo *escape_analysis_classinfo_in_var(escape_analysis_t *e, s4 var) {
instruction *iptr = escape_analysis_get_allocation(e, var);
return;
}
+ if (e->verbose) printf("Merging (%d,%d)\n", var1, var2);
+
ve1 = var_extra_get(e, var1);
ve2 = var_extra_get(e, var2);
ve2->representant = var1;
- /* Adjust is_argument to logical or. */
+ /* Adjust is_arg to logical or. */
- has_become_arg = ve1->is_arg != ve2->is_arg;
- ve1->is_arg = ve1->is_arg || ve2->is_arg;
+ has_become_arg = ve1->contains_arg != ve2->contains_arg;
+ ve1->contains_arg = ve1->contains_arg || ve2->contains_arg;
if (e->verbose && has_become_arg) printf("(%d,%d) has become arg.\n", var1, var2);
dependency_list_item_get_dependency(itd),
ESCAPE_GLOBAL
);
+ {
+ instruction *iptr = NULL;
+ E2("has become arg", dependency_list_item_get_dependency(itd));
+ }
+ }
+ }
+
+ /* Adjust contains_only_args to logical and. */
+
+ ve1->contains_only_args = ve1->contains_only_args && ve2->contains_only_args;
+
+ /* Adjust address argument number contained in this var. */
+
+ /*
+ if (ve1->adr_arg_num != ve2->adr_arg_num) {
+ ve1->adr_arg_num = -1;
+ }
+ */
+#if defined(ENABLE_REASON)
+ if (ve1->reasons) {
+ reason_t *re = ve1->reasons;
+ while (re->next != NULL) {
+ re = re->next;
}
+ re->next = ve2->reasons;
+ } else {
+ ve1->reasons = ve2->reasons;
}
+#endif
}
static void escape_analysis_add_dependency(escape_analysis_t *e, instruction *store) {
dependency_list_add(dl, store);
if (e->verbose) {
- printf("dependency_list_add\n");
+ printf("dependency_list_add: %d.dependency_list.add( { ", obj);
+ show_icmd(e->jd, store, 0, 3);
+ printf(" } )\n");
}
}
u1 *paramescape;
unsigned i;
instruction **iarg;
- constant_FMIref *fmi;
methodinfo *mi;
- resolve_result_t result;
+ escape_state_t es;
+ const char *why;
if (e->verbose) {
- printf("processing %s@%d\n", icmd_table[iptr->opc].name, iptr->line);
+ color_start(CYAN);
+ printf("%d: ", iptr->line);
+ show_icmd(e->jd, iptr, 0, 3);
+ color_end();
+ printf("\n");
}
switch (instruction_get_opcode(iptr)) {
if (c == NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
- if (e->verbose) printf("1\n");
+ E("unresolved class", dst)
} else if (c->finalizer != NULL) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
- if (e->verbose) printf("3\n");
+ E("finalizer", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
- if (e->verbose) printf("2\n");
}
instruction_list_add(e->allocations, iptr);
break;
+ case ICMD_MONITORENTER:
+ case ICMD_MONITOREXIT:
+
+ instruction_list_add(e->monitors, iptr);
+
+ break;
+
case ICMD_NEWARRAY:
case ICMD_ANEWARRAY:
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
instruction_list_add(e->allocations, iptr);
-
+ E("untracked array", dst)
break;
case ICMD_PUTSTATIC:
if (instruction_field_type(iptr) == TYPE_ADR) {
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("putstatic", s1)
}
break;
case ICMD_PUTFIELD:
if (instruction_field_type(iptr) == TYPE_ADR) {
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- escape_analysis_assert_has_escape(e, instruction_s2(iptr));
- */
- if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+ if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_GLOBAL);
+ /* If s1 is currently not an argument, but can contain one later because
+ of a phi function, the merge function takes care to make all
+ dependencies escape globally. */
+ E("putfield into argument", s2)
} else {
+ I("putfield inherit", s2, s1);
escape_analysis_ensure_state(e, instruction_s2(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
escape_analysis_add_dependency(e, iptr);
}
break;
case ICMD_AASTORE:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- escape_analysis_assert_has_escape(e, instruction_s3(iptr));
- */
- if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+ if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
+ if (e->verbose) printf("Contains argument.\n");
escape_analysis_ensure_state(e, instruction_s3(iptr), ESCAPE_GLOBAL);
+ E("aastore into argument", s3)
} else {
+ if (e->verbose) printf("Contains no argument.\n");
+ I("aastore", s3, s1)
escape_analysis_ensure_state(e, instruction_s3(iptr), escape_analysis_get_state(e, instruction_s1(iptr)));
escape_analysis_add_dependency(e, iptr);
}
case ICMD_GETSTATIC:
if (instruction_field_type(iptr) == TYPE_ADR) {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("loaded from static var", dst)
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
}
break;
case ICMD_GETFIELD:
if (instruction_field_type(iptr) == TYPE_ADR) {
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
- if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+ if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
/* Fields loaded from arguments escape globally.
x = arg.foo;
x.bar = y;
=> y escapes globally. */
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("loaded from arg", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
break;
case ICMD_ARRAYLENGTH:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
+ escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
break;
case ICMD_AALOAD:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
- if (escape_analysis_get_is_argument(e, instruction_s1(iptr))) {
+ if (escape_analysis_get_contains_argument(e, instruction_s1(iptr))) {
/* If store into argument, escapes globally. See ICMD_GETFIELD. */
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E("aaload from argument", dst)
} else {
escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
}
case ICMD_IF_ACMPEQ:
case ICMD_IF_ACMPNE:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- escape_analysis_assert_has_escape(e, instruction_s2(iptr));
- */
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
escape_analysis_ensure_state(e, instruction_s2(iptr), ESCAPE_METHOD);
break;
case ICMD_IFNULL:
case ICMD_IFNONNULL:
+ escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+ break;
+
case ICMD_CHECKNULL:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
+ escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
break;
case ICMD_CHECKCAST:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
break;
case ICMD_INSTANCEOF:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD);
break;
count = instruction_arg_count(iptr);
mi = instruction_local_methodinfo(iptr);
paramescape = NULL;
+ why = "???";
if (mi != NULL) {
/* If the method could be resolved, it already is. */
paramescape = mi->paramescape;
+ if (e->verbose) {
+ if (paramescape) {
+ printf("Paramescape for callee available.\n");
+ }
+ }
+
+ if (paramescape) why = "Available param escape";
+
if (paramescape == NULL) {
if (e->verbose) {
printf("BC escape analyzing callee.\n");
}
+ why = "BC param escape";
bc_escape_analysis_perform(mi);
paramescape = mi->paramescape;
}
if (e->verbose) {
printf("Unresolved callee.\n");
}
+ why = "Unresolved callee";
+ }
+
+ if (iptr->opc == ICMD_INVOKEVIRTUAL || iptr->opc == ICMD_INVOKEINTERFACE) {
+ if (mi != NULL && !escape_is_monomorphic(e->jd->m, mi)) {
+ if (e->verbose) {
+ printf("Not monomorphic.\n");
+ }
+ why = "Polymorphic";
+ paramescape = NULL;
+ }
}
+ /* Set the escape state of the return value.
+ This is: global if we down have information of the callee, or the callee
+ supplied escape state. */
+
+ if (instruction_return_type(iptr) == TYPE_ADR) {
+ if (paramescape == NULL) {
+ escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_GLOBAL);
+ E(why, dst);
+ } else {
+ es = escape_state_from_u1(paramescape[-1]);
+ I2(why, instruction_dst(iptr), es)
+ escape_analysis_ensure_state(e, instruction_dst(iptr), es);
+ }
+ escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
+ }
+
for (i = 0; i < count; ++i) {
if (instruction_arg_type(iptr, i) == TYPE_ADR) {
- /*
- escape_analysis_assert_has_escape(e, instruction_arg(iptr, i));
- */
if (paramescape == NULL) {
escape_analysis_ensure_state(
e,
instruction_arg(iptr, i),
- instruction_local_methodinfo(iptr) && instruction_local_methodinfo(iptr)->jcode ?
- ESCAPE_GLOBAL_THROUGH_METHOD :
- ESCAPE_GLOBAL
+ ESCAPE_GLOBAL
);
- } else if ((escape_state_t)*paramescape < ESCAPE_METHOD) {
- escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_METHOD);
+ E2(why, instruction_arg(iptr, i));
+ } else if (escape_state_from_u1(*paramescape) <= ESCAPE_METHOD) {
+ es = escape_state_from_u1(*paramescape);
+
+ if (es < ESCAPE_METHOD) {
+ es = ESCAPE_METHOD;
+ }
+
+ I2(why, instruction_arg(iptr, i), es);
+ escape_analysis_ensure_state(e, instruction_arg(iptr, i), es);
+
+ if (*paramescape & 0x80) {
+ /* Parameter can be returned from method.
+ This creates an alias to the retur value.
+ If the return value escapes, the ES of the parameter needs
+ to be adjusted. */
+ escape_analysis_merge(e, instruction_arg(iptr, i), instruction_dst(iptr));
+ I2("return alias", instruction_arg(iptr, i), instruction_dst(iptr));
+ }
} else {
- escape_analysis_ensure_state(e, instruction_arg(iptr, i), (escape_state_t)*paramescape);
+ escape_analysis_ensure_state(e, instruction_arg(iptr, i), ESCAPE_GLOBAL);
+ E2(why, instruction_arg(iptr, i));
}
if (paramescape != NULL) {
}
}
- if (instruction_return_type(iptr) == TYPE_ADR) {
- escape_analysis_ensure_state(e, instruction_dst(iptr), ESCAPE_NONE);
- escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
- }
-
break;
case ICMD_ATHROW:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("throw", s1)
break;
case ICMD_ARETURN:
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
- escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ /* If we return only arguments, the return value escapes only the method.
+ ESCAPE_METHOD for now, and check later, if a different value than an
+ argument is possibly returned. */
+ escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_METHOD_RETURN);
+ E("return", s1)
+ instruction_list_add(e->returns, iptr);
break;
case ICMD_ALOAD:
case ICMD_MOVE:
case ICMD_COPY:
if (instruction_dst_type(iptr, jd) == TYPE_ADR) {
- /*
- escape_analysis_assert_has_escape(e, instruction_s1(iptr));
- */
escape_analysis_merge(e, instruction_s1(iptr), instruction_dst(iptr));
escape_analysis_set_allocation(e, instruction_dst(iptr), iptr);
}
FOR_EACH_BASICBLOCK(e->jd, bptr) {
+ if (e->verbose) {
+ color_printf(CYAN, "=== BB %d ===\n", bptr->nr);
+ }
+
for (iptr = bptr->phis; iptr != bptr->phis + bptr->phicount; ++iptr) {
escape_analysis_process_instruction(e, iptr);
}
}
}
+static void escape_analysis_post_process_returns(escape_analysis_t *e) {
+ instruction_list_item_t *iti;
+ instruction *iptr;
+
+ if (e->verbose) printf("Post processing returns:\n");
+
+ FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
+ iptr = iti->instr;
+
+ if (! escape_analysis_get_contains_only_arguments(e, instruction_s1(iptr))) {
+ escape_analysis_ensure_state(e, instruction_s1(iptr), ESCAPE_GLOBAL);
+ E("return of not argument", s1)
+ }
+ }
+}
+
static void escape_analysis_post_process_getfields(escape_analysis_t *e) {
instruction_list_item_t *iti;
dependency_list_item_t *itd;
instruction *iptr;
dependency_list_t *dl;
+ if (e->verbose) printf("Post processing getfields:\n");
+
FOR_EACH_INSTRUCTION_LIST(e->getfields, iti) {
iptr = iti->instr;
dependency_list_item_get_dependency(itd),
escape_analysis_get_state(e, instruction_dst(iptr))
);
+ I2("post process getfield", dependency_list_item_get_dependency(itd), escape_analysis_get_state(e, instruction_dst(iptr)));
}
}
}
}
}
-static void display_allocation(escape_analysis_t *e, const char *prefix, const instruction *iptr, escape_state_t es) {
- const char *cl = "WTF";
- classinfo *c;
+static void escape_analysis_mark_monitors(escape_analysis_t *e) {
+ instruction_list_item_t *iti;
+ instruction *iptr;
+
+ FOR_EACH_INSTRUCTION_LIST(e->monitors, iti) {
+ iptr = iti->instr;
- if (instruction_get_opcode(iptr) == ICMD_NEW) {
- c = escape_analysis_classinfo_in_var(e, instruction_arg(iptr, 0));
- if (c) {
- cl = c->name->text;
+ /* TODO if argument does not escape, mark. */
+ if (escape_analysis_get_state(e, instruction_arg(iptr, 0)) != ESCAPE_GLOBAL) {
+ if (e->verbose) {
+ printf("Monitor on thread local object!\n");
+ }
}
}
-
-
- printf(
- " %s %s %s: %s %s @%d %s\n",
- prefix,
- e->jd->m->clazz->name->text,
- e->jd->m->name->text,
- icmd_table[iptr->opc].name,
- cl,
- iptr->line,
- escape_state_to_string(es)
- );
}
static void escape_analysis_mark_allocations(escape_analysis_t *e) {
instruction_list_item_t *iti;
+ instruction *iptr;
escape_state_t es;
-/*
FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
- es = escape_analysis_get_state(e, instruction_dst(iti->instr));
- if (es < ESCAPE_GLOBAL_THROUGH_METHOD) {
- display_allocation(e, "****", iti->instr, es);
+ iptr = iti->instr;
+ es = escape_analysis_get_state(e, instruction_dst(iptr));
+
+#if defined(ENABLE_REASON)
+ if (instruction_get_opcode(iptr) == ICMD_NEW) {
+ var_extra_t *ve;
+ iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_escape_reason_new);
+ ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+ iptr->escape_reasons = ve->reasons;
+ if (es < ESCAPE_METHOD_RETURN) {
+ assert(!ve->reasons);
+ reason_t *r = NEW(reason_t);
+ r->why = "No escape\n";
+ r->iptr = NULL;
+ r->next = NULL;
+ iptr->escape_reasons = r;
+ } else {
+ assert(iptr->escape_reasons);
+ }
}
- if (es == ESCAPE_GLOBAL_THROUGH_METHOD) {
- display_allocation(e, "!!!!", iti->instr, es);
+#endif
+
+/*
+ if (instruction_get_opcode(iptr) == ICMD_NEW) {
+ es = escape_analysis_get_state(e, instruction_dst(iptr));
+ if (es < ESCAPE_METHOD_RETURN) {
+ iptr->sx.s23.s3.bte = builtintable_get_internal(BUILTIN_tlh_new);
+ e->jd->code->flags |= CODE_FLAG_TLH;
+ }
}
- }
*/
+ }
}
static void escape_analysis_process_arguments(escape_analysis_t *e) {
if (t == TYPE_ADR) {
if (varindex != UNUSED) {
escape_analysis_ensure_state(e, varindex, ESCAPE_NONE);
- escape_analysis_set_is_argument(e, varindex);
+ escape_analysis_set_contains_argument(e, varindex);
+ escape_analysis_set_contains_only_arguments(e, varindex);
+ /*escape_analysis_set_adr_arg_num(e, varindex, e->adr_args_count);*/
}
e->adr_args_count += 1;
}
s4 varindex;
methoddesc *md;
u1 *paramescape;
+ instruction_list_item_t *iti;
+ instruction *iptr;
+ escape_state_t es, re;
+ int ret_val_is_adr;
md = e->jd->m->parseddesc;
- paramescape = MNEW(u1, e->adr_args_count);
- e->jd->m->paramescape = paramescape;
+ ret_val_is_adr = (md->returntype.type == TYPE_ADR) ? 1 : 0;
+
+ paramescape = MNEW(u1, e->adr_args_count + ret_val_is_adr);
+
+ e->jd->m->paramescape = paramescape + ret_val_is_adr;
for (p = 0, l = 0; p < md->paramcount; ++p) {
t = md->paramtypes[p].type;
if (varindex == UNUSED) {
*paramescape = (u1)ESCAPE_NONE;
} else {
- *paramescape = (u1)escape_analysis_get_state(e, varindex);
- }
- if (e->verbose) {
- printf("adr parameter %d: %s\n", p, escape_state_to_string((escape_state_t)*paramescape));
+ es = escape_analysis_get_state(e, varindex);
+
+ if (es == ESCAPE_METHOD_RETURN) {
+ *paramescape = escape_state_to_u1(ESCAPE_METHOD) | 0x80;
+ if (e->verbose) {
+ printf("non-escaping adr parameter returned: %d\n", p);
+ }
+ } else {
+ *paramescape = escape_state_to_u1(es);
+ }
+
}
paramescape += 1;
}
l += IS_2_WORD_TYPE(t) ? 2 : 1;
}
+
+ if (ret_val_is_adr) {
+ /* Calculate escape state of return value as maximum escape state of all
+ values returned. */
+
+ re = ESCAPE_NONE;
+
+ FOR_EACH_INSTRUCTION_LIST(e->returns, iti) {
+ iptr = iti->instr;
+ es = escape_analysis_get_state(e, instruction_s1(iptr));
+
+ if (es > re) {
+ re = es;
+ }
+ }
+
+ e->jd->m->paramescape[-1] = escape_state_to_u1(re);
+ }
+}
+
+#if defined(ENABLE_REASON)
+void print_escape_reasons() {
+ reason_t *re = THREADOBJECT->escape_reasons;
+
+ fprintf(stderr, "DYN_REASON");
+
+ for (; re; re = re->next) {
+ fprintf(stderr,":%s", re->why);
+ }
+
+ fprintf(stderr, "\n");
+}
+
+void set_escape_reasons(void *vp) {
+ THREADOBJECT->escape_reasons = vp;
}
+#endif
static void escape_analysis_display(escape_analysis_t *e) {
instruction_list_item_t *iti;
FOR_EACH_INSTRUCTION_LIST(e->allocations, iti) {
iptr = iti->instr;
- ve = var_extra_get(e, instruction_dst(iptr));
+ ve = var_extra_get(e, var_extra_get_representant(e, instruction_dst(iptr)));
+ show_icmd(e->jd, iptr-1, 0, 3);
+ printf("\n");
+ show_icmd(e->jd, iptr, 0, 3);
+ printf("\n");
printf(
- "%s@%d: %s\n",
+ "%s@%d: --%s-- %d\n\n",
icmd_table[iptr->opc].name,
iptr->line,
- escape_state_to_string(ve->escape_state)
+ escape_state_to_string(ve->escape_state),
+ ve->representant
);
+#if defined(ENABLE_REASON)
+ {
+ reason_t *re;
+ for (re = ve->reasons; re; re = re->next) {
+ printf("ESCAPE_REASON: %s\n", re->why);
+ }
+ }
+#endif
}
}
jd->m->flags |= ACC_METHOD_EA;
- /*bc_escape_analysis_perform(jd->m);*/
-
e = DNEW(escape_analysis_t);
escape_analysis_init(e, jd);
if (e->verbose)
- printf("==== %s/%s ====\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
+ color_printf(RED, "\n\n==== %s/%s ====\n\n", e->jd->m->clazz->name->text, e->jd->m->name->text);
- /*fprintf(stderr, ".");*/
-
escape_analysis_process_arguments(e);
escape_analysis_process_instructions(e);
escape_analysis_post_process_getfields(e);
+ escape_analysis_post_process_returns(e);
+
escape_analysis_export_arguments(e);
if (e->verbose) escape_analysis_display(e);
+
+ if (e->verbose) {
+ int i, j, r;
+ for (i = 0; i < jd->vartop; ++i) {
+ r = var_extra_get_representant(e, i);
+ if (i == r) {
+ printf("EES of %d: ", i);
+ for (j = 0; j < jd->vartop; ++j) {
+ if (var_extra_get_representant(e, j) == r) {
+ printf("%d, ", j);
+ }
+ }
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+
escape_analysis_mark_allocations(e);
+ escape_analysis_mark_monitors(e);
jd->m->flags &= ~ACC_METHOD_EA;
}
void escape_analysis_escape_check(void *vp) {
}
+
+/*** monomorphic *************************************************************/
+
+bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee) {
+
+ /* Non-speculative case */
+
+ if (callee->flags & (ACC_STATIC | ACC_FINAL | ACC_PRIVATE)) {
+ return true;
+ }
+
+ if (
+ (callee->flags & (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED| ACC_ABSTRACT))
+ == (ACC_METHOD_MONOMORPHIC | ACC_METHOD_IMPLEMENTED)
+ ) {
+
+ /* Mark that we have used the information about monomorphy. */
+
+ callee->flags |= ACC_METHOD_MONOMORPHY_USED;
+
+ /* We assume the callee is monomorphic. */
+
+ method_add_assumption_monomorphic(caller, callee);
+
+ return true;
+ }
+
+ return false;
+}
+
#define _VM_JIT_OPTIMIZING_ESCAPE_H
#include "vm/jit/jit.h"
-#include "vmcore/method.h"
+#include "vm/method.h"
typedef enum {
ESCAPE_UNKNOWN,
ESCAPE_NONE,
ESCAPE_METHOD,
- ESCAPE_GLOBAL_THROUGH_METHOD,
+ ESCAPE_METHOD_RETURN,
ESCAPE_GLOBAL
} escape_state_t;
+static inline escape_state_t escape_state_from_u1(u1 x) {
+ return (escape_state_t)(x & ~0x80);
+}
+
+static inline u1 escape_state_to_u1(escape_state_t x) {
+ return (u1)x;
+}
+
void escape_analysis_perform(jitdata *jd);
void escape_analysis_escape_check(void *vp);
void bc_escape_analysis_perform(methodinfo *m);
+bool escape_is_monomorphic(methodinfo *caller, methodinfo *callee);
+
#endif
/* src/vm/jit/optimizing/graph.c - CFG
- Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Christian Ullrich
-
- $Id: graph.c$
-
*/
#include <stdlib.h>
#include "vm/jit/optimizing/graph.h"
#ifdef GRAPH_DEBUG_VERBOSE
-#include "vmcore/options.h"
+#include "vm/options.h"
#endif
/* Helpers for graph_make_cfg */
-/* src/vm/jit/ifconv/ifconv.c - if-conversion
+/* src/vm/jit/optimizing/ifconv.c - if-conversion
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
-#include "vm/vm.h"
+#include "vm/method.h"
+#include "vm/vm.hpp"
#include "vm/jit/codegen-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/reg.h"
#include "vm/jit/show.h"
-#include "vmcore/method.h"
-
/* patterns for a total number of 3 instructions ******************************/
/* src/vm/jit/optimizing/ifconv.h - if-conversion
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/jit.h"
#include "vm/jit/reg.h"
-#include "vmcore/method.h"
-
/* function prototypes ********************************************************/
-/* src/vm/jit/lsra.inc - lifetime anaylsis
+/* src/vm/jit/optimizing/lifetimes.c - lifetime anaylsis
Copyright (C) 2005, 2006, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
*/
+#include "config.h"
+
#include <stdio.h>
#include <stdlib.h>
#include "vm/builtin.h"
#include "vm/resolve.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
+#include "vm/exceptions.hpp"
+#include "vm/string.hpp"
#include "vm/jit/jit.h"
#include "vm/jit/optimizing/lifetimes.h"
#ifdef LT_DEBUG_VERBOSE
-#include "vmcore/options.h"
+#include "vm/options.h"
#endif
#include <time.h>
#include "toolbox/bitvector.h"
-#include "vmcore/statistics.h"
-#include "vmcore/options.h"
-#include "vmcore/method.h"
+#include "vm/statistics.h"
+#include "vm/options.h"
+#include "vm/method.h"
#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
#include "mm/memory.h"
#include "threads/threadlist.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
-#include "vm/stringlocal.h"
+#include "vm/class.h"
+#include "vm/classcache.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
#include "vm/jit/jit.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/optimizing/recompile.h"
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
/* profile_init ****************************************************************
-/* src/vm/jit/profile.h - runtime profiling
+/* src/vm/jit/optimizing/profile.h - runtime profiling
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#define _PROFILE_H
#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/types.h"
#include "vm/global.h"
void profile_printstats(void);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _PROFILE_H */
#include "mm/memory.h"
#include "threads/lock-common.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/list.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
#include "vm/jit/code.h"
#include "vm/jit/jit.h"
#include "vm/jit/optimizing/recompile.h"
-#include "vmcore/classcache.h"
-#include "vmcore/options.h"
-
/* global variables ***********************************************************/
/* src/vm/jit/optimizing/recompile.h - recompilation system
- Copyright (C) 1996-2005, 2006, 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, J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#define _RECOMPILE_H
#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "vm/types.h"
#include "vm/global.h"
void recompile_queue_method(methodinfo *m);
-#endif /* _PROFILE_H */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RECOMPILE_H */
/*
#include "vm/jit/python.h"
#if defined(SSA_DEBUG_VERBOSE)
-#include "vmcore/options.h" /* compileverbose */
+#include "vm/options.h" /* compileverbose */
#endif
/* function prototypes */
yssa(jd);
}
/*pythonpass_run(jd, "foo", "after");*/
+ cfg_remove_root(jd);
return;
ls = jd->ls;
-/* src/vm/optimizing/ssa3.c
+/* src/vm/jit/optimizing/ssa3.c
Copyright (C) 2008
CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
#include <limits.h>
#include <stdio.h>
-#define ELIMINATE_NOP_LOAD_STORE
+/*#define ELIMINATE_NOP_LOAD_STORE*/
#define FIXME(x) x
#define SSA_VERIFY
-/* #define SSA_VERBOSE */
+/*#define SSA_VERBOSE */
/*
__attribute__((always_inline))
/*** vars *******************************************************************/
-#define VARS_CATEGORY_SHIFT 29
-#define VARS_INDEX_MASK 0x1FFFFFFF
+#define VARS_CATEGORY_SHIFT 28
+#define VARS_INDEX_MASK 0x0FFFFFFF
#define VARS_CATEGORY_LOCAL 0
#define VARS_CATEGORY_STACK 1
#define VAR_TYPE_SUBSTITUED 666
+#define OLD_INDEX_UNUSED -2
+
+typedef struct {
+ varinfo v;
+ s4 old_index;
+} vars_item_t;
+
typedef struct {
- varinfo items[9000]; /* XXX hardcoded max */
+ vars_item_t items[9000]; /* XXX hardcoded max */
unsigned max;
unsigned count;
unsigned category;
unsigned i = vs->count;
assert(i < vs->max);
vs->count += 1;
- vs->items[i] = *item;
+ vs->items[i].v = *item;
+ vs->items[i].old_index = OLD_INDEX_UNUSED;
return (vs->category << VARS_CATEGORY_SHIFT) | i;
}
static inline varinfo *vars_back(vars_t *vs) {
assert(vs->count > 0);
- return vs->items + (vs->count - 1);
+ return &(vs->items[vs->count - 1].v);
}
static inline void vars_init(vars_t *vs, unsigned category) {
varindex = vars_get_index(varindex);
replacementindex = vars_get_index(replacementindex);
- vs->items[varindex].type = VAR_TYPE_SUBSTITUED;
- vs->items[varindex].vv.regoff = replacementindex;
+ vs->items[varindex].v.type = VAR_TYPE_SUBSTITUED;
+ vs->items[varindex].v.vv.ii[1] = replacementindex;
}
static unsigned vars_resolve_subst(const vars_t *vs, unsigned varindex) {
#endif
varindex = vars_get_index(varindex);
- if (vs->items[varindex].type == VAR_TYPE_SUBSTITUED) /*fprintf(stderr, "*")*/;
+ if (vs->items[varindex].v.type == VAR_TYPE_SUBSTITUED) /*fprintf(stderr, "*")*/;
- while (vs->items[varindex].type == VAR_TYPE_SUBSTITUED) {
+ while (vs->items[varindex].v.type == VAR_TYPE_SUBSTITUED) {
assert(loop_ctr++ != vs->count);
- varindex = vs->items[varindex].vv.regoff;
+ varindex = vs->items[varindex].v.vv.ii[1];
}
return (vs->category << VARS_CATEGORY_SHIFT) | varindex ;
}
static void vars_copy_to_final(vars_t *vs, varinfo *dst) {
- const varinfo *it;
+ const vars_item_t *it;
unsigned subst;
for (it = vs->items; it != vs->items + vs->count; ++it, ++dst) {
/* Copy variable. */
- *dst = *it;
+ *dst = it->v;
/* Eliminate VAR_TYPE_SUBSTITUED as it leads to problems. */
if (dst->type == VAR_TYPE_SUBSTITUED) {
subst = vars_get_index(vars_resolve_subst(vs, it - vs->items));
- dst->type = vs->items[subst].type;
+ dst->type = vs->items[subst].v.type;
}
}
}
+static void vars_import(vars_t *vs, varinfo *v, unsigned count, s4 old_index) {
+ vars_item_t *it;
+
+ assert((vs->count + count) <= vs->max);
+
+ it = vs->items + vs->count;
+ vs->count += count;
+
+ while (count-- > 0) {
+ it->v = *v;
+ it->old_index = old_index;
+ it += 1;
+ v += 1;
+ old_index += 1;
+ }
+}
+
+static inline void vars_record_old_index(vars_t *vs, unsigned varindex, s4 old_index) {
+ vars_item_t *item;
+ varindex = vars_get_index(varindex);
+
+ assert(varindex < vs->count);
+
+ item = vs->items + varindex;
+
+ assert(
+ item->old_index == OLD_INDEX_UNUSED ||
+ item->old_index == old_index
+ );
+
+ item->old_index = old_index;
+}
+
+static inline s4 vars_get_old_index(vars_t *vs, unsigned varindex) {
+ s4 old;
+
+ varindex = vars_get_index(varindex);
+
+ assert(varindex < vs->count);
+ old = vs->items[varindex].old_index;
+ assert(old != OLD_INDEX_UNUSED);
+
+ return old;
+}
/*** phis *******************************************************************/
}
#endif
-static inline void phis_copy_to(const phis_t *ps, instruction *dst) {
- MCOPY(
- dst,
- ps->items,
- instruction,
- ps->count
- );
+static inline unsigned phis_copy_to(const phis_t *ps, instruction *dst) {
+ instruction *it;
+ instruction *out = dst;
+
+ FOR_EACH_PHI_FUNCTION(ps, it) {
+ *(out++) = *it;
+ }
+
+ return (out - dst);
}
/*** state_array ************************************************************/
state_array_set(t->state_array, index, phi);
+ vars_record_old_index(v, phi->dst.varindex, index);
+
return phi;
}
static void traversal_rename_def(traversal_t *t, vars_t *vars, instruction *iptr) {
const varinfo *v;
unsigned index;
+ s4 old;
state_array_assert_items(t->state_array);
v = t->ops->var_num_to_varinfo(t->ops_vp, iptr->dst.varindex);
index = t->ops->var_num_to_index(t->ops_vp, iptr->dst.varindex);
+ old = iptr->dst.varindex;
iptr->dst.varindex = vars_add_item(vars, v);
state_array_set(t->state_array, index, iptr);
+
+ vars_record_old_index(vars, iptr->dst.varindex, index);
}
-static void traversal_rename_use(traversal_t *t, s4 *puse) {
+static void traversal_rename_use(traversal_t *t, vars_t *vars, s4 *puse) {
unsigned index;
+ s4 old;
state_array_assert_items(t->state_array);
index = t->ops->var_num_to_index(t->ops_vp, *puse);
assert(state_array_get(t->state_array, index));
+ old = *puse;
*puse = state_array_get_var(t->state_array, index);
+
+ vars_record_old_index(vars, *puse, index);
}
static inline unsigned traversal_variables_count(traversal_t *t) {
basicblock_chain_t *new_blocks;
+ struct {
+ s4 maxlocals;
+ s4 maxinterfaces;
+ s4 *local_map;
+ varinfo *var;
+ s4 vartop;
+ s4 varcount;
+ s4 localcount;
+ } original;
+
+ unsigned keep_in_out:1;
+
} ssa_info, ssa_info_t;
void ssa_info_init(ssa_info_t *ssa, jitdata *jd) {
vars_init(ssa->locals, VARS_CATEGORY_LOCAL);
/* Initialize first version of locals, that is always available. */
- MCOPY(ssa->locals->items, jd->var, varinfo, jd->localcount);
- ssa->locals->count = jd->localcount;
+ vars_import(ssa->locals, jd->var, jd->localcount, 0);
ssa->stack = DNEW(vars_t);
vars_init(ssa->stack, VARS_CATEGORY_STACK);
ssa->new_blocks = DNEW(basicblock_chain_t);
basicblock_chain_init(ssa->new_blocks);
+
+ ssa->original.maxlocals = jd->maxlocals;
+ ssa->original.maxinterfaces = jd->maxinterfaces;
+ ssa->original.local_map = jd->local_map;
+ ssa->original.var = jd->var;
+ ssa->original.vartop = jd->vartop;
+ ssa->original.varcount = jd->varcount;
+ ssa->original.localcount = jd->localcount;
+
+ ssa->keep_in_out = false;
}
/*** others_mapping *********************************************************/
static inline void others_mapping_set(ssa_info *ssa, s4 var, s4 new_var) {
- ssa->jd->var[var].vv.regoff = new_var;
+ ssa->jd->var[var].vv.ii[1] = new_var;
}
static inline s4 others_mapping_get(const ssa_info *ssa, s4 var) {
- return ssa->jd->var[var].vv.regoff;
+ return ssa->jd->var[var].vv.ii[1];
}
/*** code *******************************************************************/
basicblock_chain_t chain;
basicblock *last = NULL;
basicblock *marker = NULL;
+ s4 vartop;
+ unsigned i;
if (jd->exceptiontablelength == 0) {
return;
basicblock_chain_init(&chain);
- /* We need to allocate new iovars */
+ /* Remember, where we started adding IO variables. */
- avail_vars = (jd->varcount - jd->vartop);
- add_vars = jd->exceptiontablelength;
-
- if (add_vars > avail_vars) {
- add_vars -= avail_vars;
- jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
- jd->varcount += add_vars;
- }
+ vartop = jd->vartop;
/* For each exception handler block, create one block with a prologue block */
FOR_EACH_BASICBLOCK(jd, bptr) {
if (bptr->type == BBTYPE_EXH) {
+ /*
+
+ +---- EXH (exh)-------+
+ | in0 in1 in2 exc |
+ | ..... |
+ +---------------------+
+
+ === TRANSFORMED TO ===>
+
+ +---- PROL (exh) -------+
+ | in0 in1 in2 |
+ | GETEXECEPTION => OU3 |
+ | GOTO REAL_EXH |
+ | in0 in1 in2 OU3 |
+ +-----------------------+
+
+ +---- REAL_EXH (std) -+
+ | in0 in1 in2 exc |
+ | ...... |
+ +---------------------+
+
+ */
+
bptr->type = BBTYPE_STD;
bptr->predecessorcount = 0; /* legacy */
iptr = DMNEW(instruction, 2);
MZERO(iptr, instruction, 2);
+
+ /* Create outvars */
+
+ exh->outdepth = bptr->indepth;
+
+ if (exh->outdepth > 0) {
+ exh->outvars = DMNEW(s4, exh->outdepth);
+ for (i = 0; i < exh->outdepth; ++i) {
+ exh->outvars[i] = vartop++;
+ }
+ }
+
+ /* Create invars */
+ exh->indepth = exh->outdepth - 1;
+ exh->invars = exh->outvars;
+
+#if 0
/* Create new outvar */
assert(jd->vartop < jd->varcount);
jd->vartop += 1;
jd->var[v].type = TYPE_ADR;
jd->var[v].flags = INOUT;
+#endif
exh->nr = jd->basicblockcount;
jd->basicblockcount += 1;
exh->type = BBTYPE_EXH;
exh->icount = 2;
exh->iinstr = iptr;
+/*
exh->outdepth = 1;
exh->outvars = DNEW(s4);
exh->outvars[0] = v;
+*/
exh->predecessorcount = -1; /* legacy */
exh->flags = BBFINISHED;
exh->method = jd->m;
/* Get exception */
iptr->opc = ICMD_GETEXCEPTION;
- iptr->dst.varindex = v;
+ iptr->dst.varindex = exh->outvars[exh->outdepth - 1];
iptr += 1;
/* Goto real exception handler */
}
}
+ /* We need to allocate the new iovars in the var array */
+
+ avail_vars = (jd->varcount - jd->vartop);
+ add_vars = (vartop - jd->vartop);
+
+ if (add_vars > avail_vars) {
+ add_vars -= avail_vars;
+ jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, jd->varcount + add_vars);
+ jd->varcount += add_vars;
+ }
+
+ jd->vartop = vartop;
+
/* Put the chain of exception handlers between just before the last
basic block (end marker). */
for (ee = jd->exceptiontable; ee; ee = ee->down) {
assert(ee->handler->vp);
- ee->handler = ee->handler->vp;
+
+ bptr = ee->handler;
+ exh = (basicblock *)ee->handler->vp;
+
+ ee->handler = exh;
+
+ /* Set up IO variables in newly craeted exception handlers. */
+
+ for (i = 0; i < exh->outdepth; ++i) {
+ v = exh->outvars[i];
+
+ jd->var[v].flags = INOUT;
+ jd->var[v].type = jd->var[ bptr->invars[i] ].type;
+ }
+ }
+
+}
+
+void unfix_exception_handlers(jitdata *jd) {
+ basicblock *bptr, *exh;
+ unsigned i;
+ exception_entry *ee;
+#if !defined(NDEBUG)
+ bool found = false;
+#endif
+
+ FOR_EACH_BASICBLOCK(jd, bptr) {
+ if (bptr->type == BBTYPE_EXH) {
+ assert(bptr->iinstr[1].opc == ICMD_GOTO);
+ exh = bptr->iinstr[1].dst.block;
+
+ bptr->type = BBDELETED;
+ bptr->icount = 0;
+ bptr->indepth = 0;
+ bptr->outdepth = 0;
+ exh->type = BBTYPE_EXH;
+ bptr->vp = exh;
+
+ /* bptr is no more a predecessor of exh */
+
+ for (i = 0; i < exh->predecessorcount; ++i) {
+ if (exh->predecessors[i] == bptr) {
+ exh->predecessors[i] = exh->predecessors[exh->predecessorcount - 1];
+ exh->predecessorcount -= 1;
+#if !defined(NDEBUG)
+ found = true;
+#endif
+ break;
+ }
+ }
+
+ assert(found);
+
+ } else {
+ bptr->vp = NULL;
+ }
}
+ for (ee = jd->exceptiontable; ee; ee = ee->down) {
+ assert(ee->handler->vp);
+ ee->handler = ee->handler->vp;
+ }
}
/*** ssa_enter ***************************************************************/
basicblock *bptr;
basicblock_info_t *bbi;
instruction *itph;
+
+ /* XXX */
+ return;
+
FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
if (basicblock_reached(bptr)) {
bbi = bb_info(bptr);
basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
ssa->locals
);
+
+ ssa_enter_merge(
+ bbi->stack,
+ succi->stack,
+ *itsucc,
+ basicblock_get_ex_predecessor_index(bb, pei, *itsucc),
+ ssa->stack
+ );
}
}
instruction *itph;
bool ret = false;
+ /* XXX */
+ return;
+
FOR_EACH_PHI_FUNCTION(t->phis, itph) {
phi_calculate_redundancy(itph);
state_array_allocate_items(bbi->stack->state_array);
}
+#if 0
/* Exception handlers have a clean stack. */
+ /* Not true with inlining. */
+
if (bb->type == BBTYPE_EXH) {
state_array_assert_no_items(bbi->stack->state_array);
state_array_allocate_items(bbi->stack->state_array);
}
+#endif
/* Some in/out vars get marked as INOUT in simplereg,
and are not marked at this point.
Mark them manually. */
for (ituse = bb->invars; ituse != bb->invars + bb->indepth; ++ituse) {
+ if (ssa->keep_in_out && ssa->jd->var[*ituse].type == TYPE_RET) {
+ continue;
+ }
ssa->jd->var[*ituse].flags |= INOUT;
ssa->jd->var[*ituse].flags &= ~PREALLOC;
}
for (ituse = bb->outvars; ituse != bb->outvars + bb->outdepth; ++ituse) {
+ if (ssa->keep_in_out && ssa->jd->var[*ituse].type == TYPE_RET) {
+ continue;
+ }
ssa->jd->var[*ituse].flags |= INOUT;
ssa->jd->var[*ituse].flags &= ~PREALLOC;
}
if (var_is_local(ssa->jd, *ituse)) {
traversal_rename_use(
bbi->locals,
+ ssa->locals,
ituse
);
} else if (var_is_inout(ssa->jd, *ituse)) {
traversal_rename_use(
bbi->stack,
+ ssa->stack,
ituse
);
} else {
ssa->others,
ssa->jd->var + iptr->dst.varindex
);
+ vars_record_old_index(ssa->others, iptr->dst.varindex, old);
others_mapping_set(ssa, old, iptr->dst.varindex);
}
}
s4 *it;
unsigned i, j;
jitdata *jd = ssa->jd;
+ s4 *local_map;
vartop = ssa->locals->count + ssa->stack->count + ssa->others->count;
vars = DMNEW(varinfo, vartop);
/* Grow local map to accomodate all new locals and iovars.
But keep the local map for version 1 of locals, that contains the holes. */
- jd->local_map = DMREALLOC(
- jd->local_map,
- s4,
- 5 * jd->maxlocals,
+ local_map = DMNEW(
+ s4,
5 * (jd->maxlocals + ssa->locals->count + ssa->stack->count - jd->localcount)
);
+ MCOPY(local_map, jd->local_map, s4, 5 * jd->maxlocals);
+
+ jd->local_map = local_map;
+
it = jd->local_map + (jd->maxlocals * 5); /* start adding entries here */
/* Add version > 1 of all locals */
FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
bbi = bb_info(bptr);
if (bbi != NULL) {
- bptr->phicount =
- bbi->locals->phis->count +
- bbi->stack->phis->count;
-
- bptr->phis = DMNEW(instruction, bptr->phicount);
+ bptr->phis = DMNEW(instruction, bbi->locals->phis->count + bbi->stack->phis->count);
dst = bptr->phis;
- phis_copy_to(bbi->locals->phis, dst);
+ dst += phis_copy_to(bbi->locals->phis, dst);
- dst += bbi->locals->phis->count;
+ dst += phis_copy_to(bbi->stack->phis, dst);
- phis_copy_to(bbi->stack->phis, dst);
+ bptr->phicount = dst - bptr->phis;
}
}
}
bbi = bb_info(bb);
- bb->indepth = 0;
- bb->outdepth = 0;
+ if (! ssa->keep_in_out) {
+ bb->indepth = 0;
+ bb->outdepth = 0;
+ }
if (bbi != NULL) {
FOR_EACH_PHI_FUNCTION(bbi->locals->phis, itph) {
}
}
+void ssa_simple_leave_restore(ssa_info_t *ssa, basicblock *bptr, s4 *pvar) {
+ s4 var = *pvar;
+ s4 index;
+ basicblock_info_t *bbi;
+
+ if (var < ssa->locals->count) {
+ *pvar = vars_get_old_index(ssa->locals, var);
+ } else if (var < ssa->locals->count + ssa->stack->count) {
+
+ index = vars_get_old_index(
+ ssa->stack,
+ var - ssa->locals->count
+ );
+
+ bbi = bb_info(bptr);
+
+ /* We have to determine whether to take an invar or an outvar for
+ the stack depth ``index''.
+ The state array contains the last definition of the stack element
+ at the given depth.
+ */
+
+ if (state_array_get_var(bbi->stack->state_array, index) == var) {
+ /* The last definition of a stack depth inside the basicblock.
+ This is the outvar at the given depth.
+ If there is no outvar at the given depth, it must be an invar.
+ */
+ if (index < bptr->outdepth) {
+ *pvar = bptr->outvars[index];
+ } else if (index < bptr->indepth) {
+ *pvar = bptr->invars[index];
+ } else {
+ assert(0);
+ }
+ } else {
+ /* A different than the last definition of a stack depth.
+ This must be an invar.
+ */
+ assert(index < bptr->indepth);
+ *pvar = bptr->invars[index];
+ }
+ } else {
+ *pvar = vars_get_old_index(
+ ssa->others,
+ var - ssa->locals->count - ssa->stack->count
+ );
+ }
+}
+
+void ssa_simple_leave(ssa_info_t *ssa) {
+ basicblock *bptr;
+ instruction *iptr;
+ s4 *ituse, *uses;
+ unsigned uses_count;
+
+ FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
+ if (bptr->type == BBTYPE_EXH) {
+ /* (Aritifical) exception handler blocks will be eliminated. */
+ continue;
+ }
+ /* In reverse order. We need to rename the definition after any use! */
+ FOR_EACH_INSTRUCTION_REV(bptr, iptr) {
+ if (instruction_has_dst(iptr)) {
+ ssa_simple_leave_restore(ssa, bptr, &(iptr->dst.varindex));
+ }
+ instruction_get_uses(iptr, ssa->s_buf, &uses, &uses_count);
+ for (ituse = uses; ituse != uses + uses_count; ++ituse) {
+ ssa_simple_leave_restore(ssa, bptr, ituse);
+ }
+ instruction_set_uses(iptr, ssa->s_buf, uses, uses_count);
+ }
+ bptr->phicount = 0;
+ }
+
+ unfix_exception_handlers(ssa->jd);
+
+ ssa->jd->maxlocals = ssa->original.maxlocals;
+ ssa->jd->maxinterfaces = ssa->original.maxinterfaces;
+ ssa->jd->local_map =ssa->original.local_map;
+ ssa->jd->var = ssa->original.var;
+ ssa->jd->vartop = ssa->original.vartop;
+ ssa->jd->varcount = ssa->original.varcount;
+ ssa->jd->localcount = ssa->original.localcount;
+}
+
+#include "vm/rt-timing.h"
+
void yssa(jitdata *jd) {
basicblock *it;
basicblock_info_t *iti;
ssa_info *ssa;
+ struct timespec bs, es, be, ee;
+
+ RT_TIMING_GET_TIME(bs);
+
#ifdef SSA_VERBOSE
- printf("=============== [ before %s ] =========================\n", jd->m->name->text);
- show_method(jd, 3);
- printf("=============== [ /before ] =========================\n");
+ bool verb = true;
+ if (verb) {
+ printf("=============== [ before %s ] =========================\n", jd->m->name->text);
+ show_method(jd, 3);
+ printf("=============== [ /before ] =========================\n");
+ }
#endif
ssa = DNEW(ssa_info);
ssa_info_init(ssa, jd);
+ ssa->keep_in_out = true;
FOR_EACH_BASICBLOCK(jd, it) {
if (basicblock_reached(it)) {
/*ssa_enter_create_phi_graph(ssa);*/
+ RT_TIMING_GET_TIME(be);
escape_analysis_perform(ssa->jd);
+ RT_TIMING_GET_TIME(ee);
+ /*
ssa_leave_create_phi_moves(ssa);
ssa_leave_create_exceptional_phi_moves(ssa);
+ */
+
+#ifdef SSA_VERBOSE
+ if (verb) {
+ printf("=============== [ mid ] =========================\n");
+ show_method(jd, 3);
+ printf("=============== [ /mid ] =========================\n");
+ }
+#endif
+
+ ssa_simple_leave(ssa);
#ifdef SSA_VERBOSE
- printf("=============== [ after ] =========================\n");
- show_method(jd, 3);
- printf("=============== [ /after ] =========================\n");
+ if (verb) {
+ printf("=============== [ after ] =========================\n");
+ show_method(jd, 3);
+ printf("=============== [ /after ] =========================\n");
+ }
#endif
+ RT_TIMING_GET_TIME(es);
+
+ RT_TIMING_TIME_DIFF(bs, es, RT_TIMING_1);
+ RT_TIMING_TIME_DIFF(be, ee, RT_TIMING_2);
}
void eliminate_subbasicblocks(jitdata *jd) {
/* src/vm/jit/optimizing/ssa.c - static single-assignment form
- Copyright (C) 2005 - 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) 2005-2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Christian Ullrich
+*/
- $Id: $
-*/
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include "vm/jit/optimizing/ssa_phi.h"
#if defined(SSA_DEBUG_VERBOSE)
-#include "vmcore/options.h" /* compileverbose */
+#include "vm/options.h" /* compileverbose */
#endif
/* ssa_place_phi_functions *****************************************************
#include "vm/jit/optimizing/ssa_rename.h"
#if defined(SSA_DEBUG_VERBOSE)
-#include "vmcore/options.h" /* compileverbose */
+#include "vm/options.h" /* compileverbose */
#endif
/* function prototypes */
/* src/vm/jit/parisc/arch.h - architecture defines for PA-RISC
- Copyright (C) 2006, 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) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#endif
-#define USE_FAKE_ATOMIC_INSTRUCTIONS 1
-
/* replacement ****************************************************************/
#define REPLACEMENT_PATCH_SIZE 4 /* bytes */
#include "toolbox/logging.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.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/string.hpp"
+#include "vm/suck.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
#include "vm/jit/ir/bytecode.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/suck.h"
#define INSTRUCTIONS_INCREMENT 5 /* number of additional instructions to */
/* allocate if space runs out */
#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;
/* 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.
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)
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);
noinst_HEADERS = \
arch.h \
- machine-instr.h
+ md-atomic.hpp
noinst_LTLIBRARIES = \
libarch.la
.globl asm_cacheflush
- .globl asm_compare_and_swap
- .globl asm_memory_barrier
-
/* asm_vm_call_method **********************************************************
* *
blr
-/* asm_compare_and_swap ********************************************************
-
- XXX
-
-*******************************************************************************/
-
-asm_compare_and_swap:
-1:
- lwarx a6,0,a0
- subf. r0,a6,a1
- bne- 2f
- or r0,a2,a2
- stwcx. r0,0,a0
- bne- 1b
-2:
- mr a0,a6
- blr
-
-
-/* asm_memory_barrier **********************************************************
-
- XXX
-
-*******************************************************************************/
-
-asm_memory_barrier:
- sync
- blr
-
-
#if defined(__DARWIN__)
.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
#include "threads/lock-common.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.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/abi-asm.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/stacktrace.hpp"
#include "vm/jit/trap.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/* codegen *********************************************************************
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 */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ALD(REG_ITMP2, REG_PV, disp);
if (s1 != REG_ITMP1) {
M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
}
else {
M_ISUB(REG_ITMP3, REG_ITMP2, REG_ITMP3);
M_ALD(REG_ITMP2, REG_PV, disp);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-
- CODEGEN_CRITICAL_SECTION_END;
}
M_CMPU(REG_ITMP3, REG_ITMP2);
emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
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);
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMPU(REG_ITMP1, REG_ITMP2);
M_CLR(d);
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_ALD(REG_A0, REG_PV, disp);
}
#include "vm/jit/powerpc/darwin/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* register descripton arrays *************************************************/
#include "vm/jit/powerpc/codegen.h"
#include "vm/jit/powerpc/darwin/md-abi.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/stacktrace.h"
/* md_signal_handler_sigsegv ***************************************************
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t _mc;
- ppc_thread_state_t *_ss;
- u1 *pc;
- u1 *npc;
-
- _mc = _uc->uc_mcontext;
- _ss = &_mc->ss;
-
- pc = (u1 *) _ss->srr0;
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL)
- _ss->srr0 = (ptrint) npc;
-}
-#endif
-
-
/*
* 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
#include "threads/lock-common.h"
-#include "vm/exceptions.h"
+#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "vm/jit/powerpc/linux/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* register descripton arrays *************************************************/
#include "vm/jit/powerpc/md.h"
#include "vm/jit/powerpc/linux/md-abi.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
# include "vm/jit/optimizing/profile.h"
#endif
-#include "vm/jit/stacktrace.h"
#include "vm/jit/trap.h"
-#include "vmcore/system.h"
-
/* md_signal_handler_sigsegv ***************************************************
* the _mc->fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
- system_memcpy(&es->fltregs, &_mc->fpregs.fpregs, sizeof(_mc->fpregs.fpregs));
+ os_memcpy(&es->fltregs, &_mc->fpregs.fpregs, sizeof(_mc->fpregs.fpregs));
}
* the _mc->fpregs[i] can cause invalid conversions. */
assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
- system_memcpy(&_mc->fpregs.fpregs, &es->fltregs, sizeof(_mc->fpregs.fpregs));
+ os_memcpy(&_mc->fpregs.fpregs, &es->fltregs, sizeof(_mc->fpregs.fpregs));
/* write special registers */
_gregs[PT_NIP] = (ptrint) es->pc;
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- unsigned long *_gregs;
- u1 *pc;
- u1 *npc;
-
-#if defined(__UCLIBC__)
- _mc = &(_uc->uc_mcontext);
- _gregs = _mc->regs->gpr;
-#else
- _mc = _uc->uc_mcontext.uc_regs;
- _gregs = _mc->gregs;
-#endif
-
- pc = (u1 *) _gregs[PT_NIP];
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL)
- _gregs[PT_NIP] = (ptrint) npc;
-}
-#endif
-
-
/*
* 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
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-static inline long compare_and_swap(long *p, long oldval, long newval)
-{
- long ret, temp;
-
- __asm__ __volatile__ ("\n\
-1: lwarx %0,0,%4 \n\
- subf. %1,%0,%2 \n\
- bne- 2f \n\
- or %1,%3,%3 \n\
- stwcx. %1,0,%4 \n\
- bne- 1b \n\
-2: \n\
-" : "=&r"(ret), "=&r"(temp)
- : "r"(oldval), "r"(newval), "r"(p) : "cr0", "memory");
-
- return ret;
-}
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("isync" : : : "memory");
-#define MEMORY_BARRIER() __asm__ __volatile__ ( "sync" : : : "memory" );
-
-#endif
--- /dev/null
+/* src/vm/jit/powerpc/md-atomic.hpp - PowerPC atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t temp;
+ uint32_t result;
+
+ __asm__ __volatile__ (
+ "1: \n"
+ " lwarx %0,0,%4 \n"
+ " subf. %1,%0,%2 \n"
+ " bne- 2f \n"
+ " or %1,%3,%3 \n"
+ " stwcx. %1,0,%4 \n"
+ " bne- 1b \n"
+ "2: \n"
+ : "=&r" (result), "=&r" (temp)
+ : "r" (oldval), "r" (newval), "r" (p)
+ : "cr0", "memory");
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ return Atomic::generic_compare_and_swap(p, oldval, newval);
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("sync" : : : "memory");
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ __asm__ __volatile__ ("isync" : : : "memory");
+}
+
+#endif // _MD_ATOMIC_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:
+ */
/* Don't use 8 (could be a normal load offset). */
TRAP_COMPILER = 9,
+ TRAP_COUNTDOWN = 10,
TRAP_END
};
/* src/vm/jit/powerpc/md.c - machine dependent PowerPC functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/powerpc/md.h"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/jit.h"
/* src/vm/jit/powerpc/md.h - machine dependent PowerPC functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/powerpc/codegen.h"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
*******************************************************************************/
-inline static u1 *md_codegen_get_pv_from_pc(u1 *ra)
+inline static void* md_codegen_get_pv_from_pc(void* ra)
{
- u1 *pv;
- u4 mcode;
- s4 offset;
+ int32_t offset;
+
+ uint32_t* pc = (uint32_t*) ra;
/* get first instruction word after jump */
- mcode = *((u4 *) (ra + 1 * 4));
+ uint32_t mcode = pc[1];
/* check if we have 2 instructions (addis, addi) */
if ((mcode >> 16) == 0x3dab) {
/* get displacement of first instruction (addis) */
- offset = (s4) (mcode << 16);
+ offset = (int32_t) (mcode << 16);
/* get displacement of second instruction (addi) */
- mcode = *((u4 *) (ra + 2 * 4));
+ mcode = pc[2];
/* check for addi instruction */
assert((mcode >> 16) == 0x39ad);
- offset += (s2) (mcode & 0x0000ffff);
-
- } else {
+ offset += (int16_t) (mcode & 0x0000ffff);
+ }
+ else {
/* check for addi instruction */
assert((mcode >> 16) == 0x39ab);
/* get offset of first instruction (addi) */
- offset = (s2) (mcode & 0x0000ffff);
+ offset = (int16_t) (mcode & 0x0000ffff);
}
/* calculate PV via RA + offset */
- pv = ra + offset;
+ void* pv = (void*) (((uintptr_t) ra) + offset);
return pv;
}
/* src/vm/jit/powerpc/netbsd/md-os.c - machine dependent PowerPC NetBSD functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#include "vm/jit/powerpc/netbsd/md-abi.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
/* md_signal_handle_sigsegv ****************************************************
}
-#if defined(ENABLE_THREADS)
-void thread_restartcriticalsection(ucontext_t *uc)
-{
- /* XXX set pc to restart address */
-}
-#endif
-
-
/*
* 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
#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/methodheader.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 \
noinst_HEADERS = \
arch.h \
- machine-instr.h
+ md-atomic.hpp
noinst_LTLIBRARIES = libarch.la
#include "threads/lock-common.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/stringlocal.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/abi-asm.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/stacktrace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
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 */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ALD(REG_ITMP2, REG_PV, disp);
if (s1 != REG_ITMP1) {
M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP3, REG_ITMP1, REG_ITMP3);
M_EXTSW(REG_ITMP3, REG_ITMP3);
} else {
M_EXTSW(REG_ITMP3, REG_ITMP3);
M_ALD(REG_ITMP2, REG_PV, disp);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
-
- CODEGEN_CRITICAL_SECTION_END;
-
}
M_CMPU(REG_ITMP3, REG_ITMP2);
emit_classcast_check(cd, iptr, BRANCH_GT, REG_ITMP3, s1);
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);
if (s1 == d) {
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_EXTSW(REG_ITMP1, REG_ITMP1);
M_CMPU(REG_ITMP1, REG_ITMP2);
/* put env into first argument register */
- disp = dseg_add_unique_address(cd, _Jv_env);
+ disp = dseg_add_unique_address(cd, VM_get_jnienv());
M_ALD(REG_A0, REG_PV, disp);
}
#include "threads/lock-common.h"
-#include "vm/exceptions.h"
-#include "vm/vm.h"
+#include "vm/options.h"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "vm/jit/powerpc64/linux/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
-
-#define CACAO_ALIGN(a) do { if ((a) & 1) (a)++; } while (0)
-
/* register descripton array **************************************************/
#include "vm/jit/powerpc64/md.h"
#include "vm/jit/powerpc64/linux/md-abi.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
#if defined(ENABLE_PROFILING)
# include "vm/jit/optimizing/profile.h"
#endif
-#include "vm/jit/stacktrace.h"
#include "vm/jit/trap.h"
#endif
-/* md_critical_section_restart *************************************************
+/* md_executionstate_read ******************************************************
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
+ Read the given context into an executionstate.
*******************************************************************************/
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
+void md_executionstate_read(executionstate_t *es, void *context)
{
- mcontext_t *_mc;
- u1 *pc;
- u1 *npc;
+#if 0
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ unsigned long *_gregs;
+ s4 i;
- _mc = &(_uc->uc_mcontext);
+ _uc = (ucontext_t *) context;
- pc = (u1 *) _mc->gp_regs[PT_NIP];
+ _mc = _uc->uc_mcontext.uc_regs;
+ _gregs = _mc->gregs;
+
+ /* read special registers */
+ es->pc = (u1 *) _gregs[PT_NIP];
+ es->sp = (u1 *) _gregs[REG_SP];
+ es->pv = (u1 *) _gregs[REG_PV];
+ es->ra = (u1 *) _gregs[PT_LNK];
- npc = critical_find_restart_point(pc);
+ /* read integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ es->intregs[i] = _gregs[i];
+
+ /* read float registers */
+ /* Do not use the assignment operator '=', as the type of
+ * the _mc->fpregs[i] can cause invalid conversions. */
+
+ assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
+ os_memcpy(&es->fltregs, &_mc->fpregs.fpregs, sizeof(_mc->fpregs.fpregs));
+#endif
- if (npc != NULL)
- _mc->gp_regs[PT_NIP] = (ptrint) npc;
+ vm_abort("md_executionstate_read: IMPLEMENT ME!");
}
+
+
+/* md_executionstate_write *****************************************************
+
+ Write the given executionstate back to the context.
+
+*******************************************************************************/
+
+void md_executionstate_write(executionstate_t *es, void *context)
+{
+#if 0
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ unsigned long *_gregs;
+ s4 i;
+
+ _uc = (ucontext_t *) context;
+
+ _mc = _uc->uc_mcontext.uc_regs;
+ _gregs = _mc->gregs;
+
+ /* write integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ _gregs[i] = es->intregs[i];
+
+ /* write float registers */
+ /* Do not use the assignment operator '=', as the type of
+ * the _mc->fpregs[i] can cause invalid conversions. */
+
+ assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
+ os_memcpy(&_mc->fpregs.fpregs, &es->fltregs, sizeof(_mc->fpregs.fpregs));
+
+ /* write special registers */
+ _gregs[PT_NIP] = (ptrint) es->pc;
+ _gregs[REG_SP] = (ptrint) es->sp;
+ _gregs[REG_PV] = (ptrint) es->pv;
+ _gregs[PT_LNK] = (ptrint) es->ra;
#endif
+ vm_abort("md_executionstate_write: IMPLEMENT ME!");
+}
+
/*
* These are local overrides for various environment variables in Emacs.
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-static inline long compare_and_swap(long *p, long oldval, long newval)
-{
- long ret, temp;
-
- __asm__ __volatile__ ("\n\
-1: ldarx %0,0,%4 \n\
- subf. %1,%0,%2 \n\
- bne- 2f \n\
- or %1,%3,%3 \n\
- stdcx. %1,0,%4 \n\
- bne- 1b \n\
-2: \n\
-" : "=&r"(ret), "=&r"(temp)
- : "r"(oldval), "r"(newval), "r"(p) : "cr0", "memory");
-
- return ret;
-}
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("isync" : : : "memory");
-#define MEMORY_BARRIER() __asm__ __volatile__ ( "sync" : : : "memory" );
-
-#endif
--- /dev/null
+/* src/vm/jit/powerpc64/atomic.hpp - PowerPC64 atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t temp;
+ uint32_t result;
+
+ __asm__ __volatile__ (
+ "1: \n"
+ " lwarx %0,0,%4 \n"
+ " subf. %1,%0,%2 \n"
+ " bne- 2f \n"
+ " or %1,%3,%3 \n"
+ " stwcx. %1,0,%4 \n"
+ " bne- 1b \n"
+ "2: \n"
+ : "=&r" (result), "=&r" (temp)
+ : "r" (oldval), "r" (newval), "r" (p)
+ : "cr0", "memory");
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ uint64_t temp;
+ uint64_t result;
+
+ __asm__ __volatile__ (
+ "1: \n"
+ " ldarx %0,0,%4 \n"
+ " subf. %1,%0,%2 \n"
+ " bne- 2f \n"
+ " or %1,%3,%3 \n"
+ " stdcx. %1,0,%4 \n"
+ " bne- 1b \n"
+ "2: \n"
+ : "=&r" (result), "=&r" (temp)
+ : "r" (oldval), "r" (newval), "r" (p)
+ : "cr0", "memory");
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("sync" : : : "memory");
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * An instruction memory barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ __asm__ __volatile__ ("isync" : : : "memory");
+}
+
+#endif // _MD_ATOMIC_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:
+ */
/* Don't use 8 (could be a normal load offset). */
TRAP_COMPILER = 9,
+ TRAP_COUNTDOWN = 10,
TRAP_END
};
#include "vm/jit/powerpc64/codegen.h"
#include "vm/jit/powerpc64/md.h"
-#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/jit/jit.h"
/* src/vm/jit/powerpc64/md.h - machine dependent PowerPC functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/powerpc64/codegen.h"
#include "vm/global.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
*******************************************************************************/
-inline static u1 *md_codegen_get_pv_from_pc(u1 *ra)
+inline static void* md_codegen_get_pv_from_pc(void* ra)
{
- u1 *pv;
- u4 mcode;
- s4 offset;
+ int32_t offset;
+
+ uint32_t* pc = (uint32_t*) ra;
/* get first instruction word after jump */
- mcode = *((u4 *) (ra + 1 * 4));
+ uint32_t mcode = pc[1];
/* check if we have 2 instructions (addis, addi) */
if ((mcode >> 16) == 0x3dcb) {
/* get displacement of first instruction (addis) */
- offset = (s4) (mcode << 16);
+ offset = (int32_t) (mcode << 16);
/* get displacement of second instruction (addi) */
- mcode = *((u4 *) (ra + 2 * 4));
+ mcode = pc[2];
/* check for addi instruction */
assert((mcode >> 16) == 0x39ce);
- offset += (s2) (mcode & 0x0000ffff);
+ offset += (int16_t) (mcode & 0x0000ffff);
}
else if ((mcode >> 16) == 0x39cb) {
/* get offset of first instruction (addi) */
- offset = (s2) (mcode & 0x0000ffff);
+ offset = (int16_t) (mcode & 0x0000ffff);
}
else {
vm_abort("md_codegen_get_pv_from_pc: unknown instruction %x", mcode);
/* calculate PV via RA + offset */
- pv = ra + offset;
+ void* pv = (void*) (((uintptr_t) ra) + offset);
return pv;
}
#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/methodheader.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 "vmcore/references.h"
-#include "vm/resolve.h"
/* patcher_patch_code **********************************************************
float f;
double d;
basicblock *retaddr;
+ s4 ii[2];
} vv;
#if defined(ENABLE_VERIFIER)
typeinfo_t typeinfo; /* type info for reference types */
#include "mm/memory.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "vm/stringlocal.h"
+#include "vm/classcache.h"
+#include "vm/globals.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+
+#if defined(ENABLE_RT_TIMING)
+# include "vm/rt-timing.h"
+#endif
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/show.h"
#include "vm/jit/stack.h"
-#include "vmcore/options.h"
-#include "vmcore/classcache.h"
-
#define REPLACE_PATCH_DYNAMIC_CALL
/*#define REPLACE_PATCH_ALL*/
#undef REPLACE_RA_TOP_OF_FRAME
#undef REPLACE_RA_LINKAGE_AREA
#undef REPLACE_LEAFMETHODS_RA_REGISTER
-#undef REPLACE_REG_RA
/* i386, x86_64 and m68k */
#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
#elif defined(__ALPHA__)
#define REPLACE_RA_TOP_OF_FRAME
#define REPLACE_LEAFMETHODS_RA_REGISTER
-#define REPLACE_REG_RA REG_RA
/* powerpc */
#elif defined(__POWERPC__)
#define REPLACE_RA_LINKAGE_AREA
#define REPLACE_LEAFMETHODS_RA_REGISTER
-#define REPLACE_REG_RA REG_ITMP3 /* the execution state has the LR in itmp3 */
/* s390 */
#elif defined(__S390__)
#define REPLACE_RA_TOP_OF_FRAME
-#define REPLACE_REG_RA REG_ITMP3
#endif
replace_read_value(es, &instra, &(frame->instance));
#endif
}
+#if defined(__I386__)
+ else if (!(rp->method->flags & ACC_STATIC)) {
+ /* On i386 we always pass the first argument on stack. */
+ frame->instance.a = *(java_object_t **)(basesp + 1);
+ }
+#endif
#endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
/* read stack slots */
if (!topframe && ra->index == RPLALLOC_PARAM) {
/* skip it */
+ /*
+ ra->index = RPLALLOC_PARAM;
+ replace_val_t v;
+ v.l = 0;
+ replace_write_value(es,ra,&v);
+ */
}
else {
assert(i < frame->javastackdepth);
}
-/* replace_pop_activation_record ***********************************************
+/* md_pop_stackframe ***********************************************************
+
+ Restore callee-saved registers (including the RA register),
+ set the stack pointer to the next stackframe,
+ set the PC to the return address of the popped frame.
- Peel a stack frame from the execution state.
-
*** This function imitates the effects of the method epilog ***
*** and returning from the method call. ***
IN:
- es...............execution state
- frame............source frame, receives synchronization slots
+ es...............execution state
OUT:
*es..............the execution state after popping the stack frame
-
+ NOTE: es->code and es->pv are NOT updated.
+
*******************************************************************************/
-u1* replace_pop_activation_record(executionstate_t *es,
- sourceframe_t *frame)
+void md_pop_stackframe(executionstate_t *es)
{
u1 *ra;
- u1 *pv;
+ s4 ra_align_off;
s4 reg;
s4 i;
- s4 count;
- codeinfo *code;
stackslot_t *basesp;
stackslot_t *sp;
assert(es->code);
- assert(frame);
+
+ /* alignment offset of RA */
+
+ ra_align_off = 0;
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+ if (es->code->stackframesize)
+ ra_align_off = SIZE_OF_STACKSLOT - SIZEOF_VOID_P;
+#endif
/* read the return address */
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
if (code_is_leafmethod(es->code))
- ra = (u1*) (ptrint) es->intregs[REPLACE_REG_RA];
+ ra = es->ra;
else
#endif
ra = md_stacktrace_get_returnaddress(es->sp,
- SIZE_OF_STACKSLOT * es->code->stackframesize);
-
- DOLOG( printf("RA = %p\n", (void*)ra); );
-
- assert(ra);
+ SIZE_OF_STACKSLOT * es->code->stackframesize + ra_align_off);
/* calculate the base of the stack frame */
sp = (stackslot_t *) es->sp;
basesp = sp + es->code->stackframesize;
- /* read slots used for synchronization */
-
- assert(frame->syncslotcount == 0);
- assert(frame->syncslots == NULL);
- count = code_get_sync_slot_count(es->code);
- frame->syncslotcount = count;
- frame->syncslots = DMNEW(replace_val_t, count);
- for (i=0; i<count; ++i) {
- frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX */
- }
-
/* restore return address, if part of frame */
#if defined(REPLACE_RA_TOP_OF_FRAME)
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
if (!code_is_leafmethod(es->code))
#endif
- es->intregs[REPLACE_REG_RA] = *--basesp;
+ es->ra = (u1*) (ptrint) *--basesp;
#endif /* REPLACE_RA_TOP_OF_FRAME */
#if defined(REPLACE_RA_LINKAGE_AREA)
#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
if (!code_is_leafmethod(es->code))
#endif
- es->intregs[REPLACE_REG_RA] = basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
+ es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
#endif /* REPLACE_RA_LINKAGE_AREA */
/* restore saved int registers */
es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
#if defined(REPLACE_RA_BETWEEN_FRAMES)
- es->sp += SIZE_OF_STACKSLOT; /* skip return address */
+ es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
#endif
- /* Set the new pc. Subtract one so we do not hit the replacement point */
- /* of the instruction following the call, if there is one. */
-
- es->pc = ra - 1;
-
- /* find the new codeinfo */
-
- pv = md_codegen_get_pv_from_pc(ra);
- DOLOG( printf("PV = %p\n", (void*) pv); );
-
- code = code_get_codeinfo_for_pv(pv);
- DOLOG( printf("CODE = %p\n", (void*) code); );
-
- /* return NULL if we reached native code */
+ /* set the program counter to the return address */
- es->pv = pv;
- es->code = code;
+ es->pc = ra;
/* in debugging mode clobber non-saved registers */
#if !defined(NDEBUG)
/* for debugging */
for (i=0; i<INT_REG_CNT; ++i)
- if ((nregdescint[i] != REG_SAV)
-#if defined(REG_RA)
- && (i != REPLACE_REG_RA)
-#endif
- )
+ if (nregdescint[i] != REG_SAV)
es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
for (i=0; i<FLT_REG_CNT; ++i)
if (nregdescfloat[i] != REG_SAV)
es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
# endif
#endif /* !defined(NDEBUG) */
+}
+
+
+/* md_push_stackframe **********************************************************
+
+ Save the given return address, build the new stackframe,
+ and store callee-saved registers.
+
+ *** This function imitates the effects of a call and the ***
+ *** method prolog of the callee. ***
+
+ IN:
+ es...............execution state
+ calleecode.......the code we are "calling"
+ ra...............the return address to save
+
+ OUT:
+ *es..............the execution state after pushing the stack frame
+ NOTE: es->pc, es->code, and es->pv are NOT updated.
+
+*******************************************************************************/
+
+void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
+{
+ s4 reg;
+ s4 i;
+ stackslot_t *basesp;
+ stackslot_t *sp;
+
+ assert(es);
+ assert(calleecode);
+
+ /* write the return address */
+
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+ es->sp -= SIZEOF_VOID_P;
+ *((void **)es->sp) = (void *) ra;
+ if (calleecode->stackframesize)
+ es->sp -= (SIZE_OF_STACKSLOT - SIZEOF_VOID_P);
+#endif /* REPLACE_RA_BETWEEN_FRAMES */
+
+ es->ra = (u1*) (ptrint) ra;
+
+ /* build the stackframe */
+
+ DOLOG( printf("building stackframe of %d words at %p\n",
+ calleecode->stackframesize, (void*)es->sp); );
+
+ sp = (stackslot_t *) es->sp;
+ basesp = sp;
+
+ sp -= calleecode->stackframesize;
+ es->sp = (u1*) sp;
+
+ /* in debug mode, invalidate stack frame first */
+
+ /* XXX may not invalidate linkage area used by native code! */
+
+#if !defined(NDEBUG) && 0
+ for (i=0; i< (basesp - sp) && i < 1; ++i) {
+ sp[i] = 0xdeaddeadU;
+ }
+#endif
+
+#if defined(__I386__)
+ /* Stackslot 0 may contain the object instance for vftbl patching.
+ Destroy it, so there's no undefined value used. */
+ if ((basesp - sp) > 0) {
+ sp[0] = 0;
+ }
+#endif
+
+ /* save the return address register */
+
+#if defined(REPLACE_RA_TOP_OF_FRAME)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+ if (!code_is_leafmethod(calleecode))
+#endif
+ *--basesp = (ptrint) ra;
+#endif /* REPLACE_RA_TOP_OF_FRAME */
+
+#if defined(REPLACE_RA_LINKAGE_AREA)
+#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
+ if (!code_is_leafmethod(calleecode))
+#endif
+ basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
+#endif /* REPLACE_RA_LINKAGE_AREA */
+
+ /* save int registers */
+
+ reg = INT_REG_CNT;
+ for (i=0; i<calleecode->savedintcount; ++i) {
+ while (nregdescint[--reg] != REG_SAV)
+ ;
+ *--basesp = es->intregs[reg];
+
+ /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+ es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
+#endif
+ }
+
+ /* save flt registers */
+
+ /* XXX align? */
+ reg = FLT_REG_CNT;
+ for (i=0; i<calleecode->savedfltcount; ++i) {
+ while (nregdescfloat[--reg] != REG_SAV)
+ ;
+ basesp -= STACK_SLOTS_PER_FLOAT;
+ *(double*)basesp = es->fltregs[reg];
+
+ /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+ *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
+#endif
+ }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ /* save adr registers */
+
+ reg = ADR_REG_CNT;
+ for (i=0; i<calleecode->savedadrcount; ++i) {
+ while (nregdescadr[--reg] != REG_SAV)
+ ;
+ *--basesp = es->adrregs[reg];
+
+ /* XXX may not clobber saved regs used by native code! */
+#if !defined(NDEBUG) && 0
+ es->adrregs[reg] = (ptrint) 0x44dead4444dead44ULL;
+#endif
+ }
+#endif
+}
+
+
+/* replace_pop_activation_record ***********************************************
+
+ Peel a stack frame from the execution state.
+
+ *** This function imitates the effects of the method epilog ***
+ *** and returning from the method call. ***
+
+ IN:
+ es...............execution state
+ frame............source frame, receives synchronization slots
+
+ OUT:
+ *es..............the execution state after popping the stack frame
+
+ RETURN VALUE:
+ the return address of the poped activation record
+
+*******************************************************************************/
+
+u1* replace_pop_activation_record(executionstate_t *es,
+ sourceframe_t *frame)
+{
+ u1 *ra;
+ u1 *pv;
+ s4 i;
+ s4 count;
+ codeinfo *code;
+ stackslot_t *sp;
+
+ assert(es->code);
+ assert(frame);
+
+ /* calculate the base of the stack frame */
+
+ sp = (stackslot_t *) es->sp;
+ assert(frame->syncslotcount == 0);
+ assert(frame->syncslots == NULL);
+ count = code_get_sync_slot_count(es->code);
+ frame->syncslotcount = count;
+ frame->syncslots = DMNEW(replace_val_t, count);
+ for (i=0; i<count; ++i) {
+ frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX md_ function */
+ }
+
+ /* pop the stackframe */
+
+ md_pop_stackframe(es);
+
+ ra = es->pc;
+
+ DOLOG( printf("RA = %p\n", (void*)ra); );
+
+ /* Subtract one from the PC so we do not hit the replacement point */
+ /* of the instruction following the call, if there is one. */
+
+ es->pc--;
+
+ /* find the new codeinfo */
+
+ pv = md_codegen_get_pv_from_pc(ra);
+ DOLOG( printf("PV = %p\n", (void*) pv); );
+
+ code = code_get_codeinfo_for_pv(pv);
+ DOLOG( printf("CODE = %p\n", (void*) code); );
+
+ /* return NULL if we reached native code */
+
+ es->pv = pv;
+ es->code = code;
return (code) ? ra : NULL;
}
/* we can only patch such calls if we are at the entry point */
+#if !defined(__I386__)
+ /* On i386 we always know the instance argument. */
if (!atentry)
return;
+#endif
assert((calleem->flags & ACC_STATIC) == 0);
else {
/* the call was statically bound */
+#if defined(__I386__)
+ /* It happens that there is a patcher trap. (pm) */
+ if (*(u2 *)(patchpos - 1) == 0x0b0f) {
+ } else
+#endif
replace_patch_method_pointer((methodptr *) patchpos, entrypoint, "static ");
}
}
sourceframe_t *callerframe,
sourceframe_t *calleeframe)
{
- s4 reg;
s4 i;
s4 count;
- stackslot_t *basesp;
stackslot_t *sp;
u1 *ra;
codeinfo *calleecode;
else
ra = es->pc + 1 /* XXX this is ugly */;
- /* write the return address */
-
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
- es->sp -= SIZE_OF_STACKSLOT;
-
- *((stackslot_t *)es->sp) = (stackslot_t) ra;
-#endif /* REPLACE_RA_BETWEEN_FRAMES */
+ /* push the stackframe */
-#if defined(REPLACE_REG_RA)
- es->intregs[REPLACE_REG_RA] = (ptrint) ra;
-#endif
+ md_push_stackframe(es, calleecode, ra);
- /* we move into a new code unit */
+ /* we move into a new code unit, set code, PC, PV */
es->code = calleecode;
-
- /* set the new pc XXX not needed? */
-
- es->pc = calleecode->entrypoint;
-
- /* build the stackframe */
-
- DOLOG( printf("building stackframe of %d words at %p\n",
- calleecode->stackframesize, (void*)es->sp); );
-
- sp = (stackslot_t *) es->sp;
- basesp = sp;
-
- sp -= calleecode->stackframesize;
- es->sp = (u1*) sp;
-
- /* in debug mode, invalidate stack frame first */
-
- /* XXX may not invalidate linkage area used by native code! */
-#if !defined(NDEBUG) && 0
- for (i=0; i<(basesp - sp); ++i) {
- sp[i] = 0xdeaddeadU;
- }
-#endif
-
- /* save the return address register */
-
-#if defined(REPLACE_RA_TOP_OF_FRAME)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
- if (!code_is_leafmethod(calleecode))
-#endif
- *--basesp = (ptrint) ra;
-#endif /* REPLACE_RA_TOP_OF_FRAME */
-
-#if defined(REPLACE_RA_LINKAGE_AREA)
-#if defined(REPLACE_LEAFMETHODS_RA_REGISTER)
- if (!code_is_leafmethod(calleecode))
-#endif
- basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
-#endif /* REPLACE_RA_LINKAGE_AREA */
-
- /* save int registers */
-
- reg = INT_REG_CNT;
- for (i=0; i<calleecode->savedintcount; ++i) {
- while (nregdescint[--reg] != REG_SAV)
- ;
- *--basesp = es->intregs[reg];
-
- /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
- es->intregs[reg] = (ptrint) 0x44dead4444dead44ULL;
-#endif
- }
-
- /* save flt registers */
-
- /* XXX align? */
- reg = FLT_REG_CNT;
- for (i=0; i<calleecode->savedfltcount; ++i) {
- while (nregdescfloat[--reg] != REG_SAV)
- ;
- basesp -= STACK_SLOTS_PER_FLOAT;
- *(double*)basesp = es->fltregs[reg];
-
- /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
- *(u8*)&(es->fltregs[reg]) = 0x44dead4444dead44ULL;
-#endif
- }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- /* save adr registers */
-
- reg = ADR_REG_CNT;
- for (i=0; i<calleecode->savedadrcount; ++i) {
- while (nregdescadr[--reg] != REG_SAV)
- ;
- *--basesp = es->adrregs[reg];
-
- /* XXX may not clobber saved regs used by native code! */
-#if !defined(NDEBUG) && 0
- es->adrregs[reg] = (ptrint) 0x44dead4444dead44ULL;
-#endif
- }
-#endif
+ es->pc = calleecode->entrypoint; /* XXX not needed? */
+ es->pv = calleecode->entrypoint;
/* write slots used for synchronization */
+ sp = (stackslot_t *) es->sp;
count = code_get_sync_slot_count(calleecode);
assert(count == calleeframe->syncslotcount);
for (i=0; i<count; ++i) {
sp[calleecode->memuse + i] = calleeframe->syncslots[i].p;
}
- /* set the PV */
-
- es->pv = calleecode->entrypoint;
-
/* redirect future invocations */
if (callerframe && rpcall) {
*******************************************************************************/
-rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc)
+rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
{
rplpoint *found;
rplpoint *rp;
rp = code->rplpoints;
for (i=0; i<code->rplpointcount; ++i, ++rp) {
DOLOG( replace_replacement_point_println(rp, 2); );
- if (rp->pc <= pc && rp->pc + rp->callsize >= pc)
- found = rp;
+ if (rp->pc <= pc && rp->pc + rp->callsize >= pc) {
+ if (desired_flags) {
+ if (rp->flags & desired_flags) {
+ found = rp;
+ }
+ } else {
+ found = rp;
+ }
+ }
}
return found;
}
-
/* replace_pop_native_frame ****************************************************
Unroll a native frame in the execution state and create a source frame
/* remember pc and size of native frame */
frame->nativepc = es->pc;
- frame->nativeframesize = (es->sp != 0) ? (sfi->sp - es->sp) : 0;
+ frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
assert(frame->nativeframesize >= 0);
/* remember values of saved registers */
/* XXX michi: use this instead:
es->sp = sfi->sp + code->stackframesize; */
- es->sp = sfi->sp + (*(s4 *) (sfi->pv + FrameSize));
+ es->sp = (void*) (((uintptr_t) sfi->sp) + (*(s4 *) (((uintptr_t) sfi->pv) + FrameSize)));
#if defined(REPLACE_RA_BETWEEN_FRAMES)
es->sp += SIZE_OF_STACKSLOT; /* skip return address */
#endif
es->pv = md_codegen_get_pv_from_pc(sfi->ra);
- es->pc = ((sfi->xpc) ? sfi->xpc : sfi->ra) - 1;
+ es->pc = (void*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
es->code = code_get_codeinfo_for_pv(es->pv);
}
/* skip sp for the native stub */
- es->sp -= (*(s4 *) (frame->sfi->pv + FrameSize));
+ es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
#if defined(REPLACE_RA_BETWEEN_FRAMES)
es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
#endif
/* find the replacement point at the call site */
after_machine_frame:
- rp = replace_find_replacement_point_for_pc(es->code, es->pc);
+ rp = replace_find_replacement_point_for_pc(es->code, es->pc, 0);
if (rp == NULL)
vm_abort("could not find replacement point while unrolling call");
origcode = es->code;
origrp = rp;
+#if defined(ENABLE_TLH)
+ /*printf("Replacing in %s/%s\n", rp->method->clazz->name->text, rp->method->name->text);*/
+#endif
+
+ /*if (strcmp(rp->method->clazz->name->text, "antlr/AlternativeElement") == 0 && strcmp(rp->method->name->text, "getAutoGenType") ==0) opt_TraceReplacement = 2; else opt_TraceReplacement = 0;*/
+
DOLOG_SHORT( printf("REPLACING(%d %p): (id %d %p) ",
stat_replacements, (void*)THREADOBJECT,
rp->id, (void*)rp);
codeinfo *code;
rplpoint *rp;
executionstate_t es;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_end;
+#endif
/* search the codeinfo for the given PC */
/* search for a replacement point at the given PC */
- rp = replace_find_replacement_point_for_pc(code, pc);
+ rp = replace_find_replacement_point_for_pc(code, pc, (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN));
/* check if the replacement point belongs to given PC and is active */
- if ((rp != NULL) && (rp->pc == pc) && (rp->flags & RPLPOINT_FLAG_ACTIVE)) {
+ if ((rp != NULL) && (rp->pc == pc)
+ && (rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))) {
+
+ DOLOG( printf("valid replacement point\n"); );
#if !defined(NDEBUG)
executionstate_sanity_check(context);
/* do the actual replacement */
+#if defined(ENABLE_RT_TIMING)
+ RT_TIMING_GET_TIME(time_start);
+#endif
+
replace_me(rp, &es);
+#if defined(ENABLE_RT_TIMING)
+ RT_TIMING_GET_TIME(time_end);
+ RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_REPLACE);
+#endif
+
/* write execution state to current context */
md_executionstate_write(&es, context);
/* src/vm/jit/replace.h - on-stack replacement of methods
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "arch.h"
#include "md-abi.h"
-#include "vm/jit/reg.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/method.h"
-#include "vmcore/method.h"
+#include "vm/jit/reg.h"
+#include "vm/jit/stacktrace.hpp"
/*** structs *********************************************************/
};
- u1 *ra; /* return address / link register */
struct sourceframe_t {
sourceframe_t *down; /* source frame down the call chain */
noinst_HEADERS = \
arch.h \
- machine-instr.h \
\
- md-asm.h
+ md-asm.h \
+ md-atomic.hpp
noinst_LTLIBRARIES = \
libarch.la
#include "threads/lock-common.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
#include "vm/types.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#if defined(ENABLE_LSRA)
#include "vm/jit/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
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 1
- CODEGEN_CRITICAL_SECTION_START;
-
/* REG_ITMP3 := baseval(s1) */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ALD_DSEG(REG_ITMP2, disp);
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_CMPU(REG_ITMP3, REG_ITMP2); /* Unsigned compare */
/* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD_DSEG(REG_ITMP3, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_ISUB(REG_ITMP3, REG_ITMP2);
M_ALD_DSEG(REG_ITMP3, disp);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_CMPU(REG_ITMP2, REG_ITMP3); /* Unsigned compare */
/* M_CMPULE(REG_ITMP2, REG_ITMP3, REG_ITMP3); itmp3 = (itmp2 <= itmp3) */
/* M_BEQZ(REG_ITMP3, 0); branch if (! itmp) -> branch if > */
# define LABEL_EXIT_INTERFACE_DONE BRANCH_LABEL_5
# define LABEL_EXIT_CLASS_NULL BRANCH_LABEL_6
- 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);
if (s1 == d) {
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD_DSEG(REG_ITMP2, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_ISUB(REG_ITMP3, REG_ITMP1); /* itmp1 := itmp1 (sub.baseval) - itmp3 (super.baseval) */
M_CMPU(REG_ITMP1, REG_ITMP2); /* d := (uint)REG_ITMP1 <= (uint)REG_ITMP2 */
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_ALD_DSEG(REG_A0, disp);
}
#include "threads/lock-common.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/types.h"
+#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-/* Taken from linux kernel source
- * include/asm-s390/atomic.h
- *
- * S390 version
- * Copyright (C) 1999-2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- * Denis Joseph Barrow,
- * Arnd Bergmann (arndb@de.ibm.com)
- *
- * Derived from "include/asm-i386/bitops.h"
- * Copyright (C) 1992, Linus Torvalds
- */
-
-static inline long
-compare_and_swap (volatile long *p, long oldval, long newval)
-{
- __asm__ __volatile__(" cs %0,%3,0(%2)\n"
- : "+d" (oldval), "=m" (*p)
- : "a" (p), "d" (newval), "m" (*p)
- : "cc", "memory" );
- return oldval;
-}
-
-/*
- * Taken from linux kerenl source
- * include/asm-s390/system.h
- *
- * S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- *
- * Derived from "include/asm-i386/system.h"
- */
-
-/*
- * Force strict CPU ordering.
- * And yes, this is required on UP too when we're talking
- * to devices.
- *
- * This is very similar to the ppc eieio/sync instruction in that is
- * does a checkpoint syncronisation & makes sure that
- * all memory ops have completed wrt other CPU's ( see 7-15 POP DJB ).
- */
-
-#define eieio() __asm__ __volatile__ ( "bcr 15,0" : : : "memory" )
-
-#define STORE_ORDER_BARRIER() eieio()
-#define MEMORY_BARRIER() eieio()
-
-/* TODO not sure if the following two can't be just empty. */
-
-#define MEMORY_BARRIER_AFTER_ATOMIC() eieio()
-
-#endif
#include "config.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/types.h"
#include "vm/jit/s390/md-abi.h"
-#include "vmcore/descriptor.h"
-
#include <assert.h>
--- /dev/null
+/* src/vm/jit/s390/md-atomic.hpp - s390 atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ __asm__ __volatile__ (
+ "cs %0,%3,0(%2)\n"
+ : "+d" (oldval), "=m" (*p)
+ : "a" (p), "d" (newval), "m" (*p)
+ : "cc", "memory" );
+
+ return oldval;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ return generic_compare_and_swap(p, oldval, newval);
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("bcr 15,0" : : : "memory" );
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ memory_barrier();
+}
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ memory_barrier();
+}
+
+#endif // _MD_ATOMIC_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:
+ */
TRAP_ClassCastException = 4,
TRAP_CHECK_EXCEPTION = 5,
TRAP_PATCHER = 6,
- TRAP_COMPILER = 7
+ TRAP_COMPILER = 7,
+ TRAP_COUNTDOWN = 8
};
#endif /* _MD_TRAP_H */
#include "vm/jit/s390/md-abi.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/methodtree.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
-#include "vmcore/options.h" /* XXX debug */
+#include "vm/options.h" /* XXX debug */
#include "vm/jit/disass.h" /* XXX debug */
#endif
}
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- u1 *pc;
- void *npc;
-
- _mc = &_uc->uc_mcontext;
-
- pc = (u1 *)_mc->psw.addr;
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL) {
- log_println("%s: pc=%p, npc=%p", __FUNCTION__, pc, npc);
- _mc->psw.addr = (ptrint) npc;
- }
-}
-#endif
-
-
/* md_jit_method_patch_address *************************************************
Gets the patch address of the currently compiled method. The offset
#include "mm/memory.h"
#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/types.h"
+
#include "vm/jit/patcher-common.h"
#include "vm/jit/s390/codegen.h"
#include "vm/jit/s390/md-abi.h"
-#include "vm/jit/stacktrace.h"
-#include "vm/resolve.h"
-#include "vm/types.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
+
#define PATCH_BACK_ORIGINAL_MCODE \
*((u2 *) pr->mpc) = (u2) pr->mcode;
#include "vm/global.h"
#include "vm/builtin.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/jit.h"
#include "vm/jit/stack.h"
#include "vm/jit/parse.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_DEBUG_FILTER)
# include <sys/types.h>
# include <regex.h>
-# include "threads/thread.h"
+# include "threads/thread.hpp"
#endif
/* global variables ***********************************************************/
-#if defined(ENABLE_THREADS) && !defined(NDEBUG)
-static java_object_t *show_global_lock;
+#if !defined(NDEBUG)
+static Mutex* mutex;
#endif
#if defined(ENABLE_THREADS)
/* initialize the show lock */
- show_global_lock = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(show_global_lock);
+ mutex = Mutex_new();
#endif
#if defined(ENABLE_DEBUG_FILTER)
is not reentrant-able and we could not read functions printed
at the same time. */
- LOCK_MONITOR_ENTER(show_global_lock);
+ Mutex_lock(mutex);
#if defined(ENABLE_INTRP)
if (opt_intrp)
}
#endif
- LOCK_MONITOR_EXIT(show_global_lock);
+ Mutex_unlock(mutex);
/* finally flush the output */
}
#endif /* defined(ENABLE_INLINING) */
+#if defined(ENABLE_SSA)
+
+ iptr = bptr->phis;
+
+ for (i = 0; i < bptr->phicount; i++, iptr++) {
+ printf("%4d:%4d: ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
+
+ show_icmd(jd, iptr, deadcode, irstage);
+ printf("\n");
+ }
+#endif
+
iptr = bptr->iinstr;
for (i = 0; i < bptr->icount; i++, iptr++) {
case ICMD_GETEXCEPTION:
SHOW_DST(iptr);
break;
+#if defined(ENABLE_SSA)
+ case ICMD_PHI:
+ printf("[ ");
+ for (i = 0; i < iptr->s1.argcount; ++i) {
+ SHOW_VARIABLE(iptr->sx.s23.s2.iargs[i]->dst.varindex);
+ }
+ printf("] ");
+ SHOW_DST(iptr);
+ if (iptr->flags.bits & (1 << 0)) printf("used ");
+ if (iptr->flags.bits & (1 << 1)) printf("redundantAll ");
+ if (iptr->flags.bits & (1 << 2)) printf("redundantOne ");
+ break;
+#endif
}
fflush(stdout);
}
/* src/vm/jit/show.h - showing the intermediate representation
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
-
- Changes: Edwin Steiner
- Christian Thalinger
- Christian Ullrich
-
-
*/
#ifndef _SHOW_H
#define _SHOW_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include "config.h"
#include "vm/types.h"
int show_filters_test_verbosecall_exit(methodinfo *m);
#endif
+#ifdef __cplusplus
+}
+#endif
#endif /* _SHOW_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
noinst_HEADERS = \
arch.h \
- machine-instr.h \
\
- md-asm.h
+ md-asm.h \
+ md-atomic.hpp
noinst_LTLIBRARIES = libarch.la
#include "native/jni.h"
#include "native/localref.h"
#include "native/native.h"
+
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/sparc64/solaris/macro_rename.h"
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 */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP3, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
M_SUB(REG_ITMP2, REG_ITMP3, REG_ITMP2);
M_ALD(REG_ITMP3, REG_PV, disp);
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
/* } */
M_CMP(REG_ITMP3, REG_ITMP2);
emit_classcast_check(cd, iptr, BRANCH_ULT, REG_ITMP3, s1);
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);
if (s1 == d) {
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, REG_PV, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
- CODEGEN_CRITICAL_SECTION_END;
-
M_SUB(REG_ITMP1, REG_ITMP3, REG_ITMP1);
M_CMP(REG_ITMP1, REG_ITMP2);
M_XCMOVULE_IMM(1, d);
/* put env into first argument register */
- disp = dseg_add_address(cd, _Jv_env);
+ disp = dseg_add_address(cd, VM_get_jnienv());
M_ALD(REG_OUT0, REG_PV_CALLEE, disp);
/* do the native function call */
/* src/vm/jit/sparc64/emit.c - SPARC code emitter functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h" /* XXX for gen_resolvebranch */
+#include "vm/builtin.h"
+#include "vm/options.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
-#include "vm/builtin.h"
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
-#include "vmcore/options.h"
-
#include "vm/jit/sparc64/solaris/macro_rename.h"
/* how to leaf optimization in the emitted stubs?? */
#include "vm/jit/sparc64/md-abi.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
}
}
-#if defined(ENABLE_THREADS)
-/* md_critical_section_restart ************************************************
-
- Search the critical sections tree for a matching section and set
- the NPC to the restart point, if necessary.
-
- Reads PC and modifies NPC.
-
-******************************************************************************/
-
-void md_critical_section_restart(ucontext_t *_uc)
-{
- /* mcontext_t *_mc; */
- sigcontext *ctx;
- u1 *pc;
- u1 *npc;
-
- printf("ignoring md_critical_section_restart\n");
- return;
-
- /* again, we are getting sigcontext instead of ucontext */
- ctx = (sigcontext *) _uc;
-
- pc = (u1 *) ctx->sigc_regs.tpc;
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL) {
- log_println("md_critical_section_restart: pc=%p, npc=%p", pc, npc);
- ctx->sigc_regs.tnpc = (ptrint) npc;
- }
-
-}
-#endif
/*
* These are local overrides for various environment variables in Emacs.
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-#include "toolbox/logging.h"
-
-static inline long
-__attribute__ ((unused))
-compare_and_swap (volatile long *p, long oldval, long newval)
-{
- long ret;
- /*dolog("compare_and_swap(%p [%d], %d, %d)", p, *p, oldval, newval);*/
-
- __asm__ __volatile__ (
- "mov %3,%0\n\t"
- "casx [%4],%2,%0\n\t"
- : "=&r"(ret), "=m"(*p)
- : "r"(oldval), "r"(newval), "r"(p));
-
- /*dolog("compare_and_swap() return=%d mem=%d", ret, *p);*/
- return ret;
-}
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("wmb" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
-#define MEMORY_BARRIER() __asm__ __volatile__ ( \
- "membar 0x0F" : : : "memory" );
-
-#endif
#include "vm/jit/sparc64/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* temp */
#include "mm/memory.h"
#include <assert.h>
--- /dev/null
+/* src/vm/jit/sparc64/atomic.hpp - SPARC64 atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+#if 0
+ // This one should be correct.
+ uint32_t result;
+
+ __asm__ __volatile__ (
+ " mov %3,%0 \n"
+ " cas [%4],%2,%0 \n"
+ : "=&r" (result), "=m" (*p)
+ : "r" (oldval), "r" (newval), "r" (p));
+
+ return result;
+#else
+ return generic_compare_and_swap(p, oldval, newval);
+#endif
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ uint64_t result;
+
+ __asm__ __volatile__ (
+ " mov %3,%0 \n"
+ " casx [%4],%2,%0 \n"
+ : "=&r" (result), "=m" (*p)
+ : "r" (oldval), "r" (newval), "r" (p));
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("membar 0x0F" : : : "memory" );
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("wmb" : : : "memory");
+}
+
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ __asm__ __volatile__ ("mb" : : : "memory");
+}
+
+#endif // _MD_ATOMIC_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:
+ */
/* Don't use 8 (could be a normal load offset). */
TRAP_COMPILER = 9,
+ TRAP_COUNTDOWN = 10,
TRAP_END
};
/* src/vm/jit/sparc64/md.c - machine dependent SPARC64 functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/sparc64/md-abi.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/sparc64/md-abi.h"
#include "native/native.h"
+
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#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.h"
#include "vm/jit/methodheader.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/sparc64/solaris/macro_rename.h"
#include "vm/jit/sparc64/codegen.h"
#include "vm/jit/sparc64/md-abi.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
}
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
-void thread_restartcriticalsection(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- void *critical;
-
- _mc = &_uc->uc_mcontext;
-
- critical = thread_checkcritical((void *) _mc->sc_pc);
-
- if (critical)
- _mc->sc_pc = (ptrint) critical;
-}
-#endif
-
-
/* md_icacheflush **************************************************************
Calls the system's function to flush the instruction cache.
#include "toolbox/logging.h"
-#include "vm/global.h"
#include "vm/builtin.h"
-#include "vm/stringlocal.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
+#include "vm/string.hpp"
#include "vm/types.h"
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
#include "vm/jit/abi.h"
#include "vm/jit/cfg.h"
#include "vm/jit/codegen-common.h"
#endif
#endif
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
/*#define STACK_VERBOSE*/
#include "vm/types.h"
-#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/jit/jit.h"
+++ /dev/null
-/* src/vm/jit/stacktrace.c - machine independent stacktrace system
-
- 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 <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "md.h"
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vm/global.h" /* required here for native includes */
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Throwable.h"
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-# include "native/include/gnu_classpath_Pointer.h"
-# include "native/include/java_lang_VMThrowable.h"
-#endif
-
-#include "threads/thread.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/cycles-stats.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/methodheader.h"
-#include "vm/jit/methodtree.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
-
-/* global variables ***********************************************************/
-
-CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
-CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
-CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
-CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
-CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
-CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
-
-
-/* stacktrace_stackframeinfo_add ***********************************************
-
- Fills a stackframe info structure with the given or calculated
- values and adds it to the chain.
-
-*******************************************************************************/
-
-void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
-{
- stackframeinfo_t *currentsfi;
- codeinfo *code;
-#if defined(ENABLE_JIT)
- s4 framesize;
-#endif
-
- /* Get current stackframe info. */
-
- currentsfi = threads_get_current_stackframeinfo();
-
- /* sometimes we don't have pv handy (e.g. in asmpart.S:
- L_asm_call_jit_compiler_exception or in the interpreter). */
-
- if (pv == NULL) {
-#if defined(ENABLE_INTRP)
- if (opt_intrp)
- pv = methodtree_find(ra);
- else
-#endif
- {
-#if defined(ENABLE_JIT)
-# if defined(__SPARC_64__)
- pv = md_get_pv_from_stackframe(sp);
-# else
- pv = md_codegen_get_pv_from_pc(ra);
-# endif
-#endif
- }
- }
-
- /* Get codeinfo pointer for the parent Java method. */
-
- code = code_get_codeinfo_for_pv(pv);
-
- /* XXX */
- /* assert(m != NULL); */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- /* When using the interpreter, we pass RA to the function. */
-
- if (!opt_intrp) {
-# endif
-# if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
- /* On i386 and x86_64 we always have to get the return address
- from the stack. */
- /* m68k has return address on stack always */
- /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
- the RA from stack. */
-
- framesize = *((u4 *) (pv + FrameSize));
-
- ra = md_stacktrace_get_returnaddress(sp, framesize);
-# else
- /* If the method is a non-leaf function, we need to get the
- return address from the stack. For leaf functions the
- return address is set correctly. This makes the assembler
- and the signal handler code simpler. The code is NULL is
- the asm_vm_call_method special case. */
-
- if ((code == NULL) || !code_is_leafmethod(code)) {
- framesize = *((u4 *) (pv + FrameSize));
-
- ra = md_stacktrace_get_returnaddress(sp, framesize);
- }
-# endif
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif
-
- /* Calculate XPC when not given. The XPC is then the return
- address of the current method minus 1 because the RA points to
- the instruction after the call instruction. This is required
- e.g. for method stubs. */
-
- if (xpc == NULL) {
- xpc = (void *) (((intptr_t) ra) - 1);
- }
-
- /* Fill new stackframeinfo structure. */
-
- sfi->prev = currentsfi;
- sfi->code = code;
- sfi->pv = pv;
- sfi->sp = sp;
- sfi->ra = ra;
- sfi->xpc = xpc;
-
-#if !defined(NDEBUG)
- if (opt_DebugStackFrameInfo) {
- log_start();
- log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
- sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
- method_print(sfi->code->m);
- log_print("]");
- log_finish();
- }
-#endif
-
- /* Store new stackframeinfo pointer. */
-
- threads_set_current_stackframeinfo(sfi);
-
- /* set the native world flag for the current thread */
- /* ATTENTION: This flag tells the GC how to treat this thread in case of
- a collection. Set this flag _after_ a valid stackframe info was set. */
-
- THREAD_NATIVEWORLD_ENTER;
-}
-
-
-/* stacktrace_stackframeinfo_remove ********************************************
-
- Remove the given stackframeinfo from the chain in the current
- thread.
-
-*******************************************************************************/
-
-void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
-{
- /* Clear the native world flag for the current thread. */
- /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
-
- THREAD_NATIVEWORLD_EXIT;
-
-#if !defined(NDEBUG)
- if (opt_DebugStackFrameInfo) {
- log_start();
- log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
- sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
- method_print(sfi->code->m);
- log_print("]");
- log_finish();
- }
-#endif
-
- /* Set previous stackframe info. */
-
- threads_set_current_stackframeinfo(sfi->prev);
-}
-
-
-/* stacktrace_stackframeinfo_fill **********************************************
-
- Fill the temporary stackframeinfo structure with the values given
- in sfi.
-
- IN:
- tmpsfi ... temporary stackframeinfo
- sfi ...... stackframeinfo to be used in the next iteration
-
-*******************************************************************************/
-
-static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
-{
- /* Sanity checks. */
-
- assert(tmpsfi != NULL);
- assert(sfi != NULL);
-
- /* Fill the temporary stackframeinfo. */
-
- tmpsfi->code = sfi->code;
- tmpsfi->pv = sfi->pv;
- tmpsfi->sp = sfi->sp;
- tmpsfi->ra = sfi->ra;
- tmpsfi->xpc = sfi->xpc;
-
- /* Set the previous stackframe info of the temporary one to the
- next in the chain. */
-
- tmpsfi->prev = sfi->prev;
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace fill]");
-#endif
-}
-
-
-/* stacktrace_stackframeinfo_next **********************************************
-
- Walk the stack (or the stackframeinfo-chain) to the next method and
- return the new stackframe values in the temporary stackframeinfo
- passed.
-
- ATTENTION: This function does NOT skip builtin methods!
-
- IN:
- tmpsfi ... temporary stackframeinfo of current method
-
-*******************************************************************************/
-
-static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
-{
- codeinfo *code;
- void *pv;
- void *sp;
- void *ra;
- void *xpc;
- uint32_t framesize;
- stackframeinfo_t *prevsfi;
-
- /* Sanity check. */
-
- assert(tmpsfi != NULL);
-
- /* Get values from the stackframeinfo. */
-
- code = tmpsfi->code;
- pv = tmpsfi->pv;
- sp = tmpsfi->sp;
- ra = tmpsfi->ra;
- xpc = tmpsfi->xpc;
-
- /* Get the current stack frame size. */
-
- framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
-
- /* Get the RA of the current stack frame (RA to the parent Java
- method) if the current method is a non-leaf method. Otherwise
- the value in the stackframeinfo is correct (from the signal
- handler). */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
- else
-# endif
- {
- if (!code_is_leafmethod(code))
- ra = md_stacktrace_get_returnaddress(sp, framesize);
- }
-#else
- ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
-#endif
-
- /* Get the PV for the parent Java method. */
-
-#if defined(ENABLE_INTRP)
- if (opt_intrp)
- pv = methodtree_find(ra);
- else
-#endif
- {
-#if defined(ENABLE_JIT)
-# if defined(__SPARC_64__)
- sp = md_get_framepointer(sp);
- pv = md_get_pv_from_stackframe(sp);
-# else
- pv = md_codegen_get_pv_from_pc(ra);
-# endif
-#endif
- }
-
- /* Get the codeinfo pointer for the parent Java method. */
-
- code = code_get_codeinfo_for_pv(pv);
-
- /* Calculate the SP for the parent Java method. */
-
-#if defined(ENABLE_INTRP)
- if (opt_intrp)
- sp = *(u1 **) (sp - framesize);
- else
-#endif
- {
-#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
- sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
-#elif defined(__SPARC_64__)
- /* already has the new sp */
-#else
- sp = (void *) (((intptr_t) sp) + framesize);
-#endif
- }
-
- /* If the new codeinfo pointer is NULL we reached a
- asm_vm_call_method function. In this case we get the next
- values from the previous stackframeinfo in the chain.
- Otherwise the new values have been calculated before. */
-
- if (code == NULL) {
- prevsfi = tmpsfi->prev;
-
- /* If the previous stackframeinfo in the chain is NULL we
- reached the top of the stacktrace. We set code and prev to
- NULL to mark the end, which is checked in
- stacktrace_stackframeinfo_end_check. */
-
- if (prevsfi == NULL) {
- tmpsfi->code = NULL;
- tmpsfi->prev = NULL;
- return;
- }
-
- /* Fill the temporary stackframeinfo with the new values. */
-
- stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
- }
- else {
- /* Store the new values in the stackframeinfo. NOTE: We
- subtract 1 from the RA to get the XPC, because the RA
- points to the instruction after the call instruction. */
-
- tmpsfi->code = code;
- tmpsfi->pv = pv;
- tmpsfi->sp = sp;
- tmpsfi->ra = ra;
- tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
- }
-
-#if !defined(NDEBUG)
- /* Print current method information. */
-
- if (opt_DebugStackTrace) {
- log_start();
- log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
- tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
- tmpsfi->xpc);
- method_print(tmpsfi->code->m);
- log_print("]");
- log_finish();
- }
-#endif
-}
-
-
-/* stacktrace_stackframeinfo_end_check *****************************************
-
- Check if we reached the end of the stacktrace.
-
- IN:
- tmpsfi ... temporary stackframeinfo of current method
-
- RETURN:
- true .... the end is reached
- false ... the end is not reached
-
-*******************************************************************************/
-
-static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
-{
- /* Sanity check. */
-
- assert(tmpsfi != NULL);
-
- if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace stop]");
-#endif
-
- return true;
- }
-
- return false;
-}
-
-
-/* stacktrace_depth ************************************************************
-
- Calculates and returns the depth of the current stacktrace.
-
- IN:
- sfi ... stackframeinfo where to start the stacktrace
-
- RETURN:
- depth of the stacktrace
-
-*******************************************************************************/
-
-static int stacktrace_depth(stackframeinfo_t *sfi)
-{
- stackframeinfo_t tmpsfi;
- int depth;
- methodinfo *m;
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace_depth]");
-#endif
-
- /* XXX This is not correct, but a workaround for threads-dump for
- now. */
-/* assert(sfi != NULL); */
- if (sfi == NULL)
- return 0;
-
- /* Iterate over all stackframes. */
-
- depth = 0;
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
- /* Get methodinfo. */
-
- m = tmpsfi.code->m;
-
- /* Skip builtin methods. */
-
- if (m->flags & ACC_METHOD_BUILTIN)
- continue;
-
- depth++;
- }
-
- return depth;
-}
-
-
-/* stacktrace_get **************************************************************
-
- Builds and returns a stacktrace starting from the given stackframe
- info and returns the stacktrace structure wrapped in a Java
- byte-array to not confuse the GC.
-
- IN:
- sfi ... stackframe info to start stacktrace from
-
- RETURN:
- stacktrace as Java byte-array
-
-*******************************************************************************/
-
-java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
-{
- stackframeinfo_t tmpsfi;
- int depth;
- java_handle_bytearray_t *ba;
- int32_t ba_size;
- stacktrace_t *st;
- stacktrace_entry_t *ste;
- methodinfo *m;
- bool skip_fillInStackTrace;
- bool skip_init;
-
- CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace_get]");
-#endif
-
- skip_fillInStackTrace = true;
- skip_init = true;
-
- depth = stacktrace_depth(sfi);
-
- if (depth == 0)
- return NULL;
-
- /* Allocate memory from the GC heap and copy the stacktrace
- buffer. */
- /* ATTENTION: Use a Java byte-array for this to not confuse the
- GC. */
- /* FIXME: We waste some memory here as we skip some entries
- later. */
-
- ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
-
- ba = builtin_newarray_byte(ba_size);
-
- if (ba == NULL)
- goto return_NULL;
-
- /* Get a stacktrace entry pointer. */
- /* ATTENTION: We need a critical section here because we use the
- byte-array data pointer directly. */
-
- LLNI_CRITICAL_START;
-
- st = (stacktrace_t *) LLNI_array_data(ba);
-
- ste = st->entries;
-
- /* Iterate over the whole stack. */
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
- /* Get the methodinfo. */
-
- m = tmpsfi.code->m;
-
- /* Skip builtin methods. */
-
- if (m->flags & ACC_METHOD_BUILTIN)
- continue;
-
- /* This logic is taken from
- hotspot/src/share/vm/classfile/javaClasses.cpp
- (java_lang_Throwable::fill_in_stack_trace). */
-
- if (skip_fillInStackTrace == true) {
- /* Check "fillInStackTrace" only once, so we negate the
- flag after the first time check. */
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* For GNU Classpath we also need to skip
- VMThrowable.fillInStackTrace(). */
-
- if ((m->clazz == class_java_lang_VMThrowable) &&
- (m->name == utf_fillInStackTrace))
- continue;
-#endif
-
- skip_fillInStackTrace = false;
-
- if (m->name == utf_fillInStackTrace)
- continue;
- }
-
- /* Skip <init> methods of the exceptions klass. If there is
- <init> methods that belongs to a superclass of the
- exception we are going to skipping them in stack trace. */
-
- if (skip_init == true) {
- if ((m->name == utf_init) &&
- (class_issubclass(m->clazz, class_java_lang_Throwable))) {
- continue;
- }
- else {
- /* If no "Throwable.init()" method found, we stop
- checking it next time. */
-
- skip_init = false;
- }
- }
-
- /* Store the stacktrace entry and increment the pointer. */
-
- ste->code = tmpsfi.code;
- ste->pc = tmpsfi.xpc;
-
- ste++;
- }
-
- /* Store the number of entries in the stacktrace structure. */
-
- st->length = ste - st->entries;
-
- LLNI_CRITICAL_END;
-
- /* release dump memory */
-
-/* dump_release(dumpsize); */
-
- CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
- stacktrace_overhead)
- return ba;
-
-return_NULL:
-/* dump_release(dumpsize); */
-
- CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
- stacktrace_overhead)
-
- return NULL;
-}
-
-
-/* stacktrace_get_current ******************************************************
-
- Builds and returns a stacktrace from the current thread and returns
- the stacktrace structure wrapped in a Java byte-array to not
- confuse the GC.
-
- RETURN:
- stacktrace as Java byte-array
-
-*******************************************************************************/
-
-java_handle_bytearray_t *stacktrace_get_current(void)
-{
- stackframeinfo_t *sfi;
- java_handle_bytearray_t *ba;
-
- sfi = threads_get_current_stackframeinfo();
- ba = stacktrace_get(sfi);
-
- return ba;
-}
-
-
-/* stacktrace_get_caller_class *************************************************
-
- Get the class on the stack at the given depth. This function skips
- various special classes or methods.
-
- ARGUMENTS:
- depth ... depth to get caller class of
-
- RETURN:
- caller class
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-classinfo *stacktrace_get_caller_class(int depth)
-{
- stackframeinfo_t *sfi;
- stackframeinfo_t tmpsfi;
- methodinfo *m;
- classinfo *c;
- int i;
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace_get_caller_class]");
-#endif
-
- /* Get the stackframeinfo of the current thread. */
-
- sfi = threads_get_current_stackframeinfo();
-
- /* Iterate over the whole stack until we reached the requested
- depth. */
-
- i = 0;
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
-
- m = tmpsfi.code->m;
- c = m->clazz;
-
- /* Skip builtin methods. */
-
- if (m->flags & ACC_METHOD_BUILTIN)
- continue;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
- (vframeStreamCommon::security_get_caller_frame). */
-
- /* This is java.lang.reflect.Method.invoke(), skip it. */
-
- if (m == method_java_lang_reflect_Method_invoke)
- continue;
-
- /* This is an auxiliary frame, skip it. */
-
- if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
- continue;
-#endif
-
- /* We reached the requested depth. */
-
- if (i >= depth)
- return c;
-
- i++;
- }
-
- return NULL;
-}
-#endif
-
-
-/* stacktrace_first_nonnull_classloader ****************************************
-
- Returns the first non-null (user-defined) classloader on the stack.
- If none is found NULL is returned.
-
- RETURN:
- classloader
-
-*******************************************************************************/
-
-classloader_t *stacktrace_first_nonnull_classloader(void)
-{
- stackframeinfo_t *sfi;
- stackframeinfo_t tmpsfi;
- methodinfo *m;
- classloader_t *cl;
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace_first_nonnull_classloader]");
-#endif
-
- /* Get the stackframeinfo of the current thread. */
-
- sfi = threads_get_current_stackframeinfo();
-
- /* Iterate over the whole stack. */
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
-
- m = tmpsfi.code->m;
- cl = class_get_classloader(m->clazz);
-
- if (cl != NULL)
- return cl;
- }
-
- return NULL;
-}
-
-
-/* stacktrace_getClassContext **************************************************
-
- Creates a Class context array.
-
- RETURN VALUE:
- the array of java.lang.Class objects, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-java_handle_objectarray_t *stacktrace_getClassContext(void)
-{
- stackframeinfo_t *sfi;
- stackframeinfo_t tmpsfi;
- int depth;
- java_handle_objectarray_t *oa;
- java_object_t **data;
- int i;
- methodinfo *m;
-
- CYCLES_STATS_DECLARE_AND_START
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace_getClassContext]");
-#endif
-
- sfi = threads_get_current_stackframeinfo();
-
- /* Get the depth of the current stack. */
-
- depth = stacktrace_depth(sfi);
-
- /* The first stackframe corresponds to the method whose
- implementation calls this native function. We remove that
- entry. */
-
- depth--;
- stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_next(&tmpsfi);
-
- /* Allocate the Class array. */
-
- oa = builtin_anewarray(depth, class_java_lang_Class);
-
- if (oa == NULL) {
- CYCLES_STATS_END(stacktrace_getClassContext);
-
- return NULL;
- }
-
- /* Fill the Class array from the stacktrace list. */
-
- LLNI_CRITICAL_START;
-
- data = LLNI_array_data(oa);
-
- /* Iterate over the whole stack. */
-
- i = 0;
-
- for (;
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
- /* Get methodinfo. */
-
- m = tmpsfi.code->m;
-
- /* Skip builtin methods. */
-
- if (m->flags & ACC_METHOD_BUILTIN)
- continue;
-
- /* Store the class in the array. */
-
- data[i] = (java_object_t *) m->clazz;
-
- i++;
- }
-
- LLNI_CRITICAL_END;
-
- CYCLES_STATS_END(stacktrace_getClassContext)
-
- return oa;
-}
-
-
-/* stacktrace_getCurrentClass **************************************************
-
- Find the current class by walking the stack trace.
-
- Quote from the JNI documentation:
-
- In the Java 2 Platform, FindClass locates the class loader
- associated with the current native method. If the native code
- belongs to a system class, no class loader will be
- involved. Otherwise, the proper class loader will be invoked to
- load and link the named class. When FindClass is called through the
- Invocation Interface, there is no current native method or its
- associated class loader. In that case, the result of
- ClassLoader.getBaseClassLoader is used."
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-classinfo *stacktrace_get_current_class(void)
-{
- stackframeinfo_t *sfi;
- stackframeinfo_t tmpsfi;
- methodinfo *m;
-
- CYCLES_STATS_DECLARE_AND_START;
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace_get_current_class]");
-#endif
-
- /* Get the stackframeinfo of the current thread. */
-
- sfi = threads_get_current_stackframeinfo();
-
- /* If the stackframeinfo is NULL then FindClass is called through
- the Invocation Interface and we return NULL */
-
- if (sfi == NULL) {
- CYCLES_STATS_END(stacktrace_getCurrentClass);
-
- return NULL;
- }
-
- /* Iterate over the whole stack. */
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
- /* Get the methodinfo. */
-
- m = tmpsfi.code->m;
-
- if (m->clazz == class_java_security_PrivilegedAction) {
- CYCLES_STATS_END(stacktrace_getCurrentClass);
-
- return NULL;
- }
-
- if (m->clazz != NULL) {
- CYCLES_STATS_END(stacktrace_getCurrentClass);
-
- return m->clazz;
- }
- }
-
- /* No Java method found on the stack. */
-
- CYCLES_STATS_END(stacktrace_getCurrentClass);
-
- return NULL;
-}
-#endif /* ENABLE_JAVASE */
-
-
-/* stacktrace_get_stack ********************************************************
-
- Create a 2-dimensional array for java.security.VMAccessControler.
-
- RETURN VALUE:
- the arrary, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-java_handle_objectarray_t *stacktrace_get_stack(void)
-{
- stackframeinfo_t *sfi;
- stackframeinfo_t tmpsfi;
- int depth;
- java_handle_objectarray_t *oa;
- java_handle_objectarray_t *classes;
- java_handle_objectarray_t *methodnames;
- methodinfo *m;
- java_handle_t *string;
- int i;
-
- CYCLES_STATS_DECLARE_AND_START
-
-#if !defined(NDEBUG)
- if (opt_DebugStackTrace)
- log_println("[stacktrace_get_stack]");
-#endif
-
- /* Get the stackframeinfo of the current thread. */
-
- sfi = threads_get_current_stackframeinfo();
-
- /* Get the depth of the current stack. */
-
- depth = stacktrace_depth(sfi);
-
- if (depth == 0)
- return NULL;
-
- /* Allocate the required arrays. */
-
- oa = builtin_anewarray(2, arrayclass_java_lang_Object);
-
- if (oa == NULL)
- goto return_NULL;
-
- classes = builtin_anewarray(depth, class_java_lang_Class);
-
- if (classes == NULL)
- goto return_NULL;
-
- methodnames = builtin_anewarray(depth, class_java_lang_String);
-
- if (methodnames == NULL)
- goto return_NULL;
-
- /* Set up the 2-dimensional array. */
-
- array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
- array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
-
- /* Iterate over the whole stack. */
- /* TODO We should use a critical section here to speed things
- up. */
-
- i = 0;
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
- /* Get the methodinfo. */
-
- m = tmpsfi.code->m;
-
- /* Skip builtin methods. */
-
- if (m->flags & ACC_METHOD_BUILTIN)
- continue;
-
- /* Store the class in the array. */
- /* NOTE: We use a LLNI-macro here, because a classinfo is not
- a handle. */
-
- LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
-
- /* Store the name in the array. */
-
- string = javastring_new(m->name);
-
- if (string == NULL)
- goto return_NULL;
-
- array_objectarray_element_set(methodnames, i, string);
-
- i++;
- }
-
- CYCLES_STATS_END(stacktrace_get_stack)
-
- return oa;
-
-return_NULL:
- CYCLES_STATS_END(stacktrace_get_stack)
-
- return NULL;
-}
-#endif
-
-
-/* stacktrace_print_entry ****************************************************
-
- Print line for a stacktrace entry.
-
- ARGUMENTS:
- m ............ methodinfo of the entry
- linenumber ... linenumber of the entry
-
-*******************************************************************************/
-
-static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
-{
- /* Sanity check. */
-
- assert(m != NULL);
-
- printf("\tat ");
-
- if (m->flags & ACC_METHOD_BUILTIN)
- printf("NULL");
- else
- utf_display_printable_ascii_classname(m->clazz->name);
-
- printf(".");
- utf_display_printable_ascii(m->name);
- utf_display_printable_ascii(m->descriptor);
-
- if (m->flags & ACC_NATIVE) {
- puts("(Native Method)");
- }
- else {
- if (m->flags & ACC_METHOD_BUILTIN) {
- puts("(builtin)");
- }
- else {
- printf("(");
- utf_display_printable_ascii(m->clazz->sourcefile);
- printf(":%d)\n", linenumber);
- }
- }
-
- fflush(stdout);
-}
-
-
-/* stacktrace_print ************************************************************
-
- Print the given stacktrace with CACAO intern methods only (no Java
- code required).
-
- This method is used by stacktrace_dump_trace and
- builtin_trace_exception.
-
- IN:
- st ... stacktrace to print
-
-*******************************************************************************/
-
-void stacktrace_print(stacktrace_t *st)
-{
- stacktrace_entry_t *ste;
- methodinfo *m;
- int32_t linenumber;
- int i;
-
- ste = &(st->entries[0]);
-
- for (i = 0; i < st->length; i++, ste++) {
- m = ste->code->m;
-
- /* Get the line number. */
-
- linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
-
- stacktrace_print_entry(m, linenumber);
- }
-}
-
-
-/* stacktrace_print_current ****************************************************
-
- Print the current stacktrace of the current thread.
-
- NOTE: This function prints all frames of the stacktrace and does
- not skip frames like stacktrace_get.
-
-*******************************************************************************/
-
-void stacktrace_print_current(void)
-{
- stackframeinfo_t *sfi;
- stackframeinfo_t tmpsfi;
- codeinfo *code;
- methodinfo *m;
- int32_t linenumber;
-
- sfi = threads_get_current_stackframeinfo();
-
- if (sfi == NULL) {
- puts("\t<<No stacktrace available>>");
- fflush(stdout);
- return;
- }
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
- /* Get the methodinfo. */
-
- code = tmpsfi.code;
- m = code->m;
-
- /* Get the line number. */
-
- linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
-
- stacktrace_print_entry(m, linenumber);
- }
-}
-
-
-/* stacktrace_print_of_thread **************************************************
-
- Print the current stacktrace of the given thread.
-
- ARGUMENTS:
- t ... thread
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void stacktrace_print_of_thread(threadobject *t)
-{
- stackframeinfo_t *sfi;
- stackframeinfo_t tmpsfi;
- codeinfo *code;
- methodinfo *m;
- int32_t linenumber;
-
- /* Build a stacktrace for the passed thread. */
-
- sfi = t->_stackframeinfo;
-
- if (sfi == NULL) {
- puts("\t<<No stacktrace available>>");
- fflush(stdout);
- return;
- }
-
- for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
- stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
- stacktrace_stackframeinfo_next(&tmpsfi)) {
- /* Get the methodinfo. */
-
- code = tmpsfi.code;
- m = code->m;
-
- /* Get the line number. */
-
- linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
-
- stacktrace_print_entry(m, linenumber);
- }
-}
-#endif
-
-
-/* stacktrace_print_exception **************************************************
-
- Print the stacktrace of a given exception (more or less a wrapper
- to stacktrace_print).
-
- IN:
- h ... handle of exception to print
-
-*******************************************************************************/
-
-void stacktrace_print_exception(java_handle_t *h)
-{
- java_lang_Throwable *o;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- java_lang_VMThrowable *vmt;
-#endif
-
- java_lang_Object *backtrace;
- java_handle_bytearray_t *ba;
- stacktrace_t *st;
-
- o = (java_lang_Throwable *) h;
-
- if (o == NULL)
- return;
-
- /* now print the stacktrace */
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- LLNI_field_get_ref(o, vmState, vmt);
- LLNI_field_get_ref(vmt, vmdata, backtrace);
-
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- LLNI_field_get_ref(o, backtrace, backtrace);
-
-#else
-# error unknown classpath configuration
-#endif
-
- ba = (java_handle_bytearray_t *) backtrace;
-
- /* Sanity check. */
-
- assert(ba != NULL);
-
- /* We need a critical section here as we use the byte-array data
- pointer directly. */
-
- LLNI_CRITICAL_START;
-
- st = (stacktrace_t *) LLNI_array_data(ba);
-
- stacktrace_print(st);
-
- LLNI_CRITICAL_END;
-}
-
-
-#if defined(ENABLE_CYCLES_STATS)
-void stacktrace_print_cycles_stats(FILE *file)
-{
- CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
- CYCLES_STATS_PRINT(stacktrace_get, file);
- CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
- CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
- CYCLES_STATS_PRINT(stacktrace_get_stack, file);
-}
-#endif
-
-
-/*
- * 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/jit/stacktrace.cpp - machine independent stacktrace system
+
+ 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 <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vm/types.h"
+
+#include "md.h"
+
+#include "mm/gc.hpp"
+#include "mm/memory.h"
+
+#include "vm/jit/stacktrace.hpp"
+
+#include "vm/global.h" /* required here for native includes */
+#include "native/jni.h"
+#include "native/llni.h"
+
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/cycles-stats.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/linenumbertable.h"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/methodtree.h"
+
+
+// FIXME Use C-linkage for now.
+extern "C" {
+
+/* global variables ***********************************************************/
+
+CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
+CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
+CYCLES_STATS_DECLARE(stacktrace_get, 40, 5000)
+CYCLES_STATS_DECLARE(stacktrace_getClassContext , 40, 5000)
+CYCLES_STATS_DECLARE(stacktrace_getCurrentClass , 40, 5000)
+CYCLES_STATS_DECLARE(stacktrace_get_stack , 40, 10000)
+
+
+/* stacktrace_stackframeinfo_add ***********************************************
+
+ Fills a stackframe info structure with the given or calculated
+ values and adds it to the chain.
+
+*******************************************************************************/
+
+void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc)
+{
+ stackframeinfo_t *currentsfi;
+ codeinfo *code;
+#if defined(ENABLE_JIT)
+ s4 framesize;
+#endif
+
+ /* Get current stackframe info. */
+
+ currentsfi = threads_get_current_stackframeinfo();
+
+ /* sometimes we don't have pv handy (e.g. in asmpart.S:
+ L_asm_call_jit_compiler_exception or in the interpreter). */
+
+ if (pv == NULL) {
+#if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ pv = methodtree_find(ra);
+ else
+#endif
+ {
+#if defined(ENABLE_JIT)
+# if defined(__SPARC_64__)
+ pv = md_get_pv_from_stackframe(sp);
+# else
+ pv = md_codegen_get_pv_from_pc(ra);
+# endif
+#endif
+ }
+ }
+
+ /* Get codeinfo pointer for the parent Java method. */
+
+ code = code_get_codeinfo_for_pv(pv);
+
+ /* XXX */
+ /* assert(m != NULL); */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ /* When using the interpreter, we pass RA to the function. */
+
+ if (!opt_intrp) {
+# endif
+# if defined(__I386__) || defined(__X86_64__) || defined(__S390__) || defined(__M68K__)
+ /* On i386 and x86_64 we always have to get the return address
+ from the stack. */
+ /* m68k has return address on stack always */
+ /* On S390 we use REG_RA as REG_ITMP3, so we have always to get
+ the RA from stack. */
+
+ framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
+
+ ra = md_stacktrace_get_returnaddress(sp, framesize);
+# else
+ /* If the method is a non-leaf function, we need to get the
+ return address from the stack. For leaf functions the
+ return address is set correctly. This makes the assembler
+ and the signal handler code simpler. The code is NULL is
+ the asm_vm_call_method special case. */
+
+ if ((code == NULL) || !code_is_leafmethod(code)) {
+ framesize = *((u4 *) (((uintptr_t) pv) + FrameSize));
+
+ ra = md_stacktrace_get_returnaddress(sp, framesize);
+ }
+# endif
+# if defined(ENABLE_INTRP)
+ }
+# endif
+#endif
+
+ /* Calculate XPC when not given. The XPC is then the return
+ address of the current method minus 1 because the RA points to
+ the instruction after the call instruction. This is required
+ e.g. for method stubs. */
+
+ if (xpc == NULL) {
+ xpc = (void *) (((intptr_t) ra) - 1);
+ }
+
+ /* Fill new stackframeinfo structure. */
+
+ sfi->prev = currentsfi;
+ sfi->code = code;
+ sfi->pv = pv;
+ sfi->sp = sp;
+ sfi->ra = ra;
+ sfi->xpc = xpc;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackFrameInfo) {
+ log_start();
+ log_print("[stackframeinfo add : sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
+ sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
+ method_print(sfi->code->m);
+ log_print("]");
+ log_finish();
+ }
+#endif
+
+ /* Store new stackframeinfo pointer. */
+
+ threads_set_current_stackframeinfo(sfi);
+
+ /* set the native world flag for the current thread */
+ /* ATTENTION: This flag tells the GC how to treat this thread in case of
+ a collection. Set this flag _after_ a valid stackframe info was set. */
+
+ THREAD_NATIVEWORLD_ENTER;
+}
+
+
+/* stacktrace_stackframeinfo_remove ********************************************
+
+ Remove the given stackframeinfo from the chain in the current
+ thread.
+
+*******************************************************************************/
+
+void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
+{
+ /* Clear the native world flag for the current thread. */
+ /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
+
+ THREAD_NATIVEWORLD_EXIT;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackFrameInfo) {
+ log_start();
+ log_print("[stackframeinfo remove: sfi=%p, method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
+ sfi, sfi->code->m, sfi->pv, sfi->sp, sfi->ra, sfi->xpc);
+ method_print(sfi->code->m);
+ log_print("]");
+ log_finish();
+ }
+#endif
+
+ /* Set previous stackframe info. */
+
+ threads_set_current_stackframeinfo(sfi->prev);
+}
+
+
+/* stacktrace_stackframeinfo_fill **********************************************
+
+ Fill the temporary stackframeinfo structure with the values given
+ in sfi.
+
+ IN:
+ tmpsfi ... temporary stackframeinfo
+ sfi ...... stackframeinfo to be used in the next iteration
+
+*******************************************************************************/
+
+static inline void stacktrace_stackframeinfo_fill(stackframeinfo_t *tmpsfi, stackframeinfo_t *sfi)
+{
+ /* Sanity checks. */
+
+ assert(tmpsfi != NULL);
+ assert(sfi != NULL);
+
+ /* Fill the temporary stackframeinfo. */
+
+ tmpsfi->code = sfi->code;
+ tmpsfi->pv = sfi->pv;
+ tmpsfi->sp = sfi->sp;
+ tmpsfi->ra = sfi->ra;
+ tmpsfi->xpc = sfi->xpc;
+
+ /* Set the previous stackframe info of the temporary one to the
+ next in the chain. */
+
+ tmpsfi->prev = sfi->prev;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace fill]");
+#endif
+}
+
+
+/* stacktrace_stackframeinfo_next **********************************************
+
+ Walk the stack (or the stackframeinfo-chain) to the next method and
+ return the new stackframe values in the temporary stackframeinfo
+ passed.
+
+ ATTENTION: This function does NOT skip builtin methods!
+
+ IN:
+ tmpsfi ... temporary stackframeinfo of current method
+
+*******************************************************************************/
+
+static inline void stacktrace_stackframeinfo_next(stackframeinfo_t *tmpsfi)
+{
+ codeinfo *code;
+ void *pv;
+ void *sp;
+ void *ra;
+ void *xpc;
+ uint32_t framesize;
+ stackframeinfo_t *prevsfi;
+
+ /* Sanity check. */
+
+ assert(tmpsfi != NULL);
+
+ /* Get values from the stackframeinfo. */
+
+ code = tmpsfi->code;
+ pv = tmpsfi->pv;
+ sp = tmpsfi->sp;
+ ra = tmpsfi->ra;
+ xpc = tmpsfi->xpc;
+
+ /* Get the current stack frame size. */
+
+ framesize = *((uint32_t *) (((intptr_t) pv) + FrameSize));
+
+ /* Get the RA of the current stack frame (RA to the parent Java
+ method) if the current method is a non-leaf method. Otherwise
+ the value in the stackframeinfo is correct (from the signal
+ handler). */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
+ else
+# endif
+ {
+ if (!code_is_leafmethod(code))
+ ra = md_stacktrace_get_returnaddress(sp, framesize);
+ }
+#else
+ ra = intrp_md_stacktrace_get_returnaddress(sp, framesize);
+#endif
+
+ /* Get the PV for the parent Java method. */
+
+#if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ pv = methodtree_find(ra);
+ else
+#endif
+ {
+#if defined(ENABLE_JIT)
+# if defined(__SPARC_64__)
+ sp = md_get_framepointer(sp);
+ pv = md_get_pv_from_stackframe(sp);
+# else
+ pv = md_codegen_get_pv_from_pc(ra);
+# endif
+#endif
+ }
+
+ /* Get the codeinfo pointer for the parent Java method. */
+
+ code = code_get_codeinfo_for_pv(pv);
+
+ /* Calculate the SP for the parent Java method. */
+
+#if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ sp = *(u1 **) (sp - framesize);
+ else
+#endif
+ {
+#if defined(__I386__) || defined (__X86_64__) || defined (__M68K__)
+ sp = (void *) (((intptr_t) sp) + framesize + SIZEOF_VOID_P);
+#elif defined(__SPARC_64__)
+ /* already has the new sp */
+#else
+ sp = (void *) (((intptr_t) sp) + framesize);
+#endif
+ }
+
+ /* If the new codeinfo pointer is NULL we reached a
+ asm_vm_call_method function. In this case we get the next
+ values from the previous stackframeinfo in the chain.
+ Otherwise the new values have been calculated before. */
+
+ if (code == NULL) {
+ prevsfi = tmpsfi->prev;
+
+ /* If the previous stackframeinfo in the chain is NULL we
+ reached the top of the stacktrace. We set code and prev to
+ NULL to mark the end, which is checked in
+ stacktrace_stackframeinfo_end_check. */
+
+ if (prevsfi == NULL) {
+ tmpsfi->code = NULL;
+ tmpsfi->prev = NULL;
+ return;
+ }
+
+ /* Fill the temporary stackframeinfo with the new values. */
+
+ stacktrace_stackframeinfo_fill(tmpsfi, prevsfi);
+ }
+ else {
+ /* Store the new values in the stackframeinfo. NOTE: We
+ subtract 1 from the RA to get the XPC, because the RA
+ points to the instruction after the call instruction. */
+
+ tmpsfi->code = code;
+ tmpsfi->pv = pv;
+ tmpsfi->sp = sp;
+ tmpsfi->ra = ra;
+ tmpsfi->xpc = (void *) (((intptr_t) ra) - 1);
+ }
+
+#if !defined(NDEBUG)
+ /* Print current method information. */
+
+ if (opt_DebugStackTrace) {
+ log_start();
+ log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
+ tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
+ tmpsfi->xpc);
+ method_print(tmpsfi->code->m);
+ log_print("]");
+ log_finish();
+ }
+#endif
+}
+
+
+/* stacktrace_stackframeinfo_end_check *****************************************
+
+ Check if we reached the end of the stacktrace.
+
+ IN:
+ tmpsfi ... temporary stackframeinfo of current method
+
+ RETURN:
+ true .... the end is reached
+ false ... the end is not reached
+
+*******************************************************************************/
+
+static inline bool stacktrace_stackframeinfo_end_check(stackframeinfo_t *tmpsfi)
+{
+ /* Sanity check. */
+
+ assert(tmpsfi != NULL);
+
+ if ((tmpsfi->code == NULL) && (tmpsfi->prev == NULL)) {
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace stop]");
+#endif
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/* stacktrace_depth ************************************************************
+
+ Calculates and returns the depth of the current stacktrace.
+
+ IN:
+ sfi ... stackframeinfo where to start the stacktrace
+
+ RETURN:
+ depth of the stacktrace
+
+*******************************************************************************/
+
+static int stacktrace_depth(stackframeinfo_t *sfi)
+{
+ stackframeinfo_t tmpsfi;
+ int depth;
+ methodinfo *m;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_depth]");
+#endif
+
+ /* XXX This is not correct, but a workaround for threads-dump for
+ now. */
+/* assert(sfi != NULL); */
+ if (sfi == NULL)
+ return 0;
+
+ /* Iterate over all stackframes. */
+
+ depth = 0;
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get methodinfo. */
+
+ m = tmpsfi.code->m;
+
+ /* Skip builtin methods. */
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ continue;
+
+ depth++;
+ }
+
+ return depth;
+}
+
+
+/* stacktrace_get **************************************************************
+
+ Builds and returns a stacktrace starting from the given stackframe
+ info and returns the stacktrace structure wrapped in a Java
+ byte-array to not confuse the GC.
+
+ IN:
+ sfi ... stackframe info to start stacktrace from
+
+ RETURN:
+ stacktrace as Java byte-array
+
+*******************************************************************************/
+
+java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
+{
+ stackframeinfo_t tmpsfi;
+ int depth;
+ java_handle_bytearray_t *ba;
+ int32_t ba_size;
+ stacktrace_t *st;
+ stacktrace_entry_t *ste;
+ methodinfo *m;
+ bool skip_fillInStackTrace;
+ bool skip_init;
+
+ CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_get]");
+#endif
+
+ skip_fillInStackTrace = true;
+ skip_init = true;
+
+ depth = stacktrace_depth(sfi);
+
+ if (depth == 0)
+ return NULL;
+
+ /* Allocate memory from the GC heap and copy the stacktrace
+ buffer. */
+ /* ATTENTION: Use a Java byte-array for this to not confuse the
+ GC. */
+ /* FIXME: We waste some memory here as we skip some entries
+ later. */
+
+ ba_size = sizeof(stacktrace_t) + sizeof(stacktrace_entry_t) * depth;
+
+ ba = builtin_newarray_byte(ba_size);
+
+ if (ba == NULL)
+ goto return_NULL;
+
+ /* Get a stacktrace entry pointer. */
+ /* ATTENTION: We need a critical section here because we use the
+ byte-array data pointer directly. */
+
+ LLNI_CRITICAL_START;
+
+ st = (stacktrace_t *) LLNI_array_data(ba);
+
+ ste = st->entries;
+
+ /* Iterate over the whole stack. */
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get the methodinfo. */
+
+ m = tmpsfi.code->m;
+
+ /* Skip builtin methods. */
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ continue;
+
+ /* This logic is taken from
+ hotspot/src/share/vm/classfile/javaClasses.cpp
+ (java_lang_Throwable::fill_in_stack_trace). */
+
+ if (skip_fillInStackTrace == true) {
+ /* Check "fillInStackTrace" only once, so we negate the
+ flag after the first time check. */
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ /* For GNU Classpath we also need to skip
+ VMThrowable.fillInStackTrace(). */
+
+ if ((m->clazz == class_java_lang_VMThrowable) &&
+ (m->name == utf_fillInStackTrace))
+ continue;
+#endif
+
+ skip_fillInStackTrace = false;
+
+ if (m->name == utf_fillInStackTrace)
+ continue;
+ }
+
+ /* Skip <init> methods of the exceptions klass. If there is
+ <init> methods that belongs to a superclass of the
+ exception we are going to skipping them in stack trace. */
+
+ if (skip_init == true) {
+ if ((m->name == utf_init) &&
+ (class_issubclass(m->clazz, class_java_lang_Throwable))) {
+ continue;
+ }
+ else {
+ /* If no "Throwable.init()" method found, we stop
+ checking it next time. */
+
+ skip_init = false;
+ }
+ }
+
+ /* Store the stacktrace entry and increment the pointer. */
+
+ ste->code = tmpsfi.code;
+ ste->pc = tmpsfi.xpc;
+
+ ste++;
+ }
+
+ /* Store the number of entries in the stacktrace structure. */
+
+ st->length = ste - st->entries;
+
+ LLNI_CRITICAL_END;
+
+ /* release dump memory */
+
+/* dump_release(dumpsize); */
+
+ CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+ stacktrace_overhead)
+ return ba;
+
+return_NULL:
+/* dump_release(dumpsize); */
+
+ CYCLES_STATS_END_WITH_OVERHEAD(stacktrace_fillInStackTrace,
+ stacktrace_overhead)
+
+ return NULL;
+}
+
+
+/* stacktrace_get_current ******************************************************
+
+ Builds and returns a stacktrace from the current thread and returns
+ the stacktrace structure wrapped in a Java byte-array to not
+ confuse the GC.
+
+ RETURN:
+ stacktrace as Java byte-array
+
+*******************************************************************************/
+
+java_handle_bytearray_t *stacktrace_get_current(void)
+{
+ stackframeinfo_t *sfi;
+ java_handle_bytearray_t *ba;
+
+ sfi = threads_get_current_stackframeinfo();
+ ba = stacktrace_get(sfi);
+
+ return ba;
+}
+
+
+/* stacktrace_get_caller_class *************************************************
+
+ Get the class on the stack at the given depth. This function skips
+ various special classes or methods.
+
+ ARGUMENTS:
+ depth ... depth to get caller class of
+
+ RETURN:
+ caller class
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+classinfo *stacktrace_get_caller_class(int depth)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ methodinfo *m;
+ classinfo *c;
+ int i;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_get_caller_class]");
+#endif
+
+ /* Get the stackframeinfo of the current thread. */
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* Iterate over the whole stack until we reached the requested
+ depth. */
+
+ i = 0;
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+
+ m = tmpsfi.code->m;
+ c = m->clazz;
+
+ /* Skip builtin methods. */
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ continue;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
+ (vframeStreamCommon::security_get_caller_frame). */
+
+ /* This is java.lang.reflect.Method.invoke(), skip it. */
+
+ if (m == method_java_lang_reflect_Method_invoke)
+ continue;
+
+ /* This is an auxiliary frame, skip it. */
+
+ if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
+ continue;
+#endif
+
+ /* We reached the requested depth. */
+
+ if (i >= depth)
+ return c;
+
+ i++;
+ }
+
+ return NULL;
+}
+#endif
+
+
+/* stacktrace_first_nonnull_classloader ****************************************
+
+ Returns the first non-null (user-defined) classloader on the stack.
+ If none is found NULL is returned.
+
+ RETURN:
+ classloader
+
+*******************************************************************************/
+
+classloader_t *stacktrace_first_nonnull_classloader(void)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ methodinfo *m;
+ classloader_t *cl;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_first_nonnull_classloader]");
+#endif
+
+ /* Get the stackframeinfo of the current thread. */
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* Iterate over the whole stack. */
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+
+ m = tmpsfi.code->m;
+ cl = class_get_classloader(m->clazz);
+
+ if (cl != NULL)
+ return cl;
+ }
+
+ return NULL;
+}
+
+
+/* stacktrace_getClassContext **************************************************
+
+ Creates a Class context array.
+
+ RETURN VALUE:
+ the array of java.lang.Class objects, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+java_handle_objectarray_t *stacktrace_getClassContext(void)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ int depth;
+ java_handle_objectarray_t *oa;
+ java_object_t **data;
+ int i;
+ methodinfo *m;
+
+ CYCLES_STATS_DECLARE_AND_START
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_getClassContext]");
+#endif
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* Get the depth of the current stack. */
+
+ depth = stacktrace_depth(sfi);
+
+ /* The first stackframe corresponds to the method whose
+ implementation calls this native function. We remove that
+ entry. */
+
+ depth--;
+ stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_next(&tmpsfi);
+
+ /* Allocate the Class array. */
+
+ oa = builtin_anewarray(depth, class_java_lang_Class);
+
+ if (oa == NULL) {
+ CYCLES_STATS_END(stacktrace_getClassContext);
+
+ return NULL;
+ }
+
+ /* Fill the Class array from the stacktrace list. */
+
+ LLNI_CRITICAL_START;
+
+ data = LLNI_array_data(oa);
+
+ /* Iterate over the whole stack. */
+
+ i = 0;
+
+ for (;
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get methodinfo. */
+
+ m = tmpsfi.code->m;
+
+ /* Skip builtin methods. */
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ continue;
+
+ /* Store the class in the array. */
+
+ data[i] = (java_object_t *) m->clazz;
+
+ i++;
+ }
+
+ LLNI_CRITICAL_END;
+
+ CYCLES_STATS_END(stacktrace_getClassContext)
+
+ return oa;
+}
+
+
+/* stacktrace_getCurrentClass **************************************************
+
+ Find the current class by walking the stack trace.
+
+ Quote from the JNI documentation:
+
+ In the Java 2 Platform, FindClass locates the class loader
+ associated with the current native method. If the native code
+ belongs to a system class, no class loader will be
+ involved. Otherwise, the proper class loader will be invoked to
+ load and link the named class. When FindClass is called through the
+ Invocation Interface, there is no current native method or its
+ associated class loader. In that case, the result of
+ ClassLoader.getBaseClassLoader is used."
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+classinfo *stacktrace_get_current_class(void)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ methodinfo *m;
+
+ CYCLES_STATS_DECLARE_AND_START;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_get_current_class]");
+#endif
+
+ /* Get the stackframeinfo of the current thread. */
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* If the stackframeinfo is NULL then FindClass is called through
+ the Invocation Interface and we return NULL */
+
+ if (sfi == NULL) {
+ CYCLES_STATS_END(stacktrace_getCurrentClass);
+
+ return NULL;
+ }
+
+ /* Iterate over the whole stack. */
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get the methodinfo. */
+
+ m = tmpsfi.code->m;
+
+ if (m->clazz == class_java_security_PrivilegedAction) {
+ CYCLES_STATS_END(stacktrace_getCurrentClass);
+
+ return NULL;
+ }
+
+ if (m->clazz != NULL) {
+ CYCLES_STATS_END(stacktrace_getCurrentClass);
+
+ return m->clazz;
+ }
+ }
+
+ /* No Java method found on the stack. */
+
+ CYCLES_STATS_END(stacktrace_getCurrentClass);
+
+ return NULL;
+}
+#endif /* ENABLE_JAVASE */
+
+
+/* stacktrace_get_stack ********************************************************
+
+ Create a 2-dimensional array for java.security.VMAccessControler.
+
+ RETURN VALUE:
+ the arrary, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+java_handle_objectarray_t *stacktrace_get_stack(void)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ int depth;
+ java_handle_objectarray_t *oa;
+ java_handle_objectarray_t *classes;
+ java_handle_objectarray_t *methodnames;
+ methodinfo *m;
+ java_handle_t *string;
+ int i;
+
+ CYCLES_STATS_DECLARE_AND_START
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_get_stack]");
+#endif
+
+ /* Get the stackframeinfo of the current thread. */
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* Get the depth of the current stack. */
+
+ depth = stacktrace_depth(sfi);
+
+ if (depth == 0)
+ return NULL;
+
+ /* Allocate the required arrays. */
+
+ oa = builtin_anewarray(2, arrayclass_java_lang_Object);
+
+ if (oa == NULL)
+ goto return_NULL;
+
+ classes = builtin_anewarray(depth, class_java_lang_Class);
+
+ if (classes == NULL)
+ goto return_NULL;
+
+ methodnames = builtin_anewarray(depth, class_java_lang_String);
+
+ if (methodnames == NULL)
+ goto return_NULL;
+
+ /* Set up the 2-dimensional array. */
+
+ array_objectarray_element_set(oa, 0, (java_handle_t *) classes);
+ array_objectarray_element_set(oa, 1, (java_handle_t *) methodnames);
+
+ /* Iterate over the whole stack. */
+ /* TODO We should use a critical section here to speed things
+ up. */
+
+ i = 0;
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get the methodinfo. */
+
+ m = tmpsfi.code->m;
+
+ /* Skip builtin methods. */
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ continue;
+
+ /* Store the class in the array. */
+ /* NOTE: We use a LLNI-macro here, because a classinfo is not
+ a handle. */
+
+ LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
+
+ /* Store the name in the array. */
+
+ string = javastring_new(m->name);
+
+ if (string == NULL)
+ goto return_NULL;
+
+ array_objectarray_element_set(methodnames, i, string);
+
+ i++;
+ }
+
+ CYCLES_STATS_END(stacktrace_get_stack)
+
+ return oa;
+
+return_NULL:
+ CYCLES_STATS_END(stacktrace_get_stack)
+
+ return NULL;
+}
+#endif
+
+
+/* stacktrace_print_entry ****************************************************
+
+ Print line for a stacktrace entry.
+
+ ARGUMENTS:
+ m ............ methodinfo of the entry
+ linenumber ... linenumber of the entry
+
+*******************************************************************************/
+
+static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
+{
+ /* Sanity check. */
+
+ assert(m != NULL);
+
+ printf("\tat ");
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ printf("NULL");
+ else
+ utf_display_printable_ascii_classname(m->clazz->name);
+
+ printf(".");
+ utf_display_printable_ascii(m->name);
+ utf_display_printable_ascii(m->descriptor);
+
+ if (m->flags & ACC_NATIVE) {
+ puts("(Native Method)");
+ }
+ else {
+ if (m->flags & ACC_METHOD_BUILTIN) {
+ puts("(builtin)");
+ }
+ else {
+ printf("(");
+ utf_display_printable_ascii(m->clazz->sourcefile);
+ printf(":%d)\n", linenumber);
+ }
+ }
+
+ fflush(stdout);
+}
+
+
+/* stacktrace_print ************************************************************
+
+ Print the given stacktrace with CACAO intern methods only (no Java
+ code required).
+
+ This method is used by stacktrace_dump_trace and
+ builtin_trace_exception.
+
+ IN:
+ st ... stacktrace to print
+
+*******************************************************************************/
+
+void stacktrace_print(stacktrace_t *st)
+{
+ stacktrace_entry_t *ste;
+ methodinfo *m;
+ int32_t linenumber;
+ int i;
+
+ ste = &(st->entries[0]);
+
+ for (i = 0; i < st->length; i++, ste++) {
+ m = ste->code->m;
+
+ /* Get the line number. */
+
+ linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
+
+ stacktrace_print_entry(m, linenumber);
+ }
+}
+
+
+/* stacktrace_print_current ****************************************************
+
+ Print the current stacktrace of the current thread.
+
+ NOTE: This function prints all frames of the stacktrace and does
+ not skip frames like stacktrace_get.
+
+*******************************************************************************/
+
+void stacktrace_print_current(void)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ codeinfo *code;
+ methodinfo *m;
+ int32_t linenumber;
+
+ sfi = threads_get_current_stackframeinfo();
+
+ if (sfi == NULL) {
+ puts("\t<<No stacktrace available>>");
+ fflush(stdout);
+ return;
+ }
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get the methodinfo. */
+
+ code = tmpsfi.code;
+ m = code->m;
+
+ /* Get the line number. */
+
+ linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+
+ stacktrace_print_entry(m, linenumber);
+ }
+}
+
+
+/* stacktrace_print_of_thread **************************************************
+
+ Print the current stacktrace of the given thread.
+
+ ARGUMENTS:
+ t ... thread
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void stacktrace_print_of_thread(threadobject *t)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ codeinfo *code;
+ methodinfo *m;
+ int32_t linenumber;
+
+ /* Build a stacktrace for the passed thread. */
+
+ sfi = t->_stackframeinfo;
+
+ if (sfi == NULL) {
+ puts("\t<<No stacktrace available>>");
+ fflush(stdout);
+ return;
+ }
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get the methodinfo. */
+
+ code = tmpsfi.code;
+ m = code->m;
+
+ /* Get the line number. */
+
+ linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+
+ stacktrace_print_entry(m, linenumber);
+ }
+}
+#endif
+
+
+/* stacktrace_print_exception **************************************************
+
+ Print the stacktrace of a given exception (more or less a wrapper
+ to stacktrace_print).
+
+ IN:
+ h ... handle of exception to print
+
+*******************************************************************************/
+
+void stacktrace_print_exception(java_handle_t *h)
+{
+ if (h == NULL)
+ return;
+
+ java_lang_Throwable t(h);
+
+ /* now print the stacktrace */
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ java_lang_VMThrowable vmt(t.get_vmState());
+ java_handle_bytearray_t* backtrace = vmt.get_vmdata();
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ java_handle_bytearray_t* backtrace = t.get_backtrace();
+
+#else
+# error unknown classpath configuration
+#endif
+
+ // Sanity check.
+
+ assert(backtrace != NULL);
+
+ /* We need a critical section here as we use the byte-array data
+ pointer directly. */
+
+ LLNI_CRITICAL_START;
+
+ stacktrace_t* st = (stacktrace_t*) LLNI_array_data(backtrace);
+
+ stacktrace_print(st);
+
+ LLNI_CRITICAL_END;
+}
+
+
+#if defined(ENABLE_CYCLES_STATS)
+void stacktrace_print_cycles_stats(FILE *file)
+{
+ CYCLES_STATS_PRINT_OVERHEAD(stacktrace_overhead, file);
+ CYCLES_STATS_PRINT(stacktrace_get, file);
+ CYCLES_STATS_PRINT(stacktrace_getClassContext , file);
+ CYCLES_STATS_PRINT(stacktrace_getCurrentClass , file);
+ CYCLES_STATS_PRINT(stacktrace_get_stack, file);
+}
+#endif
+
+} // extern "C"
+
+
+/*
+ * 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/jit/stacktrace.h - header file for stacktrace generation
-
- 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 _STACKTRACE_H
-#define _STACKTRACE_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct stackframeinfo_t stackframeinfo_t;
-typedef struct stacktrace_entry_t stacktrace_entry_t;
-typedef struct stacktrace_t stacktrace_t;
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "md-abi.h"
-
-#include "threads/thread.h"
-
-#include "vm/global.h"
-
-#include "vm/jit/code.h"
-
-#include "vmcore/class.h"
-
-
-/* stackframeinfo **************************************************************
-
- ATTENTION: Keep the number of elements of this structure even, to
- make sure that the stack keeps aligned (e.g. 16-bytes for x86_64).
-
-*******************************************************************************/
-
-struct stackframeinfo_t {
- stackframeinfo_t *prev; /* pointer to prev stackframeinfo */
- codeinfo *code; /* codeinfo of current method */
- u1 *pv; /* PV of current function */
- u1 *sp; /* SP of parent Java function */
- u1 *ra; /* RA to parent Java function */
- u1 *xpc; /* XPC (for inline stubs) */
-#if defined(ENABLE_GC_CACAO)
- /*
- * The exact GC needs to be able to recover saved registers, so the
- * native-stub saves these registers here
- */
-# if defined(HAS_ADDRESS_REGISTER_FILE)
- uintptr_t adrregs[ADR_SAV_CNT];
-# else
- uintptr_t intregs[INT_SAV_CNT];
-# endif
-#endif
-};
-
-
-/* stacktrace_entry_t *********************************************************/
-
-struct stacktrace_entry_t {
- codeinfo *code; /* codeinfo pointer of this method */
- void *pc; /* PC in this method */
-};
-
-
-/* stacktrace_t ***************************************************************/
-
-struct stacktrace_t {
- int32_t length; /* length of the entries array */
- stacktrace_entry_t entries[1]; /* stacktrace entries */
-};
-
-
-/* function prototypes ********************************************************/
-
-void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc);
-void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi);
-
-java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi);
-java_handle_bytearray_t *stacktrace_get_current(void);
-
-#if defined(ENABLE_JAVASE)
-classinfo *stacktrace_get_caller_class(int depth);
-classloader_t *stacktrace_first_nonnull_classloader(void);
-java_handle_objectarray_t *stacktrace_getClassContext(void);
-classinfo *stacktrace_get_current_class(void);
-java_handle_objectarray_t *stacktrace_get_stack(void);
-#endif
-
-void stacktrace_print(stacktrace_t *st);
-void stacktrace_print_current(void);
-
-#if defined(ENABLE_THREADS)
-void stacktrace_print_of_thread(threadobject *t);
-#endif
-
-void stacktrace_print_exception(java_handle_t *h);
-
-/* machine dependent functions (code in ARCH_DIR/md.c) */
-
-#if defined(ENABLE_JIT)
-# if defined(__SPARC_64__)
-u1 *md_get_framepointer(u1 *sp);
-u1 *md_get_pv_from_stackframe(u1 *sp);
-# endif
-#endif
-
-#if defined(ENABLE_INTRP)
-u1 *intrp_md_stacktrace_get_returnaddress(u1 *sp, u4 framesize);
-#endif
-
-#if defined(ENABLE_CYCLES_STATS)
-void stacktrace_print_cycles_stats(FILE *file);
-#endif
-
-#endif /* _STACKTRACE_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:
- */
--- /dev/null
+/* src/vm/jit/stacktrace.hpp - header file for stacktrace generation
+
+ 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 _STACKTRACE_HPP
+#define _STACKTRACE_HPP
+
+// FIXME Use C-linkage for now.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* forward typedefs ***********************************************************/
+
+typedef struct stackframeinfo_t stackframeinfo_t;
+typedef struct stacktrace_entry_t stacktrace_entry_t;
+typedef struct stacktrace_t stacktrace_t;
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/class.h"
+#include "vm/global.h"
+
+#include "vm/jit/code.h"
+
+
+/* stackframeinfo **************************************************************
+
+ ATTENTION: Keep the number of elements of this structure even, to
+ make sure that the stack keeps aligned (e.g. 16-bytes for x86_64).
+
+*******************************************************************************/
+
+struct stackframeinfo_t {
+ stackframeinfo_t *prev; /* pointer to prev stackframeinfo */
+ codeinfo *code; /* codeinfo of current method */
+ void *pv; /* PV of current function */
+ void *sp; /* SP of parent Java function */
+ void *ra; /* RA to parent Java function */
+ void *xpc; /* XPC (for inline stubs) */
+#if defined(ENABLE_GC_CACAO)
+ /*
+ * The exact GC needs to be able to recover saved registers, so the
+ * native-stub saves these registers here
+ */
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+ uintptr_t adrregs[ADR_SAV_CNT];
+# else
+ uintptr_t intregs[INT_SAV_CNT];
+# endif
+#endif
+};
+
+
+/* stacktrace_entry_t *********************************************************/
+
+struct stacktrace_entry_t {
+ codeinfo *code; /* codeinfo pointer of this method */
+ void *pc; /* PC in this method */
+};
+
+
+/* stacktrace_t ***************************************************************/
+
+struct stacktrace_t {
+ int32_t length; /* length of the entries array */
+ stacktrace_entry_t entries[1]; /* stacktrace entries */
+};
+
+
+/* function prototypes ********************************************************/
+
+void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc);
+void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi);
+
+java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi);
+java_handle_bytearray_t *stacktrace_get_current(void);
+
+#if defined(ENABLE_JAVASE)
+classinfo *stacktrace_get_caller_class(int depth);
+classloader_t *stacktrace_first_nonnull_classloader(void);
+java_handle_objectarray_t *stacktrace_getClassContext(void);
+classinfo *stacktrace_get_current_class(void);
+java_handle_objectarray_t *stacktrace_get_stack(void);
+#endif
+
+void stacktrace_print(stacktrace_t *st);
+void stacktrace_print_current(void);
+
+#if defined(ENABLE_THREADS)
+void stacktrace_print_of_thread(threadobject *t);
+#endif
+
+void stacktrace_print_exception(java_handle_t *h);
+
+/* machine dependent functions (code in ARCH_DIR/md.c) */
+
+#if defined(ENABLE_JIT)
+# if defined(__SPARC_64__)
+u1 *md_get_framepointer(u1 *sp);
+u1 *md_get_pv_from_stackframe(u1 *sp);
+# endif
+#endif
+
+#if defined(ENABLE_INTRP)
+u1 *intrp_md_stacktrace_get_returnaddress(u1 *sp, u4 framesize);
+#endif
+
+#if defined(ENABLE_CYCLES_STATS)
+void stacktrace_print_cycles_stats(FILE *file);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _STACKTRACE_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
-/* src/vm/jit/trace.c - Functions for tracing from java code.
-
- 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 <stdio.h>
-
-#include "arch.h"
-#include "md-abi.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Throwable.h"
-
-#include "threads/thread.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/jit/argument.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/trace.h"
-#include "vm/jit/show.h"
-
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
-
-#if !defined(NDEBUG)
-
-
-/* global variables ***********************************************************/
-
-#if !defined(ENABLE_THREADS)
-s4 _no_threads_tracejavacallindent = 0;
-u4 _no_threads_tracejavacallcount= 0;
-#endif
-
-
-/* trace_java_call_print_argument **********************************************
-
- XXX: Document me!
-
-*******************************************************************************/
-
-static char *trace_java_call_print_argument(methodinfo *m, char *logtext, s4 *logtextlen, typedesc *paramtype, imm_union imu)
-{
- java_object_t *o;
- classinfo *c;
- utf *u;
- u4 len;
-
- switch (paramtype->type) {
- case TYPE_INT:
- sprintf(logtext + strlen(logtext), "%d (0x%08x)", (int32_t)imu.l, (int32_t)imu.l);
- break;
-
- case TYPE_LNG:
-#if SIZEOF_VOID_P == 4
- sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
-#else
- sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
-#endif
- break;
-
- case TYPE_FLT:
- sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
- break;
-
- case TYPE_DBL:
-#if SIZEOF_VOID_P == 4
- sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
-#else
- sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
-#endif
- break;
-
- case TYPE_ADR:
-#if SIZEOF_VOID_P == 4
- sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) imu.l);
-#else
- sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) imu.l);
-#endif
-
- /* Workaround for sun.misc.Unsafe methods. In the future
- (exact GC) we should check if the address is on the GC
- heap. */
-
- if ((m->clazz != NULL) &&
- (m->clazz->name == utf_new_char("sun/misc/Unsafe")))
- break;
-
- /* Cast to java.lang.Object. */
-
- o = (java_object_t *) (ptrint) imu.l;
-
- /* Check return argument for java.lang.Class or
- java.lang.String. */
-
- if (o != NULL) {
- if (o->vftbl->clazz == class_java_lang_String) {
- /* get java.lang.String object and the length of the
- string */
-
- u = javastring_toutf(o, false);
-
- len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
-
- /* realloc memory for string length */
-
- logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
- *logtextlen += len;
-
- /* convert to utf8 string and strcat it to the logtext */
-
- strcat(logtext, " (String = \"");
- utf_cat(logtext, u);
- strcat(logtext, "\")");
- }
- else {
- if (o->vftbl->clazz == class_java_lang_Class) {
- /* if the object returned is a java.lang.Class
- cast it to classinfo structure and get the name
- of the class */
-
- c = (classinfo *) o;
-
- u = c->name;
- }
- else {
- /* if the object returned is not a java.lang.String or
- a java.lang.Class just print the name of the class */
-
- u = o->vftbl->clazz->name;
- }
-
- len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
-
- /* realloc memory for string length */
-
- logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
- *logtextlen += len;
-
- /* strcat to the logtext */
-
- strcat(logtext, " (Class = \"");
- utf_cat_classname(logtext, u);
- strcat(logtext, "\")");
- }
- }
- }
-
- return logtext;
-}
-
-/* trace_java_call_enter ******************************************************
-
- Traces an entry into a java method.
-
- arg_regs: Array containing all argument registers as int64_t values in
- the same order as listed in m->methoddesc. The array is usually allocated
- on the stack and used for restoring the argument registers later.
-
- stack: Pointer to first on stack argument in the same format passed to
- asm_vm_call_method.
-
-*******************************************************************************/
-
-void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
-{
- methoddesc *md;
- imm_union arg;
- char *logtext;
- s4 logtextlen;
- s4 i;
- s4 pos;
- int32_t dumpmarker;
-
- /* We don't trace builtin functions here because the argument
- passing happens via the native ABI and does not fit these
- functions. */
-
- if (method_is_builtin(m))
- return;
-
-#if defined(ENABLE_DEBUG_FILTER)
- if (!show_filters_test_verbosecall_enter(m))
- return;
-#endif
-
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_enter_method(m);
- return;
-#endif
-
- md = m->parseddesc;
-
- /* calculate message length */
-
- logtextlen =
- strlen("4294967295 ") +
- strlen("-2147483647-") + /* INT_MAX should be sufficient */
- TRACEJAVACALLINDENT +
- strlen("called: ") +
- ((m->clazz == NULL) ? strlen("NULL") : utf_bytes(m->clazz->name)) +
- strlen(".") +
- utf_bytes(m->name) +
- utf_bytes(m->descriptor);
-
- /* Actually it's not possible to have all flags printed, but:
- safety first! */
-
- logtextlen +=
- strlen(" PUBLIC") +
- strlen(" PRIVATE") +
- strlen(" PROTECTED") +
- strlen(" STATIC") +
- strlen(" FINAL") +
- strlen(" SYNCHRONIZED") +
- strlen(" VOLATILE") +
- strlen(" TRANSIENT") +
- strlen(" NATIVE") +
- strlen(" INTERFACE") +
- strlen(" ABSTRACT") +
- strlen(" METHOD_BUILTIN");
-
- /* add maximal argument length */
-
- logtextlen +=
- strlen("(") +
- strlen("-9223372036854775808 (0x123456789abcdef0), ") * md->paramcount +
- strlen("...(255)") +
- strlen(")");
-
- /* allocate memory */
-
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
-
- TRACEJAVACALLCOUNT++;
-
- sprintf(logtext, "%10d ", TRACEJAVACALLCOUNT);
- sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
-
- pos = strlen(logtext);
-
- for (i = 0; i < TRACEJAVACALLINDENT; i++)
- logtext[pos++] = '\t';
-
- strcpy(logtext + pos, "called: ");
-
- if (m->clazz != NULL)
- utf_cat_classname(logtext, m->clazz->name);
- else
- strcat(logtext, "NULL");
- strcat(logtext, ".");
- utf_cat(logtext, m->name);
- utf_cat(logtext, m->descriptor);
-
- if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
- if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
- if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
- if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
- if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
- if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
- if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
- if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
- if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
- if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
- if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
-
- strcat(logtext, "(");
-
- for (i = 0; i < md->paramcount; ++i) {
- arg = argument_jitarray_load(md, i, arg_regs, stack);
- logtext = trace_java_call_print_argument(m, logtext, &logtextlen,
- &md->paramtypes[i], arg);
- if (i != (md->paramcount - 1)) {
- strcat(logtext, ", ");
- }
- }
-
- strcat(logtext, ")");
-
- log_text(logtext);
-
- /* release memory */
-
- DRELEASE;
-
- TRACEJAVACALLINDENT++;
-
-}
-
-/* trace_java_call_exit ********************************************************
-
- Traces an exit form a java method.
-
- return_regs: Array of size 1 containing return register.
- The array is usually allocated on the stack and used for restoring the
- registers later.
-
-*******************************************************************************/
-
-void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
-{
- methoddesc *md;
- char *logtext;
- s4 logtextlen;
- s4 i;
- s4 pos;
- imm_union val;
- int32_t dumpmarker;
-
- /* We don't trace builtin functions here because the argument
- passing happens via the native ABI and does not fit these
- functions. */
-
- if (method_is_builtin(m))
- return;
-
-#if defined(ENABLE_DEBUG_FILTER)
- if (!show_filters_test_verbosecall_exit(m))
- return;
-#endif
-
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_leave_method(m);
- return;
-#endif
-
- md = m->parseddesc;
-
- /* outdent the log message */
-
- if (TRACEJAVACALLINDENT)
- TRACEJAVACALLINDENT--;
- else
- log_text("trace_java_call_exit: WARNING: unmatched unindent");
-
- /* calculate message length */
-
- logtextlen =
- strlen("4294967295 ") +
- strlen("-2147483647-") + /* INT_MAX should be sufficient */
- TRACEJAVACALLINDENT +
- strlen("finished: ") +
- ((m->clazz == NULL) ? strlen("NULL") : utf_bytes(m->clazz->name)) +
- strlen(".") +
- utf_bytes(m->name) +
- utf_bytes(m->descriptor) +
- strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
-
- /* add maximal argument length */
-
- logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
-
- /* allocate memory */
-
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
-
- /* generate the message */
-
- sprintf(logtext, " ");
- sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
-
- pos = strlen(logtext);
-
- for (i = 0; i < TRACEJAVACALLINDENT; i++)
- logtext[pos++] = '\t';
-
- strcpy(logtext + pos, "finished: ");
- if (m->clazz != NULL)
- utf_cat_classname(logtext, m->clazz->name);
- else
- strcat(logtext, "NULL");
- strcat(logtext, ".");
- utf_cat(logtext, m->name);
- utf_cat(logtext, m->descriptor);
-
- if (!IS_VOID_TYPE(md->returntype.type)) {
- strcat(logtext, "->");
- val = argument_jitreturn_load(md, return_regs);
-
- logtext =
- trace_java_call_print_argument(m, logtext, &logtextlen,
- &md->returntype, val);
- }
-
- log_text(logtext);
-
- /* release memory */
-
- DRELEASE;
-}
-
-
-/* trace_exception *************************************************************
-
- Traces an exception which is handled by exceptions_handle_exception.
-
-*******************************************************************************/
-
-void trace_exception(java_object_t *xptr, methodinfo *m, void *pos)
-{
- char *logtext;
- s4 logtextlen;
- codeinfo *code;
- int32_t dumpmarker;
-
- /* calculate message length */
-
- if (xptr) {
- logtextlen =
- strlen("Exception ") + utf_bytes(xptr->vftbl->clazz->name);
- }
- else {
- logtextlen = strlen("Some Throwable");
- }
-
- logtextlen += strlen(" thrown in ");
-
- if (m) {
- logtextlen +=
- utf_bytes(m->clazz->name) +
- strlen(".") +
- utf_bytes(m->name) +
- utf_bytes(m->descriptor) +
- strlen("(NOSYNC,NATIVE");
-
-#if SIZEOF_VOID_P == 8
- logtextlen +=
- strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
-#else
- logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
-#endif
-
- if (m->clazz->sourcefile == NULL)
- logtextlen += strlen("<NO CLASSFILE INFORMATION>");
- else
- logtextlen += utf_bytes(m->clazz->sourcefile);
-
- logtextlen += strlen(":65536)");
-
- }
- else {
- logtextlen += strlen("call_java_method");
- }
-
- logtextlen += strlen("0");
-
- /* allocate memory */
-
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
-
- if (xptr) {
- strcpy(logtext, "Exception ");
- utf_cat_classname(logtext, xptr->vftbl->clazz->name);
-
- } else {
- strcpy(logtext, "Some Throwable");
- }
-
- strcat(logtext, " thrown in ");
-
- if (m) {
- utf_cat_classname(logtext, m->clazz->name);
- strcat(logtext, ".");
- utf_cat(logtext, m->name);
- utf_cat(logtext, m->descriptor);
-
- if (m->flags & ACC_SYNCHRONIZED)
- strcat(logtext, "(SYNC");
- else
- strcat(logtext, "(NOSYNC");
-
- if (m->flags & ACC_NATIVE) {
- strcat(logtext, ",NATIVE");
-
- code = m->code;
-
-#if SIZEOF_VOID_P == 8
- sprintf(logtext + strlen(logtext),
- ")(0x%016lx) at position 0x%016lx",
- (ptrint) code->entrypoint, (ptrint) pos);
-#else
- sprintf(logtext + strlen(logtext),
- ")(0x%08x) at position 0x%08x",
- (ptrint) code->entrypoint, (ptrint) pos);
-#endif
-
- } else {
-
- /* XXX preliminary: This should get the actual codeinfo */
- /* in which the exception happened. */
- code = m->code;
-
-#if SIZEOF_VOID_P == 8
- sprintf(logtext + strlen(logtext),
- ")(0x%016lx) at position 0x%016lx (",
- (ptrint) code->entrypoint, (ptrint) pos);
-#else
- sprintf(logtext + strlen(logtext),
- ")(0x%08x) at position 0x%08x (",
- (ptrint) code->entrypoint, (ptrint) pos);
-#endif
-
- if (m->clazz->sourcefile == NULL)
- strcat(logtext, "<NO CLASSFILE INFORMATION>");
- else
- utf_cat(logtext, m->clazz->sourcefile);
-
- sprintf(logtext + strlen(logtext), ":%d)", 0);
- }
-
- } else
- strcat(logtext, "call_java_method");
-
- log_text(logtext);
-
- /* release memory */
-
- DRELEASE;
-}
-
-
-/* trace_exception_builtin *****************************************************
-
- Traces an exception which is thrown by builtin_throw_exception.
-
-*******************************************************************************/
-
-void trace_exception_builtin(java_object_t *xptr)
-{
- java_lang_Throwable *t;
- java_lang_String *s;
- char *logtext;
- s4 logtextlen;
- int32_t dumpmarker;
-
- t = (java_lang_Throwable *) xptr;
-
- /* get detail message */
- if (t)
- LLNI_field_get_ref(t, detailMessage, s);
-
- /* calculate message length */
-
- logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
-
- if (t) {
- logtextlen +=
- utf_bytes(xptr->vftbl->clazz->name);
- if (s) {
- logtextlen += strlen(": ") +
- u2_utflength(LLNI_field_direct(s, value)->data
- + LLNI_field_direct(s, offset),
- LLNI_field_direct(s,count));
- }
- }
- else {
- logtextlen += strlen("(nil)");
- }
-
- /* allocate memory */
-
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
-
- strcpy(logtext, "Builtin exception thrown: ");
-
- if (t) {
- utf_cat_classname(logtext, xptr->vftbl->clazz->name);
-
- if (s) {
- char *buf;
-
- buf = javastring_tochar((java_handle_t *) s);
- strcat(logtext, ": ");
- strcat(logtext, buf);
- MFREE(buf, char, strlen(buf) + 1);
- }
-
- } else {
- strcat(logtext, "(nil)");
- }
-
- log_text(logtext);
-
- /* release memory */
-
- DRELEASE;
-}
-
-
-#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/jit/trace.cpp - Functions for tracing from java code.
+
+ 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 <stdio.h>
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+
+#include "vm/jit/argument.h"
+#include "vm/jit/codegen-common.h"
+#include "vm/jit/trace.hpp"
+#include "vm/jit/show.h"
+
+
+#if !defined(NDEBUG)
+
+// FIXME For now we export everything as C functions.
+extern "C" {
+
+/* global variables ***********************************************************/
+
+#if !defined(ENABLE_THREADS)
+s4 _no_threads_tracejavacallindent = 0;
+u4 _no_threads_tracejavacallcount= 0;
+#endif
+
+
+/* trace_java_call_print_argument **********************************************
+
+ XXX: Document me!
+
+*******************************************************************************/
+
+static char *trace_java_call_print_argument(methodinfo *m, char *logtext, s4 *logtextlen, typedesc *paramtype, imm_union imu)
+{
+ java_object_t *o;
+ classinfo *c;
+ utf *u;
+ u4 len;
+
+ switch (paramtype->type) {
+ case TYPE_INT:
+ sprintf(logtext + strlen(logtext), "%d (0x%08x)", (int32_t)imu.l, (int32_t)imu.l);
+ break;
+
+ case TYPE_LNG:
+#if SIZEOF_VOID_P == 4
+ sprintf(logtext + strlen(logtext), "%lld (0x%016llx)", imu.l, imu.l);
+#else
+ sprintf(logtext + strlen(logtext), "%ld (0x%016lx)", imu.l, imu.l);
+#endif
+ break;
+
+ case TYPE_FLT:
+ sprintf(logtext + strlen(logtext), "%g (0x%08x)", imu.f, imu.i);
+ break;
+
+ case TYPE_DBL:
+#if SIZEOF_VOID_P == 4
+ sprintf(logtext + strlen(logtext), "%g (0x%016llx)", imu.d, imu.l);
+#else
+ sprintf(logtext + strlen(logtext), "%g (0x%016lx)", imu.d, imu.l);
+#endif
+ break;
+
+ case TYPE_ADR:
+#if SIZEOF_VOID_P == 4
+ sprintf(logtext + strlen(logtext), "0x%08x", (ptrint) imu.l);
+#else
+ sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) imu.l);
+#endif
+
+ /* Workaround for sun.misc.Unsafe methods. In the future
+ (exact GC) we should check if the address is on the GC
+ heap. */
+
+ if ((m->clazz != NULL) &&
+ (m->clazz->name == utf_new_char("sun/misc/Unsafe")))
+ break;
+
+ /* Cast to java.lang.Object. */
+
+ o = (java_object_t *) (ptrint) imu.l;
+
+ /* Check return argument for java.lang.Class or
+ java.lang.String. */
+
+ if (o != NULL) {
+ if (o->vftbl->clazz == class_java_lang_String) {
+ /* get java.lang.String object and the length of the
+ string */
+
+ u = javastring_toutf(o, false);
+
+ len = strlen(" (String = \"") + utf_bytes(u) + strlen("\")");
+
+ /* realloc memory for string length */
+
+ logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
+ *logtextlen += len;
+
+ /* convert to utf8 string and strcat it to the logtext */
+
+ strcat(logtext, " (String = \"");
+ utf_cat(logtext, u);
+ strcat(logtext, "\")");
+ }
+ else {
+ if (o->vftbl->clazz == class_java_lang_Class) {
+ /* if the object returned is a java.lang.Class
+ cast it to classinfo structure and get the name
+ of the class */
+
+ c = (classinfo *) o;
+
+ u = c->name;
+ }
+ else {
+ /* if the object returned is not a java.lang.String or
+ a java.lang.Class just print the name of the class */
+
+ u = o->vftbl->clazz->name;
+ }
+
+ len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
+
+ /* realloc memory for string length */
+
+ logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
+ *logtextlen += len;
+
+ /* strcat to the logtext */
+
+ strcat(logtext, " (Class = \"");
+ utf_cat_classname(logtext, u);
+ strcat(logtext, "\")");
+ }
+ }
+ }
+
+ return logtext;
+}
+
+/* trace_java_call_enter ******************************************************
+
+ Traces an entry into a java method.
+
+ arg_regs: Array containing all argument registers as int64_t values in
+ the same order as listed in m->methoddesc. The array is usually allocated
+ on the stack and used for restoring the argument registers later.
+
+ stack: Pointer to first on stack argument in the same format passed to
+ asm_vm_call_method.
+
+*******************************************************************************/
+
+void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
+{
+ methoddesc *md;
+ imm_union arg;
+ char *logtext;
+ s4 logtextlen;
+ s4 i;
+ s4 pos;
+ int32_t dumpmarker;
+
+ /* We don't trace builtin functions here because the argument
+ passing happens via the native ABI and does not fit these
+ functions. */
+
+ if (method_is_builtin(m))
+ return;
+
+#if defined(ENABLE_DEBUG_FILTER)
+ if (!show_filters_test_verbosecall_enter(m))
+ return;
+#endif
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_enter_method(m);
+ return;
+#endif
+
+ md = m->parseddesc;
+
+ /* calculate message length */
+
+ logtextlen =
+ strlen("4294967295 ") +
+ strlen("-2147483647-") + /* INT_MAX should be sufficient */
+ TRACEJAVACALLINDENT +
+ strlen("called: ") +
+ ((m->clazz == NULL) ? strlen("NULL") : utf_bytes(m->clazz->name)) +
+ strlen(".") +
+ utf_bytes(m->name) +
+ utf_bytes(m->descriptor);
+
+ /* Actually it's not possible to have all flags printed, but:
+ safety first! */
+
+ logtextlen +=
+ strlen(" PUBLIC") +
+ strlen(" PRIVATE") +
+ strlen(" PROTECTED") +
+ strlen(" STATIC") +
+ strlen(" FINAL") +
+ strlen(" SYNCHRONIZED") +
+ strlen(" VOLATILE") +
+ strlen(" TRANSIENT") +
+ strlen(" NATIVE") +
+ strlen(" INTERFACE") +
+ strlen(" ABSTRACT") +
+ strlen(" METHOD_BUILTIN");
+
+ /* add maximal argument length */
+
+ logtextlen +=
+ strlen("(") +
+ strlen("-9223372036854775808 (0x123456789abcdef0), ") * md->paramcount +
+ strlen("...(255)") +
+ strlen(")");
+
+ /* allocate memory */
+
+ DMARKER;
+
+ logtext = DMNEW(char, logtextlen);
+
+ TRACEJAVACALLCOUNT++;
+
+ sprintf(logtext, "%10d ", TRACEJAVACALLCOUNT);
+ sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
+
+ pos = strlen(logtext);
+
+ for (i = 0; i < TRACEJAVACALLINDENT; i++)
+ logtext[pos++] = '\t';
+
+ strcpy(logtext + pos, "called: ");
+
+ if (m->clazz != NULL)
+ utf_cat_classname(logtext, m->clazz->name);
+ else
+ strcat(logtext, "NULL");
+ strcat(logtext, ".");
+ utf_cat(logtext, m->name);
+ utf_cat(logtext, m->descriptor);
+
+ if (m->flags & ACC_PUBLIC) strcat(logtext, " PUBLIC");
+ if (m->flags & ACC_PRIVATE) strcat(logtext, " PRIVATE");
+ if (m->flags & ACC_PROTECTED) strcat(logtext, " PROTECTED");
+ if (m->flags & ACC_STATIC) strcat(logtext, " STATIC");
+ if (m->flags & ACC_FINAL) strcat(logtext, " FINAL");
+ if (m->flags & ACC_SYNCHRONIZED) strcat(logtext, " SYNCHRONIZED");
+ if (m->flags & ACC_VOLATILE) strcat(logtext, " VOLATILE");
+ if (m->flags & ACC_TRANSIENT) strcat(logtext, " TRANSIENT");
+ if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
+ if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
+ if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
+
+ strcat(logtext, "(");
+
+ for (i = 0; i < md->paramcount; ++i) {
+ arg = argument_jitarray_load(md, i, arg_regs, stack);
+ logtext = trace_java_call_print_argument(m, logtext, &logtextlen,
+ &md->paramtypes[i], arg);
+ if (i != (md->paramcount - 1)) {
+ strcat(logtext, ", ");
+ }
+ }
+
+ strcat(logtext, ")");
+
+ log_text(logtext);
+
+ /* release memory */
+
+ DRELEASE;
+
+ TRACEJAVACALLINDENT++;
+
+}
+
+/* trace_java_call_exit ********************************************************
+
+ Traces an exit form a java method.
+
+ return_regs: Array of size 1 containing return register.
+ The array is usually allocated on the stack and used for restoring the
+ registers later.
+
+*******************************************************************************/
+
+void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
+{
+ methoddesc *md;
+ char *logtext;
+ s4 logtextlen;
+ s4 i;
+ s4 pos;
+ imm_union val;
+ int32_t dumpmarker;
+
+ /* We don't trace builtin functions here because the argument
+ passing happens via the native ABI and does not fit these
+ functions. */
+
+ if (method_is_builtin(m))
+ return;
+
+#if defined(ENABLE_DEBUG_FILTER)
+ if (!show_filters_test_verbosecall_exit(m))
+ return;
+#endif
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_leave_method(m);
+ return;
+#endif
+
+ md = m->parseddesc;
+
+ /* outdent the log message */
+
+ if (TRACEJAVACALLINDENT)
+ TRACEJAVACALLINDENT--;
+ else
+ log_text("trace_java_call_exit: WARNING: unmatched unindent");
+
+ /* calculate message length */
+
+ logtextlen =
+ strlen("4294967295 ") +
+ strlen("-2147483647-") + /* INT_MAX should be sufficient */
+ TRACEJAVACALLINDENT +
+ strlen("finished: ") +
+ ((m->clazz == NULL) ? strlen("NULL") : utf_bytes(m->clazz->name)) +
+ strlen(".") +
+ utf_bytes(m->name) +
+ utf_bytes(m->descriptor) +
+ strlen(" SYNCHRONIZED") + strlen("(") + strlen(")");
+
+ /* add maximal argument length */
+
+ logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
+
+ /* allocate memory */
+
+ DMARKER;
+
+ logtext = DMNEW(char, logtextlen);
+
+ /* generate the message */
+
+ sprintf(logtext, " ");
+ sprintf(logtext + strlen(logtext), "-%d-", TRACEJAVACALLINDENT);
+
+ pos = strlen(logtext);
+
+ for (i = 0; i < TRACEJAVACALLINDENT; i++)
+ logtext[pos++] = '\t';
+
+ strcpy(logtext + pos, "finished: ");
+ if (m->clazz != NULL)
+ utf_cat_classname(logtext, m->clazz->name);
+ else
+ strcat(logtext, "NULL");
+ strcat(logtext, ".");
+ utf_cat(logtext, m->name);
+ utf_cat(logtext, m->descriptor);
+
+ if (!IS_VOID_TYPE(md->returntype.type)) {
+ strcat(logtext, "->");
+ val = argument_jitreturn_load(md, return_regs);
+
+ logtext =
+ trace_java_call_print_argument(m, logtext, &logtextlen,
+ &md->returntype, val);
+ }
+
+ log_text(logtext);
+
+ /* release memory */
+
+ DRELEASE;
+}
+
+
+/* trace_exception *************************************************************
+
+ Traces an exception which is handled by exceptions_handle_exception.
+
+*******************************************************************************/
+
+void trace_exception(java_object_t *xptr, methodinfo *m, void *pos)
+{
+ char *logtext;
+ s4 logtextlen;
+ codeinfo *code;
+ int32_t dumpmarker;
+
+ /* calculate message length */
+
+ if (xptr) {
+ logtextlen =
+ strlen("Exception ") + utf_bytes(xptr->vftbl->clazz->name);
+ }
+ else {
+ logtextlen = strlen("Some Throwable");
+ }
+
+ logtextlen += strlen(" thrown in ");
+
+ if (m) {
+ logtextlen +=
+ utf_bytes(m->clazz->name) +
+ strlen(".") +
+ utf_bytes(m->name) +
+ utf_bytes(m->descriptor) +
+ strlen("(NOSYNC,NATIVE");
+
+#if SIZEOF_VOID_P == 8
+ logtextlen +=
+ strlen(")(0x123456789abcdef0) at position 0x123456789abcdef0 (");
+#else
+ logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
+#endif
+
+ if (m->clazz->sourcefile == NULL)
+ logtextlen += strlen("<NO CLASSFILE INFORMATION>");
+ else
+ logtextlen += utf_bytes(m->clazz->sourcefile);
+
+ logtextlen += strlen(":65536)");
+
+ }
+ else {
+ logtextlen += strlen("call_java_method");
+ }
+
+ logtextlen += strlen("0");
+
+ /* allocate memory */
+
+ DMARKER;
+
+ logtext = DMNEW(char, logtextlen);
+
+ if (xptr) {
+ strcpy(logtext, "Exception ");
+ utf_cat_classname(logtext, xptr->vftbl->clazz->name);
+
+ } else {
+ strcpy(logtext, "Some Throwable");
+ }
+
+ strcat(logtext, " thrown in ");
+
+ if (m) {
+ utf_cat_classname(logtext, m->clazz->name);
+ strcat(logtext, ".");
+ utf_cat(logtext, m->name);
+ utf_cat(logtext, m->descriptor);
+
+ if (m->flags & ACC_SYNCHRONIZED)
+ strcat(logtext, "(SYNC");
+ else
+ strcat(logtext, "(NOSYNC");
+
+ if (m->flags & ACC_NATIVE) {
+ strcat(logtext, ",NATIVE");
+
+ code = m->code;
+
+#if SIZEOF_VOID_P == 8
+ sprintf(logtext + strlen(logtext),
+ ")(0x%016lx) at position 0x%016lx",
+ (ptrint) code->entrypoint, (ptrint) pos);
+#else
+ sprintf(logtext + strlen(logtext),
+ ")(0x%08x) at position 0x%08x",
+ (ptrint) code->entrypoint, (ptrint) pos);
+#endif
+
+ } else {
+
+ /* XXX preliminary: This should get the actual codeinfo */
+ /* in which the exception happened. */
+ code = m->code;
+
+#if SIZEOF_VOID_P == 8
+ sprintf(logtext + strlen(logtext),
+ ")(0x%016lx) at position 0x%016lx (",
+ (ptrint) code->entrypoint, (ptrint) pos);
+#else
+ sprintf(logtext + strlen(logtext),
+ ")(0x%08x) at position 0x%08x (",
+ (ptrint) code->entrypoint, (ptrint) pos);
+#endif
+
+ if (m->clazz->sourcefile == NULL)
+ strcat(logtext, "<NO CLASSFILE INFORMATION>");
+ else
+ utf_cat(logtext, m->clazz->sourcefile);
+
+ sprintf(logtext + strlen(logtext), ":%d)", 0);
+ }
+
+ } else
+ strcat(logtext, "call_java_method");
+
+ log_text(logtext);
+
+ /* release memory */
+
+ DRELEASE;
+}
+
+
+/* trace_exception_builtin *****************************************************
+
+ Traces an exception which is thrown by builtin_throw_exception.
+
+*******************************************************************************/
+
+void trace_exception_builtin(java_handle_t* h)
+{
+ char *logtext;
+ s4 logtextlen;
+ int32_t dumpmarker;
+
+ java_lang_Throwable jlt(h);
+
+ // Get detail message.
+ java_handle_t* s = NULL;
+
+ if (jlt.get_handle() != NULL)
+ s = jlt.get_detailMessage();
+
+ java_lang_String jls(s);
+
+ /* calculate message length */
+
+ logtextlen = strlen("Builtin exception thrown: ") + strlen("0");
+
+ if (jlt.get_handle() != NULL) {
+ logtextlen += utf_bytes(jlt.get_vftbl()->clazz->name);
+
+ if (jls.get_handle()) {
+ // FIXME This is not handle capable!
+ logtextlen += strlen(": ") +
+ u2_utflength(jls.get_value()->data + jls.get_offset(), jls.get_count());
+ }
+ }
+ else {
+ logtextlen += strlen("(nil)");
+ }
+
+ /* allocate memory */
+
+ DMARKER;
+
+ logtext = DMNEW(char, logtextlen);
+
+ strcpy(logtext, "Builtin exception thrown: ");
+
+ if (jlt.get_handle()) {
+ utf_cat_classname(logtext, jlt.get_vftbl()->clazz->name);
+
+ if (s) {
+ char *buf;
+
+ buf = javastring_tochar(jls.get_handle());
+ strcat(logtext, ": ");
+ strcat(logtext, buf);
+ MFREE(buf, char, strlen(buf) + 1);
+ }
+
+ } else {
+ strcat(logtext, "(nil)");
+ }
+
+ log_text(logtext);
+
+ /* release memory */
+
+ DRELEASE;
+}
+
+} // extern "C"
+
+#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/jit/trace.h - Functions for tracing from java code.
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _VM_JIT_TRACE_H
-#define _VM_JIT_TRACE_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vmcore/method.h"
-
-#if !defined(NDEBUG)
-
-void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack);
-void trace_java_call_exit(methodinfo *m, uint64_t *return_regs);
-
-void trace_exception(java_object_t *xptr, methodinfo *m, void *pos);
-void trace_exception_builtin(java_object_t *xptr);
-
-#endif /* !defined(NDEBUG) */
-
-#endif /* _VM_JIT_TRACE_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:
- */
--- /dev/null
+/* src/vm/jit/trace.hpp - Functions for tracing from java code.
+
+ 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 _VM_JIT_TRACE_HPP
+#define _VM_JIT_TRACE_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/method.h"
+
+#if !defined(NDEBUG)
+
+// FIXME For now we export everything as C functions.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack);
+void trace_java_call_exit(methodinfo *m, uint64_t *return_regs);
+
+void trace_exception(java_object_t *xptr, methodinfo *m, void *pos);
+void trace_exception_builtin(java_object_t *xptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(NDEBUG) */
+
+#endif // _VM_JIT_TRACE_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:
+ */
#include "md-trap.h"
+#include "mm/memory.h"
+
#include "native/llni.h"
#include "toolbox/logging.h"
-#include "vm/exceptions.h"
-#include "vm/vm.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/vm.hpp"
#include "vm/jit/code.h"
#include "vm/jit/disass.h"
#include "vm/jit/methodtree.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/options.h"
-#include "vmcore/system.h"
+#include "vm/jit/stacktrace.hpp"
/**
/* mmap a memory page at address 0x0, so our hardware-exceptions
work. */
- pagesize = system_getpagesize();
+ pagesize = os_getpagesize();
- (void) system_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
+ (void) os_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
#endif
TRACESUBSYSTEMINITIALIZATION("trap_init");
p = jit_compile_handle(m, sfi.pv, ra, (void *) val);
break;
+#if defined(ENABLE_REPLACEMENT)
+ case TRAP_COUNTDOWN:
+#if defined(__I386__)
+ replace_me_wrapper((char*)xpc - 13, context);
+#endif
+ p = NULL;
+ break;
+#endif
+
default:
/* Let's try to get a backtrace. */
#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* Include machine dependent trap stuff. */
#include "md-trap.h"
void trap_init(void);
void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _TRAP_H */
/* src/vm/jit/verify/icmds.c - ICMD-specific type checking code
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <assert.h>
-#include <vm/exceptions.h>
-#include <vm/jit/show.h>
-#include <typecheck-common.h>
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+
+#include "vm/jit/show.h"
+
+#include "typecheck-common.h"
+
/****************************************************************************/
/* DEBUG HELPERS */
#include "mm/memory.h"
#include "vm/array.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/primitive.h"
+#include "vm/globals.hpp"
+#include "vm/primitive.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/show.h"
/* src/vm/jit/verify/typecheck-typeinferer.c - type inference pass
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "toolbox/logging.h"
-#include "vm/array.h"
#include "vm/access.h"
+#include "vm/array.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/primitive.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
#include "vm/resolve.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/jit.h"
#include "vm/jit/show.h"
#include "vm/jit/verify/typecheck-typeinferer.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#define TYPECHECK_NO_STATISTICS
#include <typecheck-common.h>
#include "vm/access.h"
#include "vm/array.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
+#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/primitive.h"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/jit/jit.h"
#include "vm/jit/parse.h"
#include "vm/jit/show.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#include <typecheck-common.h>
#include "toolbox/logging.h"
#include "vm/array.h"
-#include "vm/exceptions.h"
-#include "vm/primitive.h"
+#include "vm/class.h"
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/jit/jit.h"
#include "vm/jit/verify/typeinfo.h"
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/loader.h"
-
/* check if a linked class is an array class. Only use for linked classes! */
#define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL)
#include "vm/types.h"
#include "vm/global.h"
-
-#include "vmcore/references.h"
+#include "vm/references.h"
/* configuration **************************************************************/
DIST_SUBDIRS = \
freebsd \
- linux
+ linux \
+ solaris
SUBDIRS = $(OS_DIR)
noinst_HEADERS = \
arch.h \
- machine-instr.h \
\
- md-asm.h
+ md-asm.h \
+ md-atomic.hpp
noinst_LTLIBRARIES = libarch.la
/* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
- Copyright (C) 1996-2005, 2006, 2007, 2008 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
.globl asm_builtin_d2i
.globl asm_builtin_d2l
- .globl asm_compare_and_swap
- .globl asm_memory_barrier
-
.globl asm_get_cycle_count
ret
-/* asm_compare_and_swap ********************************************************
-
- Does an atomic compare and swap. Required for the lock
- implementation.
-
-*******************************************************************************/
-
-asm_compare_and_swap:
- mov a1,v0 /* v0 is %rax */
- lock cmpxchg a2,(a0)
- ret
-
-
-/* asm_memory_barrier **********************************************************
-
- A memory barrier for the Java Memory Model.
-
-*******************************************************************************/
-
-asm_memory_barrier:
- mfence
- ret
-
-
/* asm_get_cycle_count *********************************************************
Get the current time-stamp counter from the CPU.
/* src/vm/jit/x86_64/codegen.c - machine code generator for x86_64
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#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/statistics.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.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/stacktrace.hpp"
#include "vm/jit/trap.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* codegen_emit ****************************************************************
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 */
M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP3, RIP, disp);
- CODEGEN_CRITICAL_SECTION_START;
-
M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
/* if (s1 != REG_ITMP1) { */
M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
/* } */
- CODEGEN_CRITICAL_SECTION_END;
-
M_ICMP(REG_ITMP3, REG_ITMP2);
emit_classcast_check(cd, iptr, BRANCH_UGT, REG_ITMP3, s1);
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);
M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
M_ALD(REG_ITMP2, RIP, disp);
- 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_ICMP(REG_ITMP3, REG_ITMP1);
/* put env into first argument register */
- M_MOV_IMM(_Jv_env, REG_A0);
+ M_MOV_IMM(VM_get_jnienv(), REG_A0);
}
/* Call the native function. */
case TYPE_INT:
case TYPE_LNG:
case TYPE_ADR:
- switch (md->returntype.decltype) {
+ switch (md->returntype.primitivetype) {
case PRIMITIVETYPE_BOOLEAN:
M_BZEXT(REG_RESULT, REG_RESULT);
break;
/* src/vm/jit/x86_64/emit.c - x86_64 code emitter functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "threads/lock-common.h"
+#include "vm/options.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include <stdlib.h>
#include <ucontext.h>
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
/* md_signal_handler_sigsegv ***************************************************
#endif
-#if defined(ENABLE_THREADS)
-void thread_restartcriticalsection(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- u1 *pc;
- void *critical;
-
- _mc = &_uc->uc_mcontext;
-
- pc = (u1 *) _mc->mc_rip;
-
- critical = critical_find_restart_point(pc);
-
- if (critical != NULL)
- _mc->mc_rip = (ptrint) critical;
-}
-#endif
-
-
/*
* 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
#include "vm/jit/x86_64/codegen.h"
#include "vm/jit/x86_64/md.h"
-#include "threads/thread.h"
+#include "threads/thread.hpp"
#include "vm/builtin.h"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
#include "vm/jit/trap.h"
-#include "vm/jit/stacktrace.h"
+#include "vm/jit/stacktrace.hpp"
/* md_signal_handler_sigsegv ***************************************************
}
-/* md_critical_section_restart *************************************************
-
- Search the critical sections tree for a matching section and set
- the PC to the restart point, if necessary.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS)
-void md_critical_section_restart(ucontext_t *_uc)
-{
- mcontext_t *_mc;
- u1 *pc;
- u1 *npc;
-
- _mc = &_uc->uc_mcontext;
-
- /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
- different to the ones in <ucontext.h>. */
-
- pc = (u1 *) _mc->gregs[REG_RIP];
-
- npc = critical_find_restart_point(pc);
-
- if (npc != NULL)
- _mc->gregs[REG_RIP] = (ptrint) npc;
-}
-#endif
-
-
/*
* 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
+++ /dev/null
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-static inline long
-__attribute__ ((unused))
-compare_and_swap (volatile long *p, long oldval, long newval)
-{
- long ret;
-
- __asm__ __volatile__ ("lock; cmpxchgq %2, %1"
- : "=a" (ret), "=m" (*p)
- : "r" (newval), "m" (*p), "0" (oldval));
- return ret;
-}
-
-#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() /* nothing */
-#define MEMORY_BARRIER() __asm__ __volatile__ ( \
- "mfence" : : : "memory" );
-
-#endif
#include "vm/jit/x86_64/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/jit.h" /* for REG_* (maybe can be removed) */
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* register descripton array **************************************************/
--- /dev/null
+/* src/vm/jit/x86_64/atomic.hpp - x86_64 atomic instructions
+
+ Copyright (C) 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 _MD_ATOMIC_HPP
+#define _MD_ATOMIC_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * An atomic compare and swap for 32-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+{
+ uint32_t result;
+
+ __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
+ : "=a" (result), "=m" (*p)
+ : "r" (newval), "m" (*p), "0" (oldval));
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for 64-bit integer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+{
+ uint64_t result;
+
+ __asm__ __volatile__ ("lock; cmpxchgq %2, %1"
+ : "=a" (result), "=m" (*p)
+ : "r" (newval), "m" (*p), "0" (oldval));
+
+ return result;
+}
+
+
+/**
+ * An atomic compare and swap for pointer values.
+ *
+ * @param p Pointer to memory address.
+ * @param oldval Old value to be expected.
+ * @param newval New value to be stored.
+ *
+ * @return value of the memory location before the store
+ */
+inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
+{
+ return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
+}
+
+
+/**
+ * A memory barrier.
+ */
+inline void Atomic::memory_barrier(void)
+{
+ __asm__ __volatile__ ("mfence" : : : "memory");
+}
+
+
+/**
+ * A write memory barrier.
+ */
+inline void Atomic::write_memory_barrier(void)
+{
+ __asm__ __volatile__ ("" : : : "memory");
+}
+
+
+/**
+ * An instruction barrier.
+ */
+inline void Atomic::instruction_barrier(void)
+{
+ // Nothing.
+}
+
+#endif // _MD_ATOMIC_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:
+ */
/* Don't use 8 (could be a normal load offset). */
TRAP_COMPILER = 9,
+ TRAP_COUNTDOWN = 10,
TRAP_END
};
/* src/vm/jit/x86_64/md.c - machine dependent x86_64 functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/x86_64/md-abi.h"
-#include "vm/vm.h"
+#include "vm/vm.hpp"
#include "vm/jit/codegen-common.h"
#include "vm/jit/jit.h"
#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 "vmcore/references.h"
-#include "vm/resolve.h"
#define PATCH_BACK_ORIGINAL_MCODE \
--- /dev/null
+## src/vm/jit/x86_64/solaris/Makefile.am
+##
+## Copyright (C) 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.
+
+
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_builddir)/src
+
+LIBS =
+
+noinst_HEADERS =
+
+noinst_LTLIBRARIES = \
+ libmd.la
+
+libmd_la_SOURCES = \
+ md-os.c
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+/* src/vm/jit/x86_64/solaris/md-os.c - machine dependent x86_64 Solaris functions
+
+ Copyright (C) 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 <stdint.h>
+#include <stdlib.h>
+#include <ucontext.h>
+
+#include "vm/types.h"
+
+#include "vm/jit/x86_64/codegen.h"
+#include "vm/jit/x86_64/md.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/builtin.h"
+#include "vm/signallocal.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
+#include "vm/jit/trap.h"
+#include "vm/jit/stacktrace.hpp"
+
+
+/* md_signal_handler_sigsegv ***************************************************
+
+ Signal handler for hardware exception.
+
+*******************************************************************************/
+
+void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ void *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ u1 opc;
+ u1 mod;
+ u1 rm;
+ s4 d;
+ s4 disp;
+ int type;
+ intptr_t val;
+ void *p;
+ java_object_t *o;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+ different to the ones in <ucontext.h>. */
+
+ pv = NULL; /* is resolved during stackframeinfo creation */
+ sp = (u1 *) _mc->gregs[REG_RSP];
+ xpc = (u1 *) _mc->gregs[REG_RIP];
+ ra = xpc; /* return address is equal to XPC */
+
+#if 0
+ /* check for StackOverflowException */
+
+ threads_check_stackoverflow(sp);
+#endif
+
+ /* get exception-throwing instruction */
+
+ opc = M_ALD_MEM_GET_OPC(xpc);
+ mod = M_ALD_MEM_GET_MOD(xpc);
+ rm = M_ALD_MEM_GET_RM(xpc);
+
+ /* for values see emit_mov_mem_reg and emit_mem */
+
+ if ((opc == 0x8b) && (mod == 0) && (rm == 4)) {
+ /* this was a hardware-exception */
+
+ d = M_ALD_MEM_GET_REG(xpc);
+ disp = M_ALD_MEM_GET_DISP(xpc);
+
+ /* we use the exception type as load displacement */
+
+ type = disp;
+
+ /* XXX FIX ME! */
+
+ /* ATTENTION: The _mc->gregs layout is even worse than on
+ i386! See /usr/include/sys/ucontext.h. We need a
+ switch-case here... */
+
+ switch (d) {
+ case 0: /* REG_RAX == 14 */
+ d = REG_RAX;
+ break;
+ case 1: /* REG_RCX == 13 */
+ d = REG_RCX;
+ break;
+ case 2: /* REG_RDX == 12 */
+ d = REG_RDX;
+ break;
+ case 3: /* REG_RBX == 11 */
+ d = REG_RBX;
+ break;
+ case 4: /* REG_RSP == 20 */
+ d = REG_RSP;
+ break;
+ case 5: /* REG_RBP == 10 */
+ d = REG_RBP;
+ break;
+ case 6: /* REG_RSI == 9 */
+ d = REG_RSI;
+ break;
+ case 7: /* REG_RDI == 8 */
+ d = REG_RDI;
+ break;
+ case 8: /* REG_R8 == 7 */
+ d = REG_R8;
+ break;
+ case 9: /* REG_R9 == 6 */
+ d = REG_R9;
+ break;
+ case 10: /* REG_R10 == 5 */
+ d = REG_R10;
+ break;
+ case 11: /* REG_R11 == 4 */
+ d = REG_R11;
+ break;
+ case 12: /* REG_R12 == 3 */
+ d = REG_R12;
+ break;
+ case 13: /* REG_R13 == 2 */
+ d = REG_R13;
+ break;
+ case 14: /* REG_R14 == 1 */
+ d = REG_R14;
+ break;
+ case 15: /* REG_R15 == 0 */
+ d = REG_R15;
+ break;
+ }
+
+ val = _mc->gregs[d];
+
+ if (type == TRAP_COMPILER) {
+ /* The PV from the compiler stub is equal to the XPC. */
+
+ pv = xpc;
+
+ /* We use a framesize of zero here because the call pushed
+ the return addres onto the stack. */
+
+ ra = md_stacktrace_get_returnaddress(sp, 0);
+
+ /* Skip the RA on the stack. */
+
+ sp = sp + 1 * SIZEOF_VOID_P;
+
+ /* The XPC is the RA minus 1, because the RA points to the
+ instruction after the call. */
+
+ xpc = ra - 3;
+ }
+ }
+ else {
+ /* this was a normal NPE */
+
+ type = TRAP_NullPointerException;
+ val = 0;
+ }
+
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* Set registers. */
+
+ if (type == TRAP_COMPILER) {
+ if (p == NULL) {
+ o = builtin_retrieve_exception();
+
+ _mc->gregs[REG_RSP] = (uintptr_t) sp; /* Remove RA from stack. */
+
+ _mc->gregs[REG_RAX] = (uintptr_t) o;
+ _mc->gregs[REG_R10] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[REG_RIP] = (uintptr_t) asm_handle_exception;
+ }
+ else {
+ _mc->gregs[REG_RIP] = (uintptr_t) p;
+ }
+ }
+ else {
+ _mc->gregs[REG_RAX] = (uintptr_t) p;
+ _mc->gregs[REG_R10] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[REG_RIP] = (uintptr_t) asm_handle_exception;
+ }
+}
+
+
+/* md_signal_handler_sigfpe ****************************************************
+
+ ArithmeticException signal handler for hardware divide by zero
+ check.
+
+*******************************************************************************/
+
+void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ int type;
+ intptr_t val;
+ void *p;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+ different to the ones in <ucontext.h>. */
+
+ pv = NULL;
+ sp = (u1 *) _mc->gregs[REG_RSP];
+ xpc = (u1 *) _mc->gregs[REG_RIP];
+ ra = xpc; /* return address is equal to xpc */
+
+ /* This is an ArithmeticException. */
+
+ type = TRAP_ArithmeticException;
+ val = 0;
+
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* set registers */
+
+ _mc->gregs[REG_RAX] = (intptr_t) p;
+ _mc->gregs[REG_R10] = (intptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[REG_RIP] = (intptr_t) asm_handle_exception;
+}
+
+
+/* md_signal_handler_sigill ****************************************************
+
+ Signal handler for patchers.
+
+*******************************************************************************/
+
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ int type;
+ intptr_t val;
+ void *p;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+ different to the ones in <ucontext.h>. */
+
+ pv = NULL;
+ sp = (u1 *) _mc->gregs[REG_RSP];
+ xpc = (u1 *) _mc->gregs[REG_RIP];
+ ra = xpc; /* return address is equal to xpc */
+
+ /* This is a patcher. */
+
+ type = TRAP_PATCHER;
+ val = 0;
+
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* set registers */
+
+ if (p != NULL) {
+ _mc->gregs[REG_RAX] = (intptr_t) p;
+ _mc->gregs[REG_R10] = (intptr_t) xpc; /* REG_ITMP2_XPC */
+ _mc->gregs[REG_RIP] = (intptr_t) asm_handle_exception;
+ }
+}
+
+
+/* md_signal_handler_sigusr1 ***************************************************
+
+ Signal handler for suspending threads.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pc;
+ u1 *sp;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+ different to the ones in <ucontext.h>. */
+
+ /* get the PC and SP for this thread */
+ pc = (u1 *) _mc->gregs[REG_RIP];
+ sp = (u1 *) _mc->gregs[REG_RSP];
+
+ /* now suspend the current thread */
+ threads_suspend_ack(pc, sp);
+}
+#endif
+
+
+/* md_signal_handler_sigusr2 ***************************************************
+
+ Signal handler for profiling sampling.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
+{
+ threadobject *t;
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pc;
+
+ t = THREADOBJECT;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
+ different to the ones in <ucontext.h>. */
+
+ pc = (u1 *) _mc->gregs[REG_RIP];
+
+ t->pc = pc;
+}
+#endif
+
+
+/* md_executionstate_read ******************************************************
+
+ Read the given context into an executionstate.
+
+*******************************************************************************/
+
+void md_executionstate_read(executionstate_t *es, void *context)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ s4 i;
+ s4 d;
+
+ _uc = (ucontext_t *) context;
+ _mc = &_uc->uc_mcontext;
+
+ /* read special registers */
+ es->pc = (u1 *) _mc->gregs[REG_RIP];
+ es->sp = (u1 *) _mc->gregs[REG_RSP];
+ es->pv = NULL;
+
+ /* read integer registers */
+ for (i = 0; i < INT_REG_CNT; i++) {
+ /* XXX FIX ME! */
+
+ switch (i) {
+ case 0: /* REG_RAX == 13 */
+ d = REG_RAX;
+ break;
+ case 1: /* REG_RCX == 14 */
+ d = REG_RCX;
+ break;
+ case 2: /* REG_RDX == 12 */
+ d = REG_RDX;
+ break;
+ case 3: /* REG_RBX == 11 */
+ d = REG_RBX;
+ break;
+ case 4: /* REG_RSP == 15 */
+ d = REG_RSP;
+ break;
+ case 5: /* REG_RBP == 10 */
+ d = REG_RBP;
+ break;
+ case 6: /* REG_RSI == 9 */
+ d = REG_RSI;
+ break;
+ case 7: /* REG_RDI == 8 */
+ d = REG_RDI;
+ break;
+ case 8: /* REG_R8 == 0 */
+ case 9: /* REG_R9 == 1 */
+ case 10: /* REG_R10 == 2 */
+ case 11: /* REG_R11 == 3 */
+ case 12: /* REG_R12 == 4 */
+ case 13: /* REG_R13 == 5 */
+ case 14: /* REG_R14 == 6 */
+ case 15: /* REG_R15 == 7 */
+ d = i - 8;
+ break;
+ }
+
+ es->intregs[i] = _mc->gregs[d];
+ }
+
+ /* read float registers */
+ for (i = 0; i < FLT_REG_CNT; i++)
+ es->fltregs[i] = 0xdeadbeefdeadbeefL;
+}
+
+
+/* md_executionstate_write *****************************************************
+
+ Write the given executionstate back to the context.
+
+*******************************************************************************/
+
+void md_executionstate_write(executionstate_t *es, void *context)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ s4 i;
+ s4 d;
+
+ _uc = (ucontext_t *) context;
+ _mc = &_uc->uc_mcontext;
+
+ /* write integer registers */
+ for (i = 0; i < INT_REG_CNT; i++) {
+ /* XXX FIX ME! */
+
+ switch (i) {
+ case 0: /* REG_RAX == 13 */
+ d = REG_RAX;
+ break;
+ case 1: /* REG_RCX == 14 */
+ d = REG_RCX;
+ break;
+ case 2: /* REG_RDX == 12 */
+ d = REG_RDX;
+ break;
+ case 3: /* REG_RBX == 11 */
+ d = REG_RBX;
+ break;
+ case 4: /* REG_RSP == 15 */
+ d = REG_RSP;
+ break;
+ case 5: /* REG_RBP == 10 */
+ d = REG_RBP;
+ break;
+ case 6: /* REG_RSI == 9 */
+ d = REG_RSI;
+ break;
+ case 7: /* REG_RDI == 8 */
+ d = REG_RDI;
+ break;
+ case 8: /* REG_R8 == 0 */
+ case 9: /* REG_R9 == 1 */
+ case 10: /* REG_R10 == 2 */
+ case 11: /* REG_R11 == 3 */
+ case 12: /* REG_R12 == 4 */
+ case 13: /* REG_R13 == 5 */
+ case 14: /* REG_R14 == 6 */
+ case 15: /* REG_R15 == 7 */
+ d = i - 8;
+ break;
+ }
+
+ _mc->gregs[d] = es->intregs[i];
+ }
+
+ /* write special registers */
+ _mc->gregs[REG_RIP] = (ptrint) es->pc;
+ _mc->gregs[REG_RSP] = (ptrint) es->sp;
+}
+
+
+/*
+ * 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/jit_interface.h - prototypes of jit functions used in vm/ code
-
- 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 _JIT_INTERFACE
-#define _JIT_INTERFACE
-
-#include "config.h"
-#include "vm/types.h"
-
-
-/* These functions are used from vm/ but defined in vm/jit/ */
-
-void code_free_code_of_method(methodinfo *m);
-
-u1 *codegen_generate_stub_compiler(methodinfo *m);
-codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f);
-
-#if defined(ENABLE_INTRP)
-u1 *intrp_createcompilerstub(methodinfo *m);
-#endif
-
-void removecompilerstub(u1 *stub);
-void removenativestub(u1 *stub);
-
-void jit_invalidate_code(methodinfo *m);
-
-void md_param_alloc(methoddesc *md);
-void md_param_alloc_native(methoddesc *md);
-
-/* stub for throwing AbstractMethodError's */
-#if defined(ENABLE_JIT)
-void asm_abstractmethoderror(void);
-#endif
-
-#if defined(ENABLE_INTRP)
-void intrp_asm_abstractmethoderror(void);
-#endif
-
-#endif /* _JIT_INTERFACE */
-
-
-/*
- * 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/linker.c - class linker 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 <stdint.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/native.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/access.h"
+#include "vm/array.h"
+#include "vm/class.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/rt-timing.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+
+
+/* debugging macros ***********************************************************/
+
+#if !defined(NDEBUG)
+# define TRACELINKCLASS(c) \
+ do { \
+ if (opt_TraceLinkClass) { \
+ log_start(); \
+ log_print("[Linking "); \
+ class_print((c)); \
+ log_print("]"); \
+ log_finish(); \
+ } \
+ } while (0)
+#else
+# define TRACELINKCLASS(c)
+#endif
+
+
+/* #include "vm/resolve.h" */
+/* copied prototype to avoid bootstrapping problem: */
+classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
+#else
+#define INLINELOG(code)
+#endif
+
+
+/* global variables ***********************************************************/
+
+static s4 interfaceindex; /* sequential numbering of interfaces */
+static s4 classvalue;
+
+java_object_t *linker_classrenumber_lock;
+
+
+/* private functions **********************************************************/
+
+static classinfo *link_class_intern(classinfo *c);
+static arraydescriptor *link_array(classinfo *c);
+static void linker_compute_class_values(classinfo *c);
+static void linker_compute_subclasses(classinfo *c);
+static bool linker_addinterface(classinfo *c, classinfo *ic);
+static s4 class_highestinterface(classinfo *c);
+
+
+/* linker_init *****************************************************************
+
+ Initializes the linker subsystem and links classes required for the
+ primitive table.
+
+*******************************************************************************/
+
+void linker_preinit(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("linker_preinit");
+
+ /* Reset interface index. */
+
+ interfaceindex = 0;
+
+#if defined(ENABLE_THREADS)
+ /* create the global lock object */
+
+ linker_classrenumber_lock = NEW(java_object_t);
+
+ LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
+#endif
+
+ /* Link the most basic classes. */
+
+ if (!link_class(class_java_lang_Object))
+ vm_abort("linker_preinit: linking java/lang/Object failed");
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_Cloneable))
+ vm_abort("linker_preinit: linking java/lang/Cloneable failed");
+
+ if (!link_class(class_java_io_Serializable))
+ vm_abort("linker_preinit: linking java/io/Serializable failed");
+#endif
+}
+
+
+/* linker_init *****************************************************************
+
+ Links all classes required in the VM.
+
+*******************************************************************************/
+
+void linker_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("linker_init");
+
+ /* Link java.lang.Class as first class of the system, because we
+ need it's vftbl for all other classes so we can use a class as
+ object. */
+
+ if (!link_class(class_java_lang_Class))
+ vm_abort("linker_init: linking java/lang/Class failed");
+
+ /* Now set the header.vftbl of all classes which were created
+ before java.lang.Class was linked. */
+
+ class_postset_header_vftbl();
+
+ /* Link primitive-type wrapping classes. */
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_Void))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ if (!link_class(class_java_lang_Boolean))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Byte))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Character))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Short))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Integer))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Long))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Float))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Double))
+ vm_abort("linker_init: linking failed");
+
+ /* Link important system classes. */
+
+ if (!link_class(class_java_lang_String))
+ vm_abort("linker_init: linking java/lang/String failed");
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_ClassLoader))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_SecurityManager))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ if (!link_class(class_java_lang_System))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Thread))
+ vm_abort("linker_init: linking failed");
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_ThreadGroup))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ if (!link_class(class_java_lang_Throwable))
+ vm_abort("linker_init: linking failed");
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ if (!link_class(class_java_lang_VMSystem))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_VMThread))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_VMThrowable))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ /* Important system exceptions. */
+
+ if (!link_class(class_java_lang_Exception))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_ClassNotFoundException))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_RuntimeException))
+ vm_abort("linker_init: linking failed");
+
+ /* some classes which may be used more often */
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_StackTraceElement))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_Constructor))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_Field))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_Method))
+ vm_abort("linker_init: linking failed");
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ if (!link_class(class_java_lang_reflect_VMConstructor))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_VMField))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_VMMethod))
+ vm_abort("linker_init: linking failed");
+# endif
+
+ if (!link_class(class_java_security_PrivilegedAction))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_util_Vector))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_util_HashMap))
+ vm_abort("linker_init: linking failed");
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ if (!link_class(class_sun_misc_Signal))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_sun_reflect_MagicAccessorImpl))
+ vm_abort("linker_init: linking failed");
+# endif
+
+ if (!link_class(arrayclass_java_lang_Object))
+ vm_abort("linker_init: linking failed");
+#endif
+
+
+ /* create pseudo classes used by the typechecker */
+
+ /* pseudo class for Arraystubs (extends java.lang.Object) */
+
+ pseudo_class_Arraystub =
+ class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
+ pseudo_class_Arraystub->state |= CLASS_LOADED;
+ pseudo_class_Arraystub->super = class_java_lang_Object;
+
+#if defined(ENABLE_JAVASE)
+
+ pseudo_class_Arraystub->interfacescount = 2;
+ pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
+ pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
+ pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ pseudo_class_Arraystub->interfacescount = 0;
+ pseudo_class_Arraystub->interfaces = NULL;
+
+#else
+# error unknown Java configuration
+#endif
+
+ if (!classcache_store_unique(pseudo_class_Arraystub))
+ vm_abort("linker_init: could not cache pseudo_class_Arraystub");
+
+ if (!link_class(pseudo_class_Arraystub))
+ vm_abort("linker_init: linking pseudo_class_Arraystub failed");
+
+ /* pseudo class representing the null type */
+
+ pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
+ pseudo_class_Null->state |= CLASS_LOADED;
+ pseudo_class_Null->super = class_java_lang_Object;
+
+ if (!classcache_store_unique(pseudo_class_Null))
+ vm_abort("linker_init: could not cache pseudo_class_Null");
+
+ if (!link_class(pseudo_class_Null))
+ vm_abort("linker_init: linking failed");
+
+ /* pseudo class representing new uninitialized objects */
+
+ pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
+ pseudo_class_New->state |= CLASS_LOADED;
+ pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
+ pseudo_class_New->super = class_java_lang_Object;
+
+ if (!classcache_store_unique(pseudo_class_New))
+ vm_abort("linker_init: could not cache pseudo_class_New");
+
+ /* Correct vftbl-entries (retarded loading and linking of class
+ java/lang/String). */
+
+ stringtable_update();
+}
+
+
+/* link_class ******************************************************************
+
+ Wrapper function for link_class_intern to ease monitor enter/exit
+ and exception handling.
+
+*******************************************************************************/
+
+classinfo *link_class(classinfo *c)
+{
+ classinfo *r;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_end;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ if (c == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ LOCK_MONITOR_ENTER(c);
+
+ /* Maybe the class is currently linking or is already linked.*/
+
+ if ((c->state & CLASS_LINKING) || (c->state & CLASS_LINKED)) {
+ LOCK_MONITOR_EXIT(c);
+
+ return c;
+ }
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ compilingtime_stop();
+
+ if (opt_getloadingtime)
+ loadingtime_start();
+#endif
+
+ /* call the internal function */
+
+ r = link_class_intern(c);
+
+ /* If return value is NULL, we had a problem and the class is not
+ linked. */
+
+ if (r == NULL)
+ c->state &= ~CLASS_LINKING;
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_stop();
+
+ if (opt_getcompilingtime)
+ compilingtime_start();
+#endif
+
+ LOCK_MONITOR_EXIT(c);
+
+ RT_TIMING_GET_TIME(time_end);
+
+ RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
+
+ return r;
+}
+
+
+/* linker_overwrite_method *****************************************************
+
+ Overwrite a method with another one, update method flags and check
+ assumptions.
+
+ IN:
+ mg................the general method being overwritten
+ ms................the overwriting (more specialized) method
+ wl................worklist where to add invalidated methods
+
+ RETURN VALUE:
+ true..............everything ok
+ false.............an exception has been thrown
+
+*******************************************************************************/
+
+static bool linker_overwrite_method(methodinfo *mg,
+ methodinfo *ms,
+ method_worklist **wl)
+{
+ classinfo *cg;
+ classinfo *cs;
+
+ cg = mg->clazz;
+ cs = ms->clazz;
+
+ /* overriding a final method is illegal */
+
+ if (mg->flags & ACC_FINAL) {
+ exceptions_throw_verifyerror(mg, "Overriding final method");
+ return false;
+ }
+
+ /* method ms overwrites method mg */
+
+#if defined(ENABLE_VERIFIER)
+ /* Add loading constraints (for the more general types of method mg). */
+ /* Not for <init>, as it is not invoked virtually. */
+
+ if ((ms->name != utf_init)
+ && !classcache_add_constraints_for_params(
+ cs->classloader, cg->classloader, mg))
+ {
+ return false;
+ }
+#endif
+
+ /* inherit the vftbl index, and record the overwriting */
+
+ ms->vftblindex = mg->vftblindex;
+ ms->overwrites = mg;
+
+ /* update flags and check assumptions */
+ /* <init> methods are a special case, as they are never dispatched dynamically */
+
+ if ((ms->flags & ACC_METHOD_IMPLEMENTED) && ms->name != utf_init) {
+ do {
+
+#if defined(ENABLE_TLH)
+ if (mg->flags & ACC_METHOD_MONOMORPHY_USED) {
+ printf("%s/%s is evil! the siner is %s/%s\n", mg->clazz->name->text, mg->name->text,
+ ms->clazz->name->text, ms->name->text);
+ ms->flags |= ACC_METHOD_PARENT_MONOMORPHY_USED;
+ }
+#endif
+
+ if (mg->flags & ACC_METHOD_IMPLEMENTED) {
+ /* this adds another implementation */
+
+ mg->flags &= ~ACC_METHOD_MONOMORPHIC;
+
+ INLINELOG( printf("becomes polymorphic: "); method_println(mg); );
+
+ method_break_assumption_monomorphic(mg, wl);
+ }
+ else {
+ /* this is the first implementation */
+
+ mg->flags |= ACC_METHOD_IMPLEMENTED;
+
+ INLINELOG( printf("becomes implemented: "); method_println(mg); );
+ }
+
+ ms = mg;
+ mg = mg->overwrites;
+ } while (mg != NULL);
+ }
+
+ return true;
+}
+
+
+/* link_class_intern ***********************************************************
+
+ Tries to link a class. The function calculates the length in bytes
+ that an instance of this class requires as well as the VTBL for
+ methods and interface methods.
+
+*******************************************************************************/
+
+static classinfo *link_class_intern(classinfo *c)
+{
+ classinfo *super; /* super class */
+ classinfo *tc; /* temporary class variable */
+ s4 supervftbllength; /* vftbllegnth of super class */
+ s4 vftbllength; /* vftbllength of current class */
+ s4 interfacetablelength; /* interface table length */
+ vftbl_t *v; /* vftbl of current class */
+ s4 i; /* interface/method/field counter */
+ arraydescriptor *arraydesc; /* descriptor for array classes */
+ method_worklist *worklist; /* worklist for recompilation */
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_resolving, time_compute_vftbl,
+ time_abstract, time_compute_iftbl, time_fill_vftbl,
+ time_offsets, time_fill_iftbl, time_finalizer,
+ time_subclasses;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ TRACELINKCLASS(c);
+
+ /* the class must be loaded */
+
+ /* XXX should this be a specific exception? */
+ assert(c->state & CLASS_LOADED);
+
+ /* This is check in link_class. */
+
+ assert(!(c->state & CLASS_LINKED));
+
+ /* cache the self-reference of this class */
+ /* we do this for cases where the defining loader of the class */
+ /* has not yet been recorded as an initiating loader for the class */
+ /* this is needed so subsequent code can assume that self-refs */
+ /* will always resolve lazily */
+ /* No need to do it for the bootloader - it is always registered */
+ /* as initiating loader for the classes it loads. */
+ if (c->classloader)
+ classcache_store(c->classloader,c,false);
+
+ /* this class is currently linking */
+
+ c->state |= CLASS_LINKING;
+
+ arraydesc = NULL;
+ worklist = NULL;
+
+ /* Link the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ tc = c->interfaces[i];
+
+ if (!(tc->state & CLASS_LINKED))
+ if (!link_class(tc))
+ return NULL;
+ }
+
+ /* check super class */
+
+ super = NULL;
+
+ /* Check for java/lang/Object. */
+
+ if (c->super == NULL) {
+ c->index = 0;
+ c->instancesize = sizeof(java_object_t);
+
+ vftbllength = supervftbllength = 0;
+
+ c->finalizer = NULL;
+ }
+ else {
+ /* Get super class. */
+
+ super = c->super;
+
+ /* Link the super class if necessary. */
+
+ if (!(super->state & CLASS_LINKED))
+ if (!link_class(super))
+ return NULL;
+
+ /* OR the ACC_CLASS_HAS_POINTERS and the ACC_CLASS_REFERENCE_*
+ flags. */
+
+ c->flags |= (super->flags &
+ (ACC_CLASS_HAS_POINTERS | ACC_CLASS_REFERENCE_MASK));
+
+ /* handle array classes */
+
+ if (c->name->text[0] == '[')
+ if (!(arraydesc = link_array(c)))
+ return NULL;
+
+ if (c->flags & ACC_INTERFACE)
+ c->index = interfaceindex++;
+ else
+ c->index = super->index + 1;
+
+ c->instancesize = super->instancesize;
+
+ vftbllength = supervftbllength = super->vftbl->vftbllength;
+
+ c->finalizer = super->finalizer;
+ }
+ RT_TIMING_GET_TIME(time_resolving);
+
+
+ /* compute vftbl length */
+
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ if (!(m->flags & ACC_STATIC)) { /* is instance method */
+ tc = super;
+
+ while (tc) {
+ s4 j;
+
+ for (j = 0; j < tc->methodscount; j++) {
+ if (method_canoverwrite(m, &(tc->methods[j]))) {
+ if (tc->methods[j].flags & ACC_PRIVATE)
+ goto notfoundvftblindex;
+
+ /* package-private methods in other packages */
+ /* must not be overridden */
+ /* (see Java Language Specification 8.4.8.1) */
+ if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
+ && !SAME_PACKAGE(c,tc) )
+ {
+ goto notfoundvftblindex;
+ }
+
+ if (!linker_overwrite_method(&(tc->methods[j]), m, &worklist))
+ return NULL;
+
+ goto foundvftblindex;
+ }
+ }
+
+ tc = tc->super;
+ }
+
+ notfoundvftblindex:
+ m->vftblindex = (vftbllength++);
+ foundvftblindex:
+ ;
+ }
+ }
+ RT_TIMING_GET_TIME(time_compute_vftbl);
+
+
+ /* Check all interfaces of an abstract class (maybe be an
+ interface too) for unimplemented methods. Such methods are
+ called miranda-methods and are marked with the ACC_MIRANDA
+ flag. VMClass.getDeclaredMethods does not return such
+ methods. */
+
+ if (c->flags & ACC_ABSTRACT) {
+ classinfo *ic;
+ methodinfo *im;
+ s4 abstractmethodscount;
+ s4 j;
+ s4 k;
+
+ abstractmethodscount = 0;
+
+ /* check all interfaces of the abstract class */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ ic = c->interfaces[i];
+
+ for (j = 0; j < ic->methodscount; j++) {
+ im = &(ic->methods[j]);
+
+ /* skip `<clinit>' and `<init>' */
+
+ if ((im->name == utf_clinit) || (im->name == utf_init))
+ continue;
+
+ for (tc = c; tc != NULL; tc = tc->super) {
+ for (k = 0; k < tc->methodscount; k++) {
+ if (method_canoverwrite(im, &(tc->methods[k])))
+ goto noabstractmethod;
+ }
+ }
+
+ abstractmethodscount++;
+
+ noabstractmethod:
+ ;
+ }
+ }
+
+ if (abstractmethodscount > 0) {
+ methodinfo *am;
+
+ /* reallocate methods memory */
+
+ c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
+ c->methodscount + abstractmethodscount);
+
+ for (i = 0; i < c->interfacescount; i++) {
+ ic = c->interfaces[i];
+
+ for (j = 0; j < ic->methodscount; j++) {
+ im = &(ic->methods[j]);
+
+ /* skip `<clinit>' and `<init>' */
+
+ if ((im->name == utf_clinit) || (im->name == utf_init))
+ continue;
+
+ for (tc = c; tc != NULL; tc = tc->super) {
+ for (k = 0; k < tc->methodscount; k++) {
+ if (method_canoverwrite(im, &(tc->methods[k])))
+ goto noabstractmethod2;
+ }
+ }
+
+ /* Copy the method found into the new c->methods
+ array and tag it as miranda-method. */
+
+ am = &(c->methods[c->methodscount]);
+ c->methodscount++;
+
+ MCOPY(am, im, methodinfo, 1);
+
+ am->vftblindex = (vftbllength++);
+ am->clazz = c;
+ am->flags |= ACC_MIRANDA;
+
+ noabstractmethod2:
+ ;
+ }
+ }
+ }
+ }
+ RT_TIMING_GET_TIME(time_abstract);
+
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_vftbl_len +=
+ sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
+#endif
+
+ /* compute interfacetable length */
+
+ interfacetablelength = 0;
+
+ for (tc = c; tc != NULL; tc = tc->super) {
+ for (i = 0; i < tc->interfacescount; i++) {
+ s4 h = class_highestinterface(tc->interfaces[i]) + 1;
+
+ if (h > interfacetablelength)
+ interfacetablelength = h;
+ }
+ }
+ RT_TIMING_GET_TIME(time_compute_iftbl);
+
+ /* allocate virtual function table */
+
+ v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
+ sizeof(methodptr) * (vftbllength - 1) +
+ sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
+ v = (vftbl_t *) (((methodptr *) v) +
+ (interfacetablelength - 1) * (interfacetablelength > 1));
+
+ c->vftbl = v;
+ v->clazz = c;
+ v->vftbllength = vftbllength;
+ v->interfacetablelength = interfacetablelength;
+ v->arraydesc = arraydesc;
+
+ /* store interface index in vftbl */
+
+ if (c->flags & ACC_INTERFACE)
+ v->baseval = -(c->index);
+
+ /* copy virtual function table of super class */
+
+ for (i = 0; i < supervftbllength; i++)
+ v->table[i] = super->vftbl->table[i];
+
+ /* Fill the remaining vftbl slots with the AbstractMethodError
+ stub (all after the super class slots, because they are already
+ initialized). */
+
+ for (; i < vftbllength; i++) {
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+ else
+# endif
+ v->table[i] = (methodptr) (ptrint) &asm_abstractmethoderror;
+#else
+ v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+#endif
+ }
+
+ /* add method stubs into virtual function table */
+
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ assert(m->stubroutine == NULL);
+
+ /* Don't create a compiler stub for abstract methods as they
+ throw an AbstractMethodError with the default stub in the
+ vftbl. This entry is simply copied by sub-classes. */
+
+ if (m->flags & ACC_ABSTRACT)
+ continue;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ m->stubroutine = intrp_createcompilerstub(m);
+ else
+#endif
+ m->stubroutine = codegen_generate_stub_compiler(m);
+#else
+ m->stubroutine = intrp_createcompilerstub(m);
+#endif
+
+ /* static methods are not in the vftbl */
+
+ if (m->flags & ACC_STATIC)
+ continue;
+
+ /* insert the stubroutine into the vftbl */
+
+ v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
+ }
+ RT_TIMING_GET_TIME(time_fill_vftbl);
+
+ /* compute instance size and offset of each field */
+
+ for (i = 0; i < c->fieldscount; i++) {
+ s4 dsize;
+ fieldinfo *f = &(c->fields[i]);
+
+ if (!(f->flags & ACC_STATIC)) {
+ dsize = descriptor_typesize(f->parseddesc);
+ c->instancesize = MEMORY_ALIGN(c->instancesize, dsize);
+ f->offset = c->instancesize;
+ c->instancesize += dsize;
+ }
+ }
+ RT_TIMING_GET_TIME(time_offsets);
+
+ /* initialize interfacetable and interfacevftbllength */
+
+ v->interfacevftbllength = MNEW(s4, interfacetablelength);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
+#endif
+
+ for (i = 0; i < interfacetablelength; i++) {
+ v->interfacevftbllength[i] = 0;
+ v->interfacetable[-i] = NULL;
+ }
+
+ /* add interfaces */
+
+ for (tc = c; tc != NULL; tc = tc->super)
+ for (i = 0; i < tc->interfacescount; i++)
+ if (!linker_addinterface(c, tc->interfaces[i]))
+ return NULL;
+
+ RT_TIMING_GET_TIME(time_fill_iftbl);
+
+ /* add finalizer method (not for java.lang.Object) */
+
+ if (super) {
+ methodinfo *fi;
+
+ fi = class_findmethod(c, utf_finalize, utf_void__void);
+
+ if (fi)
+ if (!(fi->flags & ACC_STATIC))
+ c->finalizer = fi;
+ }
+ RT_TIMING_GET_TIME(time_finalizer);
+
+ /* final tasks */
+
+ linker_compute_subclasses(c);
+
+ RT_TIMING_GET_TIME(time_subclasses);
+
+ /* revert the linking state and class is linked */
+
+ c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
+
+ /* check worklist */
+
+ /* XXX must this also be done in case of exception? */
+
+ while (worklist != NULL) {
+ method_worklist *wi = worklist;
+
+ worklist = worklist->next;
+
+ INLINELOG( printf("MUST BE RECOMPILED: "); method_println(wi->m); );
+ jit_invalidate_code(wi->m);
+
+ /* XXX put worklist into dump memory? */
+ FREE(wi, method_worklist);
+ }
+
+ RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
+ RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
+ RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
+ RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
+ RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
+ RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
+ RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
+ RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
+ RT_TIMING_TIME_DIFF(time_finalizer ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
+
+ /* just return c to show that we didn't had a problem */
+
+ return c;
+}
+
+
+/* link_array ******************************************************************
+
+ This function is called by link_class to create the arraydescriptor
+ for an array class.
+
+ This function returns NULL if the array cannot be linked because
+ the component type has not been linked yet.
+
+*******************************************************************************/
+
+static arraydescriptor *link_array(classinfo *c)
+{
+ classinfo *comp;
+ s4 namelen;
+ arraydescriptor *desc;
+ vftbl_t *compvftbl;
+ utf *u;
+
+ comp = NULL;
+ namelen = c->name->blength;
+
+ /* Check the component type */
+
+ switch (c->name->text[1]) {
+ case '[':
+ /* c is an array of arrays. */
+ u = utf_new(c->name->text + 1, namelen - 1);
+ if (!(comp = load_class_from_classloader(u, c->classloader)))
+ return NULL;
+ break;
+
+ case 'L':
+ /* c is an array of objects. */
+ u = utf_new(c->name->text + 2, namelen - 3);
+ if (!(comp = load_class_from_classloader(u, c->classloader)))
+ return NULL;
+ break;
+ }
+
+ /* If the component type has not been linked, link it now */
+
+ assert(!comp || (comp->state & CLASS_LOADED));
+
+ if (comp && !(comp->state & CLASS_LINKED))
+ if (!link_class(comp))
+ return NULL;
+
+ /* Allocate the arraydescriptor */
+
+ desc = NEW(arraydescriptor);
+
+ if (comp) {
+ /* c is an array of references */
+ desc->arraytype = ARRAYTYPE_OBJECT;
+ desc->componentsize = sizeof(void*);
+ desc->dataoffset = OFFSET(java_objectarray_t, data);
+
+ compvftbl = comp->vftbl;
+
+ if (!compvftbl) {
+ log_text("Component class has no vftbl");
+ assert(0);
+ }
+
+ desc->componentvftbl = compvftbl;
+
+ if (compvftbl->arraydesc) {
+ desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
+
+ if (compvftbl->arraydesc->dimension >= 255) {
+ log_text("Creating array of dimension >255");
+ assert(0);
+ }
+
+ desc->dimension = compvftbl->arraydesc->dimension + 1;
+ desc->elementtype = compvftbl->arraydesc->elementtype;
+
+ } else {
+ desc->elementvftbl = compvftbl;
+ desc->dimension = 1;
+ desc->elementtype = ARRAYTYPE_OBJECT;
+ }
+
+ } else {
+ /* c is an array of a primitive type */
+ switch (c->name->text[1]) {
+ case 'Z':
+ desc->arraytype = ARRAYTYPE_BOOLEAN;
+ desc->dataoffset = OFFSET(java_booleanarray_t,data);
+ desc->componentsize = sizeof(u1);
+ break;
+
+ case 'B':
+ desc->arraytype = ARRAYTYPE_BYTE;
+ desc->dataoffset = OFFSET(java_bytearray_t,data);
+ desc->componentsize = sizeof(u1);
+ break;
+
+ case 'C':
+ desc->arraytype = ARRAYTYPE_CHAR;
+ desc->dataoffset = OFFSET(java_chararray_t,data);
+ desc->componentsize = sizeof(u2);
+ break;
+
+ case 'D':
+ desc->arraytype = ARRAYTYPE_DOUBLE;
+ desc->dataoffset = OFFSET(java_doublearray_t,data);
+ desc->componentsize = sizeof(double);
+ break;
+
+ case 'F':
+ desc->arraytype = ARRAYTYPE_FLOAT;
+ desc->dataoffset = OFFSET(java_floatarray_t,data);
+ desc->componentsize = sizeof(float);
+ break;
+
+ case 'I':
+ desc->arraytype = ARRAYTYPE_INT;
+ desc->dataoffset = OFFSET(java_intarray_t,data);
+ desc->componentsize = sizeof(s4);
+ break;
+
+ case 'J':
+ desc->arraytype = ARRAYTYPE_LONG;
+ desc->dataoffset = OFFSET(java_longarray_t,data);
+ desc->componentsize = sizeof(s8);
+ break;
+
+ case 'S':
+ desc->arraytype = ARRAYTYPE_SHORT;
+ desc->dataoffset = OFFSET(java_shortarray_t,data);
+ desc->componentsize = sizeof(s2);
+ break;
+
+ default:
+ exceptions_throw_noclassdeffounderror(c->name);
+ return NULL;
+ }
+
+ desc->componentvftbl = NULL;
+ desc->elementvftbl = NULL;
+ desc->dimension = 1;
+ desc->elementtype = desc->arraytype;
+ }
+
+ return desc;
+}
+
+
+/* linker_compute_subclasses ***************************************************
+
+ XXX
+
+ ATTENTION: DO NOT REMOVE ANY OF THE LOCKING MECHANISMS BELOW:
+ This function needs to take the class renumber lock and stop the
+ world during class renumbering. The lock is used in C code which
+ is not that performance critical. Whereas JIT code uses critical
+ sections to atomically access the class values.
+
+*******************************************************************************/
+
+static void linker_compute_subclasses(classinfo *c)
+{
+ LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+ if (!(c->flags & ACC_INTERFACE)) {
+ c->nextsub = NULL;
+ c->sub = NULL;
+ }
+
+ if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
+ c->nextsub = c->super->sub;
+ c->super->sub = c;
+ }
+
+ classvalue = 0;
+
+ /* compute class values */
+
+ linker_compute_class_values(class_java_lang_Object);
+
+ LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+}
+
+
+/* linker_compute_class_values *************************************************
+
+ XXX
+
+*******************************************************************************/
+
+static void linker_compute_class_values(classinfo *c)
+{
+ classinfo *subs;
+
+ c->vftbl->baseval = ++classvalue;
+
+ subs = c->sub;
+
+ while (subs) {
+ linker_compute_class_values(subs);
+
+ subs = subs->nextsub;
+ }
+
+ c->vftbl->diffval = classvalue - c->vftbl->baseval;
+}
+
+
+/* linker_addinterface *********************************************************
+
+ Is needed by link_class for adding a VTBL to a class. All
+ interfaces implemented by ic are added as well.
+
+ RETURN VALUE:
+ true.........everything ok
+ false........an exception has been thrown
+
+*******************************************************************************/
+
+static bool linker_addinterface(classinfo *c, classinfo *ic)
+{
+ s4 j, k;
+ vftbl_t *v;
+ s4 i;
+ classinfo *sc;
+ methodinfo *m;
+
+ v = c->vftbl;
+ i = ic->index;
+
+ if (i >= v->interfacetablelength)
+ vm_abort("Internal error: interfacetable overflow");
+
+ /* if this interface has already been added, return immediately */
+
+ if (v->interfacetable[-i] != NULL)
+ return true;
+
+ if (ic->methodscount == 0) { /* fake entry needed for subtype test */
+ v->interfacevftbllength[i] = 1;
+ v->interfacetable[-i] = MNEW(methodptr, 1);
+ v->interfacetable[-i][0] = NULL;
+ }
+ else {
+ v->interfacevftbllength[i] = ic->methodscount;
+ v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_vftbl_len += sizeof(methodptr) *
+ (ic->methodscount + (ic->methodscount == 0));
+#endif
+
+ for (j = 0; j < ic->methodscount; j++) {
+ for (sc = c; sc != NULL; sc = sc->super) {
+ for (k = 0; k < sc->methodscount; k++) {
+ m = &(sc->methods[k]);
+
+ if (method_canoverwrite(m, &(ic->methods[j]))) {
+ /* method m overwrites the (abstract) method */
+#if defined(ENABLE_VERIFIER)
+ /* Add loading constraints (for the more
+ general types of the method
+ ic->methods[j]). */
+ if (!classcache_add_constraints_for_params(
+ c->classloader, ic->classloader,
+ &(ic->methods[j])))
+ {
+ return false;
+ }
+#endif
+
+ /* XXX taken from gcj */
+ /* check for ACC_STATIC: IncompatibleClassChangeError */
+
+ /* check for !ACC_PUBLIC: IllegalAccessError */
+
+ /* check for ACC_ABSTRACT: AbstracMethodError,
+ not sure about that one */
+
+ v->interfacetable[-i][j] = v->table[m->vftblindex];
+ goto foundmethod;
+ }
+ }
+ }
+
+ /* If no method was found, insert the AbstractMethodError
+ stub. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ v->interfacetable[-i][j] =
+ (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+ else
+# endif
+ v->interfacetable[-i][j] =
+ (methodptr) (ptrint) &asm_abstractmethoderror;
+#else
+ v->interfacetable[-i][j] =
+ (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+#endif
+
+ foundmethod:
+ ;
+ }
+ }
+
+ /* add superinterfaces of this interface */
+
+ for (j = 0; j < ic->interfacescount; j++)
+ if (!linker_addinterface(c, ic->interfaces[j]))
+ return false;
+
+ /* everything ok */
+
+ return true;
+}
+
+
+/* class_highestinterface ******************************************************
+
+ Used by the function link_class to determine the amount of memory
+ needed for the interface table.
+
+*******************************************************************************/
+
+static s4 class_highestinterface(classinfo *c)
+{
+ s4 h;
+ s4 h2;
+ s4 i;
+
+ /* check for ACC_INTERFACE bit already done in link_class_intern */
+
+ h = c->index;
+
+ for (i = 0; i < c->interfacescount; i++) {
+ h2 = class_highestinterface(c->interfaces[i]);
+
+ if (h2 > h)
+ h = h2;
+ }
+
+ return 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:
+ */
--- /dev/null
+/* src/vm/linker.h - class linker 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 _LINKER_H
+#define _LINKER_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct _vftbl vftbl_t;
+typedef struct arraydescriptor arraydescriptor;
+typedef struct primitivetypeinfo primitivetypeinfo;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/class.h"
+#include "vm/references.h"
+
+
+/* virtual function table ******************************************************
+
+ The vtbl has a bidirectional layout with open ends at both sides.
+ interfacetablelength gives the number of entries of the interface
+ table at the start of the vftbl. The vftbl pointer points to
+ &interfacetable[0]. vftbllength gives the number of entries of
+ table at the end of the vftbl.
+
+ runtime type check (checkcast):
+
+ Different methods are used for runtime type check depending on the
+ argument of checkcast/instanceof.
+
+ A check against a class is implemented via relative numbering on
+ the class hierachy tree. The tree is numbered in a depth first
+ traversal setting the base field and the diff field. The diff field
+ gets the result of (high - base) so that a range check can be
+ implemented by an unsigned compare. A sub type test is done by
+ checking the inclusion of base of the sub class in the range of the
+ superclass.
+
+ A check against an interface is implemented via the
+ interfacevftbl. If the interfacevftbl contains a nonnull value a
+ class is a subclass of this interface.
+
+ interfacetable:
+
+ Like standard virtual methods interface methods are called using
+ virtual function tables. All interfaces are numbered sequentially
+ (starting with zero). For each class there exist an interface table
+ of virtual function tables for each implemented interface. The
+ length of the interface table is determined by the highest number
+ of an implemented interface.
+
+ The following example assumes a class which implements interface 0 and 3:
+
+ interfacetablelength = 4
+
+ | ... | +----------+
+ +-----------+ | method 2 |---> method z
+ | class | | method 1 |---> method y
+ +-----------+ | method 0 |---> method x
+ | ivftbl 0 |----------> +----------+
+ vftblptr ---> +-----------+
+ | ivftbl -1 |--> NULL +----------+
+ | ivftbl -2 |--> NULL | method 1 |---> method x
+ | ivftbl -3 |-----+ | method 0 |---> method a
+ +-----------+ +----> +----------+
+
+ +---------------+
+ | length 3 = 2 |
+ | length 2 = 0 |
+ | length 1 = 0 |
+ | length 0 = 3 |
+ interfacevftbllength ---> +---------------+
+
+*******************************************************************************/
+
+struct _vftbl {
+ methodptr *interfacetable[1]; /* interface table (access via macro) */
+ classinfo *clazz; /* class, the vtbl belongs to */
+ arraydescriptor *arraydesc; /* for array classes, otherwise NULL */
+ s4 vftbllength; /* virtual function table length */
+ s4 interfacetablelength; /* interface table length */
+ s4 baseval; /* base for runtime type check */
+ /* (-index for interfaces) */
+ s4 diffval; /* high - base for runtime type check */
+ s4 *interfacevftbllength; /* length of interface vftbls */
+ methodptr table[1]; /* class vftbl */
+};
+
+
+/* arraydescriptor *************************************************************
+
+ For every array class an arraydescriptor is allocated which
+ describes the array class. The arraydescriptor is referenced from
+ the vftbl of the array class.
+
+*******************************************************************************/
+
+struct arraydescriptor {
+ vftbl_t *componentvftbl; /* vftbl of the component type, NULL for primit. */
+ vftbl_t *elementvftbl; /* vftbl of the element type, NULL for primitive */
+ s2 arraytype; /* ARRAYTYPE_* constant */
+ s2 dimension; /* dimension of the array (always >= 1) */
+ s4 dataoffset; /* offset of the array data from object pointer */
+ s4 componentsize; /* size of a component in bytes */
+ s2 elementtype; /* ARRAYTYPE_* constant */
+};
+
+
+/* global variables ***********************************************************/
+
+/* This lock must be taken while renumbering classes or while atomically */
+/* accessing classes. */
+
+extern java_object_t *linker_classrenumber_lock;
+
+
+/* function prototypes ********************************************************/
+
+void linker_preinit(void);
+void linker_init(void);
+classinfo *link_class(classinfo *c);
+
+#endif /* _LINKER_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/loader.c - class loader 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/package.hpp"
+#include "vm/primitive.hpp"
+#include "vm/resolve.h"
+#include "vm/rt-timing.h"
+#include "vm/string.hpp"
+#include "vm/suck.h"
+#include "vm/vm.hpp"
+
+
+#if defined(ENABLE_JAVASE)
+# include "vm/annotation.h"
+# include "vm/stackmap.h"
+#endif
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#if defined(ENABLE_ZLIB)
+# include "vm/zip.h"
+#endif
+
+#if defined(ENABLE_JVMTI)
+# include "native/jvmti/cacaodbg.h"
+#endif
+
+
+/* global variables ***********************************************************/
+
+static hashtable *hashtable_classloader;
+
+
+/* loader_preinit **************************************************************
+
+ Initializes the classpath list and loads classes required for the
+ primitive table.
+
+ NOTE: Exceptions thrown during VM initialization are caught in the
+ exception functions themselves.
+
+*******************************************************************************/
+
+void loader_preinit(void)
+{
+#if defined(ENABLE_THREADS)
+ list_classpath_entry *lce;
+#endif
+
+ TRACESUBSYSTEMINITIALIZATION("loader_preinit");
+
+#if defined(ENABLE_THREADS)
+ /* Initialize the monitor pointer for zip/jar file locking. */
+
+ for (lce = list_first(list_classpath_entries); lce != NULL;
+ lce = list_next(list_classpath_entries, lce)) {
+ if (lce->type == CLASSPATH_ARCHIVE)
+ LOCK_INIT_OBJECT_LOCK(lce);
+ }
+#endif
+
+ /* initialize classloader hashtable, 10 entries should be enough */
+
+ hashtable_classloader = NEW(hashtable);
+ hashtable_create(hashtable_classloader, 10);
+
+ /* Load the most basic classes. */
+
+ assert(VM_is_initializing() == true);
+
+ class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object);
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_Cloneable = load_class_bootstrap(utf_java_lang_Cloneable);
+ class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable);
+#endif
+}
+
+
+/* loader_init *****************************************************************
+
+ Loads all classes required in the VM.
+
+ NOTE: Exceptions thrown during VM initialization are caught in the
+ exception functions themselves.
+
+*******************************************************************************/
+
+void loader_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("loader_init");
+
+ /* Load primitive-type wrapping classes. */
+
+ assert(VM_is_initializing() == true);
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void);
+#endif
+
+ class_java_lang_Boolean = load_class_bootstrap(utf_java_lang_Boolean);
+ class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte);
+ class_java_lang_Character = load_class_bootstrap(utf_java_lang_Character);
+ class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short);
+ class_java_lang_Integer = load_class_bootstrap(utf_java_lang_Integer);
+ class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long);
+ class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float);
+ class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double);
+
+ /* Load important system classes. */
+
+ class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class);
+ class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_ClassLoader =
+ load_class_bootstrap(utf_java_lang_ClassLoader);
+
+ class_java_lang_SecurityManager =
+ load_class_bootstrap(utf_java_lang_SecurityManager);
+#endif
+
+ class_java_lang_System =
+ load_class_bootstrap(utf_new_char("java/lang/System"));
+
+ class_java_lang_Thread =
+ load_class_bootstrap(utf_new_char("java/lang/Thread"));
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_ThreadGroup =
+ load_class_bootstrap(utf_java_lang_ThreadGroup);
+#endif
+
+ class_java_lang_Throwable = load_class_bootstrap(utf_java_lang_Throwable);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ class_java_lang_VMSystem =
+ load_class_bootstrap(utf_new_char("java/lang/VMSystem"));
+
+ class_java_lang_VMThread =
+ load_class_bootstrap(utf_new_char("java/lang/VMThread"));
+
+ class_java_lang_VMThrowable =
+ load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
+#endif
+
+ /* Important system exceptions. */
+
+ class_java_lang_Exception = load_class_bootstrap(utf_java_lang_Exception);
+
+ class_java_lang_ClassNotFoundException =
+ load_class_bootstrap(utf_java_lang_ClassNotFoundException);
+
+ class_java_lang_RuntimeException =
+ load_class_bootstrap(utf_java_lang_RuntimeException);
+
+ /* Some classes which may be used often. */
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_StackTraceElement = load_class_bootstrap(utf_java_lang_StackTraceElement);
+
+ class_java_lang_reflect_Constructor = load_class_bootstrap(utf_java_lang_reflect_Constructor);
+ class_java_lang_reflect_Field = load_class_bootstrap(utf_java_lang_reflect_Field);
+ class_java_lang_reflect_Method = load_class_bootstrap(utf_java_lang_reflect_Method);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ class_java_lang_reflect_VMConstructor = load_class_bootstrap(utf_java_lang_reflect_VMConstructor);
+ class_java_lang_reflect_VMField = load_class_bootstrap(utf_java_lang_reflect_VMField);
+ class_java_lang_reflect_VMMethod = load_class_bootstrap(utf_java_lang_reflect_VMMethod);
+# endif
+
+ class_java_security_PrivilegedAction = load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
+
+ class_java_util_HashMap = load_class_bootstrap(utf_new_char("java/util/HashMap"));
+ class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ class_sun_misc_Signal = load_class_bootstrap(utf_new_char("sun/misc/Signal"));
+ class_sun_reflect_MagicAccessorImpl = load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
+# endif
+
+ arrayclass_java_lang_Object =
+ load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
+
+# if defined(ENABLE_ANNOTATIONS)
+ /* needed by annotation support */
+ class_sun_reflect_ConstantPool =
+ load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ /* needed by GNU Classpaths annotation support */
+ class_sun_reflect_annotation_AnnotationParser =
+ load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
+# endif
+# endif
+#endif
+}
+
+
+/* loader_hashtable_classloader_add ********************************************
+
+ Adds an entry to the classloader hashtable.
+
+ REMEMBER: Also use this to register native loaders!
+
+*******************************************************************************/
+
+classloader_t *loader_hashtable_classloader_add(java_handle_t *cl)
+{
+ hashtable_classloader_entry *cle;
+ u4 key;
+ u4 slot;
+
+ if (cl == NULL)
+ return NULL;
+
+ LOCK_MONITOR_ENTER(hashtable_classloader->header);
+
+ LLNI_CRITICAL_START;
+
+ /* key for entry is the hashcode of the classloader;
+ aligned to 16-byte boundaries */
+
+ key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
+ slot = key & (hashtable_classloader->size - 1);
+ cle = hashtable_classloader->ptr[slot];
+
+ /* search hashchain for existing entry */
+
+ while (cle) {
+ if (cle->object == LLNI_DIRECT(cl))
+ break;
+
+ cle = cle->hashlink;
+ }
+
+ LLNI_CRITICAL_END;
+
+ /* if no classloader was found, we create a new entry here */
+
+ if (cle == NULL) {
+ cle = NEW(hashtable_classloader_entry);
+
+#if defined(ENABLE_GC_CACAO)
+ /* register the classloader object with the GC */
+
+ gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
+#endif
+
+ LLNI_CRITICAL_START;
+
+ cle->object = LLNI_DIRECT(cl);
+
+ LLNI_CRITICAL_END;
+
+/*#define LOADER_DEBUG_CLASSLOADER*/
+#ifdef LOADER_DEBUG_CLASSLOADER
+ printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
+ class_print(LLNI_vftbl_direct(cl)->class);
+ printf("\n");
+ fflush(stdout);
+#endif
+
+ /* insert entry into hashtable */
+
+ cle->hashlink = hashtable_classloader->ptr[slot];
+ hashtable_classloader->ptr[slot] = cle;
+
+ /* update number of entries */
+
+ hashtable_classloader->entries++;
+ }
+
+
+ LOCK_MONITOR_EXIT(hashtable_classloader->header);
+
+#if defined(ENABLE_HANDLES)
+ return cle;
+#else
+ return cl;
+#endif
+}
+
+
+/* loader_hashtable_classloader_find *******************************************
+
+ Find an entry in the classloader hashtable.
+
+*******************************************************************************/
+
+classloader_t *loader_hashtable_classloader_find(java_handle_t *cl)
+{
+ hashtable_classloader_entry *cle;
+ u4 key;
+ u4 slot;
+
+ if (cl == NULL)
+ return NULL;
+
+ LLNI_CRITICAL_START;
+
+ /* key for entry is the hashcode of the classloader;
+ aligned to 16-byte boundaries */
+
+ key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
+ slot = key & (hashtable_classloader->size - 1);
+ cle = hashtable_classloader->ptr[slot];
+
+ /* search hashchain for existing entry */
+
+ while (cle) {
+ if (cle->object == LLNI_DIRECT(cl))
+ break;
+
+ cle = cle->hashlink;
+ }
+
+#ifdef LOADER_DEBUG_CLASSLOADER
+ if (cle == NULL) {
+ printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
+ class_print(LLNI_vftbl_direct(cl)->class);
+ printf("\n");
+ fflush(stdout);
+ }
+#endif
+
+ LLNI_CRITICAL_END;
+
+#if defined(ENABLE_HANDLES)
+ return cle;
+#else
+ return cl;
+#endif
+}
+
+
+/* loader_load_all_classes *****************************************************
+
+ Loads all classes specified in the BOOTCLASSPATH.
+
+*******************************************************************************/
+
+void loader_load_all_classes(void)
+{
+ list_classpath_entry *lce;
+#if defined(ENABLE_ZLIB)
+ hashtable *ht;
+ s4 slot;
+ hashtable_zipfile_entry *htzfe;
+ utf *u;
+#endif
+
+ for (lce = list_first(list_classpath_entries); lce != NULL;
+ lce = list_next(list_classpath_entries, lce)) {
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+ /* get the classes hashtable */
+
+ ht = lce->htclasses;
+
+ for (slot = 0; slot < ht->size; slot++) {
+ htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
+
+ for (; htzfe; htzfe = htzfe->hashlink) {
+ u = htzfe->filename;
+
+ /* skip all entries in META-INF and .properties,
+ .png files */
+
+ if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
+ strstr(u->text, ".properties") ||
+ strstr(u->text, ".png"))
+ continue;
+
+ /* load class from bootstrap classloader */
+
+ if (!load_class_bootstrap(u)) {
+ fprintf(stderr, "Error loading: ");
+ utf_fprint_printable_ascii_classname(stderr, u);
+ fprintf(stderr, "\n");
+
+#if !defined(NDEBUG)
+ /* print out exception and cause */
+
+ exceptions_print_current_exception();
+#endif
+ }
+ }
+ }
+
+ } else {
+#endif
+#if defined(ENABLE_ZLIB)
+ }
+#endif
+ }
+}
+
+
+/* loader_skip_attribute_body **************************************************
+
+ Skips an attribute the attribute_name_index has already been read.
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+*******************************************************************************/
+
+bool loader_skip_attribute_body(classbuffer *cb)
+{
+ u4 attribute_length;
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ attribute_length = suck_u4(cb);
+
+ if (!suck_check_classbuffer_size(cb, attribute_length))
+ return false;
+
+ suck_skip_nbytes(cb, attribute_length);
+
+ return true;
+}
+
+
+/* load_constantpool ***********************************************************
+
+ Loads the constantpool of a class, the entries are transformed into
+ a simpler format by resolving references (a detailed overview of
+ the compact structures can be found in global.h).
+
+*******************************************************************************/
+
+static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
+{
+
+ /* The following structures are used to save information which cannot be
+ processed during the first pass. After the complete constantpool has
+ been traversed the references can be resolved.
+ (only in specific order) */
+
+ /* CONSTANT_Class entries */
+ typedef struct forward_class {
+ struct forward_class *next;
+ u2 thisindex;
+ u2 name_index;
+ } forward_class;
+
+ /* CONSTANT_String */
+ typedef struct forward_string {
+ struct forward_string *next;
+ u2 thisindex;
+ u2 string_index;
+ } forward_string;
+
+ /* CONSTANT_NameAndType */
+ typedef struct forward_nameandtype {
+ struct forward_nameandtype *next;
+ u2 thisindex;
+ u2 name_index;
+ u2 sig_index;
+ } forward_nameandtype;
+
+ /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
+ typedef struct forward_fieldmethint {
+ struct forward_fieldmethint *next;
+ u2 thisindex;
+ u1 tag;
+ u2 class_index;
+ u2 nameandtype_index;
+ } forward_fieldmethint;
+
+
+ classinfo *c;
+ u4 idx;
+
+ forward_class *forward_classes = NULL;
+ forward_string *forward_strings = NULL;
+ forward_nameandtype *forward_nameandtypes = NULL;
+ forward_fieldmethint *forward_fieldmethints = NULL;
+
+ forward_class *nfc;
+ forward_string *nfs;
+ forward_nameandtype *nfn;
+ forward_fieldmethint *nff;
+
+ u4 cpcount;
+ u1 *cptags;
+ void** cpinfos;
+
+ c = cb->clazz;
+
+ /* number of entries in the constant_pool table plus one */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ cpcount = c->cpcount = suck_u2(cb);
+
+ /* allocate memory */
+ cptags = c->cptags = MNEW(u1, cpcount);
+ cpinfos = c->cpinfos = MNEW(void*, cpcount);
+
+ if (cpcount < 1) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool size");
+ return false;
+ }
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += (sizeof(u1) + sizeof(void*)) * cpcount;
+#endif
+
+ /* initialize constantpool */
+ for (idx = 0; idx < cpcount; idx++) {
+ cptags[idx] = CONSTANT_UNUSED;
+ cpinfos[idx] = NULL;
+ }
+
+
+ /******* first pass *******/
+ /* entries which cannot be resolved now are written into
+ temporary structures and traversed again later */
+
+ idx = 1;
+ while (idx < cpcount) {
+ u4 t;
+
+ /* get constant type */
+ if (!suck_check_classbuffer_size(cb, 1))
+ return false;
+
+ t = suck_u1(cb);
+
+ switch (t) {
+ case CONSTANT_Class:
+ nfc = DNEW(forward_class);
+
+ nfc->next = forward_classes;
+ forward_classes = nfc;
+
+ nfc->thisindex = idx;
+ /* reference to CONSTANT_NameAndType */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ nfc->name_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_String:
+ nfs = DNEW(forward_string);
+
+ nfs->next = forward_strings;
+ forward_strings = nfs;
+
+ nfs->thisindex = idx;
+
+ /* reference to CONSTANT_Utf8_info with string characters */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ nfs->string_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_NameAndType:
+ nfn = DNEW(forward_nameandtype);
+
+ nfn->next = forward_nameandtypes;
+ forward_nameandtypes = nfn;
+
+ nfn->thisindex = idx;
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* reference to CONSTANT_Utf8_info containing simple name */
+ nfn->name_index = suck_u2(cb);
+
+ /* reference to CONSTANT_Utf8_info containing field or method
+ descriptor */
+ nfn->sig_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ nff = DNEW(forward_fieldmethint);
+
+ nff->next = forward_fieldmethints;
+ forward_fieldmethints = nff;
+
+ nff->thisindex = idx;
+ /* constant type */
+ nff->tag = t;
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* class or interface type that contains the declaration of the
+ field or method */
+ nff->class_index = suck_u2(cb);
+
+ /* name and descriptor of the field or method */
+ nff->nameandtype_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_Integer: {
+ constant_integer *ci = NEW(constant_integer);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_integer);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ ci->value = suck_s4(cb);
+ cptags[idx] = CONSTANT_Integer;
+ cpinfos[idx] = ci;
+
+ idx++;
+ break;
+ }
+
+ case CONSTANT_Float: {
+ constant_float *cf = NEW(constant_float);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_float);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ cf->value = suck_float(cb);
+ cptags[idx] = CONSTANT_Float;
+ cpinfos[idx] = cf;
+
+ idx++;
+ break;
+ }
+
+ case CONSTANT_Long: {
+ constant_long *cl = NEW(constant_long);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_long);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 8))
+ return false;
+
+ cl->value = suck_s8(cb);
+ cptags[idx] = CONSTANT_Long;
+ cpinfos[idx] = cl;
+ idx += 2;
+ if (idx > cpcount) {
+ exceptions_throw_classformaterror(c, "Invalid constant pool entry");
+ return false;
+ }
+ break;
+ }
+
+ case CONSTANT_Double: {
+ constant_double *cd = NEW(constant_double);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_double);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 8))
+ return false;
+
+ cd->value = suck_double(cb);
+ cptags[idx] = CONSTANT_Double;
+ cpinfos[idx] = cd;
+ idx += 2;
+ if (idx > cpcount) {
+ exceptions_throw_classformaterror(c, "Invalid constant pool entry");
+ return false;
+ }
+ break;
+ }
+
+ case CONSTANT_Utf8: {
+ u4 length;
+
+ /* number of bytes in the bytes array (not string-length) */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ length = suck_u2(cb);
+ cptags[idx] = CONSTANT_Utf8;
+
+ /* validate the string */
+ if (!suck_check_classbuffer_size(cb, length))
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify &&
+ !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
+ {
+ exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
+ return false;
+ }
+#endif /* ENABLE_VERIFIER */
+ /* insert utf-string into the utf-symboltable */
+ cpinfos[idx] = utf_new((char *) cb->pos, length);
+
+ /* skip bytes of the string (buffer size check above) */
+ suck_skip_nbytes(cb, length);
+ idx++;
+ break;
+ }
+
+ default:
+ exceptions_throw_classformaterror(c, "Illegal constant pool type");
+ return false;
+ } /* end switch */
+ } /* end while */
+
+
+ /* resolve entries in temporary structures */
+
+ while (forward_classes) {
+ utf *name =
+ class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
+ if (!name)
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify && !is_valid_name_utf(name)) {
+ exceptions_throw_classformaterror(c, "Class reference with invalid name");
+ return false;
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* add all class references to the descriptor_pool */
+
+ if (!descriptor_pool_add_class(descpool, name))
+ return false;
+
+ cptags[forward_classes->thisindex] = CONSTANT_Class;
+
+ /* the classref is created later */
+ cpinfos[forward_classes->thisindex] = name;
+
+ nfc = forward_classes;
+ forward_classes = forward_classes->next;
+ }
+
+ while (forward_strings) {
+ utf *text =
+ class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
+ if (!text)
+ return false;
+
+ /* resolve utf-string */
+ cptags[forward_strings->thisindex] = CONSTANT_String;
+ cpinfos[forward_strings->thisindex] = text;
+
+ nfs = forward_strings;
+ forward_strings = forward_strings->next;
+ }
+
+ while (forward_nameandtypes) {
+ constant_nameandtype *cn = NEW(constant_nameandtype);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_nameandtype);
+#endif
+
+ /* resolve simple name and descriptor */
+ cn->name = class_getconstant(c,
+ forward_nameandtypes->name_index,
+ CONSTANT_Utf8);
+ if (!cn->name)
+ return false;
+
+ cn->descriptor = class_getconstant(c,
+ forward_nameandtypes->sig_index,
+ CONSTANT_Utf8);
+ if (!cn->descriptor)
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ /* check name */
+ if (!is_valid_name_utf(cn->name)) {
+ exceptions_throw_classformaterror(c,
+ "Illegal Field name \"%s\"",
+ cn->name->text);
+
+ return false;
+ }
+
+ /* disallow referencing <clinit> among others */
+ if (cn->name->text[0] == '<' && cn->name != utf_init) {
+ exceptions_throw_classformaterror(c, "Illegal reference to special method");
+ return false;
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
+ cpinfos[forward_nameandtypes->thisindex] = cn;
+
+ nfn = forward_nameandtypes;
+ forward_nameandtypes = forward_nameandtypes->next;
+ }
+
+ while (forward_fieldmethints) {
+ constant_nameandtype *nat;
+ constant_FMIref *fmi = NEW(constant_FMIref);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_FMIref);
+#endif
+ /* resolve simple name and descriptor */
+
+ nat = class_getconstant(c,
+ forward_fieldmethints->nameandtype_index,
+ CONSTANT_NameAndType);
+ if (!nat)
+ return false;
+
+ /* add all descriptors in {Field,Method}ref to the descriptor_pool */
+
+ if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
+ return false;
+
+ /* the classref is created later */
+
+ fmi->p.index = forward_fieldmethints->class_index;
+ fmi->name = nat->name;
+ fmi->descriptor = nat->descriptor;
+
+ cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
+ cpinfos[forward_fieldmethints->thisindex] = fmi;
+
+ nff = forward_fieldmethints;
+ forward_fieldmethints = forward_fieldmethints->next;
+ }
+
+ /* everything was ok */
+
+ return true;
+}
+
+
+/* loader_load_attribute_signature *********************************************
+
+ Signature_attribute {
+ u2 attribute_name_index;
+ u4 atrribute_length;
+ u2 signature_index;
+ }
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
+{
+ classinfo *c;
+ u4 attribute_length;
+ u2 signature_index;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check remaining bytecode */
+
+ 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;
+ }
+
+ if (*signature != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple Signature attributes");
+ return false;
+ }
+
+ /* get signature */
+
+ signature_index = suck_u2(cb);
+
+ if (!(*signature = class_getconstant(c, signature_index, CONSTANT_Utf8)))
+ return false;
+
+ return true;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
+/* load_class_from_sysloader ***************************************************
+
+ Load the class with the given name using the system class loader
+
+ IN:
+ name.............the classname
+
+ RETURN VALUE:
+ the loaded class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo *load_class_from_sysloader(utf *name)
+{
+ methodinfo *m;
+ java_handle_t *clo;
+ classloader_t *cl;
+ classinfo *c;
+
+ assert(class_java_lang_Object);
+ assert(class_java_lang_ClassLoader);
+ assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
+
+ m = class_resolveclassmethod(class_java_lang_ClassLoader,
+ utf_getSystemClassLoader,
+ utf_void__java_lang_ClassLoader,
+ class_java_lang_Object,
+ false);
+
+ if (!m)
+ return false;
+
+ clo = vm_call_method(m, NULL);
+
+ if (!clo)
+ return false;
+
+ cl = loader_hashtable_classloader_add(clo);
+
+ c = load_class_from_classloader(name, cl);
+
+ return c;
+}
+
+
+/* load_class_from_classloader *************************************************
+
+ Load the class with the given name using the given user-defined class loader.
+
+ IN:
+ name.............the classname
+ cl...............user-defined class loader
+
+ RETURN VALUE:
+ the loaded class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
+{
+ java_handle_t *o;
+ classinfo *c;
+ classinfo *tmpc;
+ java_handle_t *string;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_lookup, time_prepare, time_java,
+ time_cache;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ assert(name);
+
+ /* lookup if this class has already been loaded */
+
+ c = classcache_lookup(cl, name);
+
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
+
+ if (c != NULL)
+ return c;
+
+ /* if other class loader than bootstrap, call it */
+
+ if (cl != NULL) {
+ methodinfo *lc;
+ char *text;
+ s4 namelen;
+
+ text = name->text;
+ namelen = name->blength;
+
+ /* handle array classes */
+ if (text[0] == '[') {
+ classinfo *comp;
+ utf *u;
+
+ switch (text[1]) {
+ case 'L':
+ /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+ if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
+ exceptions_throw_classnotfoundexception(name);
+ return false;
+ }
+
+ u = utf_new(text + 2, namelen - 3);
+
+ if (!(comp = load_class_from_classloader(u, cl)))
+ return false;
+
+ /* create the array class */
+
+ c = class_array_of(comp, false);
+
+ tmpc = classcache_store(cl, c, true);
+
+ if (tmpc == NULL) {
+ /* exception, free the loaded class */
+ c->state &= ~CLASS_LOADING;
+ class_free(c);
+ }
+
+ return tmpc;
+
+ case '[':
+ /* load the component class */
+
+ u = utf_new(text + 1, namelen - 1);
+
+ if (!(comp = load_class_from_classloader(u, cl)))
+ return false;
+
+ /* create the array class */
+
+ c = class_array_of(comp, false);
+
+ tmpc = classcache_store(cl, c, true);
+
+ if (tmpc == NULL) {
+ /* exception, free the loaded class */
+ c->state &= ~CLASS_LOADING;
+ class_free(c);
+ }
+
+ return tmpc;
+
+ default:
+ /* primitive array classes are loaded by the bootstrap loader */
+
+ c = load_class_bootstrap(name);
+
+ return c;
+ }
+ }
+
+ LLNI_class_get(cl, c);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* OpenJDK uses this internal function because it's
+ synchronized. */
+
+ lc = class_resolveclassmethod(c,
+ utf_loadClassInternal,
+ utf_java_lang_String__java_lang_Class,
+ NULL,
+ true);
+#else
+ lc = class_resolveclassmethod(c,
+ utf_loadClass,
+ utf_java_lang_String__java_lang_Class,
+ NULL,
+ true);
+#endif
+
+ if (lc == NULL)
+ return false; /* exception */
+
+ /* move return value into `o' and cast it afterwards to a classinfo* */
+
+ string = javastring_new_slash_to_dot(name);
+
+ RT_TIMING_GET_TIME(time_prepare);
+
+ o = vm_call_method(lc, (java_handle_t *) cl, string);
+
+ RT_TIMING_GET_TIME(time_java);
+
+ c = LLNI_classinfo_unwrap(o);
+
+ if (c != NULL) {
+ /* Store this class in the loaded class cache. If another
+ class with the same (initloader,name) pair has been
+ stored earlier it will be returned by classcache_store
+ In this case classcache_store may not free the class
+ because it has already been exposed to Java code which
+ may have kept references to that class. */
+
+ tmpc = classcache_store(cl, c, false);
+
+ if (tmpc == NULL) {
+ /* exception, free the loaded class */
+ c->state &= ~CLASS_LOADING;
+ class_free(c);
+ }
+
+ c = tmpc;
+ }
+
+ RT_TIMING_GET_TIME(time_cache);
+
+ RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
+ RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
+ RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
+
+ /* SUN compatible -verbose:class output */
+
+ if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
+ printf("[Loaded ");
+ utf_display_printable_ascii_classname(name);
+ printf("]\n");
+ }
+
+#if defined(ENABLE_JVMTI)
+ /* fire Class Load JVMTI event */
+ if (jvmti) jvmti_ClassLoadPrepare(false, c);
+#endif
+
+
+ return c;
+ }
+
+ c = load_class_bootstrap(name);
+
+ return c;
+}
+
+
+/* load_class_bootstrap ********************************************************
+
+ Load the class with the given name using the bootstrap class loader.
+
+ IN:
+ name.............the classname
+
+ RETURN VALUE:
+ loaded classinfo, or
+ NULL if an exception has been thrown
+
+ SYNCHRONIZATION:
+ load_class_bootstrap is synchronized. It can be treated as an
+ atomic operation.
+
+*******************************************************************************/
+
+classinfo *load_class_bootstrap(utf *name)
+{
+ classbuffer *cb;
+ classinfo *c;
+ classinfo *r;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_lookup, time_array, time_suck,
+ time_load, time_cache;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ /* for debugging */
+
+ assert(name);
+
+ /* lookup if this class has already been loaded */
+
+ r = classcache_lookup(NULL, name);
+
+ if (r != NULL) {
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
+
+ return r;
+ }
+
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
+
+ /* create the classinfo */
+
+ c = class_create_classinfo(name);
+
+ /* handle array classes */
+
+ if (name->text[0] == '[') {
+ c = load_newly_created_array(c, NULL);
+
+ if (c == NULL)
+ return NULL;
+
+ assert(c->state & CLASS_LOADED);
+
+ RT_TIMING_GET_TIME(time_array);
+ RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
+
+ return c;
+ }
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ compilingtime_stop();
+
+ if (opt_getloadingtime)
+ loadingtime_start();
+#endif
+
+ /* load classdata, throw exception on error */
+
+ cb = suck_start(c);
+
+ if (cb == NULL) {
+ exceptions_throw_classnotfoundexception(name);
+ return NULL;
+ }
+
+ RT_TIMING_GET_TIME(time_suck);
+
+ /* load the class from the buffer */
+
+ r = load_class_from_classbuffer(cb);
+
+ RT_TIMING_GET_TIME(time_load);
+
+ if (r == NULL) {
+ /* the class could not be loaded, free the classinfo struct */
+
+ class_free(c);
+ }
+ else {
+ /* Store this class in the loaded class cache this step also
+ checks the loading constraints. If the class has been
+ loaded before, the earlier loaded class is returned. */
+
+ classinfo *res = classcache_store(NULL, c, true);
+
+ if (res == NULL) {
+ /* exception */
+ class_free(c);
+ }
+ else {
+ /* Add the package name to the boot packages. */
+
+ Package_add(c->packagename);
+ }
+
+ r = res;
+ }
+
+ RT_TIMING_GET_TIME(time_cache);
+
+ /* SUN compatible -verbose:class output */
+
+ if (opt_verboseclass && r) {
+ printf("[Loaded ");
+ utf_display_printable_ascii_classname(name);
+ printf(" from %s]\n", cb->path);
+ }
+
+ /* free memory */
+
+ suck_stop(cb);
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_stop();
+
+ if (opt_getcompilingtime)
+ compilingtime_start();
+#endif
+
+ RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
+ RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
+ RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
+ RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
+
+ return r;
+}
+
+
+/* load_class_from_classbuffer_intern ******************************************
+
+ Loads a class from a classbuffer into a given classinfo structure.
+ Super-classes are also loaded at this point and some verfication
+ checks are done.
+
+ SYNCHRONIZATION:
+ This function is NOT synchronized!
+
+*******************************************************************************/
+
+static bool load_class_from_classbuffer_intern(classbuffer *cb)
+{
+ classinfo *c;
+ classinfo *tc;
+ utf *name;
+ utf *supername;
+ utf **interfacesnames;
+ utf *u;
+ constant_classref *cr;
+ int16_t index;
+
+ u4 i,j;
+ u4 ma, mi;
+ descriptor_pool *descpool;
+#if defined(ENABLE_STATISTICS)
+ u4 classrefsize;
+ u4 descsize;
+#endif
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_checks, time_ndpool, time_cpool,
+ time_setup, time_fields, time_methods, time_classrefs,
+ time_descs, time_setrefs, time_parsefds, time_parsemds,
+ time_parsecpool, time_verify, time_attrs;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ /* Get the classbuffer's class. */
+
+ c = cb->clazz;
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
+ /* check signature */
+
+ if (suck_u4(cb) != MAGIC) {
+ exceptions_throw_classformaterror(c, "Bad magic number");
+ return false;
+ }
+
+ /* check version */
+
+ mi = suck_u2(cb);
+ ma = suck_u2(cb);
+
+ if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
+ exceptions_throw_unsupportedclassversionerror(c, ma, mi);
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_checks);
+
+ /* create a new descriptor pool */
+
+ descpool = descriptor_pool_new(c);
+
+ RT_TIMING_GET_TIME(time_ndpool);
+
+ /* load the constant pool */
+
+ if (!load_constantpool(cb, descpool))
+ return false;
+
+ RT_TIMING_GET_TIME(time_cpool);
+
+ /* ACC flags */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* We OR the flags here, as we set already some flags in
+ class_create_classinfo. */
+
+ c->flags |= suck_u2(cb);
+
+ /* check ACC flags consistency */
+
+ if (c->flags & ACC_INTERFACE) {
+ if (!(c->flags & ACC_ABSTRACT)) {
+ /* We work around this because interfaces in JDK 1.1 are
+ * not declared abstract. */
+
+ c->flags |= ACC_ABSTRACT;
+ }
+
+ if (c->flags & ACC_FINAL) {
+ exceptions_throw_classformaterror(c,
+ "Illegal class modifiers: 0x%X",
+ c->flags);
+ return false;
+ }
+
+ if (c->flags & ACC_SUPER) {
+ c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
+ }
+ }
+
+ if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
+ exceptions_throw_classformaterror(c,
+ "Illegal class modifiers: 0x%X",
+ c->flags);
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* This class. */
+
+ index = suck_u2(cb);
+
+ name = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (name == NULL)
+ return false;
+
+ if (c->name == utf_not_named_yet) {
+ /* we finally have a name for this class */
+ c->name = name;
+ class_set_packagename(c);
+ }
+ else if (name != c->name) {
+ exceptions_throw_noclassdeffounderror_wrong_name(c, name);
+ return false;
+ }
+
+ /* Retrieve superclass. */
+
+ c->super = NULL;
+
+ index = suck_u2(cb);
+
+ if (index == 0) {
+ supername = NULL;
+
+ /* This is only allowed for java.lang.Object. */
+
+ if (c->name != utf_java_lang_Object) {
+ exceptions_throw_classformaterror(c, "Bad superclass index");
+ return false;
+ }
+ }
+ else {
+ supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (supername == NULL)
+ return false;
+
+ /* java.lang.Object may not have a super class. */
+
+ if (c->name == utf_java_lang_Object) {
+ exceptions_throw_classformaterror(NULL, "java.lang.Object with superclass");
+ return false;
+ }
+
+ /* Detect circularity. */
+
+ if (supername == c->name) {
+ exceptions_throw_classcircularityerror(c);
+ return false;
+ }
+
+ /* Interfaces must have java.lang.Object as super class. */
+
+ if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
+ exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
+ return false;
+ }
+ }
+
+ /* Parse the super interfaces. */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ c->interfacescount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
+ return false;
+
+ c->interfaces = MNEW(classinfo*, c->interfacescount);
+
+ /* Get the names of the super interfaces. */
+
+ interfacesnames = DMNEW(utf*, c->interfacescount);
+
+ for (i = 0; i < c->interfacescount; i++) {
+ index = suck_u2(cb);
+
+ u = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (u == NULL)
+ return false;
+
+ interfacesnames[i] = u;
+ }
+
+ RT_TIMING_GET_TIME(time_setup);
+
+ /* Parse fields. */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ c->fieldscount = suck_u2(cb);
+ c->fields = MNEW(fieldinfo, c->fieldscount);
+
+ MZERO(c->fields, fieldinfo, c->fieldscount);
+
+ for (i = 0; i < c->fieldscount; i++) {
+ if (!field_load(cb, &(c->fields[i]), descpool))
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_fields);
+
+ /* Parse methods. */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ c->methodscount = suck_u2(cb);
+ c->methods = MNEW(methodinfo, c->methodscount);
+
+ MZERO(c->methods, methodinfo, c->methodscount);
+
+ for (i = 0; i < c->methodscount; i++) {
+ if (!method_load(cb, &(c->methods[i]), descpool))
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_methods);
+
+ /* create the class reference table */
+
+ c->classrefs =
+ descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
+
+ RT_TIMING_GET_TIME(time_classrefs);
+
+ /* allocate space for the parsed descriptors */
+
+ descriptor_pool_alloc_parsed_descriptors(descpool);
+ c->parseddescs =
+ descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
+ count_classref_len += classrefsize;
+ count_parsed_desc_len += descsize;
+ }
+#endif
+
+ RT_TIMING_GET_TIME(time_descs);
+
+ /* put the classrefs in the constant pool */
+
+ for (i = 0; i < c->cpcount; i++) {
+ if (c->cptags[i] == CONSTANT_Class) {
+ utf *name = (utf *) c->cpinfos[i];
+ c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
+ }
+ }
+
+ /* Resolve the super class. */
+
+ if (supername != NULL) {
+ cr = descriptor_pool_lookup_classref(descpool, supername);
+
+ if (cr == NULL)
+ return false;
+
+ /* XXX This should be done better. */
+ tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+ if (tc == NULL) {
+ resolve_handle_pending_exception(true);
+ return false;
+ }
+
+ /* Interfaces are not allowed as super classes. */
+
+ if (tc->flags & ACC_INTERFACE) {
+ exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
+ return false;
+ }
+
+ /* Don't allow extending final classes */
+
+ if (tc->flags & ACC_FINAL) {
+ exceptions_throw_verifyerror(NULL,
+ "Cannot inherit from final class");
+ return false;
+ }
+
+ /* Store the super class. */
+
+ c->super = tc;
+ }
+
+ /* Resolve the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ u = interfacesnames[i];
+ cr = descriptor_pool_lookup_classref(descpool, u);
+
+ if (cr == NULL)
+ return false;
+
+ /* XXX This should be done better. */
+ tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+ if (tc == NULL) {
+ resolve_handle_pending_exception(true);
+ return false;
+ }
+
+ /* Detect circularity. */
+
+ if (tc == c) {
+ exceptions_throw_classcircularityerror(c);
+ return false;
+ }
+
+ if (!(tc->flags & ACC_INTERFACE)) {
+ exceptions_throw_incompatibleclasschangeerror(tc,
+ "Implementing class");
+ return false;
+ }
+
+ /* Store the super interface. */
+
+ c->interfaces[i] = tc;
+ }
+
+ RT_TIMING_GET_TIME(time_setrefs);
+
+ /* Parse the field descriptors. */
+
+ for (i = 0; i < c->fieldscount; i++) {
+ c->fields[i].parseddesc =
+ descriptor_pool_parse_field_descriptor(descpool,
+ c->fields[i].descriptor);
+ if (!c->fields[i].parseddesc)
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_parsefds);
+
+ /* parse method descriptors */
+
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &c->methods[i];
+ m->parseddesc =
+ descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
+ m->flags, class_get_self_classref(m->clazz));
+ if (!m->parseddesc)
+ return false;
+
+ for (j = 0; j < m->rawexceptiontablelength; j++) {
+ if (!m->rawexceptiontable[j].catchtype.any)
+ continue;
+
+ if ((m->rawexceptiontable[j].catchtype.ref =
+ descriptor_pool_lookup_classref(descpool,
+ (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL)
+ return false;
+ }
+
+ for (j = 0; j < m->thrownexceptionscount; j++) {
+ if (!m->thrownexceptions[j].any)
+ continue;
+
+ if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
+ (utf *) m->thrownexceptions[j].any)) == NULL)
+ return false;
+ }
+ }
+
+ RT_TIMING_GET_TIME(time_parsemds);
+
+ /* parse the loaded descriptors */
+
+ for (i = 0; i < c->cpcount; i++) {
+ constant_FMIref *fmi;
+ s4 index;
+
+ switch (c->cptags[i]) {
+ case CONSTANT_Fieldref:
+ fmi = (constant_FMIref *) c->cpinfos[i];
+ fmi->parseddesc.fd =
+ descriptor_pool_parse_field_descriptor(descpool,
+ fmi->descriptor);
+ if (!fmi->parseddesc.fd)
+ return false;
+
+ index = fmi->p.index;
+ fmi->p.classref =
+ (constant_classref *) class_getconstant(c, index,
+ CONSTANT_Class);
+ if (!fmi->p.classref)
+ return false;
+ break;
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ fmi = (constant_FMIref *) c->cpinfos[i];
+ index = fmi->p.index;
+ fmi->p.classref =
+ (constant_classref *) class_getconstant(c, index,
+ CONSTANT_Class);
+ if (!fmi->p.classref)
+ return false;
+ fmi->parseddesc.md =
+ descriptor_pool_parse_method_descriptor(descpool,
+ fmi->descriptor,
+ ACC_UNDEF,
+ fmi->p.classref);
+ if (!fmi->parseddesc.md)
+ return false;
+ break;
+ }
+ }
+
+ RT_TIMING_GET_TIME(time_parsecpool);
+
+#ifdef ENABLE_VERIFIER
+ /* Check if all fields and methods can be uniquely
+ * identified by (name,descriptor). */
+
+ if (opt_verify) {
+ /* We use a hash table here to avoid making the
+ * average case quadratic in # of methods, fields.
+ */
+ static int shift = 0;
+ u2 *hashtab;
+ u2 *next; /* for chaining colliding hash entries */
+ size_t len;
+ size_t hashlen;
+ u2 index;
+ u2 old;
+
+ /* Allocate hashtable */
+ len = c->methodscount;
+ if (len < c->fieldscount) len = c->fieldscount;
+ hashlen = 5 * len;
+ hashtab = MNEW(u2,(hashlen + len));
+ next = hashtab + hashlen;
+
+ /* Determine bitshift (to get good hash values) */
+ if (!shift) {
+ len = sizeof(utf);
+ while (len) {
+ len >>= 1;
+ shift++;
+ }
+ }
+
+ /* Check fields */
+ memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+
+ for (i = 0; i < c->fieldscount; ++i) {
+ fieldinfo *fi = c->fields + i;
+
+ /* It's ok if we lose bits here */
+ index = ((((size_t) fi->name) +
+ ((size_t) fi->descriptor)) >> shift) % hashlen;
+
+ if ((old = hashtab[index])) {
+ old--;
+ next[i] = old;
+ do {
+ if (c->fields[old].name == fi->name &&
+ c->fields[old].descriptor == fi->descriptor) {
+ exceptions_throw_classformaterror(c, "Repetitive field name/signature");
+ return false;
+ }
+ } while ((old = next[old]));
+ }
+ hashtab[index] = i + 1;
+ }
+
+ /* Check methods */
+ memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
+
+ for (i = 0; i < c->methodscount; ++i) {
+ methodinfo *mi = c->methods + i;
+
+ /* It's ok if we lose bits here */
+ index = ((((size_t) mi->name) +
+ ((size_t) mi->descriptor)) >> shift) % hashlen;
+
+ if ((old = hashtab[index])) {
+ old--;
+ next[i] = old;
+ do {
+ if (c->methods[old].name == mi->name &&
+ c->methods[old].descriptor == mi->descriptor) {
+ exceptions_throw_classformaterror(c, "Repetitive method name/signature");
+ return false;
+ }
+ } while ((old = next[old]));
+ }
+ hashtab[index] = i + 1;
+ }
+
+ MFREE(hashtab, u2, (hashlen + len));
+ }
+#endif /* ENABLE_VERIFIER */
+
+ RT_TIMING_GET_TIME(time_verify);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ size_classinfo += sizeof(classinfo*) * c->interfacescount;
+ size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
+ size_methodinfo += sizeof(methodinfo) * c->methodscount;
+ }
+#endif
+
+ /* load attribute structures */
+
+ if (!class_load_attributes(cb))
+ return false;
+
+ /* Pre Java 1.5 version don't check this. This implementation is
+ like Java 1.5 do it: for class file version 45.3 we don't check
+ it, older versions are checked. */
+
+ if (((ma == 45) && (mi > 3)) || (ma > 45)) {
+ /* check if all data has been read */
+ s4 classdata_left = ((cb->data + cb->size) - cb->pos);
+
+ if (classdata_left > 0) {
+ exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
+ return false;
+ }
+ }
+
+ RT_TIMING_GET_TIME(time_attrs);
+
+ RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
+ RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
+ RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
+ RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
+ RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
+ RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
+ RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
+ RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
+ RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
+ RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
+ RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
+ RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
+ RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
+ RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
+ RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
+
+ return true;
+}
+
+
+/* load_class_from_classbuffer *************************************************
+
+ Convenience wrapper for load_class_from_classbuffer.
+
+ SYNCHRONIZATION:
+ This function is NOT synchronized!
+
+*******************************************************************************/
+
+classinfo *load_class_from_classbuffer(classbuffer *cb)
+{
+ classinfo *c;
+ bool result;
+ int32_t dumpmarker;
+
+ /* Get the classbuffer's class. */
+
+ c = cb->clazz;
+
+ /* Check if the class is already loaded. */
+
+ if (c->state & CLASS_LOADED)
+ return c;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_class_loads++;
+#endif
+
+#if !defined(NDEBUG)
+ if (loadverbose)
+ log_message_class("Loading class: ", c);
+#endif
+
+ /* Mark start of dump memory area. */
+
+ DMARKER;
+
+ /* Class is currently loading. */
+
+ c->state |= CLASS_LOADING;
+
+ /* Parse the classbuffer. */
+
+ result = load_class_from_classbuffer_intern(cb);
+
+ /* Release dump area. */
+
+ DRELEASE;
+
+ /* An error occurred. */
+
+ if (result == false) {
+ /* Revert loading state. */
+
+ c->state = (c->state & ~CLASS_LOADING);
+
+ return NULL;
+ }
+
+ /* Revert loading state and set loaded. */
+
+ c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
+
+#if defined(ENABLE_JVMTI)
+ /* fire Class Prepare JVMTI event */
+
+ if (jvmti)
+ jvmti_ClassLoadPrepare(true, c);
+#endif
+
+#if !defined(NDEBUG)
+ if (loadverbose)
+ log_message_class("Loading done class: ", c);
+#endif
+
+ return c;
+}
+
+
+/* load_newly_created_array ****************************************************
+
+ Load a newly created array class.
+
+ RETURN VALUE:
+ c....................the array class C has been loaded
+ other classinfo......the array class was found in the class cache,
+ C has been freed
+ NULL.................an exception has been thrown
+
+ Note:
+ This is an internal function. Do not use it unless you know exactly
+ what you are doing!
+
+ Use one of the load_class_... functions for general array class loading.
+
+*******************************************************************************/
+
+classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
+{
+ classinfo *comp = NULL;
+ methodinfo *clone;
+ methoddesc *clonedesc;
+ constant_classref *classrefs;
+ char *text;
+ s4 namelen;
+ utf *u;
+
+ text = c->name->text;
+ namelen = c->name->blength;
+
+ /* Check array class name */
+
+ if ((namelen < 2) || (text[0] != '[')) {
+ exceptions_throw_classnotfoundexception(c->name);
+ return NULL;
+ }
+
+ /* Check the element type */
+
+ switch (text[1]) {
+ case '[':
+ /* c is an array of arrays. We have to create the component class. */
+
+ u = utf_new(text + 1, namelen - 1);
+
+ comp = load_class_from_classloader(u, loader);
+
+ if (comp == NULL)
+ return NULL;
+
+ assert(comp->state & CLASS_LOADED);
+
+ /* the array's flags are that of the component class */
+ c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+ c->classloader = comp->classloader;
+ break;
+
+ case 'L':
+ /* c is an array of objects. */
+
+ /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+ if ((namelen < 4) || (text[2] == '[') || (text[namelen - 1] != ';')) {
+ exceptions_throw_classnotfoundexception(c->name);
+ return NULL;
+ }
+
+ u = utf_new(text + 2, namelen - 3);
+
+ if (!(comp = load_class_from_classloader(u, loader)))
+ return NULL;
+
+ assert(comp->state & CLASS_LOADED);
+
+ /* the array's flags are that of the component class */
+ c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+ c->classloader = comp->classloader;
+ break;
+
+ default:
+ /* c is an array of a primitive type */
+
+ /* check for cases like `[II' and whether the character is a
+ valid primitive type */
+
+ if ((namelen > 2) || (Primitive_get_class_by_char(text[1]) == NULL)) {
+ exceptions_throw_classnotfoundexception(c->name);
+ return NULL;
+ }
+
+ /* the accessibility of the array class is public (VM Spec 5.3.3) */
+ c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+ c->classloader = NULL;
+ }
+
+ assert(class_java_lang_Object);
+#if defined(ENABLE_JAVASE)
+ assert(class_java_lang_Cloneable);
+ assert(class_java_io_Serializable);
+#endif
+
+ /* Setup the array class. */
+
+ c->super = class_java_lang_Object;
+
+#if defined(ENABLE_JAVASE)
+
+ c->interfacescount = 2;
+ c->interfaces = MNEW(classinfo*, 2);
+ c->interfaces[0] = class_java_lang_Cloneable;
+ c->interfaces[1] = class_java_io_Serializable;
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ c->interfacescount = 0;
+ c->interfaces = NULL;
+
+#else
+# error unknow Java configuration
+#endif
+
+ c->methodscount = 1;
+ c->methods = MNEW(methodinfo, c->methodscount);
+
+ MZERO(c->methods, methodinfo, c->methodscount);
+
+ classrefs = MNEW(constant_classref, 2);
+
+ CLASSREF_INIT(classrefs[0], c, c->name);
+ CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
+
+ /* create descriptor for clone method */
+ /* we need one paramslot which is reserved for the 'this' parameter */
+ clonedesc = NEW(methoddesc);
+ clonedesc->returntype.type = TYPE_ADR;
+ clonedesc->returntype.classref = classrefs + 1;
+ clonedesc->returntype.arraydim = 0;
+ /* initialize params to "empty", add real params below in
+ descriptor_params_from_paramtypes */
+ clonedesc->paramcount = 0;
+ clonedesc->paramslots = 0;
+ clonedesc->paramtypes[0].classref = classrefs + 0;
+ clonedesc->params = NULL;
+
+ /* create methodinfo */
+
+ clone = c->methods;
+ MSET(clone, 0, methodinfo, 1);
+
+#if defined(ENABLE_THREADS)
+ lock_init_object_lock(&clone->header);
+#endif
+
+ /* ATTENTION: if you delete the ACC_NATIVE below, set
+ clone->maxlocals=1 (interpreter related) */
+
+ clone->flags = ACC_PUBLIC | ACC_NATIVE;
+ clone->name = utf_clone;
+ clone->descriptor = utf_void__java_lang_Object;
+ clone->parseddesc = clonedesc;
+ clone->clazz = c;
+
+ /* parse the descriptor to get the register allocation */
+
+ if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
+ return false;
+
+ clone->code = codegen_generate_stub_native(clone, BUILTIN_clone);
+
+ /* XXX: field: length? */
+
+ /* array classes are not loaded from class files */
+
+ c->state |= CLASS_LOADED;
+ c->parseddescs = (u1 *) clonedesc;
+ c->parseddescsize = sizeof(methodinfo);
+ c->classrefs = classrefs;
+ c->classrefcount = 1;
+
+ /* insert class into the loaded class cache */
+ /* XXX free classinfo if NULL returned? */
+
+ return classcache_store(loader, c, true);
+}
+
+
+/* loader_close ****************************************************************
+
+ Frees all resources.
+
+*******************************************************************************/
+
+void loader_close(void)
+{
+ /* empty */
+}
+
+
+/*
+ * 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/loader.h - class loader 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 _LOADER_H
+#define _LOADER_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct classbuffer classbuffer;
+
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "vm/descriptor.h"
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/utf8.h"
+
+
+/* constant pool entries *******************************************************
+
+ All constant pool entries need a data structure which contain the entrys
+ value. In some cases this structure exist already, in the remaining cases
+ this structure must be generated:
+
+ kind structure generated?
+ ----------------------------------------------------------------------
+ CONSTANT_Class constant_classref yes
+ CONSTANT_Fieldref constant_FMIref yes
+ CONSTANT_Methodref constant_FMIref yes
+ CONSTANT_InterfaceMethodref constant_FMIref yes
+ CONSTANT_String unicode no
+ CONSTANT_Integer constant_integer yes
+ CONSTANT_Float constant_float yes
+ CONSTANT_Long constant_long yes
+ CONSTANT_Double constant_double yes
+ CONSTANT_NameAndType constant_nameandtype yes
+ CONSTANT_Utf8 unicode no
+ CONSTANT_UNUSED -
+
+*******************************************************************************/
+
+typedef struct { /* Integer */
+ s4 value;
+} constant_integer;
+
+
+typedef struct { /* Float */
+ float value;
+} constant_float;
+
+
+typedef struct { /* Long */
+ s8 value;
+} constant_long;
+
+
+typedef struct { /* Double */
+ double value;
+} constant_double;
+
+
+typedef struct { /* NameAndType (Field or Method) */
+ utf *name; /* field/method name */
+ utf *descriptor; /* field/method type descriptor string */
+} constant_nameandtype;
+
+
+/* classbuffer ****************************************************************/
+
+struct classbuffer {
+ classinfo *clazz; /* pointer to classinfo structure */
+ uint8_t *data; /* pointer to byte code */
+ int32_t size; /* size of the byte code */
+ uint8_t *pos; /* current read position */
+ char *path; /* path to file (for debugging) */
+};
+
+
+/* hashtable_classloader_entry *************************************************
+
+ ATTENTION: The pointer to the classloader object needs to be the
+ first field of the entry, so that it can be used as an indirection
+ cell. This is checked by gc_init() during startup.
+
+*******************************************************************************/
+
+typedef struct hashtable_classloader_entry hashtable_classloader_entry;
+
+struct hashtable_classloader_entry {
+ java_object_t *object;
+ hashtable_classloader_entry *hashlink;
+};
+
+
+/* classloader *****************************************************************
+
+ [!ENABLE_HANDLES]: The classloader is a Java Object which cannot move.
+ [ENABLE_HANDLES] : The classloader entry itself is a static handle for a
+ given classloader (use loader_hashtable_classloader_foo).
+
+*******************************************************************************/
+
+#if defined(ENABLE_HANDLES)
+typedef hashtable_classloader_entry classloader_t;
+#else
+typedef java_object_t classloader_t;
+#endif
+
+
+/* function prototypes ********************************************************/
+
+void loader_preinit(void);
+void loader_init(void);
+
+/* classloader management functions */
+classloader_t *loader_hashtable_classloader_add(java_handle_t *cl);
+classloader_t *loader_hashtable_classloader_find(java_handle_t *cl);
+
+void loader_load_all_classes(void);
+
+bool loader_skip_attribute_body(classbuffer *cb);
+
+#if defined(ENABLE_JAVASE)
+bool loader_load_attribute_signature(classbuffer *cb, utf **signature);
+#endif
+
+/* free resources */
+void loader_close(void);
+
+/* class loading functions */
+classinfo *load_class_from_sysloader(utf *name);
+classinfo *load_class_from_classloader(utf *name, classloader_t *cl);
+classinfo *load_class_bootstrap(utf *name);
+
+/* (don't use the following directly) */
+classinfo *load_class_from_classbuffer(classbuffer *cb);
+classinfo *load_newly_created_array(classinfo *c, classloader_t *loader);
+
+#endif /* _LOADER_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:
+ */
--- /dev/null
+/* src/vm/method.c - method 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 <stdint.h>
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/lock-common.h"
+
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/code.h"
+#include "vm/jit/methodheader.h"
+
+
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
+#else
+#define INLINELOG(code)
+#endif
+
+
+/* global variables ***********************************************************/
+
+methodinfo *method_java_lang_reflect_Method_invoke;
+
+
+/* method_init *****************************************************************
+
+ Initialize method subsystem.
+
+*******************************************************************************/
+
+void method_init(void)
+{
+#if defined(ENABLE_JAVASE)
+ /* Sanity check. */
+
+ if (class_java_lang_reflect_Method == NULL)
+ vm_abort("method_init: class_java_lang_reflect_Method is NULL");
+
+ /* Cache java.lang.reflect.Method.invoke() */
+
+ method_java_lang_reflect_Method_invoke =
+ class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
+
+ if (method_java_lang_reflect_Method_invoke == NULL)
+ vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
+#endif
+}
+
+
+/* method_load *****************************************************************
+
+ Loads a method from the class file and fills an existing methodinfo
+ structure.
+
+ method_info {
+ u2 access_flags;
+ u2 name_index;
+ u2 descriptor_index;
+ u2 attributes_count;
+ attribute_info attributes[attribute_count];
+ }
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+ LineNumberTable_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 line_number_table_length;
+ {
+ u2 start_pc;
+ u2 line_number;
+ } line_number_table[line_number_table_length];
+ }
+
+*******************************************************************************/
+
+bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
+{
+ classinfo *c;
+ int argcount;
+ s4 i, j, k, l;
+ utf *u;
+ u2 name_index;
+ u2 descriptor_index;
+ u2 attributes_count;
+ u2 attribute_name_index;
+ utf *attribute_name;
+ u2 code_attributes_count;
+ u2 code_attribute_name_index;
+ utf *code_attribute_name;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ LOCK_INIT_OBJECT_LOCK(&(m->header));
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_all_methods++;
+#endif
+
+ /* all fields of m have been zeroed in load_class_from_classbuffer */
+
+ m->clazz = c;
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
+ return false;
+
+ /* access flags */
+
+ m->flags = suck_u2(cb);
+
+ /* name */
+
+ name_index = suck_u2(cb);
+
+ if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8)))
+ return false;
+
+ m->name = u;
+
+ /* descriptor */
+
+ descriptor_index = suck_u2(cb);
+
+ if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
+ return false;
+
+ m->descriptor = u;
+
+ if (!descriptor_pool_add(descpool, u, &argcount))
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ if (!is_valid_name_utf(m->name)) {
+ exceptions_throw_classformaterror(c, "Method with invalid name");
+ return false;
+ }
+
+ if (m->name->text[0] == '<' &&
+ m->name != utf_init && m->name != utf_clinit) {
+ exceptions_throw_classformaterror(c, "Method with invalid special name");
+ return false;
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ if (!(m->flags & ACC_STATIC))
+ argcount++; /* count the 'this' argument */
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ if (argcount > 255) {
+ exceptions_throw_classformaterror(c, "Too many arguments in signature");
+ return false;
+ }
+
+ /* check flag consistency */
+ if (m->name != utf_clinit) {
+ i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
+
+ if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
+ exceptions_throw_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
+
+ if (m->flags & ACC_ABSTRACT) {
+ if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
+ ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
+ exceptions_throw_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
+ }
+
+ if (c->flags & ACC_INTERFACE) {
+ if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
+ exceptions_throw_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
+ }
+
+ if (m->name == utf_init) {
+ if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
+ ACC_NATIVE | ACC_ABSTRACT)) {
+ exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
+ return false;
+ }
+ }
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* mark the method as monomorphic until further notice */
+
+ m->flags |= ACC_METHOD_MONOMORPHIC;
+
+ /* non-abstract methods have an implementation in this class */
+
+ if (!(m->flags & ACC_ABSTRACT))
+ m->flags |= ACC_METHOD_IMPLEMENTED;
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* attributes count */
+
+ attributes_count = suck_u2(cb);
+
+ for (i = 0; i < attributes_count; i++) {
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* attribute name index */
+
+ 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_Code) {
+ /* Code */
+
+ if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
+ exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
+ return false;
+ }
+
+ if (m->jcode) {
+ exceptions_throw_classformaterror(c, "Multiple Code attributes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
+ suck_u4(cb);
+ m->maxstack = suck_u2(cb);
+ m->maxlocals = suck_u2(cb);
+
+ if (m->maxlocals < argcount) {
+ exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ m->jcodelength = suck_u4(cb);
+
+ if (m->jcodelength == 0) {
+ exceptions_throw_classformaterror(c, "Code of a method has length 0");
+ return false;
+ }
+
+ if (m->jcodelength > 65535) {
+ exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, m->jcodelength))
+ return false;
+
+ m->jcode = MNEW(u1, m->jcodelength);
+ suck_nbytes(m->jcode, cb, m->jcodelength);
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ m->rawexceptiontablelength = suck_u2(cb);
+ if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
+ return false;
+
+ m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ count_vmcode_len += m->jcodelength + 18;
+ count_extable_len +=
+ m->rawexceptiontablelength * sizeof(raw_exception_entry);
+ }
+#endif
+
+ for (j = 0; j < m->rawexceptiontablelength; j++) {
+ u4 idx;
+ m->rawexceptiontable[j].startpc = suck_u2(cb);
+ m->rawexceptiontable[j].endpc = suck_u2(cb);
+ m->rawexceptiontable[j].handlerpc = suck_u2(cb);
+
+ idx = suck_u2(cb);
+
+ if (!idx) {
+ m->rawexceptiontable[j].catchtype.any = NULL;
+ }
+ else {
+ /* the classref is created later */
+ if (!(m->rawexceptiontable[j].catchtype.any =
+ (utf *) class_getconstant(c, idx, CONSTANT_Class)))
+ return false;
+ }
+ }
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* code attributes count */
+
+ code_attributes_count = suck_u2(cb);
+
+ for (k = 0; k < code_attributes_count; k++) {
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* code attribute name index */
+
+ code_attribute_name_index = suck_u2(cb);
+
+ code_attribute_name =
+ class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
+
+ if (code_attribute_name == NULL)
+ return false;
+
+ /* check which code attribute */
+
+ if (code_attribute_name == utf_LineNumberTable) {
+ /* LineNumberTable */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* attribute length */
+
+ (void) suck_u4(cb);
+
+ /* line number table length */
+
+ m->linenumbercount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb,
+ (2 + 2) * m->linenumbercount))
+ return false;
+
+ m->linenumbers = MNEW(lineinfo, m->linenumbercount);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
+#endif
+
+ for (l = 0; l < m->linenumbercount; l++) {
+ m->linenumbers[l].start_pc = suck_u2(cb);
+ m->linenumbers[l].line_number = suck_u2(cb);
+ }
+ }
+#if defined(ENABLE_JAVASE)
+ else if (code_attribute_name == utf_StackMapTable) {
+ /* StackTableMap */
+
+ if (!stackmap_load_attribute_stackmaptable(cb, m))
+ return false;
+ }
+#endif
+ else {
+ /* unknown code attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+ }
+ else if (attribute_name == utf_Exceptions) {
+ /* Exceptions */
+
+ if (m->thrownexceptions != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* attribute length */
+
+ (void) suck_u4(cb);
+
+ m->thrownexceptionscount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
+ return false;
+
+ m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
+
+ for (j = 0; j < m->thrownexceptionscount; j++) {
+ /* the classref is created later */
+ if (!((m->thrownexceptions)[j].any =
+ (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+ return false;
+ }
+ }
+#if defined(ENABLE_JAVASE)
+ else if (attribute_name == utf_Signature) {
+ /* Signature */
+
+ if (!loader_load_attribute_signature(cb, &(m->signature)))
+ return false;
+ }
+
+#if defined(ENABLE_ANNOTATIONS)
+ else if (attribute_name == utf_RuntimeVisibleAnnotations) {
+ /* RuntimeVisibleAnnotations */
+ if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
+ /* RuntimeVisibleParameterAnnotations */
+ if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
+ /* RuntimeInvisibleParameterAnnotations */
+ if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_AnnotationDefault) {
+ /* AnnotationDefault */
+ if (!annotation_load_method_attribute_annotationdefault(cb, m))
+ return false;
+ }
+#endif
+#endif
+ else {
+ /* unknown attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+
+ if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
+ exceptions_throw_classformaterror(c, "Missing Code attribute");
+ return false;
+ }
+
+#if defined(ENABLE_REPLACEMENT)
+ /* initialize the hit countdown field */
+
+ m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
+#endif
+
+ /* everything was ok */
+
+ return true;
+}
+
+
+/* method_free *****************************************************************
+
+ Frees all memory that was allocated for this method.
+
+*******************************************************************************/
+
+void method_free(methodinfo *m)
+{
+ if (m->jcode)
+ MFREE(m->jcode, u1, m->jcodelength);
+
+ if (m->rawexceptiontable)
+ MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
+
+ code_free_code_of_method(m);
+
+ if (m->stubroutine) {
+ if (m->flags & ACC_NATIVE) {
+ removenativestub(m->stubroutine);
+
+ } else {
+ removecompilerstub(m->stubroutine);
+ }
+ }
+}
+
+
+/* method_canoverwrite *********************************************************
+
+ Check if m and old are identical with respect to type and
+ name. This means that old can be overwritten with m.
+
+*******************************************************************************/
+
+bool method_canoverwrite(methodinfo *m, methodinfo *old)
+{
+ if (m->name != old->name)
+ return false;
+
+ if (m->descriptor != old->descriptor)
+ return false;
+
+ if (m->flags & ACC_STATIC)
+ return false;
+
+ return true;
+}
+
+
+/* method_new_builtin **********************************************************
+
+ Creates a minimal methodinfo structure for builtins. This comes handy
+ when dealing with builtin stubs or stacktraces.
+
+*******************************************************************************/
+
+methodinfo *method_new_builtin(builtintable_entry *bte)
+{
+ methodinfo *m;
+
+ /* allocate the methodinfo structure */
+
+ m = NEW(methodinfo);
+
+ /* initialize methodinfo structure */
+
+ MZERO(m, methodinfo, 1);
+ LOCK_INIT_OBJECT_LOCK(&(m->header));
+
+ m->flags = ACC_METHOD_BUILTIN;
+ m->parseddesc = bte->md;
+ m->name = bte->name;
+ m->descriptor = bte->descriptor;
+
+ /* return the newly created methodinfo */
+
+ return m;
+}
+
+
+/* method_vftbl_lookup *********************************************************
+
+ Does a method lookup in the passed virtual function table. This
+ function does exactly the same thing as JIT, but additionally
+ relies on the fact, that the methodinfo pointer is at the first
+ data segment slot (even for compiler stubs).
+
+*******************************************************************************/
+
+methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
+{
+ methodptr mptr;
+ methodptr *pmptr;
+ methodinfo *resm; /* pointer to new resolved method */
+
+ /* If the method is not an instance method, just return it. */
+
+ if (m->flags & ACC_STATIC)
+ return m;
+
+ assert(vftbl);
+
+ /* Get the method from the virtual function table. Is this an
+ interface method? */
+
+ if (m->clazz->flags & ACC_INTERFACE) {
+ pmptr = vftbl->interfacetable[-(m->clazz->index)];
+ mptr = pmptr[(m - m->clazz->methods)];
+ }
+ else {
+ mptr = vftbl->table[m->vftblindex];
+ }
+
+ /* and now get the codeinfo pointer from the first data segment slot */
+
+ resm = code_get_methodinfo_for_pv(mptr);
+
+ return resm;
+}
+
+
+/* method_get_parametercount **************************************************
+
+ Use the descriptor of a method to determine the number of parameters
+ of the method. The this pointer of non-static methods is not counted.
+
+ IN:
+ m........the method of which the parameters should be counted
+
+ RETURN VALUE:
+ The parameter count or -1 on error.
+
+*******************************************************************************/
+
+int32_t method_get_parametercount(methodinfo *m)
+{
+ methoddesc *md; /* method descriptor of m */
+ int32_t paramcount = 0; /* the parameter count of m */
+
+ md = m->parseddesc;
+
+ /* is the descriptor fully parsed? */
+
+ if (md->params == NULL) {
+ if (!descriptor_params_from_paramtypes(md, m->flags)) {
+ return -1;
+ }
+ }
+
+ paramcount = md->paramcount;
+
+ /* skip `this' pointer */
+
+ if (!(m->flags & ACC_STATIC)) {
+ --paramcount;
+ }
+
+ return paramcount;
+}
+
+
+/* method_get_parametertypearray ***********************************************
+
+ Use the descriptor of a method to generate a java.lang.Class array
+ which contains the classes of the parametertypes of the method.
+
+ This function is called by java.lang.reflect.{Constructor,Method}.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
+{
+ methoddesc *md;
+ typedesc *paramtypes;
+ int32_t paramcount;
+ java_handle_objectarray_t *oa;
+ int32_t i;
+ classinfo *c;
+
+ md = m->parseddesc;
+
+ /* is the descriptor fully parsed? */
+
+ if (m->parseddesc->params == NULL)
+ if (!descriptor_params_from_paramtypes(md, m->flags))
+ return NULL;
+
+ paramtypes = md->paramtypes;
+ paramcount = md->paramcount;
+
+ /* skip `this' pointer */
+
+ if (!(m->flags & ACC_STATIC)) {
+ paramtypes++;
+ paramcount--;
+ }
+
+ /* create class-array */
+
+ oa = builtin_anewarray(paramcount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* get classes */
+
+ for (i = 0; i < paramcount; i++) {
+ if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
+ return NULL;
+
+ LLNI_array_direct(oa, i) = (java_object_t *) c;
+ }
+
+ return oa;
+}
+
+
+/* method_get_exceptionarray ***************************************************
+
+ Get the exceptions which can be thrown by a method.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
+{
+ java_handle_objectarray_t *oa;
+ classinfo *c;
+ s4 i;
+
+ /* create class-array */
+
+ oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* iterate over all exceptions and store the class in the array */
+
+ for (i = 0; i < m->thrownexceptionscount; i++) {
+ c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
+
+ if (c == NULL)
+ return NULL;
+
+ LLNI_array_direct(oa, i) = (java_object_t *) c;
+ }
+
+ return oa;
+}
+
+
+/* method_returntype_get *******************************************************
+
+ Get the return type of the method.
+
+*******************************************************************************/
+
+classinfo *method_returntype_get(methodinfo *m)
+{
+ typedesc *td;
+ classinfo *c;
+
+ td = &(m->parseddesc->returntype);
+
+ if (!resolve_class_from_typedesc(td, true, false, &c))
+ return NULL;
+
+ return c;
+}
+
+
+/* method_count_implementations ************************************************
+
+ Count the implementations of a method in a class cone (a class and all its
+ subclasses.)
+
+ IN:
+ m................the method to count
+ c................class at which to start the counting (this class and
+ all its subclasses will be searched)
+
+ OUT:
+ *found...........if found != NULL, *found receives the method
+ implementation that was found. This value is only
+ meaningful if the return value is 1.
+
+ RETURN VALUE:
+ the number of implementations found
+
+*******************************************************************************/
+
+s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
+{
+ s4 count;
+ methodinfo *mp;
+ methodinfo *mend;
+ classinfo *child;
+
+ count = 0;
+
+ mp = c->methods;
+ mend = mp + c->methodscount;
+
+ for (; mp < mend; ++mp) {
+ if (method_canoverwrite(mp, m)) {
+ if (found)
+ *found = mp;
+ count++;
+ break;
+ }
+ }
+
+ for (child = c->sub; child != NULL; child = child->nextsub) {
+ count += method_count_implementations(m, child, found);
+ }
+
+ return count;
+}
+
+
+/* method_get_annotations ******************************************************
+
+ Get a methods' unparsed annotations in a byte array.
+
+ IN:
+ m........the method of which the annotations should be returned
+
+ RETURN VALUE:
+ The unparsed annotations in a byte array (or NULL if there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *method_get_annotations(methodinfo *m)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* methods' declaring class */
+ int slot; /* methods' slot */
+ java_handle_t *annotations; /* methods' unparsed annotations */
+ java_handle_t *method_annotations; /* all methods' unparsed annotations */
+ /* of the declaring class */
+
+ c = m->clazz;
+ slot = m - c->methods;
+ annotations = NULL;
+
+ LLNI_classinfo_field_get(c, method_annotations, method_annotations);
+
+ /* the method_annotations array might be shorter then the method
+ * count if the methods above a certain index have no annotations.
+ */
+ if (method_annotations != NULL &&
+ array_length_get(method_annotations) > slot) {
+ annotations = array_objectarray_element_get(
+ (java_handle_objectarray_t*)method_annotations, slot);
+ }
+
+ return (java_handle_bytearray_t*)annotations;
+#else
+ return NULL;
+#endif
+}
+
+
+/* method_get_parameterannotations ********************************************
+
+ Get a methods' unparsed parameter annotations in an array of byte
+ arrays.
+
+ IN:
+ m........the method of which the parameter annotations should be
+ returned
+
+ RETURN VALUE:
+ The unparsed parameter annotations in a byte array (or NULL if
+ there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* methods' declaring class */
+ int slot; /* methods' slot */
+ java_handle_t *parameterAnnotations; /* methods' unparsed */
+ /* parameter annotations */
+ java_handle_t *method_parameterannotations; /* all methods' unparsed */
+ /* parameter annotations of */
+ /* the declaring class */
+
+ c = m->clazz;
+ slot = m - c->methods;
+ parameterAnnotations = NULL;
+
+ LLNI_classinfo_field_get(
+ c, method_parameterannotations, method_parameterannotations);
+
+ /* the method_annotations array might be shorter then the method
+ * count if the methods above a certain index have no annotations.
+ */
+ if (method_parameterannotations != NULL &&
+ array_length_get(method_parameterannotations) > slot) {
+ parameterAnnotations = array_objectarray_element_get(
+ (java_handle_objectarray_t*)method_parameterannotations,
+ slot);
+ }
+
+ return (java_handle_bytearray_t*)parameterAnnotations;
+#else
+ return NULL;
+#endif
+}
+
+
+/* method_get_annotationdefault ***********************************************
+
+ Get a methods' unparsed annotation default value in a byte array.
+
+ IN:
+ m........the method of which the annotation default value should be
+ returned
+
+ RETURN VALUE:
+ The unparsed annotation default value in a byte array (or NULL if
+ there isn't one).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* methods' declaring class */
+ int slot; /* methods' slot */
+ java_handle_t *annotationDefault; /* methods' unparsed */
+ /* annotation default value */
+ java_handle_t *method_annotationdefaults; /* all methods' unparsed */
+ /* annotation default values of */
+ /* the declaring class */
+
+ c = m->clazz;
+ slot = m - c->methods;
+ annotationDefault = NULL;
+
+ LLNI_classinfo_field_get(
+ c, method_annotationdefaults, method_annotationdefaults);
+
+ /* the method_annotations array might be shorter then the method
+ * count if the methods above a certain index have no annotations.
+ */
+ if (method_annotationdefaults != NULL &&
+ array_length_get(method_annotationdefaults) > slot) {
+ annotationDefault = array_objectarray_element_get(
+ (java_handle_objectarray_t*)method_annotationdefaults, slot);
+ }
+
+ return (java_handle_bytearray_t*)annotationDefault;
+#else
+ return NULL;
+#endif
+}
+
+
+/* method_add_to_worklist ******************************************************
+
+ Add the method to the given worklist. If the method already occurs in
+ the worklist, the worklist remains unchanged.
+
+*******************************************************************************/
+
+static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
+{
+ method_worklist *wi;
+
+ for (wi = *wl; wi != NULL; wi = wi->next)
+ if (wi->m == m)
+ return;
+
+ wi = NEW(method_worklist);
+ wi->next = *wl;
+ wi->m = m;
+
+ *wl = wi;
+}
+
+
+/* method_add_assumption_monomorphic *******************************************
+
+ Record the assumption that the method is monomorphic.
+
+ IN:
+ m.................the method
+ caller............the caller making the assumption
+
+*******************************************************************************/
+
+void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
+{
+ method_assumption *as;
+
+ /* XXX LOCKING FOR THIS FUNCTION? */
+
+ /* check if we already have registered this assumption */
+
+ for (as = m->assumptions; as != NULL; as = as->next) {
+ if (as->context == caller)
+ return;
+ }
+
+ /* register the assumption */
+
+ as = NEW(method_assumption);
+ as->next = m->assumptions;
+ as->context = caller;
+
+ m->assumptions = as;
+}
+
+/* method_break_assumption_monomorphic *****************************************
+
+ Break the assumption that this method is monomorphic. All callers that
+ have registered this assumption are added to the worklist.
+
+ IN:
+ m.................the method
+ wl................worklist where to add invalidated callers
+
+*******************************************************************************/
+
+void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
+{
+ method_assumption *as;
+
+ /* XXX LOCKING FOR THIS FUNCTION? */
+
+ for (as = m->assumptions; as != NULL; as = as->next) {
+ INLINELOG(
+ printf("ASSUMPTION BROKEN (monomorphism): ");
+ method_print(m);
+ printf(" in ");
+ method_println(as->context);
+ );
+
+ method_add_to_worklist(as->context, wl);
+
+#if defined(ENABLE_TLH) && 0
+ /* XXX hack */
+ method_assumption *as2;
+ as2 = m->assumptions;
+ m->assumptions = NULL;
+ method_break_assumption_monomorphic(as->context, wl);
+ /*
+ assert(m->assumptions == NULL);
+ m->assumptions = as2;*/
+#endif
+
+ }
+}
+
+/* method_printflags ***********************************************************
+
+ Prints the flags of a method to stdout like.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_printflags(methodinfo *m)
+{
+ if (m == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
+ if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
+ if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
+ if (m->flags & ACC_STATIC) printf(" STATIC");
+ if (m->flags & ACC_FINAL) printf(" FINAL");
+ if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (m->flags & ACC_NATIVE) printf(" NATIVE");
+ if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+ if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
+ if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
+ if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_print ****************************************************************
+
+ Prints a method to stdout like:
+
+ java.lang.Object.<init>()V
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_print(methodinfo *m)
+{
+ if (m == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (m->clazz != NULL)
+ utf_display_printable_ascii_classname(m->clazz->name);
+ else
+ printf("NULL");
+ printf(".");
+ utf_display_printable_ascii(m->name);
+ utf_display_printable_ascii(m->descriptor);
+
+ method_printflags(m);
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_println **************************************************************
+
+ Prints a method plus new line to stdout like:
+
+ java.lang.Object.<init>()V
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_println(methodinfo *m)
+{
+ if (opt_debugcolor) printf("\033[31m"); /* red */
+ method_print(m);
+ if (opt_debugcolor) printf("\033[m");
+ printf("\n");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_methodref_print ******************************************************
+
+ Prints a method reference to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_methodref_print(constant_FMIref *mr)
+{
+ if (!mr) {
+ printf("(constant_FMIref *)NULL");
+ return;
+ }
+
+ if (IS_FMIREF_RESOLVED(mr)) {
+ printf("<method> ");
+ method_print(mr->p.method);
+ }
+ else {
+ printf("<methodref> ");
+ utf_display_printable_ascii_classname(mr->p.classref->name);
+ printf(".");
+ utf_display_printable_ascii(mr->name);
+ utf_display_printable_ascii(mr->descriptor);
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_methodref_println ****************************************************
+
+ Prints a method reference to stdout, followed by a newline.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_methodref_println(constant_FMIref *mr)
+{
+ method_methodref_print(mr);
+ printf("\n");
+}
+#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/method.h - method 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 _METHOD_H
+#define _METHOD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* forward typedefs ***********************************************************/
+
+typedef struct methodinfo methodinfo;
+typedef struct raw_exception_entry raw_exception_entry;
+typedef struct lineinfo lineinfo;
+typedef struct method_assumption method_assumption;
+typedef struct method_worklist method_worklist;
+typedef struct codeinfo codeinfo;
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/builtin.h"
+#include "vm/descriptor.h"
+#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/references.h"
+
+#if defined(ENABLE_JAVASE)
+# include "vm/stackmap.h"
+#endif
+
+#include "vm/utf8.h"
+
+
+#if defined(ENABLE_REPLACEMENT)
+/* Initial value for the hit countdown field of each method. */
+#define METHOD_INITIAL_HIT_COUNTDOWN 1000
+#endif
+
+
+/* methodinfo *****************************************************************/
+
+struct methodinfo { /* method structure */
+ java_object_t header; /* we need this in jit's monitorenter */
+ s4 flags; /* ACC flags */
+ utf *name; /* name of method */
+ utf *descriptor; /* JavaVM descriptor string of method */
+#if defined(ENABLE_JAVASE)
+ utf *signature; /* Signature attribute */
+ stack_map_t *stack_map; /* StackMapTable attribute */
+#endif
+
+ methoddesc *parseddesc; /* parsed descriptor */
+
+ classinfo *clazz; /* class, the method belongs to */
+ s4 vftblindex; /* index of method in virtual function */
+ /* table (if it is a virtual method) */
+ s4 maxstack; /* maximum stack depth of method */
+ s4 maxlocals; /* maximum number of local variables */
+ s4 jcodelength; /* length of JavaVM code */
+ u1 *jcode; /* pointer to JavaVM code */
+
+ s4 rawexceptiontablelength; /* exceptiontable length */
+ raw_exception_entry *rawexceptiontable; /* the exceptiontable */
+
+ u2 thrownexceptionscount; /* number of exceptions attribute */
+ classref_or_classinfo *thrownexceptions; /* except. a method may throw */
+
+ u2 linenumbercount; /* number of linenumber attributes */
+ lineinfo *linenumbers; /* array of lineinfo items */
+
+ u1 *stubroutine; /* stub for compiling or calling natives */
+ codeinfo *code; /* current code of this method */
+
+#if defined(ENABLE_LSRA)
+ s4 maxlifetimes; /* helper for lsra */
+#endif
+
+ methodinfo *overwrites; /* method that is directly overwritten */
+ method_assumption *assumptions; /* list of assumptions about this method */
+
+#if defined(ENABLE_REPLACEMENT)
+ s4 hitcountdown; /* decreased for each hit */
+#endif
+
+#if defined(ENABLE_DEBUG_FILTER)
+ u1 filtermatches; /* flags indicating which filters the method matches */
+#endif
+
+#if defined(ENABLE_ESCAPE)
+ u1 *paramescape;
+#endif
+};
+
+/* method_assumption ***********************************************************
+
+ This struct is used for registering assumptions about methods.
+
+*******************************************************************************/
+
+struct method_assumption {
+ method_assumption *next;
+ methodinfo *context;
+};
+
+
+/* method_worklist *************************************************************
+
+ List node used for method worklists.
+
+*******************************************************************************/
+
+struct method_worklist {
+ method_worklist *next;
+ methodinfo *m;
+};
+
+
+/* raw_exception_entry ********************************************************/
+
+/* exception table entry read by the loader */
+
+struct raw_exception_entry { /* exceptiontable entry in a method */
+ classref_or_classinfo catchtype; /* catchtype of exc. (0 == catchall) */
+ u2 startpc; /* start pc of guarded area (inclusive) */
+ u2 endpc; /* end pc of guarded area (exklusive) */
+ u2 handlerpc; /* pc of exception handler */
+};
+
+
+/* lineinfo *******************************************************************/
+
+struct lineinfo {
+ u2 start_pc;
+ u2 line_number;
+};
+
+
+/* global variables ***********************************************************/
+
+extern methodinfo *method_java_lang_reflect_Method_invoke;
+
+
+/* inline functions ***********************************************************/
+
+inline static bool method_is_builtin(methodinfo* m)
+{
+ return m->flags & ACC_METHOD_BUILTIN;
+}
+
+
+/* function prototypes ********************************************************/
+
+void method_init(void);
+
+bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool);
+void method_free(methodinfo *m);
+bool method_canoverwrite(methodinfo *m, methodinfo *old);
+
+methodinfo *method_new_builtin(builtintable_entry *bte);
+
+methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m);
+
+int32_t method_get_parametercount(methodinfo *m);
+java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m);
+java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m);
+classinfo *method_returntype_get(methodinfo *m);
+
+void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller);
+void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl);
+
+s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found);
+
+java_handle_bytearray_t *method_get_annotations(methodinfo *m);
+java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m);
+java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m);
+
+#if !defined(NDEBUG)
+void method_printflags(methodinfo *m);
+void method_print(methodinfo *m);
+void method_println(methodinfo *m);
+void method_methodref_print(constant_FMIref *mr);
+void method_methodref_println(constant_FMIref *mr);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _METHOD_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:
+ */
--- /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.cpp - 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.
+
+*/
+
+
+#include "config.h"
+
+/* NOTE: In this file we check for all system headers, because we wrap
+ all system calls into functions for better portability. */
+
+#if defined(HAVE_ERRNO_H)
+# include <errno.h>
+#endif
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.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(__DARWIN__)
+# include <mach/mach.h>
+# include <mach/mach_host.h>
+# include <mach/host_info.h>
+#endif
+
+/* this should work on BSD */
+/* #include <sys/sysctl.h> */
+
+#include "vm/vm.hpp"
+
+
+/**
+ * Maps anonymous memory, even on systems not defining
+ * MAP_ANON(YMOUS).
+ *
+ * @param ...
+ */
+void* os::mmap_anonymous(void *addr, size_t len, int prot, int flags)
+{
+ void* p;
+
+#if defined(MAP_ANON) || defined(MAP_ANONYMOUS)
+ p = mmap(addr, len, prot,
+# if defined(MAP_ANON)
+ MAP_ANON | flags,
+# else
+ MAP_ANONYMOUS | flags,
+# endif
+ -1, 0);
+#else
+ int fd;
+
+ fd = open("/dev/zero", O_RDONLY, 0);
+
+ if (fd == -1)
+ vm_abort("os::mmap_anonymous: open failed: %s", os::strerror(errno));
+
+ p = mmap(addr, len, prot, flags, fd, 0);
+#endif
+
+#if defined(MAP_FAILED)
+ if (p == MAP_FAILED)
+#else
+ if (p == (void *) -1)
+#endif
+ vm_abort("os::mmap_anonymous: mmap failed: %s", os::strerror(errno));
+
+ return p;
+}
+
+
+/**
+ * Returns the number of online processors in the system.
+ *
+ * @return Number of online processors.
+ */
+int os::processors_online(void)
+{
+#if defined(_SC_NPROC_ONLN)
+
+ return (int) sysconf(_SC_NPROC_ONLN);
+
+#elif defined(_SC_NPROCESSORS_ONLN)
+
+ return (int) sysconf(_SC_NPROCESSORS_ONLN);
+
+#elif defined(__DARWIN__)
+
+ host_basic_info_data_t hinfo;
+ mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
+ kern_return_t rc;
+
+ rc = host_info(mach_host_self(), HOST_BASIC_INFO,
+ (host_info_t) &hinfo, &hinfo_count);
+
+ if (rc != KERN_SUCCESS) {
+ return -1;
+ }
+
+ /* XXX michi: according to my infos this should be
+ hinfo.max_cpus, can someone please confirm or deny that? */
+ return (int) hinfo.avail_cpus;
+
+#elif defined(__FREEBSD__)
+# error IMPLEMENT ME!
+
+ /* this should work in BSD */
+ /*
+ int ncpu, mib[2], rc;
+ size_t len;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ len = sizeof(ncpu);
+ rc = sysctl(mib, 2, &ncpu, &len, NULL, 0);
+
+ return (int32_t) ncpu;
+ */
+
+#else
+
+ return 1;
+
+#endif
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+ void* os_mmap_anonymous(void *addr, size_t len, int prot, int flags) { return os::mmap_anonymous(addr, len, prot, flags); }
+
+ void os_abort(void) { os::abort(); }
+ int os_access(const char* pathname, int mode) { return os::access(pathname, mode); }
+ int os_atoi(const char* nptr) { return os::atoi(nptr); }
+ void* os_calloc(size_t nmemb, size_t size) { return os::calloc(nmemb, size); }
+#if defined(ENABLE_JRE_LAYOUT)
+ char* os_dirname(char* path) { return os::dirname(path); }
+#endif
+ int os_dlclose(void* handle) { return os::dlclose(handle); }
+ char* os_dlerror(void) { return os::dlerror(); }
+ void* os_dlopen(const char* filename, int flag) { return os::dlopen(filename, flag); }
+ void* os_dlsym(void* handle, const char* symbol) { return os::dlsym(handle, symbol); }
+ int os_fclose(FILE* fp) { return os::fclose(fp); }
+ FILE* os_fopen(const char* path, const char* mode) { return os::fopen(path, mode); }
+ size_t os_fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { return os::fread(ptr, size, nmemb, stream); }
+ void os_free(void* ptr) { os::free(ptr); }
+ int os_getpagesize(void) { return os::getpagesize(); }
+ void* os_memcpy(void* dest, const void* src, size_t n) { return os::memcpy(dest, src, n); }
+ void* os_memset(void* s, int c, size_t n) { return os::memset(s, c, n); }
+ int os_mprotect(void* addr, size_t len, int prot) { return os::mprotect(addr, len, prot); }
+ int os_scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*)) { return os::scandir(dir, namelist, filter, compar); }
+ int os_stat(const char* path, struct stat* buf) { return os::stat(path, buf); }
+ char* os_strcat(char* dest, const char* src) { return os::strcat(dest, src); }
+ char* os_strcpy(char* dest, const char* src) { return os::strcpy(dest, src); }
+ char* os_strdup(const char* s) { return os::strdup(s); }
+ int os_strlen(const char* s) { return os::strlen(s); }
+
+}
+
+
+/*
+ * 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/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:
+ */
#include "native/jni.h"
-#include "native/include/java_lang_String.h"
-
+#include "vm/options.h"
#include "vm/package.hpp"
-#include "vm/stringlocal.h"
-
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
/* internal property structure ************************************************/
+++ /dev/null
-/* src/vm/primitive.c - primitive types
-
- 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.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "native/include/java_lang_Boolean.h"
-#include "native/include/java_lang_Byte.h"
-#include "native/include/java_lang_Short.h"
-#include "native/include/java_lang_Character.h"
-#include "native/include/java_lang_Integer.h"
-#include "native/include/java_lang_Long.h"
-#include "native/include/java_lang_Float.h"
-#include "native/include/java_lang_Double.h"
-
-#include "vm/builtin.h"
-#include "vm/global.h"
-#include "vm/primitive.h"
-#include "vm/vm.h"
-
-#include "vmcore/class.h"
-#include "vmcore/utf8.h"
-
-
-/* primitive_class_get_by_name *************************************************
-
- Returns the primitive class of the given class name.
-
-*******************************************************************************/
-
-classinfo *primitive_class_get_by_name(utf *name)
-{
- int i;
-
- /* search table of primitive classes */
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
- if (primitivetype_table[i].name == name)
- return primitivetype_table[i].class_primitive;
-
- /* keep compiler happy */
-
- return NULL;
-}
-
-
-/* primitive_class_get_by_type *************************************************
-
- Returns the primitive class of the given type.
-
-*******************************************************************************/
-
-classinfo *primitive_class_get_by_type(int type)
-{
- return primitivetype_table[type].class_primitive;
-}
-
-
-/* primitive_class_get_by_char *************************************************
-
- Returns the primitive class of the given type.
-
-*******************************************************************************/
-
-classinfo *primitive_class_get_by_char(char ch)
-{
- int index;
-
- switch (ch) {
- case 'I':
- index = PRIMITIVETYPE_INT;
- break;
- case 'J':
- index = PRIMITIVETYPE_LONG;
- break;
- case 'F':
- index = PRIMITIVETYPE_FLOAT;
- break;
- case 'D':
- index = PRIMITIVETYPE_DOUBLE;
- break;
- case 'B':
- index = PRIMITIVETYPE_BYTE;
- break;
- case 'C':
- index = PRIMITIVETYPE_CHAR;
- break;
- case 'S':
- index = PRIMITIVETYPE_SHORT;
- break;
- case 'Z':
- index = PRIMITIVETYPE_BOOLEAN;
- break;
- case 'V':
- index = PRIMITIVETYPE_VOID;
- break;
- default:
- return NULL;
- }
-
- return primitivetype_table[index].class_primitive;
-}
-
-
-/* primitive_arrayclass_get_by_name ********************************************
-
- Returns the primitive array-class of the given primitive class
- name.
-
-*******************************************************************************/
-
-classinfo *primitive_arrayclass_get_by_name(utf *name)
-{
- int i;
-
- /* search table of primitive classes */
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
- if (primitivetype_table[i].name == name)
- return primitivetype_table[i].arrayclass;
-
- /* keep compiler happy */
-
- return NULL;
-}
-
-
-/* primitive_arrayclass_get_by_type ********************************************
-
- Returns the primitive array-class of the given type.
-
-*******************************************************************************/
-
-classinfo *primitive_arrayclass_get_by_type(int type)
-{
- return primitivetype_table[type].arrayclass;
-}
-
-
-/* primitive_type_get_by_wrapperclass ******************************************
-
- Returns the primitive type of the given wrapper-class.
-
-*******************************************************************************/
-
-int primitive_type_get_by_wrapperclass(classinfo *c)
-{
- int i;
-
- /* Search primitive table. */
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
- if (primitivetype_table[i].class_wrap == c)
- return i;
-
- /* Invalid primitive wrapper-class. */
-
- return -1;
-}
-
-
-/* primitive_box ***************************************************************
-
- Box a primitive of the given type. If the type is an object,
- simply return it.
-
-*******************************************************************************/
-
-java_handle_t *primitive_box(int type, imm_union value)
-{
- java_handle_t *o;
-
- switch (type) {
- case PRIMITIVETYPE_BOOLEAN:
- o = primitive_box_boolean(value.i);
- break;
- case PRIMITIVETYPE_BYTE:
- o = primitive_box_byte(value.i);
- break;
- case PRIMITIVETYPE_CHAR:
- o = primitive_box_char(value.i);
- break;
- case PRIMITIVETYPE_SHORT:
- o = primitive_box_short(value.i);
- break;
- case PRIMITIVETYPE_INT:
- o = primitive_box_int(value.i);
- break;
- case PRIMITIVETYPE_LONG:
- o = primitive_box_long(value.l);
- break;
- case PRIMITIVETYPE_FLOAT:
- o = primitive_box_float(value.f);
- break;
- case PRIMITIVETYPE_DOUBLE:
- o = primitive_box_double(value.d);
- break;
- case PRIMITIVETYPE_VOID:
- o = value.a;
- break;
- default:
- o = NULL;
- vm_abort("primitive_box: invalid primitive type %d", type);
- }
-
- return o;
-}
-
-
-/* primitive_unbox *************************************************************
-
- Unbox a primitive of the given type. If the type is an object,
- simply return it.
-
-*******************************************************************************/
-
-imm_union primitive_unbox(java_handle_t *o)
-{
- classinfo *c;
- int type;
- imm_union value;
-
- if (o == NULL) {
- value.a = NULL;
- return value;
- }
-
- LLNI_class_get(o, c);
-
- type = primitive_type_get_by_wrapperclass(c);
-
- switch (type) {
- case PRIMITIVETYPE_BOOLEAN:
- value.i = primitive_unbox_boolean(o);
- break;
- case PRIMITIVETYPE_BYTE:
- value.i = primitive_unbox_byte(o);
- break;
- case PRIMITIVETYPE_CHAR:
- value.i = primitive_unbox_char(o);
- break;
- case PRIMITIVETYPE_SHORT:
- value.i = primitive_unbox_short(o);
- break;
- case PRIMITIVETYPE_INT:
- value.i = primitive_unbox_int(o);
- break;
- case PRIMITIVETYPE_LONG:
- value.l = primitive_unbox_long(o);
- break;
- case PRIMITIVETYPE_FLOAT:
- value.f = primitive_unbox_float(o);
- break;
- case PRIMITIVETYPE_DOUBLE:
- value.d = primitive_unbox_double(o);
- break;
- case -1:
- /* If type is -1 the object is not a primitive box but a
- normal object. */
- value.a = o;
- break;
- default:
- vm_abort("primitive_unbox: invalid primitive type %d", type);
- }
-
- return value;
-}
-
-
-/* primitive_box_xxx ***********************************************************
-
- Box a primitive type.
-
-*******************************************************************************/
-
-#define PRIMITIVE_BOX_TYPE(name, object, type) \
-java_handle_t *primitive_box_##name(type value) \
-{ \
- java_handle_t *o; \
- java_lang_##object *jo; \
- \
- o = builtin_new(class_java_lang_##object); \
- \
- if (o == NULL) \
- return NULL; \
- \
- jo = (java_lang_##object *) o; \
- \
- LLNI_field_set_val(jo, value, value); \
- \
- return o; \
-}
-
-PRIMITIVE_BOX_TYPE(boolean, Boolean, int32_t)
-PRIMITIVE_BOX_TYPE(byte, Byte, int32_t)
-PRIMITIVE_BOX_TYPE(char, Character, int32_t)
-PRIMITIVE_BOX_TYPE(short, Short, int32_t)
-PRIMITIVE_BOX_TYPE(int, Integer, int32_t)
-PRIMITIVE_BOX_TYPE(long, Long, int64_t)
-PRIMITIVE_BOX_TYPE(float, Float, float)
-PRIMITIVE_BOX_TYPE(double, Double, double)
-
-
-/* primitive_unbox_xxx *********************************************************
-
- Unbox a primitive type.
-
-*******************************************************************************/
-
-#define PRIMITIVE_UNBOX_TYPE(name, object, type) \
-type primitive_unbox_##name(java_handle_t *o) \
-{ \
- java_lang_##object *jo; \
- type value; \
- \
- jo = (java_lang_##object *) o; \
- \
- LLNI_field_get_val(jo, value, value); \
- \
- return value; \
-}
-
-PRIMITIVE_UNBOX_TYPE(boolean, Boolean, int32_t)
-PRIMITIVE_UNBOX_TYPE(byte, Byte, int32_t)
-PRIMITIVE_UNBOX_TYPE(char, Character, int32_t)
-PRIMITIVE_UNBOX_TYPE(short, Short, int32_t)
-PRIMITIVE_UNBOX_TYPE(int, Integer, int32_t)
-PRIMITIVE_UNBOX_TYPE(long, Long, int64_t)
-PRIMITIVE_UNBOX_TYPE(float, Float, float)
-PRIMITIVE_UNBOX_TYPE(double, Double, double)
-
-
-/*
- * 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/primitive.cpp - primitive types
+
+ 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.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/primitive.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/**
+ * Returns the primitive class of the given class name.
+ *
+ * @param name Name of the class.
+ *
+ * @return Class structure.
+ */
+classinfo* Primitive::get_class_by_name(utf *name)
+{
+ int i;
+
+ /* search table of primitive classes */
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
+ if (primitivetype_table[i].name == name)
+ return primitivetype_table[i].class_primitive;
+
+ /* keep compiler happy */
+
+ return NULL;
+}
+
+
+/**
+ * Returns the primitive class of the given type.
+ *
+ * @param type Integer type of the class.
+ *
+ * @return Class structure.
+ */
+classinfo* Primitive::get_class_by_type(int type)
+{
+ return primitivetype_table[type].class_primitive;
+}
+
+
+/**
+ * Returns the primitive class of the given type.
+ *
+ * @param ch
+ *
+ * @return Class structure.
+ */
+classinfo* Primitive::get_class_by_char(char ch)
+{
+ int index;
+
+ switch (ch) {
+ case 'I':
+ index = PRIMITIVETYPE_INT;
+ break;
+ case 'J':
+ index = PRIMITIVETYPE_LONG;
+ break;
+ case 'F':
+ index = PRIMITIVETYPE_FLOAT;
+ break;
+ case 'D':
+ index = PRIMITIVETYPE_DOUBLE;
+ break;
+ case 'B':
+ index = PRIMITIVETYPE_BYTE;
+ break;
+ case 'C':
+ index = PRIMITIVETYPE_CHAR;
+ break;
+ case 'S':
+ index = PRIMITIVETYPE_SHORT;
+ break;
+ case 'Z':
+ index = PRIMITIVETYPE_BOOLEAN;
+ break;
+ case 'V':
+ index = PRIMITIVETYPE_VOID;
+ break;
+ default:
+ return NULL;
+ }
+
+ return primitivetype_table[index].class_primitive;
+}
+
+
+/**
+ * Returns the primitive array-class of the given primitive class
+ * name.
+ *
+ * @param name Name of the class.
+ *
+ * @return Class structure.
+ */
+classinfo* Primitive::get_arrayclass_by_name(utf *name)
+{
+ int i;
+
+ /* search table of primitive classes */
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
+ if (primitivetype_table[i].name == name)
+ return primitivetype_table[i].arrayclass;
+
+ /* keep compiler happy */
+
+ return NULL;
+}
+
+
+/**
+ * Returns the primitive array-class of the given type.
+ *
+ * @param type Integer type of the class.
+ *
+ * @return Class structure.
+ */
+classinfo* Primitive::get_arrayclass_by_type(int type)
+{
+ return primitivetype_table[type].arrayclass;
+}
+
+
+/**
+ * Returns the primitive type of the given wrapper-class.
+ *
+ * @param c Class structure.
+ *
+ * @return Integer type of the class.
+ */
+int Primitive::get_type_by_wrapperclass(classinfo *c)
+{
+ int i;
+
+ /* Search primitive table. */
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++)
+ if (primitivetype_table[i].class_wrap == c)
+ return i;
+
+ /* Invalid primitive wrapper-class. */
+
+ return -1;
+}
+
+
+/**
+ * Box a primitive of the given type. If the type is an object,
+ * simply return it.
+ *
+ * @param type Type of the passed value.
+ * @param value Value to box.
+ *
+ * @return Handle of the boxing Java object.
+ */
+java_handle_t* Primitive::box(int type, imm_union value)
+{
+ java_handle_t* o;
+
+ switch (type) {
+ case PRIMITIVETYPE_BOOLEAN:
+ o = box((uint8_t) value.i);
+ break;
+ case PRIMITIVETYPE_BYTE:
+ o = box((int8_t) value.i);
+ break;
+ case PRIMITIVETYPE_CHAR:
+ o = box((uint16_t) value.i);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ o = box((int16_t) value.i);
+ break;
+ case PRIMITIVETYPE_INT:
+ o = box(value.i);
+ break;
+ case PRIMITIVETYPE_LONG:
+ o = box(value.l);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ o = box(value.f);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ o = box(value.d);
+ break;
+ case PRIMITIVETYPE_VOID:
+ o = (java_handle_t*) value.a;
+ break;
+ default:
+ o = NULL;
+ vm_abort("primitive_box: invalid primitive type %d", type);
+ }
+
+ return o;
+}
+
+
+/**
+ * Unbox a primitive of the given type. If the type is an object,
+ * simply return it.
+ *
+ * @param h Handle of the Java object.
+ *
+ * @return Unboxed value as union.
+ */
+imm_union Primitive::unbox(java_handle_t *h)
+{
+ classinfo *c;
+ int type;
+ imm_union value;
+
+ if (h == NULL) {
+ value.a = NULL;
+ return value;
+ }
+
+ LLNI_class_get(h, c);
+
+ type = get_type_by_wrapperclass(c);
+
+ switch (type) {
+ case PRIMITIVETYPE_BOOLEAN:
+ value.i = unbox_boolean(h);
+ break;
+ case PRIMITIVETYPE_BYTE:
+ value.i = unbox_byte(h);
+ break;
+ case PRIMITIVETYPE_CHAR:
+ value.i = unbox_char(h);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ value.i = unbox_short(h);
+ break;
+ case PRIMITIVETYPE_INT:
+ value.i = unbox_int(h);
+ break;
+ case PRIMITIVETYPE_LONG:
+ value.l = unbox_long(h);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ value.f = unbox_float(h);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ value.d = unbox_double(h);
+ break;
+ case -1:
+ /* If type is -1 the object is not a primitive box but a
+ normal object. */
+ value.a = h;
+ break;
+ default:
+ vm_abort("Primitive::unbox: invalid primitive type %d", type);
+ }
+
+ return value;
+}
+
+
+/**
+ * Box a primitive type.
+ */
+java_handle_t* Primitive::box(uint8_t value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Boolean);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Boolean b(h);
+ b.set_value(value);
+
+ return h;
+}
+
+java_handle_t* Primitive::box(int8_t value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Byte);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Byte b(h);
+ b.set_value(value);
+
+ return h;
+}
+
+java_handle_t* Primitive::box(uint16_t value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Character);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Character c(h);
+ c.set_value(value);
+
+ return h;
+}
+
+java_handle_t* Primitive::box(int16_t value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Short);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Short s(h);
+ s.set_value(value);
+
+ return h;
+}
+
+java_handle_t* Primitive::box(int32_t value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Integer);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Integer i(h);
+ i.set_value(value);
+
+ return h;
+}
+
+java_handle_t* Primitive::box(int64_t value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Long);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Long l(h);
+ l.set_value(value);
+
+ return h;
+}
+
+java_handle_t* Primitive::box(float value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Float);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Float f(h);
+ f.set_value(value);
+
+ return h;
+}
+
+java_handle_t* Primitive::box(double value)
+{
+ java_handle_t *h = builtin_new(class_java_lang_Double);
+
+ if (h == NULL)
+ return NULL;
+
+ java_lang_Double d(h);
+ d.set_value(value);
+
+ return h;
+}
+
+
+
+/**
+ * Unbox a primitive type.
+ */
+
+// template<class T> T Primitive::unbox(java_handle_t *h)
+// {
+// return java_lang_Boolean::get_value(h);
+// }
+
+inline uint8_t Primitive::unbox_boolean(java_handle_t *h)
+{
+ java_lang_Boolean b(h);
+ return b.get_value();
+}
+
+inline int8_t Primitive::unbox_byte(java_handle_t *h)
+{
+ java_lang_Byte b(h);
+ return b.get_value();
+}
+
+inline uint16_t Primitive::unbox_char(java_handle_t *h)
+{
+ java_lang_Character c(h);
+ return c.get_value();
+}
+
+inline int16_t Primitive::unbox_short(java_handle_t *h)
+{
+ java_lang_Short s(h);
+ return s.get_value();
+}
+
+inline int32_t Primitive::unbox_int(java_handle_t *h)
+{
+ java_lang_Integer i(h);
+ return i.get_value();
+}
+
+inline int64_t Primitive::unbox_long(java_handle_t *h)
+{
+ java_lang_Long l(h);
+ return l.get_value();
+}
+
+inline float Primitive::unbox_float(java_handle_t *h)
+{
+ java_lang_Float f(h);
+ return f.get_value();
+}
+
+inline double Primitive::unbox_double(java_handle_t *h)
+{
+ java_lang_Double d(h);
+ return d.get_value();
+}
+
+
+
+// Legacy C interface.
+
+extern "C" {
+
+ classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
+classinfo* Primitive_get_class_by_type(int type) { return Primitive::get_class_by_type(type); }
+classinfo* Primitive_get_class_by_char(char ch) { return Primitive::get_class_by_char(ch); }
+classinfo* Primitive_get_arrayclass_by_name(utf *name) { return Primitive::get_arrayclass_by_name(name); }
+classinfo* Primitive_get_arrayclass_by_type(int type) { return Primitive::get_arrayclass_by_type(type); }
+int Primitive_get_type_by_wrapperclass(classinfo *c) { return Primitive::get_type_by_wrapperclass(c); }
+java_handle_t* Primitive_box(int type, imm_union value) { return Primitive::box(type, value); }
+imm_union Primitive_unbox(java_handle_t *h) { return Primitive::unbox(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:
+ */
+++ /dev/null
-/* src/vm/primitive.c - primitive types
-
- 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
-
- 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 _PRIMITIVE_H
-#define _PRIMITIVE_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/linker.h"
-#include "vmcore/utf8.h"
-
-
-/* primitive data types *******************************************************/
-
-/* These values are used in parsed descriptors and in some other
- places were the different types handled internally as TYPE_INT have
- to be distinguished. */
-
-#define PRIMITIVETYPE_COUNT 11 /* number of primitive types (+ dummies) */
-
-/* CAUTION: Don't change the numerical values! These constants are
- used as indices into the primitive type table. */
-
-#define PRIMITIVETYPE_INT TYPE_INT
-#define PRIMITIVETYPE_LONG TYPE_LNG
-#define PRIMITIVETYPE_FLOAT TYPE_FLT
-#define PRIMITIVETYPE_DOUBLE TYPE_DBL
-#define PRIMITIVETYPE_DUMMY1 TYPE_ADR /* not used! */
-#define PRIMITIVETYPE_BYTE 5
-#define PRIMITIVETYPE_CHAR 6
-#define PRIMITIVETYPE_SHORT 7
-#define PRIMITIVETYPE_BOOLEAN 8
-#define PRIMITIVETYPE_DUMMY2 9 /* not used! */
-#define PRIMITIVETYPE_VOID TYPE_VOID
-
-
-/* primitivetypeinfo **********************************************************/
-
-struct primitivetypeinfo {
- char *cname; /* char name of primitive class */
- utf *name; /* name of primitive class */
- classinfo *class_wrap; /* class for wrapping primitive type */
- classinfo *class_primitive; /* primitive class */
- char *wrapname; /* name of class for wrapping */
- char typesig; /* one character type signature */
- char *arrayname; /* name of primitive array class */
- classinfo *arrayclass; /* primitive array class */
-};
-
-
-/* global variables ***********************************************************/
-
-/* This array can be indexed by the PRIMITIVETYPE_ and ARRAYTYPE_
- constants (except ARRAYTYPE_OBJECT). */
-
-extern primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT];
-
-
-/* function prototypes ********************************************************/
-
-/* this function is in src/vmcore/primitivecore.c */
-void primitive_init(void);
-void primitive_postinit(void);
-
-classinfo *primitive_class_get_by_name(utf *name);
-classinfo *primitive_class_get_by_type(int type);
-classinfo *primitive_class_get_by_char(char ch);
-
-classinfo *primitive_arrayclass_get_by_name(utf *name);
-classinfo *primitive_arrayclass_get_by_type(int type);
-
-int primitive_type_get_by_wrapperclass(classinfo *c);
-
-java_handle_t *primitive_box(int type, imm_union value);
-imm_union primitive_unbox(java_handle_t *o);
-
-java_handle_t *primitive_box_boolean(int32_t value);
-java_handle_t *primitive_box_byte(int32_t value);
-java_handle_t *primitive_box_char(int32_t value);
-java_handle_t *primitive_box_short(int32_t value);
-java_handle_t *primitive_box_int(int32_t value);
-java_handle_t *primitive_box_long(int64_t value);
-java_handle_t *primitive_box_float(float value);
-java_handle_t *primitive_box_double(double value);
-
-int32_t primitive_unbox_boolean(java_handle_t *o);
-int32_t primitive_unbox_byte(java_handle_t *o);
-int32_t primitive_unbox_char(java_handle_t *o);
-int32_t primitive_unbox_short(java_handle_t *o);
-int32_t primitive_unbox_int(java_handle_t *o);
-int64_t primitive_unbox_long(java_handle_t *o);
-float primitive_unbox_float(java_handle_t *o);
-double primitive_unbox_double(java_handle_t *o);
-
-#endif /* _PRIMITIVE_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:
- */
--- /dev/null
+/* src/vm/primitive.hpp - primitive types
+
+ 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 _PRIMITIVE_HPP
+#define _PRIMITIVE_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/utf8.h"
+
+
+#ifdef __cplusplus
+
+class Primitive {
+public:
+ static classinfo* get_class_by_name(utf *name);
+ static classinfo* get_class_by_type(int type);
+ static classinfo* get_class_by_char(char ch);
+ static classinfo* get_arrayclass_by_name(utf* name);
+ static classinfo* get_arrayclass_by_type(int type);
+
+ static int get_type_by_wrapperclass(classinfo *c);
+
+ static java_handle_t* box(int type, imm_union value);
+
+ static java_handle_t* box(uint8_t value);
+ static java_handle_t* box(int8_t value);
+ static java_handle_t* box(uint16_t value);
+ static java_handle_t* box(int16_t value);
+ static java_handle_t* box(int32_t value);
+ static java_handle_t* box(int64_t value);
+ static java_handle_t* box(float value);
+ static java_handle_t* box(double value);
+
+ static imm_union unbox(java_handle_t *o);
+
+ static uint8_t unbox_boolean(java_handle_t* o);
+ static int8_t unbox_byte(java_handle_t* o);
+ static uint16_t unbox_char(java_handle_t* o);
+ static int16_t unbox_short(java_handle_t* o);
+ static int32_t unbox_int(java_handle_t* o);
+ static int64_t unbox_long(java_handle_t* o);
+ static float unbox_float(java_handle_t* o);
+ static double unbox_double(java_handle_t* o);
+};
+
+#endif
+
+/* primitive data types *******************************************************/
+
+/* These values are used in parsed descriptors and in some other
+ places were the different types handled internally as TYPE_INT have
+ to be distinguished. */
+
+#define PRIMITIVETYPE_COUNT 11 /* number of primitive types (+ dummies) */
+
+/* CAUTION: Don't change the numerical values! These constants are
+ used as indices into the primitive type table. */
+
+#define PRIMITIVETYPE_INT TYPE_INT
+#define PRIMITIVETYPE_LONG TYPE_LNG
+#define PRIMITIVETYPE_FLOAT TYPE_FLT
+#define PRIMITIVETYPE_DOUBLE TYPE_DBL
+#define PRIMITIVETYPE_DUMMY1 TYPE_ADR /* not used! */
+#define PRIMITIVETYPE_BYTE 5
+#define PRIMITIVETYPE_CHAR 6
+#define PRIMITIVETYPE_SHORT 7
+#define PRIMITIVETYPE_BOOLEAN 8
+#define PRIMITIVETYPE_DUMMY2 9 /* not used! */
+#define PRIMITIVETYPE_VOID TYPE_VOID
+
+
+/* primitivetypeinfo **********************************************************/
+
+struct primitivetypeinfo {
+ char *cname; /* char name of primitive class */
+ utf *name; /* name of primitive class */
+ classinfo *class_wrap; /* class for wrapping primitive type */
+ classinfo *class_primitive; /* primitive class */
+ char *wrapname; /* name of class for wrapping */
+ char typesig; /* one character type signature */
+ char *arrayname; /* name of primitive array class */
+ classinfo *arrayclass; /* primitive array class */
+};
+
+
+/* global variables ***********************************************************/
+
+/* This array can be indexed by the PRIMITIVETYPE_ and ARRAYTYPE_
+ constants (except ARRAYTYPE_OBJECT). */
+
+extern primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT];
+
+/* this function is in src/vm/primitivecore.c */
+void primitive_init(void);
+void primitive_postinit(void);
+
+#ifndef __cplusplus
+// Legacy C interface.
+classinfo *Primitive_get_class_by_name(utf *name);
+classinfo *Primitive_get_class_by_type(int type);
+classinfo *Primitive_get_class_by_char(char ch);
+
+classinfo *Primitive_get_arrayclass_by_name(utf *name);
+classinfo *Primitive_get_arrayclass_by_type(int type);
+
+int Primitive_get_type_by_wrapperclass(classinfo *c);
+
+java_handle_t *Primitive_box(int type, imm_union value);
+imm_union Primitive_unbox(java_handle_t *h);
+#endif
+
+#endif // _PRIMITIVE_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
+/* src/vm/primitivecore.c - core functions for primitive types
+
+ 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.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/* primitivetype_table *********************************************************
+
+ Structure for primitive classes: contains the class for wrapping
+ the primitive type, the primitive class, the name of the class for
+ wrapping, the one character type signature and the name of the
+ primitive class.
+
+ CAUTION: Don't change the order of the types. This table is indexed
+ by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
+
+*******************************************************************************/
+
+primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
+ { "int" , NULL, NULL, NULL, "java/lang/Integer", 'I', "[I", NULL },
+ { "long" , NULL, NULL, NULL, "java/lang/Long", 'J', "[J", NULL },
+ { "float" , NULL, NULL, NULL, "java/lang/Float", 'F', "[F", NULL },
+ { "double" , NULL, NULL, NULL, "java/lang/Double", 'D', "[D", NULL },
+ { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
+ { "byte" , NULL, NULL, NULL, "java/lang/Byte", 'B', "[B", NULL },
+ { "char" , NULL, NULL, NULL, "java/lang/Character", 'C', "[C", NULL },
+ { "short" , NULL, NULL, NULL, "java/lang/Short", 'S', "[S", NULL },
+ { "boolean" , NULL, NULL, NULL, "java/lang/Boolean", 'Z', "[Z", NULL },
+ { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
+#if defined(ENABLE_JAVASE)
+ { "void" , NULL, NULL, NULL, "java/lang/Void", 'V', NULL, NULL }
+#else
+ { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
+#endif
+};
+
+
+/* primitive_init **************************************************************
+
+ Fill the primitive type table with the primitive-type classes,
+ array-classes and wrapper classes. This is important in the VM
+ startup.
+
+ We split this primitive-type table initialization because of
+ annotations in the bootstrap classes.
+
+ But we may get a problem if we have annotations in:
+
+ java/lang/Object
+ java/lang/Cloneable
+ java/io/Serializable
+
+ Also see: loader_preinit and linker_preinit.
+
+*******************************************************************************/
+
+void primitive_init(void)
+{
+ utf *name;
+ classinfo *c;
+ utf *u;
+ classinfo *ac;
+ int i;
+
+ TRACESUBSYSTEMINITIALIZATION("primitive_init");
+
+ /* Load and link primitive-type classes and array-classes. */
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+ /* Skip dummy entries. */
+
+ if (primitivetype_table[i].cname == NULL)
+ continue;
+
+ /* create UTF-8 name */
+
+ name = utf_new_char(primitivetype_table[i].cname);
+
+ primitivetype_table[i].name = name;
+
+ /* create primitive class */
+
+ c = class_create_classinfo(name);
+
+ /* Primitive type classes don't have a super class. */
+
+ c->super = NULL;
+
+ /* set flags and mark it as primitive class */
+
+ c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT | ACC_CLASS_PRIMITIVE;
+
+ /* prevent loader from loading primitive class */
+
+ c->state |= CLASS_LOADED;
+
+ /* INFO: don't put primitive classes into the classcache */
+
+ if (!link_class(c))
+ vm_abort("linker_init: linking failed");
+
+ /* Just to be sure. */
+
+ assert(c->state & CLASS_LOADED);
+ assert(c->state & CLASS_LINKED);
+
+ primitivetype_table[i].class_primitive = c;
+
+ /* Create primitive array class. */
+
+ if (primitivetype_table[i].arrayname != NULL) {
+ u = utf_new_char(primitivetype_table[i].arrayname);
+ ac = class_create_classinfo(u);
+ ac = load_newly_created_array(ac, NULL);
+
+ if (ac == NULL)
+ vm_abort("primitive_init: loading failed");
+
+ assert(ac->state & CLASS_LOADED);
+
+ if (!link_class(ac))
+ vm_abort("primitive_init: linking failed");
+
+ /* Just to be sure. */
+
+ assert(ac->state & CLASS_LOADED);
+ assert(ac->state & CLASS_LINKED);
+
+ primitivetype_table[i].arrayclass = ac;
+ }
+ }
+
+ /* We use two for-loops to have the array-classes already in the
+ primitive-type table (hint: annotations in wrapper-classes). */
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+ /* Skip dummy entries. */
+
+ if (primitivetype_table[i].cname == NULL)
+ continue;
+
+ /* Create class for wrapping the primitive type. */
+
+ u = utf_new_char(primitivetype_table[i].wrapname);
+ c = load_class_bootstrap(u);
+
+ if (c == NULL)
+ vm_abort("primitive_init: loading failed");
+
+ if (!link_class(c))
+ vm_abort("primitive_init: linking failed");
+
+ /* Just to be sure. */
+
+ assert(c->state & CLASS_LOADED);
+ assert(c->state & CLASS_LINKED);
+
+ primitivetype_table[i].class_wrap = c;
+ }
+}
+
+
+/* primitive_postinit **********************************************************
+
+ Finish the primitive-type table initialization. In this step we
+ set the vftbl of the primitive-type classes.
+
+ This is necessary because java/lang/Class is loaded and linked
+ after the primitive types have been linked.
+
+ We have to do that in an extra function, as the primitive types are
+ not stored in the classcache.
+
+*******************************************************************************/
+
+void primitive_postinit(void)
+{
+ classinfo *c;
+ int i;
+
+ TRACESUBSYSTEMINITIALIZATION("primitive_postinit");
+
+ assert(class_java_lang_Class);
+ assert(class_java_lang_Class->vftbl);
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+ /* Skip dummy entries. */
+
+ if (primitivetype_table[i].cname == NULL)
+ continue;
+
+ c = primitivetype_table[i].class_primitive;
+
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+ }
+}
+
+
+/*
+ * 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 "config.h"
+#include <stdint.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/utsname.h>
-#include "vm/types.h"
-
#include "mm/memory.h"
#include "native/jni.h"
#include "native/llni.h"
-#include "vm/global.h" /* required by java_lang_String.h */
-#include "native/include/java_lang_String.h"
-
#include "toolbox/list.h"
#include "toolbox/util.h"
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/properties.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/system.h"
-
/* internal property structure ************************************************/
typedef struct list_properties_entry_t list_properties_entry_t;
struct list_properties_entry_t {
- char *key;
- char *value;
+ const char* key;
+ const char* value;
listnode_t linkage;
};
Now let's strip two levels. */
- p = system_dirname(p);
- p = system_dirname(p);
+ p = os_dirname(p);
+ p = os_dirname(p);
# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
/* Check if that libjvm.so exists. */
- if (system_access(java_home, F_OK) == 0) {
+ if (os_access(java_home, F_OK) == 0) {
/* Yes, we add /jre to java.home. */
strcpy(java_home, p);
*******************************************************************************/
-void properties_add(char *key, char *value)
+void properties_add(const char *key, const char *value)
{
list_properties_entry_t *pe;
*******************************************************************************/
-char *properties_get(char *key)
+const char *properties_get(const char *key)
{
list_properties_entry_t *pe;
*******************************************************************************/
-void properties_system_add(java_handle_t *p, char *key, char *value)
+void properties_system_add(java_handle_t *p, const char *key, const char *value)
{
classinfo *c;
methodinfo *m;
/* src/vm/properties.h - handling commandline properties
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <stdint.h>
#include "vm/global.h"
void properties_init(void);
void properties_set(void);
-void properties_add(char *key, char *value);
-char *properties_get(char *key);
+void properties_add(const char *key, const char *value);
+const char *properties_get(const char *key);
-void properties_system_add(java_handle_t *p, char *key, char *value);
+void properties_system_add(java_handle_t *p, const char *key, const char *value);
#if defined(ENABLE_JAVASE)
void properties_system_add_all(java_handle_t *p);
void properties_dump(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _PROPERTIES_H */
--- /dev/null
+/* 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, */
#include "config.h"
#include "vm/types.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
#include "vm/jit/jit.h"
#include "vm/jit/reg.h"
#include "vm/jit/verify/typeinfo.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-
/* constants ******************************************************************/
--- /dev/null
+/* src/vm/rt-timing.c - POSIX real-time timing utilities
+
+ 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 <errno.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "vm/global.h"
+#include "vm/rt-timing.h"
+
+
+struct rt_timing_stat {
+ int index;
+ int totalindex;
+ const char *name;
+};
+
+static struct rt_timing_stat rt_timing_stat_defs[] = {
+ { RT_TIMING_JIT_CHECKS ,RT_TIMING_JIT_TOTAL , "checks at beginning" },
+ { RT_TIMING_JIT_PARSE ,RT_TIMING_JIT_TOTAL , "parse" },
+ { RT_TIMING_JIT_STACK ,RT_TIMING_JIT_TOTAL , "analyse_stack" },
+ { RT_TIMING_JIT_TYPECHECK ,RT_TIMING_JIT_TOTAL , "typecheck" },
+ { RT_TIMING_JIT_LOOP ,RT_TIMING_JIT_TOTAL , "loop" },
+ { RT_TIMING_JIT_IFCONV ,RT_TIMING_JIT_TOTAL , "if conversion" },
+ { RT_TIMING_JIT_ALLOC ,RT_TIMING_JIT_TOTAL , "register allocation" },
+ { RT_TIMING_JIT_RPLPOINTS ,RT_TIMING_JIT_TOTAL , "replacement point generation" },
+ { RT_TIMING_JIT_CODEGEN ,RT_TIMING_JIT_TOTAL , "codegen" },
+ { RT_TIMING_JIT_TOTAL ,-1 , "total compile time" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LINK_RESOLVE ,RT_TIMING_LINK_TOTAL, "link: resolve superclass/superinterfaces"},
+ { RT_TIMING_LINK_C_VFTBL ,RT_TIMING_LINK_TOTAL, "link: compute vftbl length"},
+ { RT_TIMING_LINK_ABSTRACT ,RT_TIMING_LINK_TOTAL, "link: handle abstract methods"},
+ { RT_TIMING_LINK_C_IFTBL ,RT_TIMING_LINK_TOTAL, "link: compute interface table"},
+ { RT_TIMING_LINK_F_VFTBL ,RT_TIMING_LINK_TOTAL, "link: fill vftbl"},
+ { RT_TIMING_LINK_OFFSETS ,RT_TIMING_LINK_TOTAL, "link: set offsets"},
+ { RT_TIMING_LINK_F_IFTBL ,RT_TIMING_LINK_TOTAL, "link: fill interface table"},
+ { RT_TIMING_LINK_FINALIZER ,RT_TIMING_LINK_TOTAL, "link: set finalizer"},
+ { RT_TIMING_LINK_EXCEPTS ,RT_TIMING_LINK_TOTAL, "link: resolve exception classes"},
+ { RT_TIMING_LINK_SUBCLASS ,RT_TIMING_LINK_TOTAL, "link: re-calculate subclass indices"},
+ { RT_TIMING_LINK_TOTAL ,-1 , "total link time" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LOAD_CHECKS ,RT_TIMING_LOAD_TOTAL, "load: initial checks"},
+ { RT_TIMING_LOAD_NDPOOL ,RT_TIMING_LOAD_TOTAL, "load: new descriptor pool"},
+ { RT_TIMING_LOAD_CPOOL ,RT_TIMING_LOAD_TOTAL, "load: load constant pool"},
+ { RT_TIMING_LOAD_SETUP ,RT_TIMING_LOAD_TOTAL, "load: class setup"},
+ { RT_TIMING_LOAD_FIELDS ,RT_TIMING_LOAD_TOTAL, "load: load fields"},
+ { RT_TIMING_LOAD_METHODS ,RT_TIMING_LOAD_TOTAL, "load: load methods"},
+ { RT_TIMING_LOAD_CLASSREFS ,RT_TIMING_LOAD_TOTAL, "load: create classrefs"},
+ { RT_TIMING_LOAD_DESCS ,RT_TIMING_LOAD_TOTAL, "load: allocate descriptors"},
+ { RT_TIMING_LOAD_SETREFS ,RT_TIMING_LOAD_TOTAL, "load: set classrefs"},
+ { RT_TIMING_LOAD_PARSEFDS ,RT_TIMING_LOAD_TOTAL, "load: parse field descriptors"},
+ { RT_TIMING_LOAD_PARSEMDS ,RT_TIMING_LOAD_TOTAL, "load: parse method descriptors"},
+ { RT_TIMING_LOAD_PARSECP ,RT_TIMING_LOAD_TOTAL, "load: parse descriptors in constant pool"},
+ { RT_TIMING_LOAD_VERIFY ,RT_TIMING_LOAD_TOTAL, "load: verifier checks"},
+ { RT_TIMING_LOAD_ATTRS ,RT_TIMING_LOAD_TOTAL, "load: load attributes"},
+ { RT_TIMING_LOAD_TOTAL ,-1 , "total load time (from classbuffer)"},
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LOAD_BOOT_LOOKUP,-1 , "boot: lookup in classcache"},
+ { RT_TIMING_LOAD_BOOT_ARRAY ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load array classes"},
+ { RT_TIMING_LOAD_BOOT_SUCK ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: suck class files"},
+ { RT_TIMING_LOAD_BOOT_LOAD ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load from class buffer"},
+ { RT_TIMING_LOAD_BOOT_CACHE ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: store in classcache"},
+ { RT_TIMING_LOAD_BOOT_TOTAL ,-1 , "total bootstrap loader time"},
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LOAD_CL_LOOKUP ,-1 , "classloader: lookup in classcache" },
+ { RT_TIMING_LOAD_CL_PREPARE ,-1 , "classloader: prepare loader call" },
+ { RT_TIMING_LOAD_CL_JAVA ,-1 , "classloader: loader Java code" },
+ { RT_TIMING_LOAD_CL_CACHE ,-1 , "classloader: store in classcache" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_NEW_OBJECT ,-1 , "builtin_new time" },
+ { RT_TIMING_NEW_ARRAY ,-1 , "builtin_newarray time" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_GC_ALLOC ,-1 , "heap allocation time" },
+#if defined(ENABLE_GC_CACAO)
+ { RT_TIMING_GC_SUSPEND ,RT_TIMING_GC_TOTAL , "gc: suspending threads" },
+ { RT_TIMING_GC_ROOTSET1 ,RT_TIMING_GC_TOTAL , "gc: rootset finding" },
+ { RT_TIMING_GC_MARK ,RT_TIMING_GC_TOTAL , "gc: marking phase" },
+ { RT_TIMING_GC_COMPACT ,RT_TIMING_GC_TOTAL , "gc: compaction phase" },
+ { RT_TIMING_GC_ROOTSET2 ,RT_TIMING_GC_TOTAL , "gc: rootset writeback" },
+ { RT_TIMING_GC_TOTAL ,-1 , "total garbage collection time" },
+#endif
+ { -1 ,-1 , "" },
+
+#if defined(ENABLE_REPLACEMENT)
+ { RT_TIMING_REPLACE ,-1 , "replacement" },
+ { -1 ,-1 , "" },
+#endif
+
+ { RT_TIMING_1 ,-1 , "temporary timer 1" },
+ { RT_TIMING_2 ,-1 , "temporary timer 2" },
+ { RT_TIMING_3 ,-1 , "temporary timer 3" },
+ { RT_TIMING_4 ,-1 , "temporary timer 4" },
+ { -1 ,-1 , "" },
+
+ { 0 ,-1 , NULL }
+};
+
+static long long rt_timing_sum[RT_TIMING_N] = { 0 };
+
+void rt_timing_gettime(struct timespec *ts)
+{
+ if (clock_gettime(CLOCK_THREAD_CPUTIME_ID,ts) != 0) {
+ fprintf(stderr,"could not get time by clock_gettime: %s\n",strerror(errno));
+ abort();
+ }
+}
+
+long rt_timing_diff_usec(struct timespec *a,struct timespec *b)
+{
+ long diff;
+ time_t atime;
+
+ diff = (b->tv_nsec - a->tv_nsec) / 1000;
+ atime = a->tv_sec;
+ while (atime < b->tv_sec) {
+ atime++;
+ diff += 1000000;
+ }
+ return diff;
+}
+
+void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index)
+{
+ long diff;
+
+ diff = rt_timing_diff_usec(a,b);
+ rt_timing_sum[index] += diff;
+}
+
+void rt_timing_print_time_stats(FILE *file)
+{
+ struct rt_timing_stat *stats;
+ double total;
+
+ for (stats = rt_timing_stat_defs; stats->name; ++stats) {
+ if (stats->index < 0) {
+ fprintf(file,"%s\n",stats->name);
+ continue;
+ }
+
+ if (stats->totalindex >= 0) {
+ total = rt_timing_sum[stats->totalindex];
+ fprintf(file,"%12lld usec %3.0f%% %s\n",
+ rt_timing_sum[stats->index],
+ (total != 0.0) ? rt_timing_sum[stats->index] / total * 100.0 : 0.0,
+ stats->name);
+ }
+ else {
+ fprintf(file,"%12lld usec %s\n",
+ rt_timing_sum[stats->index],
+ stats->name);
+ }
+ }
+}
+
+/*
+ * 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/rt-timing.h - POSIX real-time timing utilities
+
+ 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 _RT_TIMING_H
+#define _RT_TIMING_H
+
+#include "config.h"
+
+#if defined(ENABLE_RT_TIMING)
+
+#include <time.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "vm/global.h"
+
+
+#define RT_TIMING_GET_TIME(ts) \
+ rt_timing_gettime(&(ts));
+
+#define RT_TIMING_TIME_DIFF(a,b,index) \
+ rt_timing_time_diff(&(a),&(b),(index));
+
+#define RT_TIMING_JIT_CHECKS 0
+#define RT_TIMING_JIT_PARSE 1
+#define RT_TIMING_JIT_STACK 2
+#define RT_TIMING_JIT_TYPECHECK 3
+#define RT_TIMING_JIT_LOOP 4
+#define RT_TIMING_JIT_IFCONV 5
+#define RT_TIMING_JIT_ALLOC 6
+#define RT_TIMING_JIT_RPLPOINTS 7
+#define RT_TIMING_JIT_CODEGEN 8
+#define RT_TIMING_JIT_TOTAL 9
+
+#define RT_TIMING_LINK_RESOLVE 10
+#define RT_TIMING_LINK_C_VFTBL 11
+#define RT_TIMING_LINK_ABSTRACT 12
+#define RT_TIMING_LINK_C_IFTBL 13
+#define RT_TIMING_LINK_F_VFTBL 14
+#define RT_TIMING_LINK_OFFSETS 15
+#define RT_TIMING_LINK_F_IFTBL 16
+#define RT_TIMING_LINK_FINALIZER 17
+#define RT_TIMING_LINK_EXCEPTS 18
+#define RT_TIMING_LINK_SUBCLASS 19
+#define RT_TIMING_LINK_TOTAL 20
+
+#define RT_TIMING_LOAD_CHECKS 21
+#define RT_TIMING_LOAD_NDPOOL 22
+#define RT_TIMING_LOAD_CPOOL 23
+#define RT_TIMING_LOAD_SETUP 24
+#define RT_TIMING_LOAD_FIELDS 25
+#define RT_TIMING_LOAD_METHODS 26
+#define RT_TIMING_LOAD_CLASSREFS 27
+#define RT_TIMING_LOAD_DESCS 28
+#define RT_TIMING_LOAD_SETREFS 29
+#define RT_TIMING_LOAD_PARSEFDS 30
+#define RT_TIMING_LOAD_PARSEMDS 31
+#define RT_TIMING_LOAD_PARSECP 32
+#define RT_TIMING_LOAD_VERIFY 33
+#define RT_TIMING_LOAD_ATTRS 34
+#define RT_TIMING_LOAD_TOTAL 35
+
+#define RT_TIMING_LOAD_BOOT_LOOKUP 36
+#define RT_TIMING_LOAD_BOOT_ARRAY 37
+#define RT_TIMING_LOAD_BOOT_SUCK 38
+#define RT_TIMING_LOAD_BOOT_LOAD 39
+#define RT_TIMING_LOAD_BOOT_CACHE 40
+#define RT_TIMING_LOAD_BOOT_TOTAL 41
+
+#define RT_TIMING_LOAD_CL_LOOKUP 42
+#define RT_TIMING_LOAD_CL_PREPARE 43
+#define RT_TIMING_LOAD_CL_JAVA 44
+#define RT_TIMING_LOAD_CL_CACHE 45
+
+#define RT_TIMING_NEW_OBJECT 46
+#define RT_TIMING_NEW_ARRAY 47
+
+#define RT_TIMING_GC_ALLOC 48
+#define RT_TIMING_GC_SUSPEND 49
+#define RT_TIMING_GC_ROOTSET1 50
+#define RT_TIMING_GC_MARK 51
+#define RT_TIMING_GC_COMPACT 52
+#define RT_TIMING_GC_ROOTSET2 53
+#define RT_TIMING_GC_TOTAL 54
+
+#define RT_TIMING_REPLACE 55
+
+#define RT_TIMING_1 56
+#define RT_TIMING_2 57
+#define RT_TIMING_3 58
+#define RT_TIMING_4 59
+
+#define RT_TIMING_N 60
+
+void rt_timing_gettime(struct timespec *ts);
+
+void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index);
+
+long rt_timing_diff_usec(struct timespec *a,struct timespec *b);
+
+void rt_timing_print_time_stats(FILE *file);
+
+#else /* !defined(ENABLE_RT_TIMING) */
+
+#define RT_TIMING_GET_TIME(ts)
+#define RT_TIMING_TIME_DIFF(a,b,index)
+
+#endif /* defined(ENABLE_RT_TIMING) */
+
+#endif /* _RT_TIMING_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 "arch.h"
-#include "threads/thread.h"
+#if defined(ENABLE_GC_BOEHM)
+# include "mm/memory.h"
+#endif
-#include "vm/exceptions.h"
-#include "vm/signallocal.h"
-#include "vm/vm.h"
+#include "threads/thread.hpp"
-#include "vmcore/options.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/signallocal.h"
+#include "vm/vm.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
#if defined(ENABLE_THREADS)
/* SIGHUP handler for threads_thread_interrupt */
- signal_register_signal(SIGHUP, (functionptr) signal_handler_sighup, 0);
+ signal_register_signal(Signal_INTERRUPT_SYSTEM_CALL, (functionptr) signal_handler_sighup, 0);
#endif
#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
threadobject *t;
sigset_t mask;
int sig;
+ int result;
t = THREADOBJECT;
thread_set_state_waiting(t);
#endif
- /* XXX We don't check for an error here, although the man-page
- states sigwait does not return an error (which is wrong!),
- but it seems to make problems with Boehm-GC. We should
- revisit this code with our new exact-GC. */
+ // sigwait can return EINTR (unlike what the Linux man-page
+ // says).
+ do {
+ result = sigwait(&mask, &sig);
+ } while (result == EINTR);
-/* if (sigwait(&mask, &sig) != 0) */
-/* vm_abort_errno("signal_thread: sigwait failed"); */
- (void) sigwait(&mask, &sig);
+ if (result != 0)
+ vm_abort_errnum(result, "signal_thread: sigwait failed");
#if defined(ENABLE_THREADS)
thread_set_state_runnable(t);
statistics_print_memory_usage();
#endif
break;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ default: {
+ // For OpenJDK we dispatch all unknown signals to Java.
+ methodinfo* m = class_resolvemethod(class_sun_misc_Signal, utf_dispatch, utf_int__void);
+ (void) vm_call_method(m, NULL, sig);
+
+ if (exceptions_get_exception()) {
+ log_println("signal_thread_handler: Java signal handler throw an exception while dispatching signal %d:", sig);
+ exceptions_print_stacktrace();
+ vm_abort("signal_thread_handler: Aborting...");
+ }
+ break;
+ }
+#else
+ default:
+ vm_abort("signal_thread_handler: Unknown signal %d", sig);
+#endif
}
}
/* src/vm/signallocal.h - machine independent signal functions
- Copyright (C) 1996-2005, 2006, 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) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#include <signal.h>
#include "vm/global.h"
+// Signal defines.
+
+#if defined(__LINUX__)
+// See openjdk/jdk/src/solaris/native/java/net/linux_close.c (sigWakeup)
+// See openjdk/jdk/src/solaris/native/sun/nio/ch/NativeThread.c (INTERRUPT_SIGNAL)
+# define Signal_INTERRUPT_SYSTEM_CALL (__SIGRTMAX - 2)
+#else
+# define Signal_INTERRUPT_SYSTEM_CALL SIGHUP
+#endif
+
+
/* function prototypes ********************************************************/
bool signal_init(void);
void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _CACAO_SIGNAL_H */
--- /dev/null
+/* src/vm/stackmap.c - class attribute StackMapTable
+
+ Copyright (C) 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 "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/stackmap.h"
+#include "vm/statistics.h"
+#include "vm/suck.h"
+
+
+/* stackmap_get_verification_type_info *****************************************
+
+ union verification_type_info {
+ Top_variable_info;
+ Integer_variable_info;
+ Float_variable_info;
+ Long_variable_info;
+ Double_variable_info;
+ Null_variable_info;
+ UninitializedThis_variable_info;
+ Object_variable_info;
+ Uninitialized_variable_info;
+ }
+
+ Top_variable_info {
+ u1 tag = ITEM_Top; // 0
+ }
+
+ Integer_variable_info {
+ u1 tag = ITEM_Integer; // 1
+ }
+
+ Float_variable_info {
+ u1 tag = ITEM_Float; // 2
+ }
+
+ Long_variable_info {
+ u1 tag = ITEM_Long; // 4
+ }
+
+ Double_variable_info {
+ u1 tag = ITEM_Double; // 3
+ }
+
+ Null_variable_info {
+ u1 tag = ITEM_Null; // 5
+ }
+
+ UninitializedThis_variable_info {
+ u1 tag = ITEM_UninitializedThis; // 6
+ }
+
+ Object_variable_info {
+ u1 tag = ITEM_Object; // 7
+ u2 cpool_index;
+ }
+
+ Uninitialized_variable_info {
+ u1 tag = ITEM_Uninitialized; // 8
+ u2 offset;
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
+{
+ /* get verification type */
+
+ if (!suck_check_classbuffer_size(cb, 1))
+ return false;
+
+ verification_type_info->tag = suck_u1(cb);
+
+ /* process the tag */
+
+ switch (verification_type_info->tag) {
+ case ITEM_Top:
+ case ITEM_Integer:
+ case ITEM_Float:
+ case ITEM_Long:
+ case ITEM_Double:
+ case ITEM_Null:
+ case ITEM_UninitializedThis:
+ break;
+
+ case ITEM_Object:
+ /* get constant pool index */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
+ break;
+
+ case ITEM_Uninitialized:
+ /* get offset */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
+ break;
+ }
+
+ return true;
+}
+
+
+/* stackmap_get_same_locals_1_stack_item_frame *********************************
+
+ same_locals_1_stack_item_frame {
+ u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
+ verification_type_info stack[1];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
+{
+ same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
+
+ /* for convenience */
+
+ same_locals_1_stack_item_frame =
+ &(stack_map_frame->same_locals_1_stack_item_frame);
+
+ if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_get_same_locals_1_stack_item_frame_extended ************************
+
+ same_locals_1_stack_item_frame_extended {
+ u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
+ u2 offset_delta;
+ verification_type_info stack[1];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
+{
+ same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
+
+ /* for convenience */
+
+ same_locals_1_stack_item_frame_extended =
+ &(stack_map_frame->same_locals_1_stack_item_frame_extended);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
+
+ /* process stack */
+
+ if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_get_chop_frame *****************************************************
+
+ chop_frame {
+ u1 frame_type = CHOP_FRAME; // 248-250
+ u2 offset_delta;
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_chop_frame(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ chop_frame_t *chop_frame;
+
+ /* for convenience */
+
+ chop_frame = &(stack_map_frame->chop_frame);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ chop_frame->offset_delta = suck_u2(cb);
+
+ return true;
+}
+
+
+/* stackmap_get_same_frame_extended ********************************************
+
+ same_frame_extended {
+ u1 frame_type = SAME_FRAME_EXTENDED; // 251
+ u2 offset_delta;
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_same_frame_extended(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ same_frame_extended_t *same_frame_extended;
+
+ /* for convenience */
+
+ same_frame_extended = &(stack_map_frame->same_frame_extended);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ same_frame_extended->offset_delta = suck_u2(cb);
+
+ return true;
+}
+
+
+/* stackmap_get_append_frame ***************************************************
+
+ append_frame {
+ u1 frame_type = APPEND_FRAME; // 252-254
+ u2 offset_delta;
+ verification_type_info locals[frame_Type - 251];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_append_frame(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ append_frame_t *append_frame;
+ s4 number_of_locals;
+ s4 i;
+
+ /* for convenience */
+
+ append_frame = &(stack_map_frame->append_frame);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ append_frame->offset_delta = suck_u2(cb);
+
+ /* allocate locals array */
+
+ number_of_locals = append_frame->frame_type - 251;
+
+ append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
+
+ /* process all locals */
+
+ for (i = 0; i < number_of_locals; i++)
+ if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_get_full_frame *****************************************************
+
+ full_frame {
+ u1 frame_type = FULL_FRAME;
+ u2 offset_delta;
+ u2 number_of_locals;
+ verification_type_info locals[number_of_locals];
+ u2 number_of_stack_items;
+ verification_type_info stack[number_of_stack_items];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_full_frame(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ full_frame_t *full_frame;
+ s4 i;
+
+ /* for convenience */
+
+ full_frame = &(stack_map_frame->full_frame);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* get offset delta */
+
+ stack_map_frame->full_frame.offset_delta = suck_u2(cb);
+
+ /* get number of locals */
+
+ full_frame->number_of_locals = suck_u2(cb);
+
+ /* allocate locals array */
+
+ full_frame->locals =
+ DMNEW(verification_type_info_t, full_frame->number_of_locals);
+
+ /* process all locals */
+
+ for (i = 0; i < full_frame->number_of_locals; i++)
+ if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
+ return false;
+
+ /* get number of stack items */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ full_frame->number_of_stack_items = suck_u2(cb);
+
+ /* allocate stack array */
+
+ full_frame->stack =
+ DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
+
+ /* process all stack items */
+
+ for (i = 0; i < full_frame->number_of_stack_items; i++)
+ if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_load_attribute_stackmaptable ***************************************
+
+ stack_map {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 number_of_entries;
+ stack_map_frame entries[number_of_entries];
+ }
+
+ union stack_map_frame {
+ same_frame;
+ same_locals_1_stack_item_frame;
+ same_locals_1_stack_item_frame_extended;
+ chop_frame;
+ same_frame_extended;
+ append_frame;
+ full_frame;
+ }
+
+ same_frame {
+ u1 frame_type = SAME; // 0-63
+ }
+
+*******************************************************************************/
+
+bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
+{
+ classinfo *c;
+ stack_map_t *stack_map;
+ s4 i;
+ u1 frame_type;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* allocate stack map structure */
+
+ stack_map = DNEW(stack_map_t);
+
+ STATISTICS(size_stack_map += sizeof(stack_map_t));
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* attribute_length */
+
+ stack_map->attribute_length = suck_u4(cb);
+
+ if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
+ return false;
+
+ /* get number of entries */
+
+ stack_map->number_of_entries = suck_u2(cb);
+
+ /* process all entries */
+
+ stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
+
+ for (i = 0; i < stack_map->number_of_entries; i++) {
+ /* get the frame type */
+
+ frame_type = suck_u1(cb);
+
+ stack_map->entries[i].frame_type = frame_type;
+
+ /* process frame */
+
+ if (frame_type <= FRAME_TYPE_SAME) {
+ /* same_frame */
+ }
+ else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
+ /* same_locals_1_stack_item_frame */
+
+ if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type <= FRAME_TYPE_RESERVED) {
+ /* reserved */
+
+ exceptions_throw_classformaterror(c, "reserved frame type");
+ return false;
+ }
+ else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
+ /* same_locals_1_stack_item_frame_extended */
+
+ if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type <= FRAME_TYPE_CHOP) {
+ /* chop_frame */
+
+ if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
+ /* same_frame_extended */
+
+ if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type <= FRAME_TYPE_APPEND) {
+ /* append_frame */
+
+ if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type == FRAME_TYPE_FULL_FRAME) {
+ /* full_frame */
+
+ if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ }
+
+ /* store stack map in method structure */
+
+#if 0
+ /* currently not used */
+
+ m->stack_map = stack_map;
+#endif
+
+ return true;
+}
+
+
+/*
+ * 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/stackmap.h - class attribute StackMapTable
+
+ Copyright (C) 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 _STACKMAP_H
+#define _STACKMAP_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct stack_map_t stack_map_t;
+typedef union stack_map_frame_t stack_map_frame_t;
+typedef struct same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame_t;
+typedef struct same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended_t;
+typedef struct chop_frame_t chop_frame_t;
+typedef struct same_frame_extended_t same_frame_extended_t;
+typedef struct append_frame_t append_frame_t;
+typedef struct full_frame_t full_frame_t;
+
+typedef union verification_type_info_t verification_type_info_t;
+typedef struct Top_variable_info_t Top_variable_info_t;
+typedef struct Integer_variable_info_t Integer_variable_info_t;
+typedef struct Float_variable_info_t Float_variable_info_t;
+typedef struct Long_variable_info_t Long_variable_info_t;
+typedef struct Double_variable_info_t Double_variable_info_t;
+typedef struct Null_variable_info_t Null_variable_info_t;
+typedef struct UninitializedThis_variable_info_t UninitializedThis_variable_info_t;
+typedef struct Object_variable_info_t Object_variable_info_t;
+typedef struct Uninitialized_variable_info_t Uninitialized_variable_info_t;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+
+
+/* verification_type_info *****************************************************/
+
+#define ITEM_Top 0
+#define ITEM_Integer 1
+#define ITEM_Float 2
+#define ITEM_Double 3
+#define ITEM_Long 4
+#define ITEM_Null 5
+#define ITEM_UninitializedThis 6
+#define ITEM_Object 7
+#define ITEM_Uninitialized 8
+
+struct Top_variable_info_t {
+ u1 tag;
+};
+
+struct Integer_variable_info_t {
+ u1 tag;
+};
+
+struct Float_variable_info_t {
+ u1 tag;
+};
+
+struct Long_variable_info_t {
+ u1 tag;
+};
+
+struct Double_variable_info_t {
+ u1 tag;
+};
+
+struct Null_variable_info_t {
+ u1 tag;
+};
+
+struct UninitializedThis_variable_info_t {
+ u1 tag;
+};
+
+struct Object_variable_info_t {
+ u1 tag;
+ u2 cpool_index;
+};
+
+struct Uninitialized_variable_info_t {
+ u1 tag;
+ u2 offset;
+};
+
+union verification_type_info_t {
+ u1 tag;
+ Top_variable_info_t Top_variable_info;
+ Integer_variable_info_t Integer_variable_info;
+ Float_variable_info_t Float_variable_info;
+ Long_variable_info_t Long_variable_info;
+ Double_variable_info_t Double_variable_info;
+ Null_variable_info_t Null_variable_info;
+ UninitializedThis_variable_info_t UninitializedThis_variable_info;
+ Object_variable_info_t Object_variable_info;
+ Uninitialized_variable_info_t Uninitialized_variable_info;
+};
+
+
+/* stack_map_t ****************************************************************/
+
+struct stack_map_t {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 number_of_entries;
+ stack_map_frame_t *entries;
+};
+
+
+/* same_locals_1_stack_item_frame_t *******************************************/
+
+struct same_locals_1_stack_item_frame_t {
+ u1 frame_type;
+ verification_type_info_t stack[1];
+};
+
+
+/* same_locals_1_stack_item_frame_extended_t **********************************/
+
+struct same_locals_1_stack_item_frame_extended_t {
+ u1 frame_type;
+ u2 offset_delta;
+ verification_type_info_t stack[1];
+};
+
+
+/* chop_frame_t ***************************************************************/
+
+struct chop_frame_t {
+ u1 frame_type;
+ u2 offset_delta;
+};
+
+
+/* same_frame_extended_t ******************************************************/
+
+struct same_frame_extended_t {
+ u1 frame_type;
+ u2 offset_delta;
+};
+
+
+/* append_frame_t *************************************************************/
+
+struct append_frame_t {
+ u1 frame_type;
+ u2 offset_delta;
+ verification_type_info_t *locals;
+};
+
+
+/* full_frame_t ***************************************************************/
+
+struct full_frame_t {
+ u1 frame_type;
+ u2 offset_delta;
+ u2 number_of_locals;
+ verification_type_info_t *locals;
+ u2 number_of_stack_items;
+ verification_type_info_t *stack;
+};
+
+
+/* stack_map_frame_t **********************************************************/
+
+#define FRAME_TYPE_SAME 63 /* 0-63 */
+#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM 127 /* 0-127 */
+#define FRAME_TYPE_RESERVED 246 /* 128-246 */
+#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED 247 /* 247 */
+#define FRAME_TYPE_CHOP 250 /* 248-250 */
+#define FRAME_TYPE_SAME_FRAME_EXTENDED 251 /* 251 */
+#define FRAME_TYPE_APPEND 254 /* 252-254 */
+#define FRAME_TYPE_FULL_FRAME 255 /* 255 */
+
+union stack_map_frame_t {
+ u1 frame_type;
+ same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame;
+ same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended;
+ chop_frame_t chop_frame;
+ same_frame_extended_t same_frame_extended;
+ append_frame_t append_frame;
+ full_frame_t full_frame;
+};
+
+
+/* function prototypes ********************************************************/
+
+bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m);
+
+#endif /* _STACKMAP_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:
+ */
--- /dev/null
+/* 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/string.c - java.lang.String 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 "vmcore/system.h"
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "native/include/java_lang_String.h"
-
-#include "threads/lock-common.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/primitive.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vmcore/utf8.h"
-
-
-/* global variables ***********************************************************/
-
-/* hashsize must be power of 2 */
-
-#define HASHTABLE_STRING_SIZE 2048 /* initial size of javastring-hash */
-
-hashtable hashtable_string; /* hashtable for javastrings */
-
-#if defined(ENABLE_THREADS)
-static java_object_t *lock_hashtable_string;
-#endif
-
-
-/* XXX preliminary typedef, will be removed once string.c and utf8.c are
- unified. */
-
-#if defined(ENABLE_HANDLES)
-typedef heap_java_lang_String heapstring_t;
-#else
-typedef java_lang_String heapstring_t;
-#endif
-
-
-/* string_init *****************************************************************
-
- Initialize the string hashtable lock.
-
-*******************************************************************************/
-
-bool string_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("string_init");
-
- /* create string (javastring) hashtable */
-
- hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
-
-#if defined(ENABLE_THREADS)
- /* create string hashtable lock object */
-
- lock_hashtable_string = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(lock_hashtable_string);
-#endif
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* stringtable_update **********************************************************
-
- Traverses the javastring hashtable and sets the vftbl-entries of
- javastrings which were temporarily set to NULL, because
- java.lang.Object was not yet loaded.
-
-*******************************************************************************/
-
-void stringtable_update(void)
-{
- heapstring_t *js;
- java_chararray_t *a;
- literalstring *s; /* hashtable entry */
- int i;
-
- for (i = 0; i < hashtable_string.size; i++) {
- s = hashtable_string.ptr[i];
- if (s) {
- while (s) {
- js = (heapstring_t *) s->string;
-
- if ((js == NULL) || (js->value == NULL)) {
- /* error in hashtable found */
-
- vm_abort("stringtable_update: invalid literalstring in hashtable");
- }
-
- a = js->value;
-
- if (!js->header.vftbl)
- /* vftbl of javastring is NULL */
- js->header.vftbl = class_java_lang_String->vftbl;
-
- if (!a->header.objheader.vftbl)
- /* vftbl of character-array is NULL */
- a->header.objheader.vftbl =
- primitive_arrayclass_get_by_type(ARRAYTYPE_CHAR)->vftbl;
-
- /* follow link in external hash chain */
- s = s->hashlink;
- }
- }
- }
-}
-
-
-/* javastring_new_from_utf_buffer **********************************************
-
- Create a new object of type java/lang/String with the text from
- the specified utf8 buffer.
-
- IN:
- buffer.......points to first char in the buffer
- blength......number of bytes to read from the buffer
-
- RETURN VALUE:
- the java.lang.String object, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-static java_handle_t *javastring_new_from_utf_buffer(const char *buffer,
- u4 blength)
-{
- const char *utf_ptr; /* current utf character in utf string */
- u4 utflength; /* length of utf-string if uncompressed */
- java_handle_t *o;
- java_lang_String *s; /* result-string */
- java_handle_chararray_t *a;
- u4 i;
-
- assert(buffer);
-
- utflength = utf_get_number_of_u2s_for_buffer(buffer,blength);
-
- o = builtin_new(class_java_lang_String);
- a = builtin_newarray_char(utflength);
-
- /* javastring or character-array could not be created */
-
- if ((o == NULL) || (a == NULL))
- return NULL;
-
- /* decompress utf-string */
-
- utf_ptr = buffer;
-
- for (i = 0; i < utflength; i++)
- LLNI_array_direct(a, i) = utf_nextu2((char **) &utf_ptr);
-
- /* set fields of the javastring-object */
-
- s = (java_lang_String *) o;
-
- LLNI_field_set_ref(s, value , a);
- LLNI_field_set_val(s, offset, 0);
- LLNI_field_set_val(s, count , utflength);
-
- return o;
-}
-
-
-/* javastring_safe_new_from_utf8 ***********************************************
-
- Create a new object of type java/lang/String with the text from
- the specified UTF-8 string. This function is safe for invalid UTF-8.
- (Invalid characters will be replaced by U+fffd.)
-
- IN:
- text.........the UTF-8 string, zero-terminated.
-
- RETURN VALUE:
- the java.lang.String object, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-java_handle_t *javastring_safe_new_from_utf8(const char *text)
-{
- java_handle_t *o;
- java_handle_chararray_t *a;
- java_lang_String *s;
- s4 nbytes;
- s4 len;
-
- if (text == NULL)
- return NULL;
-
- /* Get number of bytes. We need this to completely emulate the messy */
- /* behaviour of the RI. :( */
-
- nbytes = strlen(text);
-
- /* calculate number of Java characters */
-
- len = utf8_safe_number_of_u2s(text, nbytes);
-
- /* allocate the String object and the char array */
-
- o = builtin_new(class_java_lang_String);
- a = builtin_newarray_char(len);
-
- /* javastring or character-array could not be created? */
-
- if ((o == NULL) || (a == NULL))
- return NULL;
-
- /* decompress UTF-8 string */
-
- utf8_safe_convert_to_u2s(text, nbytes, LLNI_array_data(a));
-
- /* set fields of the String object */
-
- s = (java_lang_String *) o;
-
- LLNI_field_set_ref(s, value , a);
- LLNI_field_set_val(s, offset, 0);
- LLNI_field_set_val(s, count , len);
-
- return o;
-}
-
-
-/* javastring_new_from_utf_string **********************************************
-
- Create a new object of type java/lang/String with the text from
- the specified zero-terminated utf8 string.
-
- IN:
- buffer.......points to first char in the buffer
- blength......number of bytes to read from the buffer
-
- RETURN VALUE:
- the java.lang.String object, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-java_handle_t *javastring_new_from_utf_string(const char *utfstr)
-{
- assert(utfstr);
-
- return javastring_new_from_utf_buffer(utfstr, strlen(utfstr));
-}
-
-
-/* javastring_new **************************************************************
-
- creates a new object of type java/lang/String with the text of
- the specified utf8-string
-
- return: pointer to the string or NULL if memory is exhausted.
-
-*******************************************************************************/
-
-java_handle_t *javastring_new(utf *u)
-{
- char *utf_ptr; /* current utf character in utf string */
- u4 utflength; /* length of utf-string if uncompressed */
- java_handle_t *o;
- java_handle_chararray_t *a;
- java_lang_String *s;
- s4 i;
-
- if (u == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- utf_ptr = u->text;
- utflength = utf_get_number_of_u2s(u);
-
- o = builtin_new(class_java_lang_String);
- a = builtin_newarray_char(utflength);
-
- /* javastring or character-array could not be created */
-
- if ((o == NULL) || (a == NULL))
- return NULL;
-
- /* decompress utf-string */
-
- for (i = 0; i < utflength; i++)
- LLNI_array_direct(a, i) = utf_nextu2(&utf_ptr);
-
- /* set fields of the javastring-object */
-
- s = (java_lang_String *) o;
-
- LLNI_field_set_ref(s, value , a);
- LLNI_field_set_val(s, offset, 0);
- LLNI_field_set_val(s, count , utflength);
-
- return o;
-}
-
-
-/* javastring_new_slash_to_dot *************************************************
-
- creates a new object of type java/lang/String with the text of
- the specified utf8-string with slashes changed to dots
-
- return: pointer to the string or NULL if memory is exhausted.
-
-*******************************************************************************/
-
-java_handle_t *javastring_new_slash_to_dot(utf *u)
-{
- char *utf_ptr; /* current utf character in utf string */
- u4 utflength; /* length of utf-string if uncompressed */
- java_handle_t *o;
- java_handle_chararray_t *a;
- java_lang_String *s;
- s4 i;
- u2 ch;
-
- if (u == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- utf_ptr = u->text;
- utflength = utf_get_number_of_u2s(u);
-
- o = builtin_new(class_java_lang_String);
- a = builtin_newarray_char(utflength);
-
- /* javastring or character-array could not be created */
- if ((o == NULL) || (a == NULL))
- return NULL;
-
- /* decompress utf-string */
-
- for (i = 0; i < utflength; i++) {
- ch = utf_nextu2(&utf_ptr);
- if (ch == '/')
- ch = '.';
- LLNI_array_direct(a, i) = ch;
- }
-
- /* set fields of the javastring-object */
-
- s = (java_lang_String *) o;
-
- LLNI_field_set_ref(s, value , a);
- LLNI_field_set_val(s, offset, 0);
- LLNI_field_set_val(s, count , utflength);
-
- return o;
-}
-
-
-/* javastring_new_from_ascii ***************************************************
-
- creates a new java/lang/String object which contains the given ASCII
- C-string converted to UTF-16.
-
- IN:
- text.........string of ASCII characters
-
- RETURN VALUE:
- the java.lang.String object, or
- NULL if an exception has been thrown.
-
-*******************************************************************************/
-
-java_handle_t *javastring_new_from_ascii(const char *text)
-{
- s4 i;
- s4 len; /* length of the string */
- java_handle_t *o;
- java_lang_String *s;
- java_handle_chararray_t *a;
-
- if (text == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- len = strlen(text);
-
- o = builtin_new(class_java_lang_String);
- a = builtin_newarray_char(len);
-
- /* javastring or character-array could not be created */
-
- if ((o == NULL) || (a == NULL))
- return NULL;
-
- /* copy text */
-
- for (i = 0; i < len; i++)
- LLNI_array_direct(a, i) = text[i];
-
- /* set fields of the javastring-object */
-
- s = (java_lang_String *) o;
-
- LLNI_field_set_ref(s, value , a);
- LLNI_field_set_val(s, offset, 0);
- LLNI_field_set_val(s, count , len);
-
- return o;
-}
-
-
-/* javastring_tochar ***********************************************************
-
- converts a Java string into a C string.
-
- return: pointer to C string
-
- Caution: calling method MUST release the allocated memory!
-
-*******************************************************************************/
-
-char *javastring_tochar(java_handle_t *so)
-{
- java_lang_String *s = (java_lang_String *) so;
- java_handle_chararray_t *a;
- int32_t count;
- int32_t offset;
- char *buf;
- s4 i;
-
- if (!s)
- return "";
-
- LLNI_field_get_ref(s, value, a);
-
- if (!a)
- return "";
-
- LLNI_field_get_val(s, count, count);
- LLNI_field_get_val(s, offset, offset);
-
- buf = MNEW(char, count + 1);
-
- for (i = 0; i < count; i++)
- buf[i] = LLNI_array_direct(a, offset + i);
-
- buf[i] = '\0';
-
- return buf;
-}
-
-
-/* javastring_toutf ************************************************************
-
- Make utf symbol from javastring.
-
-*******************************************************************************/
-
-utf *javastring_toutf(java_handle_t *string, bool isclassname)
-{
- java_lang_String *s;
- java_handle_chararray_t *value;
- int32_t count;
- int32_t offset;
-
- s = (java_lang_String *) string;
-
- if (s == NULL)
- return utf_null;
-
- LLNI_field_get_ref(s, value, value);
-
- if (value == NULL)
- return utf_null;
-
- LLNI_field_get_val(s, count, count);
- LLNI_field_get_val(s, offset, offset);
-
- return utf_new_u2(LLNI_array_data(value) + offset, count, isclassname);
-}
-
-
-/* literalstring_u2 ************************************************************
-
- Searches for the literalstring with the specified u2-array in the
- string hashtable, if there is no such string a new one is created.
-
- If copymode is true a copy of the u2-array is made.
-
-*******************************************************************************/
-
-static java_object_t *literalstring_u2(java_chararray_t *a, u4 length,
- u4 offset, bool copymode)
-{
- literalstring *s; /* hashtable element */
- heapstring_t *js; /* u2-array wrapped in javastring */
- java_chararray_t *ca; /* copy of u2-array */
- u4 key;
- u4 slot;
- u2 i;
-
- LOCK_MONITOR_ENTER(lock_hashtable_string);
-
- /* find location in hashtable */
-
- key = unicode_hashkey(a->data + offset, length);
- slot = key & (hashtable_string.size - 1);
- s = hashtable_string.ptr[slot];
-
- while (s) {
- js = (heapstring_t *) s->string;
-
- if (length == js->count) {
- /* compare text */
-
- for (i = 0; i < length; i++)
- if (a->data[offset + i] != js->value->data[i])
- goto nomatch;
-
- /* string already in hashtable, free memory */
-
- if (!copymode)
- mem_free(a, sizeof(java_chararray_t) + sizeof(u2) * (length - 1) + 10);
-
- LOCK_MONITOR_EXIT(lock_hashtable_string);
-
- return (java_object_t *) js;
- }
-
- nomatch:
- /* follow link in external hash chain */
- s = s->hashlink;
- }
-
- if (copymode) {
- /* create copy of u2-array for new javastring */
- u4 arraysize = sizeof(java_chararray_t) + sizeof(u2) * (length - 1) + 10;
- ca = mem_alloc(arraysize);
-/* memcpy(ca, a, arraysize); */
- memcpy(&(ca->header), &(a->header), sizeof(java_array_t));
- memcpy(&(ca->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
-
- } else {
- ca = a;
- }
-
- /* location in hashtable found, complete arrayheader */
-
- ca->header.objheader.vftbl =
- primitive_arrayclass_get_by_type(ARRAYTYPE_CHAR)->vftbl;
- ca->header.size = length;
-
- assert(class_java_lang_String);
- assert(class_java_lang_String->state & CLASS_LOADED);
-
- /* create new javastring */
-
- js = NEW(heapstring_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_string += sizeof(heapstring_t);
-#endif
-
-#if defined(ENABLE_THREADS)
- lock_init_object_lock(&js->header);
-#endif
-
- js->header.vftbl = class_java_lang_String->vftbl;
- js->value = ca;
- js->offset = 0;
- js->count = length;
-
- /* create new literalstring */
-
- s = NEW(literalstring);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_string += sizeof(literalstring);
-#endif
-
- s->hashlink = hashtable_string.ptr[slot];
- s->string = (java_object_t *) js;
- hashtable_string.ptr[slot] = s;
-
- /* update number of hashtable entries */
-
- hashtable_string.entries++;
-
- /* reorganization of hashtable */
-
- if (hashtable_string.entries > (hashtable_string.size * 2)) {
- /* reorganization of hashtable, average length of the external
- chains is approx. 2 */
-
- u4 i;
- literalstring *s;
- literalstring *nexts;
- heapstring_t *tmpjs;
- hashtable newhash; /* the new hashtable */
-
- /* create new hashtable, double the size */
-
- hashtable_create(&newhash, hashtable_string.size * 2);
- newhash.entries = hashtable_string.entries;
-
- /* transfer elements to new hashtable */
-
- for (i = 0; i < hashtable_string.size; i++) {
- s = hashtable_string.ptr[i];
-
- while (s) {
- nexts = s->hashlink;
- tmpjs = (heapstring_t *) s->string;
- slot = unicode_hashkey(tmpjs->value->data, tmpjs->count) & (newhash.size - 1);
-
- s->hashlink = newhash.ptr[slot];
- newhash.ptr[slot] = s;
-
- /* follow link in external hash chain */
- s = nexts;
- }
- }
-
- /* dispose old table */
-
- MFREE(hashtable_string.ptr, void*, hashtable_string.size);
- hashtable_string = newhash;
- }
-
- LOCK_MONITOR_EXIT(lock_hashtable_string);
-
- return (java_object_t *) js;
-}
-
-
-/* literalstring_new ***********************************************************
-
- Creates a new literalstring with the text of the utf-symbol and inserts
- it into the string hashtable.
-
-*******************************************************************************/
-
-java_object_t *literalstring_new(utf *u)
-{
- char *utf_ptr; /* pointer to current unicode character */
- /* utf string */
- u4 utflength; /* length of utf-string if uncompressed */
- java_chararray_t *a; /* u2-array constructed from utf string */
- u4 i;
-
- utf_ptr = u->text;
- utflength = utf_get_number_of_u2s(u);
-
- /* allocate memory */
- a = mem_alloc(sizeof(java_chararray_t) + sizeof(u2) * (utflength - 1) + 10);
-
- /* convert utf-string to u2-array */
- for (i = 0; i < utflength; i++)
- a->data[i] = utf_nextu2(&utf_ptr);
-
- return literalstring_u2(a, utflength, 0, false);
-}
-
-
-/* literalstring_free **********************************************************
-
- Removes a literalstring from memory.
-
-*******************************************************************************/
-
-#if 0
-/* TWISTI This one is currently not used. */
-
-static void literalstring_free(java_object_t* string)
-{
- heapstring_t *s;
- java_chararray_t *a;
-
- s = (heapstring_t *) string;
- a = s->value;
-
- /* dispose memory of java.lang.String object */
- FREE(s, heapstring_t);
-
- /* dispose memory of java-characterarray */
- FREE(a, sizeof(java_chararray_t) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
-}
-#endif
-
-
-/* javastring_intern ***********************************************************
-
- Intern the given Java string.
-
- XXX NOTE: Literal Strings are direct references since they are not placed
- onto the GC-Heap. That's why this function looks so "different".
-
-*******************************************************************************/
-
-java_handle_t *javastring_intern(java_handle_t *s)
-{
- java_lang_String *so;
- java_chararray_t *value;
- int32_t count;
- int32_t offset;
-/* java_lang_String *o; */
- java_object_t *o; /* XXX see note above */
-
- so = (java_lang_String *) s;
-
- value = LLNI_field_direct(so, value); /* XXX see note above */
- LLNI_field_get_val(so, count, count);
- LLNI_field_get_val(so, offset, offset);
-
- o = literalstring_u2(value, count, offset, true);
-
- return LLNI_WRAP(o); /* XXX see note above */
-}
-
-
-/* javastring_fprint ***********************************************************
-
- Print the given Java string to the given stream.
-
-*******************************************************************************/
-
-void javastring_fprint(java_handle_t *s, FILE *stream)
-{
- java_lang_String *so;
- java_handle_chararray_t *value;
- int32_t count;
- int32_t offset;
- uint16_t c;
- int i;
-
- so = (java_lang_String *) s;
-
- LLNI_field_get_ref(so, value, value);
- LLNI_field_get_val(so, count, count);
- LLNI_field_get_val(so, offset, offset);
-
- for (i = offset; i < offset + count; i++) {
- c = LLNI_array_direct(value, i);
- fputc(c, stream);
- }
-}
-
-
-/*
- * 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/string.cpp - java.lang.String 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 "vm/os.hpp"
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+
+#include "threads/lock-common.h"
+
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/statistics.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/* global variables ***********************************************************/
+
+/* hashsize must be power of 2 */
+
+#define HASHTABLE_STRING_SIZE 2048 /* initial size of javastring-hash */
+
+static hashtable hashtable_string; /* hashtable for javastrings */
+static Mutex* mutex;
+
+
+/* string_init *****************************************************************
+
+ Initialize the string hashtable lock.
+
+*******************************************************************************/
+
+bool string_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("string_init");
+
+ /* create string (javastring) hashtable */
+
+ hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
+
+ mutex = new Mutex();
+
+ /* everything's ok */
+
+ return true;
+}
+
+
+/* stringtable_update **********************************************************
+
+ Traverses the javastring hashtable and sets the vftbl-entries of
+ javastrings which were temporarily set to NULL, because
+ java.lang.Object was not yet loaded.
+
+*******************************************************************************/
+
+void stringtable_update(void)
+{
+ java_chararray_t *a;
+ literalstring *s; /* hashtable entry */
+
+ for (unsigned int i = 0; i < hashtable_string.size; i++) {
+ s = (literalstring*) hashtable_string.ptr[i];
+
+ if (s) {
+ while (s) {
+ // FIXME
+ java_lang_String js(LLNI_WRAP(s->string));
+
+ if (js.is_null() || (js.get_value() == NULL)) {
+ /* error in hashtable found */
+
+ vm_abort("stringtable_update: invalid literalstring in hashtable");
+ }
+
+ a = LLNI_UNWRAP(js.get_value());
+
+ if (js.get_vftbl() == NULL)
+ // FIXME
+ LLNI_UNWRAP(js.get_handle())->vftbl = class_java_lang_String->vftbl;
+
+ if (a->header.objheader.vftbl == NULL)
+ a->header.objheader.vftbl = Primitive::get_arrayclass_by_type(ARRAYTYPE_CHAR)->vftbl;
+
+ /* follow link in external hash chain */
+ s = s->hashlink;
+ }
+ }
+ }
+}
+
+
+/* javastring_new_from_utf_buffer **********************************************
+
+ Create a new object of type java/lang/String with the text from
+ the specified utf8 buffer.
+
+ IN:
+ buffer.......points to first char in the buffer
+ blength......number of bytes to read from the buffer
+
+ RETURN VALUE:
+ the java.lang.String object, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+static java_handle_t *javastring_new_from_utf_buffer(const char *buffer, u4 blength)
+{
+ const char *utf_ptr; /* current utf character in utf string */
+
+ assert(buffer);
+
+ int32_t utflength = utf_get_number_of_u2s_for_buffer(buffer, blength);
+
+ java_handle_t* h = builtin_new(class_java_lang_String);
+ java_handle_chararray_t* ca = builtin_newarray_char(utflength);
+
+ /* javastring or character-array could not be created */
+
+ if ((h == NULL) || (ca == NULL))
+ return NULL;
+
+ /* decompress utf-string */
+
+ utf_ptr = buffer;
+
+ for (int32_t i = 0; i < utflength; i++)
+ LLNI_array_direct(ca, i) = utf_nextu2((char **) &utf_ptr);
+
+ /* set fields of the javastring-object */
+
+ java_lang_String jls(h, ca, utflength);
+
+ return jls.get_handle();
+}
+
+
+/* javastring_safe_new_from_utf8 ***********************************************
+
+ Create a new object of type java/lang/String with the text from
+ the specified UTF-8 string. This function is safe for invalid UTF-8.
+ (Invalid characters will be replaced by U+fffd.)
+
+ IN:
+ text.........the UTF-8 string, zero-terminated.
+
+ RETURN VALUE:
+ the java.lang.String object, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+java_handle_t *javastring_safe_new_from_utf8(const char *text)
+{
+ if (text == NULL)
+ return NULL;
+
+ /* Get number of bytes. We need this to completely emulate the messy */
+ /* behaviour of the RI. :( */
+
+ int32_t nbytes = strlen(text);
+
+ /* calculate number of Java characters */
+
+ int32_t len = utf8_safe_number_of_u2s(text, nbytes);
+
+ /* allocate the String object and the char array */
+
+ java_handle_t* h = builtin_new(class_java_lang_String);
+ java_handle_chararray_t* ca = builtin_newarray_char(len);
+
+ /* javastring or character-array could not be created? */
+
+ if ((h == NULL) || (ca == NULL))
+ return NULL;
+
+ /* decompress UTF-8 string */
+
+ utf8_safe_convert_to_u2s(text, nbytes, LLNI_array_data(ca));
+
+ /* set fields of the String object */
+
+ java_lang_String jls(h, ca, len);
+
+ return jls.get_handle();
+}
+
+
+/* javastring_new_from_utf_string **********************************************
+
+ Create a new object of type java/lang/String with the text from
+ the specified zero-terminated utf8 string.
+
+ IN:
+ buffer.......points to first char in the buffer
+ blength......number of bytes to read from the buffer
+
+ RETURN VALUE:
+ the java.lang.String object, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+java_handle_t *javastring_new_from_utf_string(const char *utfstr)
+{
+ assert(utfstr);
+
+ return javastring_new_from_utf_buffer(utfstr, strlen(utfstr));
+}
+
+
+/* javastring_new **************************************************************
+
+ creates a new object of type java/lang/String with the text of
+ the specified utf8-string
+
+ return: pointer to the string or NULL if memory is exhausted.
+
+*******************************************************************************/
+
+java_handle_t *javastring_new(utf *u)
+{
+ if (u == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ char* utf_ptr = u->text;
+ int32_t utflength = utf_get_number_of_u2s(u);
+
+ java_handle_t* h = builtin_new(class_java_lang_String);
+ java_handle_chararray_t* ca = builtin_newarray_char(utflength);
+
+ /* javastring or character-array could not be created */
+
+ if ((h == NULL) || (ca == NULL))
+ return NULL;
+
+ /* decompress utf-string */
+
+ for (int32_t i = 0; i < utflength; i++)
+ LLNI_array_direct(ca, i) = utf_nextu2(&utf_ptr);
+
+ /* set fields of the javastring-object */
+
+ java_lang_String jls(h, ca, utflength);
+
+ return jls.get_handle();
+}
+
+
+/* javastring_new_slash_to_dot *************************************************
+
+ creates a new object of type java/lang/String with the text of
+ the specified utf8-string with slashes changed to dots
+
+ return: pointer to the string or NULL if memory is exhausted.
+
+*******************************************************************************/
+
+java_handle_t *javastring_new_slash_to_dot(utf *u)
+{
+ if (u == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ char* utf_ptr = u->text;
+ int32_t utflength = utf_get_number_of_u2s(u);
+
+ java_handle_t* h = builtin_new(class_java_lang_String);
+ java_handle_chararray_t* ca = builtin_newarray_char(utflength);
+
+ /* javastring or character-array could not be created */
+ if ((h == NULL) || (ca == NULL))
+ return NULL;
+
+ /* decompress utf-string */
+
+ for (int32_t i = 0; i < utflength; i++) {
+ uint16_t ch = utf_nextu2(&utf_ptr);
+
+ if (ch == '/')
+ ch = '.';
+
+ LLNI_array_direct(ca, i) = ch;
+ }
+
+ /* set fields of the javastring-object */
+
+ java_lang_String jls(h, ca, utflength);
+
+ return jls.get_handle();
+}
+
+
+/* javastring_new_from_ascii ***************************************************
+
+ creates a new java/lang/String object which contains the given ASCII
+ C-string converted to UTF-16.
+
+ IN:
+ text.........string of ASCII characters
+
+ RETURN VALUE:
+ the java.lang.String object, or
+ NULL if an exception has been thrown.
+
+*******************************************************************************/
+
+java_handle_t *javastring_new_from_ascii(const char *text)
+{
+ if (text == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ int32_t len = strlen(text);
+
+ java_handle_t* h = builtin_new(class_java_lang_String);
+ java_handle_chararray_t* ca = builtin_newarray_char(len);
+
+ /* javastring or character-array could not be created */
+
+ if ((h == NULL) || (ca == NULL))
+ return NULL;
+
+ /* copy text */
+
+ for (int32_t i = 0; i < len; i++)
+ LLNI_array_direct(ca, i) = text[i];
+
+ /* set fields of the javastring-object */
+
+ java_lang_String jls(h, ca, len);
+
+ return jls.get_handle();
+}
+
+
+/* javastring_tochar ***********************************************************
+
+ converts a Java string into a C string.
+
+ return: pointer to C string
+
+ Caution: calling method MUST release the allocated memory!
+
+*******************************************************************************/
+
+char* javastring_tochar(java_handle_t* h)
+{
+ java_lang_String jls(h);
+
+ if (jls.is_null())
+ return (char*) "";
+
+ java_handle_chararray_t* ca = jls.get_value();
+
+ if (ca == NULL)
+ return (char*) "";
+
+ int32_t count = jls.get_count();
+ int32_t offset = jls.get_offset();
+
+ char* buf = MNEW(char, count + 1);
+
+ int32_t i;
+ for (i = 0; i < count; i++)
+ buf[i] = LLNI_array_direct(ca, offset + i);
+
+ buf[i] = '\0';
+
+ return buf;
+}
+
+
+/* javastring_toutf ************************************************************
+
+ Make utf symbol from javastring.
+
+*******************************************************************************/
+
+utf *javastring_toutf(java_handle_t *string, bool isclassname)
+{
+ java_lang_String jls(string);
+
+ if (jls.is_null())
+ return utf_null;
+
+ java_handle_chararray_t* value = jls.get_value();
+
+ if (jls.get_value() == NULL)
+ return utf_null;
+
+ int32_t count = jls.get_count();
+ int32_t offset = jls.get_offset();
+
+ return utf_new_u2(LLNI_array_data(value) + offset, count, isclassname);
+}
+
+
+/* literalstring_u2 ************************************************************
+
+ Searches for the literalstring with the specified u2-array in the
+ string hashtable, if there is no such string a new one is created.
+
+ If copymode is true a copy of the u2-array is made.
+
+*******************************************************************************/
+
+static java_object_t *literalstring_u2(java_chararray_t *a, int32_t length,
+ u4 offset, bool copymode)
+{
+ literalstring *s; /* hashtable element */
+ java_chararray_t *ca; /* copy of u2-array */
+ u4 key;
+ u4 slot;
+ u2 i;
+
+ mutex->lock();
+
+ /* find location in hashtable */
+
+ key = unicode_hashkey(a->data + offset, length);
+ slot = key & (hashtable_string.size - 1);
+ s = (literalstring*) hashtable_string.ptr[slot];
+
+ while (s) {
+ // FIXME
+ java_lang_String js(LLNI_WRAP(s->string));
+
+ if (length == js.get_count()) {
+ /* compare text */
+
+ for (i = 0; i < length; i++)
+ // FIXME This is not handle capable!
+
+ if (a->data[offset + i] != ((java_chararray_t*) LLNI_UNWRAP(js.get_value()))->data[i])
+ goto nomatch;
+
+ /* string already in hashtable, free memory */
+
+ if (!copymode)
+ mem_free(a, sizeof(java_chararray_t) + sizeof(u2) * (length - 1) + 10);
+
+ mutex->unlock();
+
+ return (java_object_t*) LLNI_UNWRAP(js.get_handle());
+ }
+
+ nomatch:
+ /* follow link in external hash chain */
+ s = s->hashlink;
+ }
+
+ if (copymode) {
+ /* create copy of u2-array for new javastring */
+ u4 arraysize = sizeof(java_chararray_t) + sizeof(u2) * (length - 1) + 10;
+ ca = (java_chararray_t*) mem_alloc(arraysize);
+/* memcpy(ca, a, arraysize); */
+ memcpy(&(ca->header), &(a->header), sizeof(java_array_t));
+ memcpy(&(ca->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
+ }
+ else {
+ ca = a;
+ }
+
+ /* location in hashtable found, complete arrayheader */
+
+ ca->header.objheader.vftbl = Primitive::get_arrayclass_by_type(ARRAYTYPE_CHAR)->vftbl;
+ ca->header.size = length;
+
+ assert(class_java_lang_String);
+ assert(class_java_lang_String->state & CLASS_LOADED);
+
+ // Create a new java.lang.String object on the system heap.
+ java_object_t* o = (java_object_t*) MNEW(uint8_t, class_java_lang_String->instancesize);
+ // FIXME
+ java_handle_t* h = LLNI_WRAP(o);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_string += sizeof(class_java_lang_String->instancesize);
+#endif
+
+#if defined(ENABLE_THREADS)
+ lock_init_object_lock(o);
+#endif
+
+ o->vftbl = class_java_lang_String->vftbl;
+
+ // FIXME
+ java_lang_String jls(h, LLNI_WRAP(ca), length);
+
+ /* create new literalstring */
+
+ s = NEW(literalstring);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_string += sizeof(literalstring);
+#endif
+
+ s->hashlink = (literalstring*) hashtable_string.ptr[slot];
+ s->string = (java_object_t*) LLNI_UNWRAP(jls.get_handle());
+ hashtable_string.ptr[slot] = s;
+
+ /* update number of hashtable entries */
+
+ hashtable_string.entries++;
+
+ /* reorganization of hashtable */
+
+ if (hashtable_string.entries > (hashtable_string.size * 2)) {
+ /* reorganization of hashtable, average length of the external
+ chains is approx. 2 */
+
+ u4 i;
+ literalstring *s;
+ literalstring *nexts;
+ hashtable newhash; /* the new hashtable */
+
+ /* create new hashtable, double the size */
+
+ hashtable_create(&newhash, hashtable_string.size * 2);
+ newhash.entries = hashtable_string.entries;
+
+ /* transfer elements to new hashtable */
+
+ for (i = 0; i < hashtable_string.size; i++) {
+ s = (literalstring*) hashtable_string.ptr[i];
+
+ while (s) {
+ nexts = s->hashlink;
+ java_lang_String tmpjls(LLNI_WRAP(s->string));
+ // FIXME This is not handle capable!
+ slot = unicode_hashkey(((java_chararray_t*) LLNI_UNWRAP(tmpjls.get_value()))->data, tmpjls.get_count()) & (newhash.size - 1);
+
+ s->hashlink = (literalstring*) newhash.ptr[slot];
+ newhash.ptr[slot] = s;
+
+ /* follow link in external hash chain */
+ s = nexts;
+ }
+ }
+
+ /* dispose old table */
+
+ MFREE(hashtable_string.ptr, void*, hashtable_string.size);
+ hashtable_string = newhash;
+ }
+
+ mutex->unlock();
+
+ return (java_object_t*) LLNI_UNWRAP(jls.get_handle());
+}
+
+
+/* literalstring_new ***********************************************************
+
+ Creates a new literalstring with the text of the utf-symbol and inserts
+ it into the string hashtable.
+
+*******************************************************************************/
+
+java_object_t *literalstring_new(utf *u)
+{
+ char *utf_ptr; /* pointer to current unicode character */
+ /* utf string */
+ u4 utflength; /* length of utf-string if uncompressed */
+ java_chararray_t *a; /* u2-array constructed from utf string */
+ u4 i;
+
+ utf_ptr = u->text;
+ utflength = utf_get_number_of_u2s(u);
+
+ /* allocate memory */
+ a = (java_chararray_t*) mem_alloc(sizeof(java_chararray_t) + sizeof(u2) * (utflength - 1) + 10);
+
+ /* convert utf-string to u2-array */
+ for (i = 0; i < utflength; i++)
+ a->data[i] = utf_nextu2(&utf_ptr);
+
+ return literalstring_u2(a, utflength, 0, false);
+}
+
+
+/* literalstring_free **********************************************************
+
+ Removes a literalstring from memory.
+
+*******************************************************************************/
+
+#if 0
+/* TWISTI This one is currently not used. */
+
+static void literalstring_free(java_object_t* string)
+{
+ heapstring_t *s;
+ java_chararray_t *a;
+
+ s = (heapstring_t *) string;
+ a = s->value;
+
+ /* dispose memory of java.lang.String object */
+ FREE(s, heapstring_t);
+
+ /* dispose memory of java-characterarray */
+ FREE(a, sizeof(java_chararray_t) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
+}
+#endif
+
+
+/* javastring_intern ***********************************************************
+
+ Intern the given Java string.
+
+ XXX NOTE: Literal Strings are direct references since they are not placed
+ onto the GC-Heap. That's why this function looks so "different".
+
+*******************************************************************************/
+
+java_handle_t *javastring_intern(java_handle_t *string)
+{
+ java_lang_String jls(string);
+
+ java_handle_chararray_t* value = jls.get_value();
+ // FIXME
+ java_chararray_t* ca = LLNI_UNWRAP(value); /* XXX see note above */
+
+ int32_t count = jls.get_count();
+ int32_t offset = jls.get_offset();
+
+ java_object_t* o = literalstring_u2(ca, count, offset, true); /* XXX see note above */
+
+ return LLNI_WRAP(o); /* XXX see note above */
+}
+
+
+/* javastring_fprint ***********************************************************
+
+ Print the given Java string to the given stream.
+
+*******************************************************************************/
+
+void javastring_fprint(java_handle_t *s, FILE *stream)
+{
+ java_lang_String jls(s);
+
+ java_handle_chararray_t* value = jls.get_value();
+
+ int32_t count = jls.get_count();
+ int32_t offset = jls.get_offset();
+
+ for (int32_t i = offset; i < offset + count; i++) {
+ uint16_t c = LLNI_array_direct(value, i);
+ fputc(c, stream);
+ }
+}
+
+
+/*
+ * 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/string.hpp - string 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 _STRINGLOCAL_H
+#define _STRINGLOCAL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct literalstring literalstring;
+
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/global.h"
+#include "vm/os.hpp"
+#include "vm/utf8.h"
+
+
+/* data structure of internal javastrings stored in global hashtable **********/
+
+struct literalstring {
+ literalstring *hashlink; /* link for external hash chain */
+ java_object_t *string;
+};
+
+
+/* function prototypes ********************************************************/
+
+/* initialize string subsystem */
+bool string_init(void);
+
+void stringtable_update(void);
+
+/* creates a new object of type java/lang/String from a utf-text */
+java_handle_t *javastring_new(utf *text);
+
+/* creates a new object of type java/lang/String from a utf-text, changes slashes to dots */
+java_handle_t *javastring_new_slash_to_dot(utf *text);
+
+/* creates a new object of type java/lang/String from an ASCII c-string */
+java_handle_t *javastring_new_from_ascii(const char *text);
+
+/* creates a new object of type java/lang/String from UTF-8 */
+java_handle_t *javastring_new_from_utf_string(const char *utfstr);
+
+/* creates a new object of type java/lang/String from (possibly invalid) UTF-8 */
+java_handle_t *javastring_safe_new_from_utf8(const char *text);
+
+/* make c-string from a javastring (debugging) */
+char *javastring_tochar(java_handle_t *string);
+
+/* make utf symbol from javastring */
+utf *javastring_toutf(java_handle_t *string, bool isclassname);
+
+/* creates a new javastring with the text of the utf-symbol */
+java_object_t *literalstring_new(utf *u);
+
+java_handle_t *javastring_intern(java_handle_t *s);
+void javastring_fprint(java_handle_t *s, FILE *stream);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _STRINGLOCAL_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:
+ */
+++ /dev/null
-/* src/vm/stringlocal.h - string 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 _STRINGLOCAL_H
-#define _STRINGLOCAL_H
-
-typedef struct literalstring literalstring;
-
-
-#include "config.h"
-
-#include "vmcore/system.h"
-
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/global.h"
-
-#include "vmcore/utf8.h"
-
-
-/* data structure of internal javastrings stored in global hashtable **********/
-
-struct literalstring {
- literalstring *hashlink; /* link for external hash chain */
- java_object_t *string;
-};
-
-
-/* javastring-hashtable */
-extern hashtable hashtable_string;
-
-
-/* function prototypes ********************************************************/
-
-/* initialize string subsystem */
-bool string_init(void);
-
-void stringtable_update(void);
-
-/* creates a new object of type java/lang/String from a utf-text */
-java_handle_t *javastring_new(utf *text);
-
-/* creates a new object of type java/lang/String from a utf-text, changes slashes to dots */
-java_handle_t *javastring_new_slash_to_dot(utf *text);
-
-/* creates a new object of type java/lang/String from an ASCII c-string */
-java_handle_t *javastring_new_from_ascii(const char *text);
-
-/* creates a new object of type java/lang/String from UTF-8 */
-java_handle_t *javastring_new_from_utf_string(const char *utfstr);
-
-/* creates a new object of type java/lang/String from (possibly invalid) UTF-8 */
-java_handle_t *javastring_safe_new_from_utf8(const char *text);
-
-/* make c-string from a javastring (debugging) */
-char *javastring_tochar(java_handle_t *string);
-
-/* make utf symbol from javastring */
-utf *javastring_toutf(java_handle_t *string, bool isclassname);
-
-/* creates a new javastring with the text of the utf-symbol */
-java_object_t *literalstring_new(utf *u);
-
-java_handle_t *javastring_intern(java_handle_t *s);
-void javastring_fprint(java_handle_t *s, FILE *stream);
-
-#endif /* _STRINGLOCAL_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:
- */
--- /dev/null
+/* src/vm/suck.c - functions to read LE ordered types from a buffer
+
+ 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 <stdlib.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/list.h"
+#include "toolbox/logging.h"
+#include "toolbox/util.h"
+
+#include "vm/exceptions.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/properties.h"
+#include "vm/suck.h"
+#include "vm/vm.hpp"
+#include "vm/zip.h"
+
+
+/* global variables ***********************************************************/
+
+list_t *list_classpath_entries;
+
+
+/* suck_init *******************************************************************
+
+ Initializes the suck subsystem like initializing the classpath
+ entries list.
+
+*******************************************************************************/
+
+bool suck_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("suck_init");
+
+ list_classpath_entries = list_create(OFFSET(list_classpath_entry, linkage));
+
+ /* everything's ok */
+
+ return true;
+}
+
+
+/* scandir_filter **************************************************************
+
+ Filters for zip/jar files.
+
+*******************************************************************************/
+
+static int scandir_filter(const struct dirent *a)
+{
+ s4 namlen;
+
+#if defined(_DIRENT_HAVE_D_NAMLEN)
+ namlen = a->d_namlen;
+#else
+ namlen = strlen(a->d_name);
+#endif
+
+ if ((strncasecmp(a->d_name + namlen - 4, ".zip", 4) == 0) ||
+ (strncasecmp(a->d_name + namlen - 4, ".jar", 4) == 0))
+ return 1;
+
+ return 0;
+}
+
+
+/* suck_add ********************************************************************
+
+ Adds a classpath to the global classpath entries list.
+
+*******************************************************************************/
+
+void suck_add(char *classpath)
+{
+ list_classpath_entry *lce;
+ char *start;
+ char *end;
+ char *filename;
+ s4 filenamelen;
+ bool is_zip;
+ char *cwd;
+ s4 cwdlen;
+#if defined(ENABLE_ZLIB)
+ hashtable *ht;
+#endif
+
+ /* parse the classpath string */
+
+ for (start = classpath; (*start) != '\0'; ) {
+
+ /* search for ':' delimiter to get the end of the current entry */
+ for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
+
+ if (start != end) {
+ is_zip = false;
+ filenamelen = end - start;
+
+ if (filenamelen > 4) {
+ if ((strncasecmp(end - 4, ".zip", 4) == 0) ||
+ (strncasecmp(end - 4, ".jar", 4) == 0)) {
+ is_zip = true;
+ }
+ }
+
+ /* save classpath entries as absolute pathnames */
+
+ cwd = NULL;
+ cwdlen = 0;
+
+ if (*start != '/') { /* XXX fix me for win32 */
+ cwd = _Jv_getcwd();
+ cwdlen = strlen(cwd) + strlen("/");
+ }
+
+ /* allocate memory for filename and fill it */
+
+ filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
+ strlen("0"));
+
+ if (cwd) {
+ strcpy(filename, cwd);
+ strcat(filename, "/");
+ strncat(filename, start, filenamelen);
+
+ /* add cwd length to file length */
+ filenamelen += cwdlen;
+
+ } else {
+ strncpy(filename, start, filenamelen);
+ filename[filenamelen] = '\0';
+ }
+
+ lce = NULL;
+
+ if (is_zip) {
+#if defined(ENABLE_ZLIB)
+ ht = zip_open(filename);
+
+ if (ht != NULL) {
+ lce = NEW(list_classpath_entry);
+
+ lce->type = CLASSPATH_ARCHIVE;
+ lce->htclasses = ht;
+ lce->path = filename;
+ lce->pathlen = filenamelen;
+
+ /* SUN compatible -verbose:class output */
+
+ if (opt_verboseclass)
+ printf("[Opened %s]\n", filename);
+ }
+
+#else
+ vm_abort("suck_add: zip/jar files not supported");
+#endif
+ }
+ else {
+ if (filename[filenamelen - 1] != '/') {/* XXX fixme for win32 */
+ filename[filenamelen] = '/';
+ filename[filenamelen + 1] = '\0';
+ filenamelen++;
+ }
+
+ lce = NEW(list_classpath_entry);
+
+ lce->type = CLASSPATH_PATH;
+ lce->path = filename;
+ lce->pathlen = filenamelen;
+ }
+
+ /* add current classpath entry, if no error */
+
+ if (lce != NULL)
+ list_add_last(list_classpath_entries, lce);
+ }
+
+ /* goto next classpath entry, skip ':' delimiter */
+
+ if ((*end) == ':')
+ start = end + 1;
+ else
+ start = end;
+ }
+}
+
+
+/* suck_add_from_property ******************************************************
+
+ Adds a classpath form a property entry to the global classpath
+ entries list.
+
+*******************************************************************************/
+
+void suck_add_from_property(const char *key)
+{
+ const char *value;
+ const char *start;
+ const char *end;
+ char *path;
+ s4 pathlen;
+ struct dirent **namelist;
+ s4 n;
+ s4 i;
+ s4 namlen;
+ char *boot_class_path;
+ char *p;
+
+ /* get the property value */
+
+ value = properties_get(key);
+
+ if (value == NULL)
+ return;
+
+ /* get the directory entries of the property */
+
+ for (start = value; (*start) != '\0'; ) {
+
+ /* search for ':' delimiter to get the end of the current entry */
+
+ for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
+
+ /* found an entry */
+
+ if (start != end) {
+ /* allocate memory for the path entry */
+
+ pathlen = end - start;
+ path = MNEW(char, pathlen + strlen("0"));
+
+ /* copy and terminate the string */
+
+ strncpy(path, start, pathlen);
+ path[pathlen] = '\0';
+
+ /* Reset namelist to NULL for the freeing in an error case
+ (see below). */
+
+ namelist = NULL;
+
+ /* scan the directory found for zip/jar files */
+
+ n = os_scandir(path, &namelist, scandir_filter, alphasort);
+
+ /* On error, just continue, this should be ok. */
+
+ if (n > 0) {
+ for (i = 0; i < n; i++) {
+#if defined(_DIRENT_HAVE_D_NAMLEN)
+ namlen = namelist[i]->d_namlen;
+#else
+ namlen = strlen(namelist[i]->d_name);
+#endif
+
+ /* Allocate memory for bootclasspath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ p = MNEW(char,
+ pathlen + strlen("/") + namlen +
+ strlen(":") +
+ strlen(boot_class_path) +
+ strlen("0"));
+
+ /* Prepend the file found to the bootclasspath. */
+
+ strcpy(p, path);
+ strcat(p, "/");
+ strcat(p, namelist[i]->d_name);
+ 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, strlen(boot_class_path));
+
+ /* free the memory allocated by scandir */
+ /* (We use `free` as the memory came from the C library.) */
+
+ free(namelist[i]);
+ }
+ }
+
+ /* On some systems (like Linux) when n == 0, then namelist
+ returned from scnadir is NULL, thus we don't have to
+ free it.
+ (Use `free` as the memory came from the C library.) */
+
+ if (namelist != NULL)
+ free(namelist);
+
+ MFREE(path, char, pathlen + strlen("0"));
+ }
+
+ /* goto next entry, skip ':' delimiter */
+
+ if ((*end) == ':')
+ start = end + 1;
+ else
+ start = end;
+ }
+}
+
+
+/* suck_check_classbuffer_size *************************************************
+
+ Assert that at least <len> bytes are left to read <len> is limited
+ to the range of non-negative s4 values.
+
+*******************************************************************************/
+
+bool suck_check_classbuffer_size(classbuffer *cb, s4 len)
+{
+#ifdef ENABLE_VERIFIER
+ if (len < 0 || ((cb->data + cb->size) - cb->pos) < len) {
+ exceptions_throw_classformaterror(cb->clazz, "Truncated class file");
+ return false;
+ }
+#endif /* ENABLE_VERIFIER */
+
+ return true;
+}
+
+
+u1 suck_u1(classbuffer *cb)
+{
+ u1 a;
+
+ a = SUCK_BE_U1(cb->pos);
+ cb->pos++;
+
+ return a;
+}
+
+
+u2 suck_u2(classbuffer *cb)
+{
+ u2 a;
+
+ a = SUCK_BE_U2(cb->pos);
+ cb->pos += 2;
+
+ return a;
+}
+
+
+u4 suck_u4(classbuffer *cb)
+{
+ u4 a;
+
+ a = SUCK_BE_U4(cb->pos);
+ cb->pos += 4;
+
+ return a;
+}
+
+
+u8 suck_u8(classbuffer *cb)
+{
+#if U8_AVAILABLE == 1
+ u8 a;
+
+ a = SUCK_BE_U8(cb->pos);
+ cb->pos += 8;
+
+ return a;
+#else
+ u8 v;
+
+ v.high = suck_u4(cb);
+ v.low = suck_u4(cb);
+
+ return v;
+#endif
+}
+
+
+float suck_float(classbuffer *cb)
+{
+ float f;
+
+#if WORDS_BIGENDIAN == 0
+ u1 buffer[4];
+ u2 i;
+
+ for (i = 0; i < 4; i++)
+ buffer[3 - i] = suck_u1(cb);
+
+ MCOPY((u1 *) (&f), buffer, u1, 4);
+#else
+ suck_nbytes((u1*) (&f), cb, 4);
+#endif
+
+ assert(sizeof(float) == 4);
+
+ return f;
+}
+
+
+double suck_double(classbuffer *cb)
+{
+ double d;
+
+#if WORDS_BIGENDIAN == 0
+ u1 buffer[8];
+ u2 i;
+
+# if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
+ /*
+ * On little endian ARM processors when using FPA, word order
+ * of doubles is still big endian. So take that into account
+ * here. When using VFP, word order of doubles follows byte
+ * order. (michi 2005/07/24)
+ */
+ for (i = 0; i < 4; i++)
+ buffer[3 - i] = suck_u1(cb);
+ for (i = 0; i < 4; i++)
+ buffer[7 - i] = suck_u1(cb);
+# else
+ for (i = 0; i < 8; i++)
+ buffer[7 - i] = suck_u1(cb);
+# endif /* defined(__ARM__) && ... */
+
+ MCOPY((u1 *) (&d), buffer, u1, 8);
+#else
+ suck_nbytes((u1*) (&d), cb, 8);
+#endif
+
+ assert(sizeof(double) == 8);
+
+ return d;
+}
+
+
+/* suck_nbytes *****************************************************************
+
+ Transfer block of classfile data into a buffer.
+
+*******************************************************************************/
+
+void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
+{
+ MCOPY(buffer, cb->pos, u1, len);
+ cb->pos += len;
+}
+
+
+/* suck_skip_nbytes ************************************************************
+
+ Skip block of classfile data.
+
+*******************************************************************************/
+
+void suck_skip_nbytes(classbuffer *cb, s4 len)
+{
+ cb->pos += len;
+}
+
+
+/* suck_start ******************************************************************
+
+ Returns true if classbuffer is already loaded or a file for the
+ specified class has succussfully been read in. All directories of
+ the searchpath are used to find the classfile (<classname>.class).
+ Returns NULL if no classfile is found and writes an error message.
+
+*******************************************************************************/
+
+classbuffer *suck_start(classinfo *c)
+{
+ list_classpath_entry *lce;
+ char *filename;
+ s4 filenamelen;
+ char *path;
+ FILE *classfile;
+ s4 len;
+ struct stat buffer;
+ classbuffer *cb;
+
+ /* initialize return value */
+
+ cb = NULL;
+
+ /* get the classname as char string (do it here for the warning at
+ the end of the function) */
+
+ filenamelen = utf_bytes(c->name) + strlen(".class") + strlen("0");
+ filename = MNEW(char, filenamelen);
+
+ utf_copy(filename, c->name);
+ strcat(filename, ".class");
+
+ /* walk through all classpath entries */
+
+ for (lce = list_first(list_classpath_entries); lce != NULL && cb == NULL;
+ lce = list_next(list_classpath_entries, lce)) {
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+
+ /* enter a monitor on zip/jar archives */
+
+ LOCK_MONITOR_ENTER(lce);
+
+ /* try to get the file in current archive */
+
+ cb = zip_get(lce, c);
+
+ /* leave the monitor */
+
+ LOCK_MONITOR_EXIT(lce);
+
+ } else {
+#endif /* defined(ENABLE_ZLIB) */
+ path = MNEW(char, lce->pathlen + filenamelen);
+ strcpy(path, lce->path);
+ strcat(path, filename);
+
+ classfile = os_fopen(path, "r");
+
+ if (classfile) { /* file exists */
+ if (!os_stat(path, &buffer)) { /* read classfile data */
+ cb = NEW(classbuffer);
+ cb->clazz = c;
+ cb->size = buffer.st_size;
+ cb->data = MNEW(u1, cb->size);
+ cb->pos = cb->data;
+ cb->path = lce->path;
+
+ /* read class data */
+
+ len = os_fread((void *) cb->data, 1, cb->size,
+ classfile);
+
+ if (len != buffer.st_size) {
+ suck_stop(cb);
+/* if (ferror(classfile)) { */
+/* } */
+ }
+
+ /* close the class file */
+
+ os_fclose(classfile);
+ }
+ }
+
+ MFREE(path, char, lce->pathlen + filenamelen);
+#if defined(ENABLE_ZLIB)
+ }
+#endif
+ }
+
+ if (opt_verbose)
+ if (cb == NULL)
+ dolog("Warning: Can not open class file '%s'", filename);
+
+ MFREE(filename, char, filenamelen);
+
+ return cb;
+}
+
+
+/* suck_stop *******************************************************************
+
+ Frees memory for buffer with classfile data.
+
+ CAUTION: This function may only be called if buffer has been
+ allocated by suck_start with reading a file.
+
+*******************************************************************************/
+
+void suck_stop(classbuffer *cb)
+{
+ /* free memory */
+
+ MFREE(cb->data, u1, cb->size);
+ FREE(cb, classbuffer);
+}
+
+
+/*
+ * 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/suck.h - functions to read LE ordered types from a buffer
+
+ 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 _SUCK_H
+#define _SUCK_H
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/list.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+
+
+/* list_classpath_entry *******************************************************/
+
+enum {
+ CLASSPATH_PATH,
+ CLASSPATH_ARCHIVE
+};
+
+typedef struct list_classpath_entry list_classpath_entry;
+
+struct list_classpath_entry {
+#if defined(ENABLE_THREADS)
+ java_object_t header; /* monitor locking on zip/jar files */
+#endif
+ s4 type;
+ char *path;
+ s4 pathlen;
+#if defined(ENABLE_ZLIB)
+ hashtable *htclasses;
+#endif
+ listnode_t linkage;
+};
+
+
+/* macros to read LE and BE types from a buffer ********************************
+
+ BE macros are for Java class file loading.
+ LE macros are for ZIP file loading.
+
+*******************************************************************************/
+
+/* LE macros (for ZIP files ) *************************************************/
+
+#if defined(__I386__) || defined(__X86_64__)
+
+/* we can optimize the LE access on little endian machines without alignment */
+
+#define SUCK_LE_U1(p) *((u1 *) (p))
+#define SUCK_LE_U2(p) *((u2 *) (p))
+#define SUCK_LE_U4(p) *((u4 *) (p))
+
+#if U8_AVAILABLE == 1
+#define SUCK_LE_U8(p) *((u8 *) (p))
+#endif
+
+#else /* defined(__I386__) || defined(__X86_64__) */
+
+#define SUCK_LE_U1(p) \
+ ((u1) (p)[0])
+
+#define SUCK_LE_U2(p) \
+ ((((u2) (p)[1]) << 8) + \
+ ((u2) (p)[0]))
+
+#define SUCK_LE_U4(p) \
+ ((((u4) (p)[3]) << 24) + \
+ (((u4) (p)[2]) << 16) + \
+ (((u4) (p)[1]) << 8) + \
+ ((u4) (p)[0]))
+
+#if U8_AVAILABLE == 1
+#define SUCK_LE_U8(p) \
+ ((((u8) (p)[7]) << 56) + \
+ (((u8) (p)[6]) << 48) + \
+ (((u8) (p)[5]) << 40) + \
+ (((u8) (p)[4]) << 32) + \
+ (((u8) (p)[3]) << 24) + \
+ (((u8) (p)[2]) << 16) + \
+ (((u8) (p)[1]) << 8) + \
+ ((u8) (p)[0]))
+#endif
+
+#endif /* defined(__I386__) || defined(__X86_64__) */
+
+
+/* BE macros (for Java class files ) ******************************************/
+
+#define SUCK_BE_U1(p) \
+ ((u1) (p)[0])
+
+#define SUCK_BE_U2(p) \
+ ((((u2) (p)[0]) << 8) + \
+ ((u2) (p)[1]))
+
+#define SUCK_BE_U4(p) \
+ ((((u4) (p)[0]) << 24) + \
+ (((u4) (p)[1]) << 16) + \
+ (((u4) (p)[2]) << 8) + \
+ ((u4) (p)[3]))
+
+#if U8_AVAILABLE == 1
+#define SUCK_BE_U8(p) \
+ ((((u8) (p)[0]) << 56) + \
+ (((u8) (p)[1]) << 48) + \
+ (((u8) (p)[2]) << 40) + \
+ (((u8) (p)[3]) << 32) + \
+ (((u8) (p)[4]) << 24) + \
+ (((u8) (p)[5]) << 16) + \
+ (((u8) (p)[6]) << 8) + \
+ ((u8) (p)[7]))
+#endif
+
+
+#define SUCK_BE_S1(p) (s1) SUCK_BE_U1(p)
+#define SUCK_BE_S2(p) (s2) SUCK_BE_U2(p)
+#define SUCK_BE_S4(p) (s4) SUCK_BE_U4(p)
+#define SUCK_BE_S8(p) (s8) SUCK_BE_U8(p)
+
+
+/* signed suck defines ********************************************************/
+
+#define suck_s1(a) (s1) suck_u1((a))
+#define suck_s2(a) (s2) suck_u2((a))
+#define suck_s4(a) (s4) suck_u4((a))
+#define suck_s8(a) (s8) suck_u8((a))
+
+
+/* export variables ***********************************************************/
+
+extern list_t *list_classpath_entries;
+
+
+/* function prototypes ********************************************************/
+
+bool suck_init(void);
+
+void suck_add(char *classpath);
+void suck_add_from_property(const char *key);
+
+bool suck_check_classbuffer_size(classbuffer *cb, s4 len);
+
+u1 suck_u1(classbuffer *cb);
+u2 suck_u2(classbuffer *cb);
+u4 suck_u4(classbuffer *cb);
+u8 suck_u8(classbuffer *cb);
+
+float suck_float(classbuffer *cb);
+double suck_double(classbuffer *cb);
+
+void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len);
+void suck_skip_nbytes(classbuffer *cb, s4 len);
+
+classbuffer *suck_start(classinfo *c);
+
+void suck_stop(classbuffer *cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SUCK_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/utf8.c - utf8 string 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 <string.h>
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/utf8.h"
+
+
+/* global variables ***********************************************************/
+
+/* hashsize must be power of 2 */
+
+#define HASHTABLE_UTF_SIZE 16384 /* initial size of utf-hash */
+
+hashtable *hashtable_utf; /* hashtable for utf8-symbols */
+
+
+/* utf-symbols for pointer comparison of frequently used strings **************/
+
+utf *utf_java_lang_Object;
+
+utf *utf_java_lang_Class;
+utf *utf_java_lang_ClassLoader;
+utf *utf_java_lang_Cloneable;
+utf *utf_java_lang_SecurityManager;
+utf *utf_java_lang_String;
+utf *utf_java_lang_ThreadGroup;
+utf *utf_java_lang_ref_SoftReference;
+utf *utf_java_lang_ref_WeakReference;
+utf *utf_java_lang_ref_PhantomReference;
+utf *utf_java_io_Serializable;
+
+utf *utf_java_lang_Throwable;
+utf *utf_java_lang_Error;
+
+utf *utf_java_lang_AbstractMethodError;
+utf *utf_java_lang_ClassCircularityError;
+utf *utf_java_lang_ClassFormatError;
+utf *utf_java_lang_ExceptionInInitializerError;
+utf *utf_java_lang_IncompatibleClassChangeError;
+utf *utf_java_lang_InstantiationError;
+utf *utf_java_lang_InternalError;
+utf *utf_java_lang_LinkageError;
+utf *utf_java_lang_NoClassDefFoundError;
+utf *utf_java_lang_NoSuchFieldError;
+utf *utf_java_lang_NoSuchMethodError;
+utf *utf_java_lang_OutOfMemoryError;
+utf *utf_java_lang_UnsatisfiedLinkError;
+utf *utf_java_lang_UnsupportedClassVersionError;
+utf *utf_java_lang_VerifyError;
+utf *utf_java_lang_VirtualMachineError;
+
+utf *utf_java_lang_Exception;
+
+utf *utf_java_lang_ArithmeticException;
+utf *utf_java_lang_ArrayIndexOutOfBoundsException;
+utf *utf_java_lang_ArrayStoreException;
+utf *utf_java_lang_ClassCastException;
+utf *utf_java_lang_ClassNotFoundException;
+utf *utf_java_lang_CloneNotSupportedException;
+utf *utf_java_lang_IllegalAccessException;
+utf *utf_java_lang_IllegalArgumentException;
+utf *utf_java_lang_IllegalMonitorStateException;
+utf *utf_java_lang_InstantiationException;
+utf *utf_java_lang_InterruptedException;
+utf *utf_java_lang_NegativeArraySizeException;
+utf *utf_java_lang_NullPointerException;
+utf *utf_java_lang_RuntimeException;
+utf *utf_java_lang_StringIndexOutOfBoundsException;
+
+utf *utf_java_lang_reflect_InvocationTargetException;
+
+utf *utf_java_security_PrivilegedActionException;
+
+#if defined(ENABLE_JAVASE)
+utf* utf_java_lang_Void;
+#endif
+
+utf* utf_java_lang_Boolean;
+utf* utf_java_lang_Byte;
+utf* utf_java_lang_Character;
+utf* utf_java_lang_Short;
+utf* utf_java_lang_Integer;
+utf* utf_java_lang_Long;
+utf* utf_java_lang_Float;
+utf* utf_java_lang_Double;
+
+#if defined(ENABLE_JAVASE)
+utf *utf_java_lang_StackTraceElement;
+utf *utf_java_lang_reflect_Constructor;
+utf *utf_java_lang_reflect_Field;
+utf *utf_java_lang_reflect_Method;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+utf *utf_java_lang_reflect_VMConstructor;
+utf *utf_java_lang_reflect_VMField;
+utf *utf_java_lang_reflect_VMMethod;
+# endif
+
+utf *utf_java_util_Vector;
+#endif
+
+utf *utf_InnerClasses; /* InnerClasses */
+utf *utf_ConstantValue; /* ConstantValue */
+utf *utf_Code; /* Code */
+utf *utf_Exceptions; /* Exceptions */
+utf *utf_LineNumberTable; /* LineNumberTable */
+utf *utf_SourceFile; /* SourceFile */
+
+#if defined(ENABLE_JAVASE)
+utf *utf_EnclosingMethod;
+utf *utf_Signature;
+utf *utf_StackMapTable;
+
+#if defined(ENABLE_ANNOTATIONS)
+utf *utf_RuntimeVisibleAnnotations; /* RuntimeVisibleAnnotations */
+utf *utf_RuntimeInvisibleAnnotations; /* RuntimeInvisibleAnnotations */
+utf *utf_RuntimeVisibleParameterAnnotations; /* RuntimeVisibleParameterAnnotations */
+utf *utf_RuntimeInvisibleParameterAnnotations; /* RuntimeInvisibleParameterAnnotations */
+utf *utf_AnnotationDefault; /* AnnotationDefault */
+#endif
+#endif
+
+utf *utf_init; /* <init> */
+utf *utf_clinit; /* <clinit> */
+utf *utf_clone; /* clone */
+utf *utf_finalize; /* finalize */
+utf *utf_invoke;
+utf *utf_main;
+utf *utf_run; /* run */
+
+utf *utf_add;
+utf *utf_dispatch;
+utf *utf_remove;
+utf *utf_addThread;
+utf *utf_removeThread;
+utf *utf_put;
+utf *utf_get;
+utf *utf_uncaughtException;
+utf *utf_value;
+
+utf *utf_fillInStackTrace;
+utf *utf_findNative;
+utf *utf_getSystemClassLoader;
+utf *utf_initCause;
+utf *utf_loadClass;
+utf *utf_loadClassInternal;
+utf *utf_printStackTrace;
+
+utf *utf_division_by_zero;
+
+utf *utf_Z; /* Z */
+utf *utf_B; /* B */
+utf *utf_C; /* C */
+utf *utf_S; /* S */
+utf *utf_I; /* I */
+utf *utf_J; /* J */
+utf *utf_F; /* F */
+utf *utf_D; /* D */
+
+utf *utf_void__void; /* ()V */
+utf *utf_boolean__void; /* (Z)V */
+utf *utf_byte__void; /* (B)V */
+utf *utf_char__void; /* (C)V */
+utf *utf_short__void; /* (S)V */
+utf *utf_int__void; /* (I)V */
+utf *utf_long__void; /* (J)V */
+utf *utf_float__void; /* (F)V */
+utf *utf_double__void; /* (D)V */
+
+utf *utf_void__java_lang_ClassLoader; /* ()Ljava/lang/ClassLoader; */
+utf *utf_void__java_lang_Object; /* ()Ljava/lang/Object; */
+utf *utf_void__java_lang_Throwable; /* ()Ljava/lang/Throwable; */
+utf *utf_java_lang_ClassLoader_java_lang_String__J;
+utf *utf_java_lang_Exception__V; /* (Ljava/lang/Exception;)V */
+utf *utf_java_lang_Object__java_lang_Object;
+utf *utf_java_lang_String__void; /* (Ljava/lang/String;)V */
+utf *utf_java_lang_String__java_lang_Class;
+utf *utf_java_lang_Thread__V; /* (Ljava/lang/Thread;)V */
+utf *utf_java_lang_Thread_java_lang_Throwable__V;
+utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
+utf *utf_java_lang_Throwable__void; /* (Ljava/lang/Throwable;)V */
+utf *utf_java_lang_Throwable__java_lang_Throwable;
+
+utf *utf_not_named_yet; /* special name for unnamed classes */
+utf *utf_null;
+utf *array_packagename;
+
+
+/* utf_init ********************************************************************
+
+ Initializes the utf8 subsystem.
+
+*******************************************************************************/
+
+void utf8_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("utf8_init");
+
+ /* create utf8 hashtable */
+
+ hashtable_utf = NEW(hashtable);
+
+ hashtable_create(hashtable_utf, HASHTABLE_UTF_SIZE);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_len += sizeof(utf*) * hashtable_utf->size;
+#endif
+
+ /* create utf-symbols for pointer comparison of frequently used strings */
+
+ utf_java_lang_Object = utf_new_char("java/lang/Object");
+
+ utf_java_lang_Class = utf_new_char("java/lang/Class");
+ utf_java_lang_ClassLoader = utf_new_char("java/lang/ClassLoader");
+ utf_java_lang_Cloneable = utf_new_char("java/lang/Cloneable");
+ utf_java_lang_SecurityManager = utf_new_char("java/lang/SecurityManager");
+ utf_java_lang_String = utf_new_char("java/lang/String");
+ utf_java_lang_ThreadGroup = utf_new_char("java/lang/ThreadGroup");
+
+ utf_java_lang_ref_SoftReference =
+ utf_new_char("java/lang/ref/SoftReference");
+
+ utf_java_lang_ref_WeakReference =
+ utf_new_char("java/lang/ref/WeakReference");
+
+ utf_java_lang_ref_PhantomReference =
+ utf_new_char("java/lang/ref/PhantomReference");
+
+ utf_java_io_Serializable = utf_new_char("java/io/Serializable");
+
+ utf_java_lang_Throwable = utf_new_char("java/lang/Throwable");
+ utf_java_lang_Error = utf_new_char("java/lang/Error");
+
+ utf_java_lang_ClassCircularityError =
+ utf_new_char("java/lang/ClassCircularityError");
+
+ utf_java_lang_ClassFormatError = utf_new_char("java/lang/ClassFormatError");
+
+ utf_java_lang_ExceptionInInitializerError =
+ utf_new_char("java/lang/ExceptionInInitializerError");
+
+ utf_java_lang_IncompatibleClassChangeError =
+ utf_new_char("java/lang/IncompatibleClassChangeError");
+
+ utf_java_lang_InstantiationError =
+ utf_new_char("java/lang/InstantiationError");
+
+ utf_java_lang_InternalError = utf_new_char("java/lang/InternalError");
+ utf_java_lang_LinkageError = utf_new_char("java/lang/LinkageError");
+
+ utf_java_lang_NoClassDefFoundError =
+ utf_new_char("java/lang/NoClassDefFoundError");
+
+ utf_java_lang_OutOfMemoryError = utf_new_char("java/lang/OutOfMemoryError");
+
+ utf_java_lang_UnsatisfiedLinkError =
+ utf_new_char("java/lang/UnsatisfiedLinkError");
+
+ utf_java_lang_UnsupportedClassVersionError =
+ utf_new_char("java/lang/UnsupportedClassVersionError");
+
+ utf_java_lang_VerifyError = utf_new_char("java/lang/VerifyError");
+
+ utf_java_lang_VirtualMachineError =
+ utf_new_char("java/lang/VirtualMachineError");
+
+#if defined(ENABLE_JAVASE)
+ utf_java_lang_AbstractMethodError =
+ utf_new_char("java/lang/AbstractMethodError");
+
+ utf_java_lang_NoSuchFieldError =
+ utf_new_char("java/lang/NoSuchFieldError");
+
+ utf_java_lang_NoSuchMethodError =
+ utf_new_char("java/lang/NoSuchMethodError");
+#endif
+
+ utf_java_lang_Exception = utf_new_char("java/lang/Exception");
+
+ utf_java_lang_ArithmeticException =
+ utf_new_char("java/lang/ArithmeticException");
+
+ utf_java_lang_ArrayIndexOutOfBoundsException =
+ utf_new_char("java/lang/ArrayIndexOutOfBoundsException");
+
+ utf_java_lang_ArrayStoreException =
+ utf_new_char("java/lang/ArrayStoreException");
+
+ utf_java_lang_ClassCastException =
+ utf_new_char("java/lang/ClassCastException");
+
+ utf_java_lang_ClassNotFoundException =
+ utf_new_char("java/lang/ClassNotFoundException");
+
+ utf_java_lang_CloneNotSupportedException =
+ utf_new_char("java/lang/CloneNotSupportedException");
+
+ utf_java_lang_IllegalAccessException =
+ utf_new_char("java/lang/IllegalAccessException");
+
+ utf_java_lang_IllegalArgumentException =
+ utf_new_char("java/lang/IllegalArgumentException");
+
+ utf_java_lang_IllegalMonitorStateException =
+ utf_new_char("java/lang/IllegalMonitorStateException");
+
+ utf_java_lang_InstantiationException =
+ utf_new_char("java/lang/InstantiationException");
+
+ utf_java_lang_InterruptedException =
+ utf_new_char("java/lang/InterruptedException");
+
+ utf_java_lang_NegativeArraySizeException =
+ utf_new_char("java/lang/NegativeArraySizeException");
+
+ utf_java_lang_NullPointerException =
+ utf_new_char("java/lang/NullPointerException");
+
+ utf_java_lang_RuntimeException =
+ utf_new_char("java/lang/RuntimeException");
+
+ utf_java_lang_StringIndexOutOfBoundsException =
+ utf_new_char("java/lang/StringIndexOutOfBoundsException");
+
+ utf_java_lang_reflect_InvocationTargetException =
+ utf_new_char("java/lang/reflect/InvocationTargetException");
+
+ utf_java_security_PrivilegedActionException =
+ utf_new_char("java/security/PrivilegedActionException");
+
+#if defined(ENABLE_JAVASE)
+ utf_java_lang_Void = utf_new_char("java/lang/Void");
+#endif
+
+ utf_java_lang_Boolean = utf_new_char("java/lang/Boolean");
+ utf_java_lang_Byte = utf_new_char("java/lang/Byte");
+ utf_java_lang_Character = utf_new_char("java/lang/Character");
+ utf_java_lang_Short = utf_new_char("java/lang/Short");
+ utf_java_lang_Integer = utf_new_char("java/lang/Integer");
+ utf_java_lang_Long = utf_new_char("java/lang/Long");
+ utf_java_lang_Float = utf_new_char("java/lang/Float");
+ utf_java_lang_Double = utf_new_char("java/lang/Double");
+
+#if defined(ENABLE_JAVASE)
+ utf_java_lang_StackTraceElement =
+ utf_new_char("java/lang/StackTraceElement");
+
+ utf_java_lang_reflect_Constructor =
+ utf_new_char("java/lang/reflect/Constructor");
+
+ utf_java_lang_reflect_Field = utf_new_char("java/lang/reflect/Field");
+ utf_java_lang_reflect_Method = utf_new_char("java/lang/reflect/Method");
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ utf_java_lang_reflect_VMConstructor = utf_new_char("java/lang/reflect/VMConstructor");
+ utf_java_lang_reflect_VMField = utf_new_char("java/lang/reflect/VMField");
+ utf_java_lang_reflect_VMMethod = utf_new_char("java/lang/reflect/VMMethod");
+# endif
+
+ utf_java_util_Vector = utf_new_char("java/util/Vector");
+#endif
+
+ utf_InnerClasses = utf_new_char("InnerClasses");
+ utf_ConstantValue = utf_new_char("ConstantValue");
+ utf_Code = utf_new_char("Code");
+ utf_Exceptions = utf_new_char("Exceptions");
+ utf_LineNumberTable = utf_new_char("LineNumberTable");
+ utf_SourceFile = utf_new_char("SourceFile");
+
+#if defined(ENABLE_JAVASE)
+ utf_EnclosingMethod = utf_new_char("EnclosingMethod");
+ utf_Signature = utf_new_char("Signature");
+ utf_StackMapTable = utf_new_char("StackMapTable");
+
+# if defined(ENABLE_ANNOTATIONS)
+ utf_RuntimeVisibleAnnotations = utf_new_char("RuntimeVisibleAnnotations");
+ utf_RuntimeInvisibleAnnotations = utf_new_char("RuntimeInvisibleAnnotations");
+ utf_RuntimeVisibleParameterAnnotations = utf_new_char("RuntimeVisibleParameterAnnotations");
+ utf_RuntimeInvisibleParameterAnnotations = utf_new_char("RuntimeInvisibleParameterAnnotations");
+ utf_AnnotationDefault = utf_new_char("AnnotationDefault");
+# endif
+#endif
+
+ utf_init = utf_new_char("<init>");
+ utf_clinit = utf_new_char("<clinit>");
+ utf_clone = utf_new_char("clone");
+ utf_finalize = utf_new_char("finalize");
+ utf_invoke = utf_new_char("invoke");
+ utf_main = utf_new_char("main");
+ utf_run = utf_new_char("run");
+
+ utf_add = utf_new_char("add");
+ utf_dispatch = utf_new_char("dispatch");
+ utf_remove = utf_new_char("remove");
+ utf_addThread = utf_new_char("addThread");
+ utf_removeThread = utf_new_char("removeThread");
+ utf_put = utf_new_char("put");
+ utf_get = utf_new_char("get");
+ utf_uncaughtException = utf_new_char("uncaughtException");
+ utf_value = utf_new_char("value");
+
+ utf_fillInStackTrace = utf_new_char("fillInStackTrace");
+ utf_findNative = utf_new_char("findNative");
+ utf_getSystemClassLoader = utf_new_char("getSystemClassLoader");
+ utf_initCause = utf_new_char("initCause");
+ utf_loadClass = utf_new_char("loadClass");
+ utf_loadClassInternal = utf_new_char("loadClassInternal");
+ utf_printStackTrace = utf_new_char("printStackTrace");
+
+ utf_division_by_zero = utf_new_char("/ by zero");
+
+ utf_Z = utf_new_char("Z");
+ utf_B = utf_new_char("B");
+ utf_C = utf_new_char("C");
+ utf_S = utf_new_char("S");
+ utf_I = utf_new_char("I");
+ utf_J = utf_new_char("J");
+ utf_F = utf_new_char("F");
+ utf_D = utf_new_char("D");
+
+ utf_void__void = utf_new_char("()V");
+ utf_boolean__void = utf_new_char("(Z)V");
+ utf_byte__void = utf_new_char("(B)V");
+ utf_char__void = utf_new_char("(C)V");
+ utf_short__void = utf_new_char("(S)V");
+ utf_int__void = utf_new_char("(I)V");
+ utf_long__void = utf_new_char("(J)V");
+ utf_float__void = utf_new_char("(F)V");
+ utf_double__void = utf_new_char("(D)V");
+ utf_void__java_lang_Object = utf_new_char("()Ljava/lang/Object;");
+ utf_void__java_lang_Throwable = utf_new_char("()Ljava/lang/Throwable;");
+
+ utf_void__java_lang_ClassLoader =
+ utf_new_char("()Ljava/lang/ClassLoader;");
+
+ utf_java_lang_ClassLoader_java_lang_String__J =
+ utf_new_char("(Ljava/lang/ClassLoader;Ljava/lang/String;)J");
+
+ utf_java_lang_Exception__V = utf_new_char("(Ljava/lang/Exception;)V");
+
+ utf_java_lang_Object__java_lang_Object =
+ utf_new_char("(Ljava/lang/Object;)Ljava/lang/Object;");
+
+ utf_java_lang_String__void = utf_new_char("(Ljava/lang/String;)V");
+
+ utf_java_lang_String__java_lang_Class =
+ utf_new_char("(Ljava/lang/String;)Ljava/lang/Class;");
+
+ utf_java_lang_Thread__V = utf_new_char("(Ljava/lang/Thread;)V");
+
+ utf_java_lang_Thread_java_lang_Throwable__V =
+ utf_new_char("(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
+
+ utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V =
+ utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
+
+ utf_java_lang_Throwable__void = utf_new_char("(Ljava/lang/Throwable;)V");
+
+ utf_java_lang_Throwable__java_lang_Throwable =
+ utf_new_char("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
+
+ utf_null = utf_new_char("null");
+ utf_not_named_yet = utf_new_char("\t<not_named_yet>");
+ array_packagename = utf_new_char("\t<the array package>");
+}
+
+
+/* utf_hashkey *****************************************************************
+
+ The hashkey is computed from the utf-text by using up to 8
+ characters. For utf-symbols longer than 15 characters 3 characters
+ are taken from the beginning and the end, 2 characters are taken
+ from the middle.
+
+*******************************************************************************/
+
+#define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
+#define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
+
+u4 utf_hashkey(const char *text, u4 length)
+{
+ const char *start_pos = text; /* pointer to utf text */
+ u4 a;
+
+ switch (length) {
+ case 0: /* empty string */
+ return 0;
+
+ case 1: return fbs(0);
+ case 2: return fbs(0) ^ nbs(3);
+ case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
+ case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
+ case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
+ case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
+ case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
+ case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
+
+ case 9:
+ a = fbs(0);
+ a ^= nbs(1);
+ a ^= nbs(2);
+ text++;
+ return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
+
+ case 10:
+ a = fbs(0);
+ text++;
+ a ^= nbs(2);
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text++;
+ return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
+
+ case 11:
+ a = fbs(0);
+ text++;
+ a ^= nbs(2);
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text++;
+ return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
+
+ case 12:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(2);
+ a ^= nbs(3);
+ text++;
+ a ^= nbs(5);
+ a ^= nbs(6);
+ a ^= nbs(7);
+ text++;
+ return a ^ nbs(9) ^ nbs(10);
+
+ case 13:
+ a = fbs(0);
+ a ^= nbs(1);
+ text++;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
+ return a ^ nbs(9) ^ nbs(10);
+
+ case 14:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
+ return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
+
+ case 15:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
+ return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
+
+ default: /* 3 characters from beginning */
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+
+ /* 2 characters from middle */
+ text = start_pos + (length / 2);
+ a ^= fbs(5);
+ text += 2;
+ a ^= nbs(6);
+
+ /* 3 characters from end */
+ text = start_pos + length - 4;
+
+ a ^= fbs(7);
+ text++;
+
+ return a ^ nbs(10) ^ nbs(11);
+ }
+}
+
+/* utf_full_hashkey ************************************************************
+
+ This function computes a hash value using all bytes in the string.
+
+ The algorithm is the "One-at-a-time" algorithm as published
+ by Bob Jenkins on http://burtleburtle.net/bob/hash/doobs.html.
+
+*******************************************************************************/
+
+u4 utf_full_hashkey(const char *text, u4 length)
+{
+ register const unsigned char *p = (const unsigned char *) text;
+ register u4 hash;
+ register u4 i;
+
+ hash = 0;
+ for (i=length; i--;)
+ {
+ hash += *p++;
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+
+ return hash;
+}
+
+/* unicode_hashkey *************************************************************
+
+ Compute the hashkey of a unicode string.
+
+*******************************************************************************/
+
+u4 unicode_hashkey(u2 *text, u2 len)
+{
+ return utf_hashkey((char *) text, len);
+}
+
+
+/* utf_new *********************************************************************
+
+ Creates a new utf-symbol, the text of the symbol is passed as a
+ u1-array. The function searches the utf-hashtable for a utf-symbol
+ with this text. On success the element returned, otherwise a new
+ hashtable element is created.
+
+ If the number of entries in the hashtable exceeds twice the size of
+ the hashtable slots a reorganization of the hashtable is done and
+ the utf symbols are copied to a new hashtable with doubled size.
+
+*******************************************************************************/
+
+utf *utf_new(const char *text, u2 length)
+{
+ u4 key; /* hashkey computed from utf-text */
+ u4 slot; /* slot in hashtable */
+ utf *u; /* hashtable element */
+ u2 i;
+
+ LOCK_MONITOR_ENTER(hashtable_utf->header);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_new++;
+#endif
+
+ key = utf_hashkey(text, length);
+ slot = key & (hashtable_utf->size - 1);
+ u = hashtable_utf->ptr[slot];
+
+ /* search external hash chain for utf-symbol */
+
+ while (u) {
+ if (u->blength == length) {
+ /* compare text of hashtable elements */
+
+ for (i = 0; i < length; i++)
+ if (text[i] != u->text[i])
+ goto nomatch;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_new_found++;
+#endif
+
+ /* symbol found in hashtable */
+
+ LOCK_MONITOR_EXIT(hashtable_utf->header);
+
+ return u;
+ }
+
+ nomatch:
+ u = u->hashlink; /* next element in external chain */
+ }
+
+ /* location in hashtable found, create new utf element */
+
+ u = NEW(utf);
+
+ u->blength = length; /* length in bytes of utfstring */
+ u->hashlink = hashtable_utf->ptr[slot]; /* link in external hashchain */
+ u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
+
+ memcpy(u->text, text, length); /* copy utf-text */
+ u->text[length] = '\0';
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_len += sizeof(utf) + length + 1;
+#endif
+
+ hashtable_utf->ptr[slot] = u; /* insert symbol into table */
+ hashtable_utf->entries++; /* update number of entries */
+
+ if (hashtable_utf->entries > (hashtable_utf->size * 2)) {
+
+ /* reorganization of hashtable, average length of the external
+ chains is approx. 2 */
+
+ hashtable *newhash; /* the new hashtable */
+ u4 i;
+ utf *u;
+ utf *nextu;
+ u4 slot;
+
+ /* create new hashtable, double the size */
+
+ newhash = hashtable_resize(hashtable_utf, hashtable_utf->size * 2);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_len += sizeof(utf*) * hashtable_utf->size;
+#endif
+
+ /* transfer elements to new hashtable */
+
+ for (i = 0; i < hashtable_utf->size; i++) {
+ u = hashtable_utf->ptr[i];
+
+ while (u) {
+ nextu = u->hashlink;
+ slot = utf_hashkey(u->text, u->blength) & (newhash->size - 1);
+
+ u->hashlink = (utf *) newhash->ptr[slot];
+ newhash->ptr[slot] = u;
+
+ /* follow link in external hash chain */
+
+ u = nextu;
+ }
+ }
+
+ /* dispose old table */
+
+ hashtable_free(hashtable_utf);
+
+ hashtable_utf = newhash;
+ }
+
+ LOCK_MONITOR_EXIT(hashtable_utf->header);
+
+ return u;
+}
+
+
+/* utf_new_u2 ******************************************************************
+
+ Make utf symbol from u2 array, if isclassname is true '.' is
+ replaced by '/'.
+
+*******************************************************************************/
+
+utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
+{
+ char *buffer; /* memory buffer for unicode characters */
+ char *pos; /* pointer to current position in buffer */
+ u4 left; /* unicode characters left */
+ u4 buflength; /* utf length in bytes of the u2 array */
+ utf *result; /* resulting utf-string */
+ int i;
+
+ /* determine utf length in bytes and allocate memory */
+
+ buflength = u2_utflength(unicode_pos, unicode_length);
+ buffer = MNEW(char, buflength);
+
+ left = buflength;
+ pos = buffer;
+
+ for (i = 0; i++ < unicode_length; unicode_pos++) {
+ /* next unicode character */
+ u2 c = *unicode_pos;
+
+ if ((c != 0) && (c < 0x80)) {
+ /* 1 character */
+ left--;
+ if ((int) left < 0) break;
+ /* convert classname */
+ if (isclassname && c == '.')
+ *pos++ = '/';
+ else
+ *pos++ = (char) c;
+
+ } else if (c < 0x800) {
+ /* 2 characters */
+ unsigned char high = c >> 6;
+ unsigned char low = c & 0x3F;
+ left = left - 2;
+ if ((int) left < 0) break;
+ *pos++ = high | 0xC0;
+ *pos++ = low | 0x80;
+
+ } else {
+ /* 3 characters */
+ char low = c & 0x3f;
+ char mid = (c >> 6) & 0x3F;
+ char high = c >> 12;
+ left = left - 3;
+ if ((int) left < 0) break;
+ *pos++ = high | 0xE0;
+ *pos++ = mid | 0x80;
+ *pos++ = low | 0x80;
+ }
+ }
+
+ /* insert utf-string into symbol-table */
+ result = utf_new(buffer,buflength);
+
+ MFREE(buffer, char, buflength);
+
+ return result;
+}
+
+
+/* utf_new_char ****************************************************************
+
+ Creates a new utf symbol, the text for this symbol is passed as a
+ c-string ( = char* ).
+
+*******************************************************************************/
+
+utf *utf_new_char(const char *text)
+{
+ return utf_new(text, strlen(text));
+}
+
+
+/* utf_new_char_classname ******************************************************
+
+ Creates a new utf symbol, the text for this symbol is passed as a
+ c-string ( = char* ) "." characters are going to be replaced by
+ "/". Since the above function is used often, this is a separte
+ function, instead of an if.
+
+*******************************************************************************/
+
+utf *utf_new_char_classname(const char *text)
+{
+ if (strchr(text, '.')) {
+ char *txt = strdup(text);
+ char *end = txt + strlen(txt);
+ char *c;
+ utf *tmpRes;
+
+ for (c = txt; c < end; c++)
+ if (*c == '.') *c = '/';
+
+ tmpRes = utf_new(txt, strlen(txt));
+ FREE(txt, 0);
+
+ return tmpRes;
+
+ } else
+ return utf_new(text, strlen(text));
+}
+
+
+/* utf_nextu2 ******************************************************************
+
+ Read the next unicode character from the utf string and increment
+ the utf-string pointer accordingly.
+
+ CAUTION: This function is unsafe for input that was not checked
+ by is_valid_utf!
+
+*******************************************************************************/
+
+u2 utf_nextu2(char **utf_ptr)
+{
+ /* uncompressed unicode character */
+ u2 unicode_char = 0;
+ /* current position in utf text */
+ unsigned char *utf = (unsigned char *) (*utf_ptr);
+ /* bytes representing the unicode character */
+ unsigned char ch1, ch2, ch3;
+ /* number of bytes used to represent the unicode character */
+ int len = 0;
+
+ switch ((ch1 = utf[0]) >> 4) {
+ default: /* 1 byte */
+ (*utf_ptr)++;
+ return (u2) ch1;
+ case 0xC:
+ case 0xD: /* 2 bytes */
+ if (((ch2 = utf[1]) & 0xC0) == 0x80) {
+ unsigned char high = ch1 & 0x1F;
+ unsigned char low = ch2 & 0x3F;
+ unicode_char = (high << 6) + low;
+ len = 2;
+ }
+ break;
+
+ case 0xE: /* 2 or 3 bytes */
+ if (((ch2 = utf[1]) & 0xC0) == 0x80) {
+ if (((ch3 = utf[2]) & 0xC0) == 0x80) {
+ unsigned char low = ch3 & 0x3f;
+ unsigned char mid = ch2 & 0x3f;
+ unsigned char high = ch1 & 0x0f;
+ unicode_char = (((high << 6) + mid) << 6) + low;
+ len = 3;
+ } else
+ len = 2;
+ }
+ break;
+ }
+
+ /* update position in utf-text */
+ *utf_ptr = (char *) (utf + len);
+
+ return unicode_char;
+}
+
+
+/* utf_bytes *******************************************************************
+
+ Determine number of bytes (aka. octets) in the utf string.
+
+ IN:
+ u............utf string
+
+ OUT:
+ The number of octets of this utf string.
+ There is _no_ terminating zero included in this count.
+
+*******************************************************************************/
+
+u4 utf_bytes(utf *u)
+{
+ return u->blength;
+}
+
+
+/* utf_get_number_of_u2s_for_buffer ********************************************
+
+ Determine number of UTF-16 u2s in the given UTF-8 buffer
+
+ CAUTION: This function is unsafe for input that was not checked
+ by is_valid_utf!
+
+ CAUTION: Use this function *only* when you want to convert an UTF-8 buffer
+ to an array of u2s (UTF-16) and want to know how many of them you will get.
+ All other uses of this function are probably wrong.
+
+ IN:
+ buffer........points to first char in buffer
+ blength.......number of _bytes_ in the buffer
+
+ OUT:
+ the number of u2s needed to hold this string in UTF-16 encoding.
+ There is _no_ terminating zero included in this count.
+
+ NOTE: Unlike utf_get_number_of_u2s, this function never throws an
+ exception.
+
+*******************************************************************************/
+
+u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength)
+{
+ const char *endpos; /* points behind utf string */
+ const char *utf_ptr; /* current position in utf text */
+ u4 len = 0; /* number of unicode characters */
+
+ utf_ptr = buffer;
+ endpos = utf_ptr + blength;
+
+ while (utf_ptr < endpos) {
+ len++;
+ /* next unicode character */
+ utf_nextu2((char **)&utf_ptr);
+ }
+
+ assert(utf_ptr == endpos);
+
+ return len;
+}
+
+
+/* utf_get_number_of_u2s *******************************************************
+
+ Determine number of UTF-16 u2s in the utf string.
+
+ CAUTION: This function is unsafe for input that was not checked
+ by is_valid_utf!
+
+ CAUTION: Use this function *only* when you want to convert a utf string
+ to an array of u2s and want to know how many of them you will get.
+ All other uses of this function are probably wrong.
+
+ IN:
+ u............utf string
+
+ OUT:
+ the number of u2s needed to hold this string in UTF-16 encoding.
+ There is _no_ terminating zero included in this count.
+ XXX 0 if a NullPointerException has been thrown (see below)
+
+*******************************************************************************/
+
+u4 utf_get_number_of_u2s(utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u4 len = 0; /* number of unicode characters */
+
+ /* XXX this is probably not checked by most callers! Review this after */
+ /* the invalid uses of this function have been eliminated */
+ if (u == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ len++;
+ /* next unicode character */
+ utf_nextu2(&utf_ptr);
+ }
+
+ if (utf_ptr != endpos) {
+ /* string ended abruptly */
+ exceptions_throw_internalerror("Illegal utf8 string");
+ return 0;
+ }
+
+ return len;
+}
+
+
+/* utf8_safe_number_of_u2s *****************************************************
+
+ Determine number of UTF-16 u2s needed for decoding the given UTF-8 string.
+ (For invalid UTF-8 the U+fffd replacement character will be counted.)
+
+ This function is safe even for invalid UTF-8 strings.
+
+ IN:
+ text..........zero-terminated(!) UTF-8 string (may be invalid)
+ must NOT be NULL
+ nbytes........strlen(text). (This is needed to completely emulate
+ the RI).
+
+ OUT:
+ the number of u2s needed to hold this string in UTF-16 encoding.
+ There is _no_ terminating zero included in this count.
+
+*******************************************************************************/
+
+s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes) {
+ register const unsigned char *t;
+ register s4 byte;
+ register s4 len;
+ register const unsigned char *tlimit;
+ s4 byte1;
+ s4 byte2;
+ s4 byte3;
+ s4 value;
+ s4 skip;
+
+ assert(text);
+ assert(nbytes >= 0);
+
+ len = 0;
+ t = (const unsigned char *) text;
+ tlimit = t + nbytes;
+
+ /* CAUTION: Keep this code in sync with utf8_safe_convert_to_u2s! */
+
+ while (1) {
+ byte = *t++;
+
+ if (byte & 0x80) {
+ /* highest bit set, non-ASCII character */
+
+ if ((byte & 0xe0) == 0xc0) {
+ /* 2-byte: should be 110..... 10...... ? */
+
+ if ((*t++ & 0xc0) == 0x80)
+ ; /* valid 2-byte */
+ else
+ t--; /* invalid */
+ }
+ else if ((byte & 0xf0) == 0xe0) {
+ /* 3-byte: should be 1110.... 10...... 10...... */
+ /* ^t */
+
+ if (t + 2 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ if ((*t++ & 0xc0) == 0x80) {
+ if ((*t++ & 0xc0) == 0x80)
+ ; /* valid 3-byte */
+ else
+ t--; /* invalid */
+ }
+ else
+ t--; /* invalid */
+ }
+ else if ((byte & 0xf8) == 0xf0) {
+ /* 4-byte: should be 11110... 10...... 10...... 10...... */
+ /* ^t */
+
+ if (t + 3 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ if (((byte2 = *t++) & 0xc0) == 0x80) {
+ if (((byte3 = *t++) & 0xc0) == 0x80) {
+ /* valid 4-byte UTF-8? */
+ value = ((byte & 0x07) << 18)
+ | ((byte1 & 0x3f) << 12)
+ | ((byte2 & 0x3f) << 6)
+ | ((byte3 & 0x3f) );
+
+ if (value > 0x10FFFF)
+ ; /* invalid */
+ else if (value > 0xFFFF)
+ len += 1; /* we need surrogates */
+ else
+ ; /* 16bit suffice */
+ }
+ else
+ t--; /* invalid */
+ }
+ else
+ t--; /* invalid */
+ }
+ else
+ t--; /* invalid */
+ }
+ else if ((byte & 0xfc) == 0xf8) {
+ /* invalid 5-byte */
+ if (t + 4 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ skip = 4;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ }
+ else if ((byte & 0xfe) == 0xfc) {
+ /* invalid 6-byte */
+ if (t + 5 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ skip = 5;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ }
+ else
+ ; /* invalid */
+ }
+ else {
+ /* NUL */
+
+ if (byte == 0)
+ break;
+
+ /* ASCII character, common case */
+ }
+
+ len++;
+ }
+
+ return len;
+}
+
+
+/* utf8_safe_convert_to_u2s ****************************************************
+
+ Convert the given UTF-8 string to UTF-16 into a pre-allocated buffer.
+ (Invalid UTF-8 will be replaced with the U+fffd replacement character.)
+ Use utf8_safe_number_of_u2s to determine the number of u2s to allocate.
+
+ This function is safe even for invalid UTF-8 strings.
+
+ IN:
+ text..........zero-terminated(!) UTF-8 string (may be invalid)
+ must NOT be NULL
+ nbytes........strlen(text). (This is needed to completely emulate
+ the RI).
+ buffer........a preallocated array of u2s to receive the decoded
+ string. Use utf8_safe_number_of_u2s to get the
+ required number of u2s for allocating this.
+
+*******************************************************************************/
+
+#define UNICODE_REPLACEMENT 0xfffd
+
+void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer) {
+ register const unsigned char *t;
+ register s4 byte;
+ register const unsigned char *tlimit;
+ s4 byte1;
+ s4 byte2;
+ s4 byte3;
+ s4 value;
+ s4 skip;
+
+ assert(text);
+ assert(nbytes >= 0);
+
+ t = (const unsigned char *) text;
+ tlimit = t + nbytes;
+
+ /* CAUTION: Keep this code in sync with utf8_safe_number_of_u2s! */
+
+ while (1) {
+ byte = *t++;
+
+ if (byte & 0x80) {
+ /* highest bit set, non-ASCII character */
+
+ if ((byte & 0xe0) == 0xc0) {
+ /* 2-byte: should be 110..... 10...... */
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ /* valid 2-byte UTF-8 */
+ *buffer++ = ((byte & 0x1f) << 6)
+ | ((byte1 & 0x3f) );
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else if ((byte & 0xf0) == 0xe0) {
+ /* 3-byte: should be 1110.... 10...... 10...... */
+
+ if (t + 2 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ if (((byte2 = *t++) & 0xc0) == 0x80) {
+ /* valid 3-byte UTF-8 */
+ *buffer++ = ((byte & 0x0f) << 12)
+ | ((byte1 & 0x3f) << 6)
+ | ((byte2 & 0x3f) );
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else if ((byte & 0xf8) == 0xf0) {
+ /* 4-byte: should be 11110... 10...... 10...... 10...... */
+
+ if (t + 3 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ if (((byte2 = *t++) & 0xc0) == 0x80) {
+ if (((byte3 = *t++) & 0xc0) == 0x80) {
+ /* valid 4-byte UTF-8? */
+ value = ((byte & 0x07) << 18)
+ | ((byte1 & 0x3f) << 12)
+ | ((byte2 & 0x3f) << 6)
+ | ((byte3 & 0x3f) );
+
+ if (value > 0x10FFFF) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else if (value > 0xFFFF) {
+ /* we need surrogates */
+ *buffer++ = 0xd800 | ((value >> 10) - 0x40);
+ *buffer++ = 0xdc00 | (value & 0x03ff);
+ }
+ else
+ *buffer++ = value; /* 16bit suffice */
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else if ((byte & 0xfc) == 0xf8) {
+ if (t + 4 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ skip = 4;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else if ((byte & 0xfe) == 0xfc) {
+ if (t + 5 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ skip = 5;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else {
+ /* NUL */
+
+ if (byte == 0)
+ break;
+
+ /* ASCII character, common case */
+
+ *buffer++ = byte;
+ }
+ }
+}
+
+
+/* u2_utflength ****************************************************************
+
+ Returns the utf length in bytes of a u2 array.
+
+*******************************************************************************/
+
+u4 u2_utflength(u2 *text, u4 u2_length)
+{
+ u4 result_len = 0; /* utf length in bytes */
+ u2 ch; /* current unicode character */
+ u4 len;
+
+ for (len = 0; len < u2_length; len++) {
+ /* next unicode character */
+ ch = *text++;
+
+ /* determine bytes required to store unicode character as utf */
+ if (ch && (ch < 0x80))
+ result_len++;
+ else if (ch < 0x800)
+ result_len += 2;
+ else
+ result_len += 3;
+ }
+
+ return result_len;
+}
+
+
+/* utf_copy ********************************************************************
+
+ Copy the given utf string byte-for-byte to a buffer.
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_copy(char *buffer, utf *u)
+{
+ /* our utf strings are zero-terminated (done by utf_new) */
+ MCOPY(buffer, u->text, char, u->blength + 1);
+}
+
+
+/* utf_cat *********************************************************************
+
+ Append the given utf string byte-for-byte to a buffer.
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_cat(char *buffer, utf *u)
+{
+ /* our utf strings are zero-terminated (done by utf_new) */
+ MCOPY(buffer + strlen(buffer), u->text, char, u->blength + 1);
+}
+
+
+/* utf_copy_classname **********************************************************
+
+ Copy the given utf classname byte-for-byte to a buffer.
+ '/' is replaced by '.'
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_copy_classname(char *buffer, utf *u)
+{
+ char *bufptr;
+ char *srcptr;
+ char *endptr;
+ char ch;
+
+ bufptr = buffer;
+ srcptr = u->text;
+ endptr = UTF_END(u) + 1; /* utfs are zero-terminared by utf_new */
+
+ while (srcptr != endptr) {
+ ch = *srcptr++;
+ if (ch == '/')
+ ch = '.';
+ *bufptr++ = ch;
+ }
+}
+
+
+/* utf_cat *********************************************************************
+
+ Append the given utf classname byte-for-byte to a buffer.
+ '/' is replaced by '.'
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_cat_classname(char *buffer, utf *u)
+{
+ utf_copy_classname(buffer + strlen(buffer), u);
+}
+
+/* utf_display_printable_ascii *************************************************
+
+ Write utf symbol to stdout (for debugging purposes).
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_display_printable_ascii(utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (u == NULL) {
+ printf("NULL");
+ fflush(stdout);
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+
+ u2 c = utf_nextu2(&utf_ptr);
+
+ if ((c >= 32) && (c <= 127))
+ printf("%c", c);
+ else
+ printf("?");
+ }
+
+ fflush(stdout);
+}
+
+
+/* utf_display_printable_ascii_classname ***************************************
+
+ Write utf symbol to stdout with `/' converted to `.' (for debugging
+ purposes).
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_display_printable_ascii_classname(utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (u == NULL) {
+ printf("NULL");
+ fflush(stdout);
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+
+ u2 c = utf_nextu2(&utf_ptr);
+
+ if (c == '/')
+ c = '.';
+
+ if ((c >= 32) && (c <= 127))
+ printf("%c", c);
+ else
+ printf("?");
+ }
+
+ fflush(stdout);
+}
+
+
+/* utf_sprint_convert_to_latin1 ************************************************
+
+ Write utf symbol into c-string (for debugging purposes).
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_sprint_convert_to_latin1(char *buffer, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u2 pos = 0; /* position in c-string */
+
+ if (!u) {
+ strcpy(buffer, "NULL");
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos)
+ /* copy next unicode character */
+ buffer[pos++] = utf_nextu2(&utf_ptr);
+
+ /* terminate string */
+ buffer[pos] = '\0';
+}
+
+
+/* utf_sprint_convert_to_latin1_classname **************************************
+
+ Write utf symbol into c-string with `/' converted to `.' (for debugging
+ purposes).
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u2 pos = 0; /* position in c-string */
+
+ if (!u) {
+ strcpy(buffer, "NULL");
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* copy next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+ if (c == '/') c = '.';
+ buffer[pos++] = c;
+ }
+
+ /* terminate string */
+ buffer[pos] = '\0';
+}
+
+
+/* utf_strcat_convert_to_latin1 ************************************************
+
+ Like libc strcat, but uses an utf8 string.
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_strcat_convert_to_latin1(char *buffer, utf *u)
+{
+ utf_sprint_convert_to_latin1(buffer + strlen(buffer), u);
+}
+
+
+/* utf_strcat_convert_to_latin1_classname **************************************
+
+ Like libc strcat, but uses an utf8 string.
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u)
+{
+ utf_sprint_convert_to_latin1_classname(buffer + strlen(buffer), u);
+}
+
+
+/* utf_fprint_printable_ascii **************************************************
+
+ Write utf symbol into file.
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_fprint_printable_ascii(FILE *file, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (!u)
+ return;
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+
+ if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+ else fprintf(file, "?");
+ }
+}
+
+
+/* utf_fprint_printable_ascii_classname ****************************************
+
+ Write utf symbol into file with `/' converted to `.'.
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_fprint_printable_ascii_classname(FILE *file, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (!u)
+ return;
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+ if (c == '/') c = '.';
+
+ if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+ else fprintf(file, "?");
+ }
+}
+
+
+/* is_valid_utf ****************************************************************
+
+ Return true if the given string is a valid UTF-8 string.
+
+ utf_ptr...points to first character
+ end_pos...points after last character
+
+*******************************************************************************/
+
+/* static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26}; */
+
+bool is_valid_utf(char *utf_ptr, char *end_pos)
+{
+ int bytes;
+ int len,i;
+ char c;
+ unsigned long v;
+
+ if (end_pos < utf_ptr) return false;
+ bytes = end_pos - utf_ptr;
+ while (bytes--) {
+ c = *utf_ptr++;
+
+ if (!c) return false; /* 0x00 is not allowed */
+ if ((c & 0x80) == 0) continue; /* ASCII */
+
+ if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
+ else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
+ else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
+ else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
+ else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
+ else return false; /* invalid leading byte */
+
+ if (len > 2) return false; /* Java limitation */
+
+ v = (unsigned long)c & (0x3f >> len);
+
+ if ((bytes -= len) < 0) return false; /* missing bytes */
+
+ for (i = len; i--; ) {
+ c = *utf_ptr++;
+ if ((c & 0xc0) != 0x80) /* 10xx xxxx */
+ return false;
+ v = (v << 6) | (c & 0x3f);
+ }
+
+ if (v == 0) {
+ if (len != 1) return false; /* Java special */
+
+ } else {
+ /* Sun Java seems to allow overlong UTF-8 encodings */
+
+ /* if (v < min_codepoint[len]) */
+ /* XXX throw exception? */
+ }
+
+ /* surrogates in UTF-8 seem to be allowed in Java classfiles */
+ /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
+
+ /* even these seem to be allowed */
+ /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
+ }
+
+ return true;
+}
+
+
+/* is_valid_name ***************************************************************
+
+ Return true if the given string may be used as a class/field/method
+ name. (Currently this only disallows empty strings and control
+ characters.)
+
+ NOTE: The string is assumed to have passed is_valid_utf!
+
+ utf_ptr...points to first character
+ end_pos...points after last character
+
+*******************************************************************************/
+
+bool is_valid_name(char *utf_ptr, char *end_pos)
+{
+ if (end_pos <= utf_ptr) return false; /* disallow empty names */
+
+ while (utf_ptr < end_pos) {
+ unsigned char c = *utf_ptr++;
+
+ if (c < 0x20) return false; /* disallow control characters */
+ if (c == 0xc0 && (unsigned char) *utf_ptr == 0x80) /* disallow zero */
+ return false;
+ }
+
+ return true;
+}
+
+bool is_valid_name_utf(utf *u)
+{
+ return is_valid_name(u->text, UTF_END(u));
+}
+
+
+/* utf_show ********************************************************************
+
+ Writes the utf symbols in the utfhash to stdout and displays the
+ number of external hash chains grouped according to the chainlength
+ (for debugging purposes).
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void utf_show(void)
+{
+
+#define CHAIN_LIMIT 20 /* limit for seperated enumeration */
+
+ u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
+ u4 max_chainlength = 0; /* maximum length of the chains */
+ u4 sum_chainlength = 0; /* sum of the chainlengths */
+ u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
+ u4 i;
+
+ printf("UTF-HASH:\n");
+
+ /* show element of utf-hashtable */
+
+ for (i = 0; i < hashtable_utf->size; i++) {
+ utf *u = hashtable_utf->ptr[i];
+
+ if (u) {
+ printf("SLOT %d: ", (int) i);
+
+ while (u) {
+ printf("'");
+ utf_display_printable_ascii(u);
+ printf("' ");
+ u = u->hashlink;
+ }
+ printf("\n");
+ }
+ }
+
+ printf("UTF-HASH: %d slots for %d entries\n",
+ (int) hashtable_utf->size, (int) hashtable_utf->entries );
+
+ if (hashtable_utf->entries == 0)
+ return;
+
+ printf("chains:\n chainlength number of chains %% of utfstrings\n");
+
+ for (i=0;i<CHAIN_LIMIT;i++)
+ chain_count[i]=0;
+
+ /* count numbers of hashchains according to their length */
+ for (i=0; i<hashtable_utf->size; i++) {
+
+ utf *u = (utf*) hashtable_utf->ptr[i];
+ u4 chain_length = 0;
+
+ /* determine chainlength */
+ while (u) {
+ u = u->hashlink;
+ chain_length++;
+ }
+
+ /* update sum of all chainlengths */
+ sum_chainlength+=chain_length;
+
+ /* determine the maximum length of the chains */
+ if (chain_length>max_chainlength)
+ max_chainlength = chain_length;
+
+ /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
+ if (chain_length>=CHAIN_LIMIT) {
+ beyond_limit+=chain_length;
+ chain_length=CHAIN_LIMIT-1;
+ }
+
+ /* update number of hashchains of current length */
+ chain_count[chain_length]++;
+ }
+
+ /* display results */
+ for (i=1;i<CHAIN_LIMIT-1;i++)
+ printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/hashtable_utf->entries));
+
+ printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/hashtable_utf->entries);
+
+
+ printf("max. chainlength:%5d\n",max_chainlength);
+
+ /* avg. chainlength = sum of chainlengths / number of chains */
+ printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (hashtable_utf->size-chain_count[0]));
+}
+#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/utf8.h - utf8 string 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.
+
+*/
+
+
+#ifndef _UTF_H
+#define _UTF_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct utf utf;
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+
+/* data structure for utf8 symbols ********************************************/
+
+struct utf {
+ utf *hashlink; /* link for external hash chain */
+ s4 blength; /* text length in bytes */
+ char *text; /* pointer to text */
+};
+
+/* to determine the end of utf strings */
+
+#define UTF_END(u) ((char *) u->text + u->blength)
+
+
+/* utf-symbols for pointer comparison of frequently used strings **************/
+
+extern utf *utf_java_lang_Object;
+
+extern utf *utf_java_lang_Class;
+extern utf *utf_java_lang_ClassLoader;
+extern utf *utf_java_lang_Cloneable;
+extern utf *utf_java_lang_SecurityManager;
+extern utf *utf_java_lang_String;
+extern utf *utf_java_lang_ThreadGroup;
+extern utf *utf_java_lang_ref_SoftReference;
+extern utf *utf_java_lang_ref_WeakReference;
+extern utf *utf_java_lang_ref_PhantomReference;
+extern utf *utf_java_io_Serializable;
+
+extern utf *utf_java_lang_Throwable;
+extern utf *utf_java_lang_Error;
+
+extern utf *utf_java_lang_AbstractMethodError;
+extern utf *utf_java_lang_ClassCircularityError;
+extern utf *utf_java_lang_ClassFormatError;
+extern utf *utf_java_lang_ExceptionInInitializerError;
+extern utf *utf_java_lang_IncompatibleClassChangeError;
+extern utf *utf_java_lang_InstantiationError;
+extern utf *utf_java_lang_InternalError;
+extern utf *utf_java_lang_LinkageError;
+extern utf *utf_java_lang_NoClassDefFoundError;
+extern utf *utf_java_lang_NoSuchFieldError;
+extern utf *utf_java_lang_NoSuchMethodError;
+extern utf *utf_java_lang_OutOfMemoryError;
+extern utf *utf_java_lang_UnsatisfiedLinkError;
+extern utf *utf_java_lang_UnsupportedClassVersionError;
+extern utf *utf_java_lang_VerifyError;
+extern utf *utf_java_lang_VirtualMachineError;
+
+extern utf *utf_java_lang_Exception;
+
+extern utf *utf_java_lang_ArithmeticException;
+extern utf *utf_java_lang_ArrayIndexOutOfBoundsException;
+extern utf *utf_java_lang_ArrayStoreException;
+extern utf *utf_java_lang_ClassCastException;
+extern utf *utf_java_lang_ClassNotFoundException;
+extern utf *utf_java_lang_CloneNotSupportedException;
+extern utf *utf_java_lang_IllegalAccessException;
+extern utf *utf_java_lang_IllegalArgumentException;
+extern utf *utf_java_lang_IllegalMonitorStateException;
+extern utf *utf_java_lang_InstantiationException;
+extern utf *utf_java_lang_InterruptedException;
+extern utf *utf_java_lang_NegativeArraySizeException;
+extern utf *utf_java_lang_NullPointerException;
+extern utf *utf_java_lang_RuntimeException;
+extern utf *utf_java_lang_StringIndexOutOfBoundsException;
+
+extern utf *utf_java_lang_reflect_InvocationTargetException;
+
+extern utf *utf_java_security_PrivilegedActionException;
+
+#if defined(ENABLE_JAVASE)
+extern utf* utf_java_lang_Void;
+#endif
+
+extern utf* utf_java_lang_Boolean;
+extern utf* utf_java_lang_Byte;
+extern utf* utf_java_lang_Character;
+extern utf* utf_java_lang_Short;
+extern utf* utf_java_lang_Integer;
+extern utf* utf_java_lang_Long;
+extern utf* utf_java_lang_Float;
+extern utf* utf_java_lang_Double;
+
+#if defined(ENABLE_JAVASE)
+extern utf *utf_java_lang_StackTraceElement;
+extern utf *utf_java_lang_reflect_Constructor;
+extern utf *utf_java_lang_reflect_Field;
+extern utf *utf_java_lang_reflect_Method;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern utf *utf_java_lang_reflect_VMConstructor;
+extern utf *utf_java_lang_reflect_VMField;
+extern utf *utf_java_lang_reflect_VMMethod;
+# endif
+
+extern utf *utf_java_util_Vector;
+#endif
+
+extern utf *utf_InnerClasses;
+extern utf *utf_ConstantValue;
+extern utf *utf_Code;
+extern utf *utf_Exceptions;
+extern utf *utf_LineNumberTable;
+extern utf *utf_SourceFile;
+
+#if defined(ENABLE_JAVASE)
+extern utf *utf_EnclosingMethod;
+extern utf *utf_Signature;
+extern utf *utf_StackMapTable;
+
+#if defined(ENABLE_ANNOTATIONS)
+extern utf *utf_RuntimeVisibleAnnotations;
+extern utf *utf_RuntimeInvisibleAnnotations;
+extern utf *utf_RuntimeVisibleParameterAnnotations;
+extern utf *utf_RuntimeInvisibleParameterAnnotations;
+extern utf *utf_AnnotationDefault;
+#endif
+#endif
+
+extern utf *utf_init;
+extern utf *utf_clinit;
+extern utf *utf_clone;
+extern utf *utf_finalize;
+extern utf *utf_invoke;
+extern utf *utf_main;
+extern utf *utf_run;
+
+extern utf *utf_add;
+extern utf *utf_dispatch;
+extern utf *utf_remove;
+extern utf *utf_addThread;
+extern utf *utf_removeThread;
+extern utf *utf_put;
+extern utf *utf_get;
+extern utf *utf_uncaughtException;
+extern utf *utf_value;
+
+extern utf *utf_fillInStackTrace;
+extern utf *utf_findNative;
+extern utf *utf_getSystemClassLoader;
+extern utf *utf_initCause;
+extern utf *utf_loadClass;
+extern utf *utf_loadClassInternal;
+extern utf *utf_printStackTrace;
+
+extern utf *utf_division_by_zero;
+
+extern utf *utf_Z;
+extern utf *utf_B;
+extern utf *utf_C;
+extern utf *utf_S;
+extern utf *utf_I;
+extern utf *utf_J;
+extern utf *utf_F;
+extern utf *utf_D;
+
+extern utf *utf_void__void;
+extern utf *utf_boolean__void;
+extern utf *utf_byte__void;
+extern utf *utf_char__void;
+extern utf *utf_short__void;
+extern utf *utf_int__void;
+extern utf *utf_long__void;
+extern utf *utf_float__void;
+extern utf *utf_double__void;
+
+extern utf *utf_void__java_lang_ClassLoader;
+extern utf *utf_void__java_lang_Object;
+extern utf *utf_void__java_lang_Throwable;
+extern utf *utf_java_lang_ClassLoader_java_lang_String__J;
+extern utf *utf_java_lang_Exception__V;
+extern utf *utf_java_lang_Object__java_lang_Object;
+extern utf *utf_java_lang_String__void;
+extern utf *utf_java_lang_String__java_lang_Class;
+extern utf *utf_java_lang_Thread__V;
+extern utf *utf_java_lang_Thread_java_lang_Throwable__V;
+extern utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
+extern utf *utf_java_lang_Throwable__void;
+extern utf *utf_java_lang_Throwable__java_lang_Throwable;
+
+extern utf *utf_not_named_yet;
+extern utf *utf_null;
+extern utf *array_packagename;
+
+
+/* function prototypes ********************************************************/
+
+/* initialize the utf8 subsystem */
+void utf8_init(void);
+
+u4 utf_hashkey(const char *text, u4 length);
+u4 utf_full_hashkey(const char *text, u4 length);
+
+/* determine hashkey of a unicode-symbol */
+u4 unicode_hashkey(u2 *text, u2 length);
+
+/* create new utf-symbol */
+utf *utf_new(const char *text, u2 length);
+
+/* make utf symbol from u2 array */
+utf *utf_new_u2(u2 *unicodedata, u4 unicodelength, bool isclassname);
+
+utf *utf_new_char(const char *text);
+utf *utf_new_char_classname(const char *text);
+
+/* get number of bytes */
+u4 utf_bytes(utf *u);
+
+/* get next unicode character of a utf-string */
+u2 utf_nextu2(char **utf);
+
+/* get (number of) unicode characters of a utf string (safe) */
+s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes);
+void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer);
+
+/* get (number of) unicode characters of a utf string (UNSAFE!) */
+u4 utf_get_number_of_u2s(utf *u);
+u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength);
+
+/* determine utf length in bytes of a u2 array */
+u4 u2_utflength(u2 *text, u4 u2_length);
+
+void utf_copy(char *buffer, utf *u);
+void utf_cat(char *buffer, utf *u);
+void utf_copy_classname(char *buffer, utf *u);
+void utf_cat_classname(char *buffer, utf *u);
+
+/* write utf symbol to file/buffer */
+void utf_display_printable_ascii(utf *u);
+void utf_display_printable_ascii_classname(utf *u);
+
+void utf_sprint_convert_to_latin1(char *buffer, utf *u);
+void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u);
+
+void utf_strcat_convert_to_latin1(char *buffer, utf *u);
+void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u);
+
+void utf_fprint_printable_ascii(FILE *file, utf *u);
+void utf_fprint_printable_ascii_classname(FILE *file, utf *u);
+
+/* check if a UTF-8 string is valid */
+bool is_valid_utf(char *utf_ptr, char *end_pos);
+
+/* check if a UTF-8 string may be used as a class/field/method name */
+bool is_valid_name(char *utf_ptr, char *end_pos);
+bool is_valid_name_utf(utf *u);
+
+/* show utf-table */
+void utf_show(void);
+
+#endif /* _UTF_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:
+ */
+++ /dev/null
-/* src/vm/vm.c - 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 <assert.h>
-#include <errno.h>
-#include <stdint.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-common.h"
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h" /* required by j.l.C */
-#include "native/include/java_lang_String.h" /* required by j.l.C */
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-# include "native/include/java_lang_ClassLoader.h" /* required by j.l.C */
-#endif
-
-#include "native/include/java_lang_Class.h"
-
-#include "native/vm/nativevm.h"
-
-#include "threads/lock-common.h"
-#include "threads/mutex.h"
-#include "threads/threadlist.h"
-#include "threads/thread.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/array.h"
-
-#if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
-#endif
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/finalizer.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-#include "vm/package.hpp"
-#include "vm/primitive.h"
-#include "vm/properties.h"
-#include "vm/signallocal.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/argument.h"
-#include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
-#include "vm/jit/jitcache.h"
-
-#if defined(ENABLE_DISASSEMBLER)
-# include "vm/jit/disass.h"
-#endif
-
-#include "vm/jit/jit.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"
-
-#include "vmcore/classcache.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vmcore/suck.h"
-#include "vmcore/system.h"
-
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-
-/* Invocation API variables ***************************************************/
-
-_Jv_JavaVM *_Jv_jvm; /* denotes a Java VM */
-_Jv_JNIEnv *_Jv_env; /* pointer to native method interface */
-
-
-/* global variables ***********************************************************/
-
-s4 vms = 0; /* number of VMs created */
-
-bool vm_initializing = false;
-bool vm_created = false;
-bool vm_exiting = false;
-
-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
-
-
-/* vm_createjvm ****************************************************************
-
- Implementation for JNI_CreateJavaVM.
-
-*******************************************************************************/
-
-bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args)
-{
- JavaVMInitArgs *_vm_args;
- _Jv_JNIEnv *env;
- _Jv_JavaVM *vm;
-
- /* get the arguments for the new JVM */
-
- _vm_args = (JavaVMInitArgs *) vm_args;
-
- /* get the VM and Env tables (must be set before vm_create) */
-
- env = NEW(_Jv_JNIEnv);
-
-#if defined(ENABLE_JNI)
- env->env = &_Jv_JNINativeInterface;
-#endif
-
- /* XXX Set the global variable. Maybe we should do that differently. */
-
- _Jv_env = env;
-
- /* create and fill a JavaVM structure */
-
- vm = NEW(_Jv_JavaVM);
-
-#if defined(ENABLE_JNI)
- vm->functions = &_Jv_JNIInvokeInterface;
-#endif
-
- /* XXX Set the global variable. Maybe we should do that differently. */
- /* XXX JVMTI Agents needs a JavaVM */
-
- _Jv_jvm = vm;
-
- /* actually create the JVM */
-
- if (!vm_create(_vm_args))
- goto error;
-
- /* now return the values */
-
- *p_vm = (JavaVM *) vm;
- *p_env = (void *) env;
-
- return true;
-
- error:
- /* release allocated memory */
-
- FREE(env, _Jv_JNIEnv);
- FREE(vm, _Jv_JavaVM);
-
- return false;
-}
-
-
-/* vm_create *******************************************************************
-
- Creates a JVM. Called by vm_createjvm.
-
-*******************************************************************************/
-
-bool vm_create(JavaVMInitArgs *vm_args)
-{
- int len;
- char *p;
- char *boot_class_path;
- char *class_path;
- int opt;
- int i, j;
- 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))
- return false;
-#endif
-
- /* We only support 1 JVM instance. */
-
- if (vms > 0)
- return false;
-
- /* 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/vmcore/class.h. */
-
- 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 */
-
- _Jv_jvm->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. */
-
- class_path = 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 (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. */
-
- boot_class_path = 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. */
-
- boot_class_path = properties_get("sun.boot.class.path");
-
- len = strlen(boot_class_path);
-
- p = 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. */
-
- boot_class_path = 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. */
-
- boot_class_path = 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;
- 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 (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 (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 (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 (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 this JVM ****************************************************/
-
- vm_initializing = true;
-
- /* initialize the garbage collector */
-
- gc_init(opt_heapmaxsize, opt_heapstartsize);
-
-#if defined(ENABLE_THREADS)
- /* BEFORE: threads_preinit */
-
- threadlist_init();
-
- /* AFTER: gc_init (directly after, as this initializes the
- stopworldlock lock */
-
- threads_preinit();
- lock_init();
- critical_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 */
-
- boot_class_path = 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.. */
-
- vm_created = true;
- vm_initializing = false;
-
- /* Print the VM configuration after all stuff is set and the VM is
- initialized. */
-
- if (opt_PrintConfig)
- vm_printconfig();
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* 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;
- int i;
-
- // 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 (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 (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;
-
- /* 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 = "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. */
-
- vm_created = false;
-
- /* 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 */
-
- vm_exiting = true;
-
- 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. */
-
- system_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", system_strerror(errnum));
-
- log_finish();
-
- /* Now abort the VM. */
-
- system_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++)
- pc = disassinstr(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.decltype) {
- 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.decltype);
- }
-
- /* release dump area */
-
- DRELEASE;
-
- /* enter the nativeworld again */
-
- THREAD_NATIVEWORLD_ENTER;
-
- /* box the return value if necesarry */
-
- if (m->parseddesc->returntype.decltype != TYPE_ADR)
- ro = primitive_box(m->parseddesc->returntype.decltype, 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;
-}
-
-
-/*
- * 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/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:
+ */
+++ /dev/null
-/* src/vm/vm.h - basic JVM 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.
-
-*/
-
-
-#ifndef _VM_H
-#define _VM_H
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-
-
-/* export global variables ****************************************************/
-
-extern _Jv_JavaVM *_Jv_jvm;
-extern _Jv_JNIEnv *_Jv_env;
-
-extern bool vm_initializing;
-extern bool vm_created;
-extern bool vm_exiting;
-
-#if defined(ENABLE_INTRP)
-extern u1 *intrp_main_stack;
-#endif
-
-
-/* function prototypes ********************************************************/
-
-void usage(void);
-
-bool vm_createjvm(JavaVM **p_vm, void **p_env, void *vm_args);
-bool vm_create(JavaVMInitArgs *vm_args);
-void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args);
-s4 vm_destroy(JavaVM *vm);
-void vm_exit(s4 status);
-void vm_shutdown(s4 status);
-
-void vm_exit_handler(void);
-
-void vm_abort(const char *text, ...);
-void vm_abort_errnum(int errnum, const char *text, ...);
-void vm_abort_errno(const char *text, ...);
-void vm_abort_disassemble(void *pc, int count, const char *text, ...);
-
-/* Java method calling functions */
-
-java_handle_t *vm_call_method(methodinfo *m, java_handle_t *o, ...);
-java_handle_t *vm_call_method_valist(methodinfo *m, java_handle_t *o,
- va_list ap);
-java_handle_t *vm_call_method_jvalue(methodinfo *m, java_handle_t *o,
- const jvalue *args);
-
-int32_t vm_call_method_int(methodinfo *m, java_handle_t *o, ...);
-int32_t vm_call_method_int_valist(methodinfo *m, java_handle_t *o, va_list ap);
-int32_t vm_call_method_int_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
-
-int64_t vm_call_method_long(methodinfo *m, java_handle_t *o, ...);
-int64_t vm_call_method_long_valist(methodinfo *m, java_handle_t *o, va_list ap);
-int64_t vm_call_method_long_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
-
-float vm_call_method_float(methodinfo *m, java_handle_t *o, ...);
-float vm_call_method_float_valist(methodinfo *m, java_handle_t *o, va_list ap);
-float vm_call_method_float_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
-
-double vm_call_method_double(methodinfo *m, java_handle_t *o, ...);
-double vm_call_method_double_valist(methodinfo *m, java_handle_t *o, va_list ap);
-double vm_call_method_double_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
-
-java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params);
-
-#endif /* _VM_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:
- */
--- /dev/null
+/* src/vm/vm.hpp - basic JVM 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.
+
+*/
+
+
+#ifndef _VM_HPP
+#define _VM_HPP
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "native/jni.h"
+
+#include "vm/global.h"
+
+#include "vm/class.h"
+#include "vm/method.h"
+
+#ifdef __cplusplus
+
+/**
+ * Represent an instance of a VM.
+ */
+class VM {
+private:
+ // JNI variables.
+ JavaVM* _javavm;
+ JNIEnv* _jnienv;
+
+ // VM variables.
+ bool _initializing;
+ bool _created;
+ bool _exiting;
+ int64_t _starttime;
+
+public:
+ // Constructor, Destructor.
+ VM(JavaVMInitArgs*);
+ ~VM();
+
+ // Static methods.
+ static bool create(JavaVM** p_vm, void** p_env, void* vm_args);
+
+ // Getters for private members.
+ JavaVM* get_javavm() { return _javavm; }
+ JNIEnv* get_jnienv() { return _jnienv; }
+ bool is_initializing() { return _initializing; }
+ bool is_created() { return _created; }
+ bool is_exiting() { return _exiting; }
+ int64_t get_starttime() { return _starttime; }
+};
+
+
+/**
+ * This is _the_ instance of the VM.
+ */
+extern VM* vm;
+
+#else
+
+JavaVM* VM_get_javavm();
+JNIEnv* VM_get_jnienv();
+bool VM_is_initializing();
+bool VM_is_created();
+int64_t VM_get_starttime();
+
+#endif
+
+/* These C methods are the exported interface. ********************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool VM_create(JavaVM** p_vm, void** p_env, void* vm_args);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* export global variables ****************************************************/
+
+#if defined(ENABLE_INTRP)
+extern u1 *intrp_main_stack;
+#endif
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void usage(void);
+
+bool vm_create(JavaVMInitArgs *vm_args);
+void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args);
+s4 vm_destroy(JavaVM *vm);
+void vm_exit(s4 status);
+void vm_shutdown(s4 status);
+
+void vm_exit_handler(void);
+
+void vm_abort(const char *text, ...);
+void vm_abort_errnum(int errnum, const char *text, ...);
+void vm_abort_errno(const char *text, ...);
+void vm_abort_disassemble(void *pc, int count, const char *text, ...);
+
+/* Java method calling functions */
+
+java_handle_t *vm_call_method(methodinfo *m, java_handle_t *o, ...);
+java_handle_t *vm_call_method_valist(methodinfo *m, java_handle_t *o,
+ va_list ap);
+java_handle_t *vm_call_method_jvalue(methodinfo *m, java_handle_t *o,
+ const jvalue *args);
+
+int32_t vm_call_method_int(methodinfo *m, java_handle_t *o, ...);
+int32_t vm_call_method_int_valist(methodinfo *m, java_handle_t *o, va_list ap);
+int32_t vm_call_method_int_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
+
+int64_t vm_call_method_long(methodinfo *m, java_handle_t *o, ...);
+int64_t vm_call_method_long_valist(methodinfo *m, java_handle_t *o, va_list ap);
+int64_t vm_call_method_long_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
+
+float vm_call_method_float(methodinfo *m, java_handle_t *o, ...);
+float vm_call_method_float_valist(methodinfo *m, java_handle_t *o, va_list ap);
+float vm_call_method_float_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
+
+double vm_call_method_double(methodinfo *m, java_handle_t *o, ...);
+double vm_call_method_double_valist(methodinfo *m, java_handle_t *o, va_list ap);
+double vm_call_method_double_jvalue(methodinfo *m, java_handle_t *o, const jvalue *args);
+
+java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _VM_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
+/* src/vm/zip.c - ZIP file handling for bootstrap classloader
+
+ 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 <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <zlib.h>
+#include <sys/mman.h>
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "mm/memory.h"
+
+#include "vm/global.h"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+#include "vm/zip.h"
+
+
+/* start size for classes hashtable *******************************************/
+
+#define HASHTABLE_CLASSES_SIZE (1 << 10)
+
+
+/* info taken from:
+ http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
+*/
+
+/* all signatures in the ZIP file have a length of 4 bytes ********************/
+
+#define SIGNATURE_LENGTH 4
+
+/* Central directory structure *************************************************
+
+ [file header 1]
+ .
+ .
+ .
+ [file header n]
+ [digital signature]
+
+ File header:
+
+ central file header signature 4 bytes (0x02014b50)
+ version made by 2 bytes
+ version needed to extract 2 bytes
+ general purpose bit flag 2 bytes
+ compression method 2 bytes
+ last mod file time 2 bytes
+ last mod file date 2 bytes
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+ file name length 2 bytes
+ extra field length 2 bytes
+ file comment length 2 bytes
+ disk number start 2 bytes
+ internal file attributes 2 bytes
+ external file attributes 4 bytes
+ relative offset of local header 4 bytes
+
+ file name (variable size)
+ extra field (variable size)
+ file comment (variable size)
+
+ Digital signature:
+
+ header signature 4 bytes (0x05054b50)
+ size of data 2 bytes
+ signature data (variable size)
+
+*******************************************************************************/
+
+#define CDSFH_HEADER_SIZE 46
+
+#define CDSFH_SIGNATURE 0x02014b50
+#define CDSFH_COMPRESSION_METHOD 10
+#define CDSFH_COMPRESSED_SIZE 20
+#define CDSFH_UNCOMPRESSED_SIZE 24
+#define CDSFH_FILE_NAME_LENGTH 28
+#define CDSFH_EXTRA_FIELD_LENGTH 30
+#define CDSFH_FILE_COMMENT_LENGTH 32
+#define CDSFH_RELATIVE_OFFSET 42
+#define CDSFH_FILENAME 46
+
+typedef struct cdsfh cdsfh;
+
+struct cdsfh {
+ u2 compressionmethod;
+ u4 compressedsize;
+ u4 uncompressedsize;
+ u2 filenamelength;
+ u2 extrafieldlength;
+ u2 filecommentlength;
+ u4 relativeoffset;
+};
+
+
+/* End of central directory record *********************************************
+
+ end of central dir signature 4 bytes (0x06054b50)
+ number of this disk 2 bytes
+ number of the disk with the
+ start of the central directory 2 bytes
+ total number of entries in the
+ central directory on this disk 2 bytes
+ total number of entries in
+ the central directory 2 bytes
+ size of the central directory 4 bytes
+ offset of start of central
+ directory with respect to
+ the starting disk number 4 bytes
+ .ZIP file comment length 2 bytes
+ .ZIP file comment (variable size)
+
+*******************************************************************************/
+
+#define EOCDR_SIGNATURE 0x06054b50
+#define EOCDR_ENTRIES 10
+#define EOCDR_OFFSET 16
+
+typedef struct eocdr eocdr;
+
+struct eocdr {
+ u2 entries;
+ u4 offset;
+};
+
+
+/* zip_open ********************************************************************
+
+ XXX
+
+*******************************************************************************/
+
+hashtable *zip_open(char *path)
+{
+ hashtable *ht;
+ hashtable_zipfile_entry *htzfe;
+ int fd;
+ u1 lfh_signature[SIGNATURE_LENGTH];
+ off_t len;
+ u1 *filep;
+ s4 i;
+ u1 *p;
+ eocdr eocdr;
+ cdsfh cdsfh;
+ const char *filename;
+ const char *classext;
+ utf *u;
+ u4 key; /* hashkey computed from utf-text */
+ u4 slot; /* slot in hashtable */
+
+ /* first of all, open the file */
+
+ if ((fd = open(path, O_RDONLY)) == -1)
+ return NULL;
+
+ /* check for signature in first local file header */
+
+ if (read(fd, lfh_signature, SIGNATURE_LENGTH) != SIGNATURE_LENGTH)
+ return NULL;
+
+ if (SUCK_LE_U4(lfh_signature) != LFH_SIGNATURE)
+ return NULL;
+
+ /* get the file length */
+
+ if ((len = lseek(fd, 0, SEEK_END)) == -1)
+ return NULL;
+
+ /* we better mmap the file */
+
+ filep = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ /* some older compilers, like DEC OSF cc, don't like comparisons
+ on void* types */
+
+ if ((ptrint) filep == (ptrint) MAP_FAILED)
+ return NULL;
+
+ /* find end of central directory record */
+
+ for (p = filep + len; p >= filep; p--)
+ if (SUCK_LE_U4(p) == EOCDR_SIGNATURE)
+ break;
+
+ /* get number of entries in central directory */
+
+ eocdr.entries = SUCK_LE_U2(p + EOCDR_ENTRIES);
+ eocdr.offset = SUCK_LE_U4(p + EOCDR_OFFSET);
+
+ /* create hashtable for filenames */
+
+ ht = NEW(hashtable);
+
+ hashtable_create(ht, HASHTABLE_CLASSES_SIZE);
+
+ /* add all file entries into the hashtable */
+
+ for (i = 0, p = filep + eocdr.offset; i < eocdr.entries; i++) {
+ /* check file header signature */
+
+ if (SUCK_LE_U4(p) != CDSFH_SIGNATURE)
+ return NULL;
+
+ /* we found an entry */
+
+ cdsfh.compressionmethod = SUCK_LE_U2(p + CDSFH_COMPRESSION_METHOD);
+ cdsfh.compressedsize = SUCK_LE_U4(p + CDSFH_COMPRESSED_SIZE);
+ cdsfh.uncompressedsize = SUCK_LE_U4(p + CDSFH_UNCOMPRESSED_SIZE);
+ cdsfh.filenamelength = SUCK_LE_U2(p + CDSFH_FILE_NAME_LENGTH);
+ cdsfh.extrafieldlength = SUCK_LE_U2(p + CDSFH_EXTRA_FIELD_LENGTH);
+ cdsfh.filecommentlength = SUCK_LE_U2(p + CDSFH_FILE_COMMENT_LENGTH);
+ cdsfh.relativeoffset = SUCK_LE_U4(p + CDSFH_RELATIVE_OFFSET);
+
+ /* create utf8 string of filename, strip .class from classes */
+
+ filename = (const char *) (p + CDSFH_FILENAME);
+ classext = filename + cdsfh.filenamelength - strlen(".class");
+
+ /* skip directory entries */
+
+ if (filename[cdsfh.filenamelength - 1] != '/') {
+ if (strncmp(classext, ".class", strlen(".class")) == 0)
+ u = utf_new(filename, cdsfh.filenamelength - strlen(".class"));
+ else
+ u = utf_new(filename, cdsfh.filenamelength);
+
+ /* insert class into hashtable */
+
+ htzfe = NEW(hashtable_zipfile_entry);
+
+ htzfe->filename = u;
+ htzfe->compressionmethod = cdsfh.compressionmethod;
+ htzfe->compressedsize = cdsfh.compressedsize;
+ htzfe->uncompressedsize = cdsfh.uncompressedsize;
+ htzfe->data = filep + cdsfh.relativeoffset;
+
+ /* get hashtable slot */
+
+ key = utf_hashkey(u->text, u->blength);
+ slot = key & (ht->size - 1);
+
+ /* insert into external chain */
+
+ htzfe->hashlink = ht->ptr[slot];
+
+ /* insert hashtable zipfile entry */
+
+ ht->ptr[slot] = htzfe;
+ ht->entries++;
+ }
+
+ /* move to next central directory structure file header */
+
+ p = p +
+ CDSFH_HEADER_SIZE +
+ cdsfh.filenamelength +
+ cdsfh.extrafieldlength +
+ cdsfh.filecommentlength;
+ }
+
+ /* return pointer to hashtable */
+
+ return ht;
+}
+
+
+/* zip_find ********************************************************************
+
+ Search for the given filename in the classpath entries of a zip file.
+
+ NOTE: The '.class' extension is stripped when reading a zip file, so if
+ you want to find a .class file, you must search for its name _without_
+ the '.class' extension.
+ XXX I dont like that, it makes foo and foo.class ambiguous. -Edwin
+
+ IN:
+ lce..........the classpath entries for the zip file
+ u............the filename to look for
+
+ RETURN VALUE:
+ hashtable_zipfile_entry * of the entry if found, or
+ NULL if not found
+
+*******************************************************************************/
+
+hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u)
+{
+ hashtable *ht;
+ u4 key; /* hashkey computed from utf-text */
+ u4 slot; /* slot in hashtable */
+ hashtable_zipfile_entry *htzfe; /* hashtable element */
+
+ /* get classes hashtable from the classpath entry */
+
+ ht = lce->htclasses;
+
+ /* get the hashtable slot of the name searched */
+
+ key = utf_hashkey(u->text, u->blength);
+ slot = key & (ht->size - 1);
+ htzfe = ht->ptr[slot];
+
+ /* search external hash chain for utf-symbol */
+
+ while (htzfe) {
+ if (htzfe->filename == u)
+ return htzfe;
+
+ /* next element in external chain */
+
+ htzfe = htzfe->hashlink;
+ }
+
+ /* file not found in this archive */
+
+ return NULL;
+}
+
+
+/* zip_get ********************************************************************
+
+ XXX
+
+*******************************************************************************/
+
+classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
+{
+ hashtable_zipfile_entry *htzfe;
+ lfh lfh;
+ u1 *indata;
+ u1 *outdata;
+ z_stream zs;
+ int err;
+ classbuffer *cb;
+
+ /* try to find the class in the current archive */
+
+ htzfe = zip_find(lce, c->name);
+
+ if (htzfe == NULL)
+ return NULL;
+
+ /* read stuff from local file header */
+
+ lfh.filenamelength = SUCK_LE_U2(htzfe->data + LFH_FILE_NAME_LENGTH);
+ lfh.extrafieldlength = SUCK_LE_U2(htzfe->data + LFH_EXTRA_FIELD_LENGTH);
+
+ indata = htzfe->data +
+ LFH_HEADER_SIZE +
+ lfh.filenamelength +
+ lfh.extrafieldlength;
+
+ /* allocate buffer for uncompressed data */
+
+ outdata = MNEW(u1, htzfe->uncompressedsize);
+
+ /* how is the file stored? */
+
+ switch (htzfe->compressionmethod) {
+ case Z_DEFLATED:
+ /* fill z_stream structure */
+
+ zs.next_in = indata;
+ zs.avail_in = htzfe->compressedsize;
+ zs.next_out = outdata;
+ zs.avail_out = htzfe->uncompressedsize;
+
+ zs.zalloc = Z_NULL;
+ zs.zfree = Z_NULL;
+ zs.opaque = Z_NULL;
+
+ /* initialize this inflate run */
+
+ if (inflateInit2(&zs, -MAX_WBITS) != Z_OK)
+ vm_abort("zip_get: inflateInit2 failed: %s", strerror(errno));
+
+ /* decompress the file into buffer */
+
+ err = inflate(&zs, Z_SYNC_FLUSH);
+
+ if ((err != Z_STREAM_END) && (err != Z_OK))
+ vm_abort("zip_get: inflate failed: %s", strerror(errno));
+
+ /* finish this inflate run */
+
+ if (inflateEnd(&zs) != Z_OK)
+ vm_abort("zip_get: inflateEnd failed: %s", strerror(errno));
+ break;
+
+ case 0:
+ /* uncompressed file, just copy the data */
+ MCOPY(outdata, indata, u1, htzfe->compressedsize);
+ break;
+
+ default:
+ vm_abort("zip_get: unknown compression method %d",
+ htzfe->compressionmethod);
+ }
+
+ /* allocate classbuffer */
+
+ cb = NEW(classbuffer);
+
+ cb->clazz = c;
+ cb->size = htzfe->uncompressedsize;
+ cb->data = outdata;
+ cb->pos = outdata;
+ cb->path = lce->path;
+
+ /* return the filled classbuffer structure */
+
+ return cb;
+}
+
+
+/*
+ * 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/zip.c - ZIP file handling for bootstrap classloader
+
+ 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 _ZIP_H
+#define _ZIP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+
+
+/* Local file header ***********************************************************
+
+ local file header signature 4 bytes (0x04034b50)
+ version needed to extract 2 bytes
+ general purpose bit flag 2 bytes
+ compression method 2 bytes
+ last mod file time 2 bytes
+ last mod file date 2 bytes
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+ file name length 2 bytes
+ extra field length 2 bytes
+
+ file name (variable size)
+ extra field (variable size)
+
+*******************************************************************************/
+
+#define LFH_HEADER_SIZE 30
+
+#define LFH_SIGNATURE 0x04034b50
+#define LFH_FILE_NAME_LENGTH 26
+#define LFH_EXTRA_FIELD_LENGTH 28
+
+typedef struct lfh lfh;
+
+struct lfh {
+ u2 compressionmethod;
+ u4 compressedsize;
+ u4 uncompressedsize;
+ u2 filenamelength;
+ u2 extrafieldlength;
+};
+
+/* hashtable_zipfile_entry ****************************************************/
+
+typedef struct hashtable_zipfile_entry hashtable_zipfile_entry;
+
+struct hashtable_zipfile_entry {
+ utf *filename;
+ u2 compressionmethod;
+ u4 compressedsize;
+ u4 uncompressedsize;
+ u1 *data;
+ hashtable_zipfile_entry *hashlink;
+};
+
+
+/* function prototypes ********************************************************/
+
+hashtable *zip_open(char *path);
+hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u);
+classbuffer *zip_get(list_classpath_entry *lce, classinfo *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZIP_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/vmcore/Makefile.am
-##
-## 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
-##
-## 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.
-
-
-AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
-
-LIBS =
-
-if ENABLE_JAVASE
-if ENABLE_ANNOTATIONS
-ANNOTATION_SOURCES = \
- annotation.c \
- annotation.h
-endif
-
-STACKMAP_SOURCES = \
- stackmap.c \
- stackmap.h
-endif
-
-if ENABLE_RT_TIMING
-RT_TIMING_SOURCES = \
- rt-timing.c \
- rt-timing.h
-endif
-
-if ENABLE_STATISTICS
-STATISTICS_SOURCES = \
- statistics.c \
- statistics.h
-endif
-
-if ENABLE_ZLIB
-ZLIB_SOURCES = \
- zip.c \
- zip.h
-endif
-
-noinst_LTLIBRARIES = \
- libvmcore.la
-
-libvmcore_la_SOURCES = \
- $(ANNOTATION_SOURCES) \
- class.c \
- class.h \
- classcache.c \
- classcache.h \
- descriptor.c \
- descriptor.h \
- field.c \
- field.h \
- linker.c \
- linker.h \
- loader.c \
- loader.h \
- method.c \
- method.h \
- options.c \
- options.h \
- primitivecore.c \
- references.h \
- $(RT_TIMING_SOURCES) \
- $(STACKMAP_SOURCES) \
- $(STATISTICS_SOURCES) \
- suck.c \
- suck.h \
- system.c \
- system.h \
- utf8.c \
- utf8.h \
- $(ZLIB_SOURCES)
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
+++ /dev/null
-/* src/vmcore/annotation.c - class annotations
-
- Copyright (C) 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 <stdint.h>
-
-#include "native/llni.h"
-
-#include "vm/types.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/primitive.h"
-
-#include "mm/memory.h"
-
-#include "toolbox/logging.h"
-
-#include "vmcore/annotation.h"
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/suck.h"
-
-#if !defined(ENABLE_ANNOTATIONS)
-# error annotation support has to be enabled when compling this file!
-#endif
-
-
-/* annotation_bytearrays_resize ***********************************************
-
- Resize an array of bytearrays.
-
- IN:
- bytearrays.....array of bytearrays
- size...........new size of the refered array
-
- RETURN VALUE:
- The new array if a resize was neccessarry, the old if the given size
- equals the current size or NULL if an error occured.
-
-*******************************************************************************/
-
-static java_handle_objectarray_t *annotation_bytearrays_resize(
- java_handle_objectarray_t *bytearrays, uint32_t size)
-{
- java_handle_objectarray_t *newbas = NULL; /* new array */
- uint32_t minsize = 0; /* count of object refs to copy */
- uint32_t oldsize = 0; /* size of old array */
-
- if (bytearrays != NULL) {
- oldsize = array_length_get((java_handle_t*)bytearrays);
-
- /* if the size already fits do nothing */
- if (size == oldsize) {
- return bytearrays;
- }
- }
-
- newbas = builtin_anewarray(size,
- primitive_arrayclass_get_by_type(PRIMITIVETYPE_BYTE));
-
- /* is there a old byte array array? */
- if (newbas != NULL && bytearrays != NULL) {
- minsize = size < oldsize ? size : oldsize;
-
- LLNI_CRITICAL_START;
- MCOPY(
- LLNI_array_data(newbas), LLNI_array_data(bytearrays),
- java_object_t*, minsize);
- LLNI_CRITICAL_END;
- }
-
- return newbas;
-}
-
-
-/* annotation_bytearrays_insert ***********************************************
-
- Insert a bytearray into an array of bytearrays.
-
- IN:
- bytearrays........array of bytearrays where 'bytearray' has to be
- inserted at position 'index'.
- index.............position where 'ba' has to be inserted into
- 'bytearrays'.
- bytearray.........byte array which has to be inserted into
- 'bytearrays'.
-
- RETURN VALUE:
- The new array if a resize was neccessarry, the old if the given size
- equals the current size or NULL if an error occured.
-
-*******************************************************************************/
-
-static java_handle_t *annotation_bytearrays_insert(
- java_handle_t *bytearrays, uint32_t index,
- java_handle_bytearray_t *bytearray)
-{
- java_handle_objectarray_t *bas; /* bytearrays */
- uint32_t size = 0; /* current size of the array */
-
- /* do nothing if NULL is inserted but no array exists */
- if (bytearray == NULL && bytearrays == NULL) {
- return NULL;
- }
-
- /* get lengths if array exists */
- if (bytearrays != NULL) {
- size = array_length_get(bytearrays);
- }
-
- bas = (java_handle_objectarray_t*)bytearrays;
-
- if (bytearray == NULL) {
- /* insert NULL only if array is big enough */
- if (size > index) {
- array_objectarray_element_set(bas, index, NULL);
- }
- }
- else {
- /* resize array if it's not enough for inserted value */
- if (size <= index) {
- bas = annotation_bytearrays_resize(bas, index + 1);
-
- if (bas == NULL) {
- /* out of memory */
- return NULL;
- }
- }
-
- array_objectarray_element_set(bas, index, (java_handle_t*)bytearray);
- }
-
- return (java_handle_t*)bas;
-}
-
-
-/* annotation_load_attribute_body *********************************************
-
- This function loads the body of a generic attribute.
-
- XXX: Maybe this function should be called loader_load_attribute_body and
- located in vmcore/loader.c?
-
- attribute_info {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- errormsg_prefix....prefix for error messages (if any).
-
- OUT:
- attribute..........bytearray-pointer which will be set to the read data.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-static bool annotation_load_attribute_body(classbuffer *cb,
- java_handle_bytearray_t **attribute, const char *errormsg_prefix)
-{
- uint32_t size = 0; /* size of the attribute */
- java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */
-
- assert(cb != NULL);
- assert(attribute != NULL);
-
- if (!suck_check_classbuffer_size(cb, 4)) {
- log_println("%s: size missing", errormsg_prefix);
- return false;
- }
-
- /* load attribute_length */
- size = suck_u4(cb);
-
- if (!suck_check_classbuffer_size(cb, size)) {
- log_println("%s: invalid size", errormsg_prefix);
- return false;
- }
-
- /* if attribute_length == 0 then NULL is
- * the right value for this attribute */
- if (size > 0) {
- ba = builtin_newarray_byte(size);
-
- if (ba == NULL) {
- /* out of memory */
- return false;
- }
-
- /* load data */
- LLNI_CRITICAL_START;
-
- suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size);
-
- LLNI_CRITICAL_END;
-
- /* return data */
- *attribute = ba;
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_annotationdefault *************************
-
- Load annotation default value.
-
- AnnotationDefault_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- element_value default_value;
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- m..................methodinfo for the method of which the annotation
- default value is read and into which the value is
- stored into.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_annotationdefault(
- classbuffer *cb, methodinfo *m)
-{
- int slot = 0;
- /* the slot of the method */
- java_handle_bytearray_t *annotationdefault = NULL;
- /* unparsed annotation defalut value */
- java_handle_t *annotationdefaults = NULL;
- /* array of unparsed annotation default values */
-
- assert(cb != NULL);
- assert(m != NULL);
-
- LLNI_classinfo_field_get(
- m->clazz, method_annotationdefaults, annotationdefaults);
-
- if (!annotation_load_attribute_body(
- cb, &annotationdefault,
- "invalid annotation default method attribute")) {
- return false;
- }
-
- if (annotationdefault != NULL) {
- slot = m - m->clazz->methods;
- annotationdefaults = annotation_bytearrays_insert(
- annotationdefaults, slot, annotationdefault);
-
- if (annotationdefaults == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- m->clazz, method_annotationdefaults, annotationdefaults);
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_runtimevisibleparameterannotations ********
-
- Load runtime visible parameter annotations.
-
- RuntimeVisibleParameterAnnotations_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 num_parameters;
- {
- u2 num_annotations;
- annotation annotations[num_annotations];
- } parameter_annotations[num_parameters];
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- m..................methodinfo for the method of which the parameter
- annotations are read and into which the parameter
- annotations are stored into.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimevisibleparameterannotations(
- classbuffer *cb, methodinfo *m)
-{
- int slot = 0;
- /* the slot of the method */
- java_handle_bytearray_t *annotations = NULL;
- /* unparsed parameter annotations */
- java_handle_t *parameterannotations = NULL;
- /* array of unparsed parameter annotations */
-
- assert(cb != NULL);
- assert(m != NULL);
-
- LLNI_classinfo_field_get(
- m->clazz, method_parameterannotations, parameterannotations);
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible parameter annotations method attribute")) {
- return false;
- }
-
- if (annotations != NULL) {
- slot = m - m->clazz->methods;
- parameterannotations = annotation_bytearrays_insert(
- parameterannotations, slot, annotations);
-
- if (parameterannotations == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- m->clazz, method_parameterannotations, parameterannotations);
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
-
- Load runtime invisible parameter annotations.
-
- <quote cite="http://jcp.org/en/jsr/detail?id=202">
- The RuntimeInvisibleParameterAnnotations attribute is similar to the
- RuntimeVisibleParameterAnnotations attribute, except that the annotations
- represented by a RuntimeInvisibleParameterAnnotations attribute must not be
- made available for return by reflective APIs, unless the the JVM has
- specifically been instructed to retain these annotations via some
- implementation-specific mechanism such as a command line flag. In the
- absence of such instructions, the JVM ignores this attribute.
- </quote>
-
- Hotspot loads them into the same bytearray as the runtime visible parameter
- annotations (after the runtime visible parameter annotations). But in J2SE
- the bytearray will only be parsed as if there is only one annotation
- structure in it, so the runtime invisible parameter annotatios will be
- ignored.
-
- Therefore I do not even bother to read them.
-
- RuntimeInvisibleParameterAnnotations_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 num_parameters;
- {
- u2 num_annotations;
- annotation annotations[num_annotations];
- } parameter_annotations[num_parameters];
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- m..................methodinfo for the method of which the parameter
- annotations are read and into which the parameter
- annotations are stored into.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
- classbuffer *cb, methodinfo *m)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/* annotation_load_class_attribute_runtimevisibleannotations ******************
-
- Load runtime visible annotations of a class.
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_class_attribute_runtimevisibleannotations(
- classbuffer *cb)
-{
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible annotations class attribute")) {
- return false;
- }
-
- LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations);
-
- return true;
-}
-
-
-/* annotation_load_class_attribute_runtimeinvisibleannotations ****************
-
- Load runtime invisible annotations of a class (just skip them).
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_class_attribute_runtimeinvisibleannotations(
- classbuffer *cb)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/* annotation_load_method_attribute_runtimevisibleannotations *****************
-
- Load runtime visible annotations of a method.
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- m.........the method of which the runtime visible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimevisibleannotations(
- classbuffer *cb, methodinfo *m)
-{
- int slot = 0;
- /* slot of the method */
- java_handle_bytearray_t *annotations = NULL;
- /* unparsed annotations */
- java_handle_t *method_annotations = NULL;
- /* array of unparsed method annotations */
-
- assert(cb != NULL);
- assert(m != NULL);
-
- LLNI_classinfo_field_get(
- m->clazz, method_annotations, method_annotations);
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible annotations method attribute")) {
- return false;
- }
-
- if (annotations != NULL) {
- slot = m - m->clazz->methods;
- method_annotations = annotation_bytearrays_insert(
- method_annotations, slot, annotations);
-
- if (method_annotations == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- m->clazz, method_annotations, method_annotations);
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_runtimeinvisibleannotations ****************
-
- Load runtime invisible annotations of a method (just skip them).
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- m.........the method of which the runtime invisible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimeinvisibleannotations(
- classbuffer *cb, methodinfo *m)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/* annotation_load_field_attribute_runtimevisibleannotations ******************
-
- Load runtime visible annotations of a field.
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- f.........the field of which the runtime visible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_field_attribute_runtimevisibleannotations(
- classbuffer *cb, fieldinfo *f)
-{
- int slot = 0;
- /* slot of the field */
- java_handle_bytearray_t *annotations = NULL;
- /* unparsed annotations */
- java_handle_t *field_annotations = NULL;
- /* array of unparsed field annotations */
-
- assert(cb != NULL);
- assert(f != NULL);
-
- LLNI_classinfo_field_get(
- f->clazz, field_annotations, field_annotations);
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible annotations field attribute")) {
- return false;
- }
-
- if (annotations != NULL) {
- slot = f - f->clazz->fields;
- field_annotations = annotation_bytearrays_insert(
- field_annotations, slot, annotations);
-
- if (field_annotations == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- f->clazz, field_annotations, field_annotations);
- }
-
- return true;
-}
-
-
-/* annotation_load_field_attribute_runtimeinvisibleannotations ****************
-
- Load runtime invisible annotations of a field (just skip them).
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- f.........the field of which the runtime invisible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_field_attribute_runtimeinvisibleannotations(
- classbuffer *cb, fieldinfo *f)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/*
- * 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/vmcore/annotation.h - class annotations
-
- Copyright (C) 2006, 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
-
- 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 _ANNOTATION_H
-#define _ANNOTATION_H
-
-
-#include "config.h"
-
-#include "vm/types.h"
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-
-
-/* function prototypes ********************************************************/
-
-bool annotation_load_class_attribute_runtimevisibleannotations(
- classbuffer *cb);
-
-bool annotation_load_class_attribute_runtimeinvisibleannotations(
- classbuffer *cb);
-
-bool annotation_load_method_attribute_runtimevisibleannotations(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_method_attribute_runtimeinvisibleannotations(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_field_attribute_runtimevisibleannotations(
- classbuffer *cb, fieldinfo *f);
-
-bool annotation_load_field_attribute_runtimeinvisibleannotations(
- classbuffer *cb, fieldinfo *f);
-
-bool annotation_load_method_attribute_annotationdefault(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_method_attribute_runtimevisibleparameterannotations(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
- classbuffer *cb, methodinfo *m);
-
-#endif /* _ANNOTATION_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:
- */
+++ /dev/null
-/* src/vmcore/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/exceptions.h"
-#include "vm/global.h"
-#include "vm/resolve.h"
-
-#include "vm/jit/asmpart.h"
-#include "vm/jit/jitcache.h"
-
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-#if defined(ENABLE_JAVASE)
-/* We need to define some reflection functions here since we cannot
- include native/vm/reflect.h as it includes generated header
- files. */
-
-java_object_t *reflect_constructor_new(methodinfo *m);
-java_object_t *reflect_field_new(fieldinfo *f);
-java_object_t *reflect_method_new(methodinfo *m);
-#endif
-
-
-/* global variables ***********************************************************/
-
-/* frequently used classes ****************************************************/
-
-/* Important system classes. */
-
-classinfo *class_java_lang_Object;
-classinfo *class_java_lang_Class;
-classinfo *class_java_lang_ClassLoader;
-classinfo *class_java_lang_Cloneable;
-classinfo *class_java_lang_SecurityManager;
-classinfo *class_java_lang_String;
-classinfo *class_java_lang_System;
-classinfo *class_java_lang_Thread;
-classinfo *class_java_lang_ThreadGroup;
-classinfo *class_java_lang_Throwable;
-classinfo *class_java_io_Serializable;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-classinfo *class_java_lang_VMSystem;
-classinfo *class_java_lang_VMThread;
-classinfo *class_java_lang_VMThrowable;
-#endif
-
-/* Important system exceptions. */
-
-classinfo *class_java_lang_Exception;
-classinfo *class_java_lang_ClassNotFoundException;
-classinfo *class_java_lang_RuntimeException;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-classinfo *class_sun_reflect_MagicAccessorImpl;
-#endif
-
-#if defined(ENABLE_JAVASE)
-classinfo *class_java_lang_Void;
-#endif
-classinfo *class_java_lang_Boolean;
-classinfo *class_java_lang_Byte;
-classinfo *class_java_lang_Character;
-classinfo *class_java_lang_Short;
-classinfo *class_java_lang_Integer;
-classinfo *class_java_lang_Long;
-classinfo *class_java_lang_Float;
-classinfo *class_java_lang_Double;
-
-/* some classes which may be used more often */
-
-#if defined(ENABLE_JAVASE)
-classinfo *class_java_lang_StackTraceElement;
-classinfo *class_java_lang_reflect_Constructor;
-classinfo *class_java_lang_reflect_Field;
-classinfo *class_java_lang_reflect_Method;
-classinfo *class_java_security_PrivilegedAction;
-classinfo *class_java_util_Vector;
-classinfo *class_java_util_HashMap;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-classinfo *class_java_lang_reflect_VMConstructor;
-classinfo *class_java_lang_reflect_VMField;
-classinfo *class_java_lang_reflect_VMMethod;
-# endif
-
-classinfo *arrayclass_java_lang_Object;
-
-# if defined(ENABLE_ANNOTATIONS)
-classinfo *class_sun_reflect_ConstantPool;
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-classinfo *class_sun_reflect_annotation_AnnotationParser;
-# endif
-# endif
-#endif
-
-/* pseudo classes for the typechecker */
-
-classinfo *pseudo_class_Arraystub;
-classinfo *pseudo_class_Null;
-classinfo *pseudo_class_New;
-
-
-/* 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;
- voidptr 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, voidptr, 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.
-
-*******************************************************************************/
-
-voidptr 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.
-
-*******************************************************************************/
-
-voidptr 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)
-{
- s4 i;
-
- /* get field index */
-
- i = class_findfield_index_by_name(c, name);
-
- /* field was not found, return */
-
- if (i == -1)
- return NULL;
-
- /* return field address */
-
- return &(c->fields[i]);
-}
-
-
-s4 class_findfield_index_by_name(classinfo *c, utf *name)
-{
- s4 i;
-
- for (i = 0; i < c->fieldscount; i++) {
- /* compare field names */
-
- if ((c->fields[i].name == name))
- return i;
- }
-
- /* field was not found, raise exception */
-
- exceptions_throw_nosuchfielderror(c, name);
-
- return -1;
-}
-
-
-/****************** 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 the return value is NULL. If EXCEPT is
- true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc,
- classinfo *referer, bool throwexception)
-{
- fieldinfo *fi;
-
- fi = class_resolvefield_int(c, name, desc);
-
- if (!fi) {
- if (throwexception)
- 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_class_get_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 Constructor object. This is actualy a
- java_lang_reflect_Constructor pointer, but we use a
- java_handle_t here, because we don't have the header
- available when building vmcore. */
-
- rc = reflect_constructor_new(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 Field object. This is actualy a
- java_lang_reflect_Field pointer, but we use a
- java_handle_t here, because we don't have the header
- available when building vmcore. */
-
- h = reflect_field_new(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 method object. This is actualy a
- java_lang_reflect_Method pointer, but we use a
- java_handle_t here, because we don't have the header
- available when building vmcore. */
-
- h = reflect_method_new(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 Constructor object. */
-
- rc = reflect_constructor_new(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 java.lang.reflect.Method object */
-
- rm = reflect_method_new(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;
- voidptr 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/vmcore/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
-
-/* forward typedefs ***********************************************************/
-
-typedef struct classinfo classinfo;
-typedef struct innerclassinfo innerclassinfo;
-typedef struct extra_classref extra_classref;
-typedef struct castinfo castinfo;
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-
-#if defined(ENABLE_JAVASE)
-# include "vmcore/annotation.h"
-#endif
-
-#include "vmcore/field.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vmcore/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 */
- voidptr *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;
-};
-
-
-/* castinfo *******************************************************************/
-
-struct castinfo {
- s4 super_baseval;
- s4 super_diffval;
- s4 sub_baseval;
-};
-
-
-/* global variables ***********************************************************/
-
-/* frequently used classes ****************************************************/
-
-/* Important system classes. */
-
-extern classinfo *class_java_lang_Object;
-extern classinfo *class_java_lang_Class;
-extern classinfo *class_java_lang_ClassLoader;
-extern classinfo *class_java_lang_Cloneable;
-extern classinfo *class_java_lang_SecurityManager;
-extern classinfo *class_java_lang_String;
-extern classinfo *class_java_lang_System;
-extern classinfo *class_java_lang_Thread;
-extern classinfo *class_java_lang_ThreadGroup;
-extern classinfo *class_java_lang_Throwable;
-extern classinfo *class_java_io_Serializable;
-
-/* Important system exceptions. */
-
-extern classinfo *class_java_lang_Exception;
-extern classinfo *class_java_lang_ClassNotFoundException;
-extern classinfo *class_java_lang_RuntimeException;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern classinfo *class_java_lang_VMSystem;
-extern classinfo *class_java_lang_VMThread;
-extern classinfo *class_java_lang_VMThrowable;
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-extern classinfo *class_sun_reflect_MagicAccessorImpl;
-#endif
-
-#if defined(ENABLE_JAVASE)
-extern classinfo *class_java_lang_Void;
-#endif
-
-extern classinfo *class_java_lang_Boolean;
-extern classinfo *class_java_lang_Byte;
-extern classinfo *class_java_lang_Character;
-extern classinfo *class_java_lang_Short;
-extern classinfo *class_java_lang_Integer;
-extern classinfo *class_java_lang_Long;
-extern classinfo *class_java_lang_Float;
-extern classinfo *class_java_lang_Double;
-
-/* some classes which may be used more often */
-
-#if defined(ENABLE_JAVASE)
-extern classinfo *class_java_lang_StackTraceElement;
-extern classinfo *class_java_lang_reflect_Constructor;
-extern classinfo *class_java_lang_reflect_Field;
-extern classinfo *class_java_lang_reflect_Method;
-extern classinfo *class_java_security_PrivilegedAction;
-extern classinfo *class_java_util_Vector;
-extern classinfo *class_java_util_HashMap;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern classinfo *class_java_lang_reflect_VMConstructor;
-extern classinfo *class_java_lang_reflect_VMField;
-extern classinfo *class_java_lang_reflect_VMMethod;
-# endif
-
-extern classinfo *arrayclass_java_lang_Object;
-
-# if defined(ENABLE_ANNOTATIONS)
-extern classinfo *class_sun_reflect_ConstantPool;
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern classinfo *class_sun_reflect_annotation_AnnotationParser;
-# endif
-# endif
-#endif
-
-
-/* pseudo classes for the type checker ****************************************/
-
-/*
- * pseudo_class_Arraystub
- * (extends Object implements Cloneable, java.io.Serializable)
- *
- * If two arrays of incompatible component types are merged,
- * the resulting reference has no accessible components.
- * The result does, however, implement the interfaces Cloneable
- * and java.io.Serializable. This pseudo class is used internally
- * to represent such results. (They are *not* considered arrays!)
- *
- * pseudo_class_Null
- *
- * This pseudo class is used internally to represent the
- * null type.
- *
- * pseudo_class_New
- *
- * This pseudo class is used internally to represent the
- * the 'uninitialized object' type.
- */
-
-extern classinfo *pseudo_class_Arraystub;
-extern classinfo *pseudo_class_Null;
-extern classinfo *pseudo_class_New;
-
-
-/* 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 */
-voidptr class_getconstant(classinfo *c, u4 pos, u4 ctype);
-voidptr 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);
-s4 class_findfield_index_by_name(classinfo *c, utf *name);
-
-/* search class for a field */
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer, bool throwexception);
-
-/* 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);
-
-#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:
- */
+++ /dev/null
-/* src/vmcore/classcache.c - loaded class cache and loading constraints
-
- 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 "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
-
-#include "vm/exceptions.h"
-
-#include "vmcore/classcache.h"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
-
-/*************************************************************************
-
- Class Cache
-
- The classcache has two functions:
-
- 1) caching the resolution of class references
- 2) storing and checking loading constraints
-
- We will use the following terms in this description:
-
- N a class name: a utf string
- (N,L) a class reference with initiating loader L and class name N
- C a class (object): the result of resolving a reference (N,L)
- We will write resultion as
- C = *(N,L)
- (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
- resolve to the same class C. So (N,L1,L2) means
- *(N,L1) = *(N,L2)
-
- The functions of the classcache require:
-
- 1) a mapping (N,L) |--> C for looking up prior resolution results.
- 2) storing the current set of loading constraints { (N,L1,L2) }
-
- These functions can be rearranged like that:
-
- a mapping N |--> (a mapping L |--> C or NULL,
- a set of constraints {(L1,L2)})
-
- Thus we can treat the mapping and constraints for each name N
- separately. The implementation does this by keeping a hash table
- mapping a name N to a `classcache_name_entry` which contains all
- info with respect to N.
-
- For a class name N we can define an equivalence relation ~N~ on
- class loaders:
-
- L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
-
- A loading constraint (N,L1,L2) implies L1 ~N~ L2.
-
- Also, if two references (N,L1) and (N,L2) resolve to the same class C
- we have L1 ~N~ L2 because class loaders are required to return
- consistent resolutions for a name N [XXX].
-
- A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
- where
- Cx...is a class C or NULL
- IL...is the set of initiating loaders
- CL...is the set of constrained loaders
-
- Such a tuple is called `classcache_class_entry` in the source code.
-
- The following holds for each tuple (Cx,IL,CL):
-
- . (Cx is NULL) implies IL = {}.
-
- . If Cx is a class, IL is the set of loaders that have been
- recorded as initiating loaders for Cx. IL may be the
- empty set {} in case Cx has already been defined but no
- initiating loader has been recorded, yet.
-
- . (IL u CL) is a subset of an equivalence class of ~N~.
-
- (This means that all loaders in IL and CL must resolve
- the name N to the same class.)
-
- The following holds for the set of tuples { (Cx,IL,CL) }:
-
- . For a given class C there is at most one tuple with Cx = C
- in the set. (There may be an arbitrary number of tuples
- with Cx = NULL, however.)
-
- . For a given loader L there is at most one tuple with
- L in (IL u CL).
-
- The implementation stores sets of loaders as linked lists of
- `classcache_loader_entry`s.
-
- Comments about manipulating the classcache can be found in the
- individual functions below.
-
-*************************************************************************/
-
-
-/* initial number of slots in the classcache hash table */
-#define CLASSCACHE_INIT_SIZE 2048
-
-/*============================================================================*/
-/* DEBUG HELPERS */
-/*============================================================================*/
-
-/* #define CLASSCACHE_VERBOSE */
-
-/*============================================================================*/
-/* STATISTICS */
-/*============================================================================*/
-
-/*#define CLASSCACHE_STATS*/
-
-#ifdef CLASSCACHE_STATS
-static int stat_classnames_stored = 0;
-static int stat_classes_stored = 0;
-static int stat_trivial_constraints = 0;
-static int stat_nontriv_constraints = 0;
-static int stat_nontriv_constraints_both = 0;
-static int stat_nontriv_constraints_merged = 0;
-static int stat_nontriv_constraints_one = 0;
-static int stat_nontriv_constraints_none = 0;
-static int stat_new_loader_entry = 0;
-static int stat_merge_class_entries = 0;
-static int stat_merge_loader_entries = 0;
-static int stat_lookup = 0;
-static int stat_lookup_class_entry_checked = 0;
-static int stat_lookup_loader_checked = 0;
-static int stat_lookup_name = 0;
-static int stat_lookup_name_entry = 0;
-static int stat_lookup_name_notfound = 0;
-static int stat_lookup_new_name = 0;
-static int stat_lookup_new_name_entry = 0;
-static int stat_lookup_new_name_collisions = 0;
-static int stat_rehash_names = 0;
-static int stat_rehash_names_collisions = 0;
-
-#define CLASSCACHE_COUNT(cnt) (cnt)++
-#define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
-
-void classcache_print_statistics(FILE *file) {
- fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
- fprintf(file,"classes stored : %8d\n",stat_classes_stored);
- fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
- fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
- fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
- fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
- fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
- fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
- fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
- fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
- fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
- fprintf(file,"lookups : %8d\n",stat_lookup);
- fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
- fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
- fprintf(file,"lookup name : %8d\n",stat_lookup_name);
- fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
- fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
- fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
- fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
- fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
- fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
- fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
-}
-#else
-#define CLASSCACHE_COUNT(cnt)
-#define CLASSCACHE_COUNTIF(cond,cnt)
-#endif
-
-/*============================================================================*/
-/* THREAD-SAFE LOCKING */
-/*============================================================================*/
-
- /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
- /* CAUTION: The static functions below are */
- /* NOT synchronized! */
- /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-#if defined(ENABLE_THREADS)
-# define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
-# define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
-#else
-# define CLASSCACHE_LOCK()
-# define CLASSCACHE_UNLOCK()
-#endif
-
-/*============================================================================*/
-/* GLOBAL VARIABLES */
-/*============================================================================*/
-
-hashtable hashtable_classcache;
-
-#if defined(ENABLE_THREADS)
-static java_object_t *lock_hashtable_classcache;
-#endif
-
-
-/*============================================================================*/
-/* */
-/*============================================================================*/
-
-/* prototypes */
-
-static void classcache_free_class_entry(classcache_class_entry *clsen);
-static void classcache_remove_class_entry(classcache_name_entry *en,
- classcache_class_entry *clsen);
-
-/* hash function to use */
-
-#define CLASSCACHE_HASH utf_full_hashkey
-
-/* classcache_init *************************************************************
-
- Initialize the class cache
-
- Note: NOT synchronized!
-
-*******************************************************************************/
-
-bool classcache_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("classcache_init");
-
- /* create the hashtable */
-
- hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
-
-#if defined(ENABLE_THREADS)
- /* create utf hashtable lock object */
-
- lock_hashtable_classcache = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
-#endif
-
- /* everything's ok */
-
- return true;
-}
-
-/* classcache_new_loader_entry *************************************************
-
- Create a new classcache_loader_entry struct
- (internally used helper function)
-
- IN:
- loader...........the ClassLoader object
- next.............the next classcache_loader_entry
-
- RETURN VALUE:
- the new classcache_loader_entry
-
-*******************************************************************************/
-
-static classcache_loader_entry * classcache_new_loader_entry(
- classloader_t * loader,
- classcache_loader_entry * next)
-{
- classcache_loader_entry *lden;
-
- lden = NEW(classcache_loader_entry);
- lden->loader = loader;
- lden->next = next;
- CLASSCACHE_COUNT(stat_new_loader_entry);
-
- return lden;
-}
-
-/* classcache_merge_loaders ****************************************************
-
- Merge two lists of loaders into one
- (internally used helper function)
-
- IN:
- lista............first list (may be NULL)
- listb............second list (may be NULL)
-
- RETURN VALUE:
- the merged list (may be NULL)
-
- NOTE:
- The lists given as arguments are destroyed!
-
-*******************************************************************************/
-
-static classcache_loader_entry * classcache_merge_loaders(
- classcache_loader_entry * lista,
- classcache_loader_entry * listb)
-{
- classcache_loader_entry *result;
- classcache_loader_entry *ldenA;
- classcache_loader_entry *ldenB;
- classcache_loader_entry **chain;
-
- CLASSCACHE_COUNT(stat_merge_loader_entries);
-
- /* XXX This is a quadratic algorithm. If this ever
- * becomes a problem, the loader lists should be
- * stored as sorted lists and merged in linear time. */
-
- result = NULL;
- chain = &result;
-
- for (ldenA = lista; ldenA; ldenA = ldenA->next) {
-
- for (ldenB = listb; ldenB; ldenB = ldenB->next) {
- if (ldenB->loader == ldenA->loader)
- goto common_element;
- }
-
- /* this loader is only in lista */
- *chain = ldenA;
- chain = &(ldenA->next);
-
- common_element:
- /* XXX free the duplicated element */
- ;
- }
-
- /* concat listb to the result */
- *chain = listb;
-
- return result;
-}
-
-/* classcache_merge_class_entries **********************************************
-
- Merge two `classcache_class_entry`s into one.
- (internally used helper function)
-
- IN:
- en...............the classcache_name_entry containing both class entries
- clsenA...........first class entry, will receive the result
- clsenB...........second class entry
-
- PRE-CONDITION:
- Either both entries must have the same classobj, or one of them has
- classobj == NULL.
-
- NOTE:
- clsenB is freed by this function!
-
-*******************************************************************************/
-
-static void classcache_merge_class_entries(classcache_name_entry *en,
- classcache_class_entry *clsenA,
- classcache_class_entry *clsenB)
-{
-#ifdef CLASSCACHE_VERBOSE
- char logbuffer[1024];
-#endif
-
- assert(en);
- assert(clsenA);
- assert(clsenB);
- assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
-
-#ifdef CLASSCACHE_VERBOSE
- sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
- (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
- if (clsenA->classobj)
- utf_cat_classname(logbuffer, clsenA->classobj->name);
- if (clsenB->classobj)
- utf_cat_classname(logbuffer, clsenB->classobj->name);
- log_println(logbuffer);
-#endif
-
- CLASSCACHE_COUNT(stat_merge_class_entries);
-
- /* clsenB will be merged into clsenA */
- clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
- clsenB->loaders = NULL; /* these have been freed or reused */
-
- clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
- clsenB->constraints);
- clsenB->constraints = NULL; /* these have been freed or reused */
-
- if (!clsenA->classobj)
- clsenA->classobj = clsenB->classobj;
-
- /* remove clsenB from the list of class entries */
- classcache_remove_class_entry(en, clsenB);
-}
-
-
-/* classcache_lookup_name ******************************************************
-
- Lookup a name in the first level of the cache
- (internally used helper function)
-
- IN:
- name.............the name to look up
-
- RETURN VALUE:
- a pointer to the classcache_name_entry for this name, or
- null if no entry was found.
-
-*******************************************************************************/
-
-static classcache_name_entry *classcache_lookup_name(utf *name)
-{
- classcache_name_entry *c; /* hash table element */
- u4 key; /* hashkey computed from classname */
- u4 slot; /* slot in hashtable */
-
- CLASSCACHE_COUNT(stat_lookup_name);
-
- key = CLASSCACHE_HASH(name->text, (u4) name->blength);
- slot = key & (hashtable_classcache.size - 1);
- c = hashtable_classcache.ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (c) {
- /* entry found in hashtable */
- CLASSCACHE_COUNT(stat_lookup_name_entry);
-
- if (c->name == name)
- return c;
-
- c = c->hashlink; /* next element in external chain */
- }
-
- /* not found */
-
- CLASSCACHE_COUNT(stat_lookup_name_notfound);
- return NULL;
-}
-
-
-/* classcache_new_name *********************************************************
-
- Return a classcache_name_entry for the given name. The entry is created
- if it is not already in the cache.
- (internally used helper function)
-
- IN:
- name.............the name to look up / create an entry for
-
- RETURN VALUE:
- a pointer to the classcache_name_entry for this name
-
-*******************************************************************************/
-
-static classcache_name_entry *classcache_new_name(utf *name)
-{
- classcache_name_entry *c; /* hash table element */
- u4 key; /* hashkey computed from classname */
- u4 slot; /* slot in hashtable */
- u4 i;
-
- CLASSCACHE_COUNT(stat_lookup_new_name);
-
- key = CLASSCACHE_HASH(name->text, (u4) name->blength);
- slot = key & (hashtable_classcache.size - 1);
- c = hashtable_classcache.ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (c) {
- /* entry found in hashtable */
- CLASSCACHE_COUNT(stat_lookup_new_name_entry);
-
- if (c->name == name)
- return c;
-
- c = c->hashlink; /* next element in external chain */
- }
-
- /* location in hashtable found, create new entry */
-
- c = NEW(classcache_name_entry);
-
- c->name = name;
- c->classes = NULL;
-
- /* insert entry into hashtable */
- c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
- CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
- hashtable_classcache.ptr[slot] = c;
-
- /* update number of hashtable-entries */
- hashtable_classcache.entries++;
- CLASSCACHE_COUNT(stat_classnames_stored);
-
- if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
- /* reorganization of hashtable */
-
- classcache_name_entry *c2;
- hashtable newhash; /* the new hashtable */
-
- CLASSCACHE_COUNT(stat_rehash_names);
-
- /* create new hashtable, double the size */
-
- hashtable_create(&newhash, hashtable_classcache.size * 2);
- newhash.entries = hashtable_classcache.entries;
-
- /* transfer elements to new hashtable */
-
- for (i = 0; i < hashtable_classcache.size; i++) {
- c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
- while (c2) {
- classcache_name_entry *nextc = c2->hashlink;
- u4 newslot =
- (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
-
- c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
- CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
- newhash.ptr[newslot] = c2;
-
- c2 = nextc;
- }
- }
-
- /* dispose old table */
-
- MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
- hashtable_classcache = newhash;
- }
-
- return c;
-}
-
-
-/* classcache_lookup ***********************************************************
-
- Lookup a possibly loaded class
-
- IN:
- initloader.......initiating loader for resolving the class name
- classname........class name to look up
-
- RETURN VALUE:
- The return value is a pointer to the cached class object,
- or NULL, if the class is not in the cache.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-classinfo *classcache_lookup(classloader_t *initloader, utf *classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
- classinfo *cls = NULL;
-
- CLASSCACHE_LOCK();
-
- CLASSCACHE_COUNT(stat_lookup);
- en = classcache_lookup_name(classname);
-
- if (en) {
- /* iterate over all class entries */
-
- for (clsen = en->classes; clsen; clsen = clsen->next) {
- CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
- /* check if this entry has been loaded by initloader */
-
- for (lden = clsen->loaders; lden; lden = lden->next) {
- CLASSCACHE_COUNT(stat_lookup_loader_checked);
- if (lden->loader == initloader) {
- /* found the loaded class entry */
-
- assert(clsen->classobj);
- cls = clsen->classobj;
- goto found;
- }
- }
- }
- }
-
- found:
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-
-/* classcache_lookup_defined ***************************************************
-
- Lookup a class with the given name and defining loader
-
- IN:
- defloader........defining loader
- classname........class name
-
- RETURN VALUE:
- The return value is a pointer to the cached class object,
- or NULL, if the class is not in the cache.
-
-*******************************************************************************/
-
-classinfo *classcache_lookup_defined(classloader_t *defloader, utf *classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classinfo *cls = NULL;
-
- CLASSCACHE_LOCK();
-
- en = classcache_lookup_name(classname);
-
- if (en) {
- /* iterate over all class entries */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
- if (!clsen->classobj)
- continue;
-
- /* check if this entry has been defined by defloader */
- if (clsen->classobj->classloader == defloader) {
- cls = clsen->classobj;
- goto found;
- }
- }
- }
-
- found:
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-
-/* classcache_lookup_defined_or_initiated **************************************
-
- Lookup a class that has been defined or initiated by the given loader
-
- IN:
- loader...........defining or initiating loader
- classname........class name to look up
-
- RETURN VALUE:
- The return value is a pointer to the cached class object,
- or NULL, if the class is not in the cache.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-classinfo *classcache_lookup_defined_or_initiated(classloader_t *loader,
- utf *classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
- classinfo *cls = NULL;
-
- CLASSCACHE_LOCK();
-
- en = classcache_lookup_name(classname);
-
- if (en) {
- /* iterate over all class entries */
-
- for (clsen = en->classes; clsen; clsen = clsen->next) {
-
- /* check if this entry has been defined by loader */
- if (clsen->classobj && clsen->classobj->classloader == loader) {
- cls = clsen->classobj;
- goto found;
- }
-
- /* check if this entry has been initiated by loader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == loader) {
- /* found the loaded class entry */
-
- assert(clsen->classobj);
- cls = clsen->classobj;
- goto found;
- }
- }
- }
- }
-
- found:
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-
-/* classcache_store ************************************************************
-
- Store a loaded class. If a class of the same name has already been stored
- with the same initiating loader, then the given class CLS is freed (if
- possible) and the previously stored class is returned.
-
- IN:
- initloader.......initiating loader used to load the class
- (may be NULL indicating the bootstrap loader)
- cls..............class object to cache
- mayfree..........true if CLS may be freed in case another class is
- returned
-
- RETURN VALUE:
- cls..............everything ok, the class was stored in the cache,
- other classinfo..another class with the same (initloader,name) has been
- stored earlier. CLS has been freed[1] and the earlier
- stored class is returned.
- NULL.............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
- [1]...in case MAYFREE is true
-
-*******************************************************************************/
-
-classinfo *classcache_store(classloader_t *initloader, classinfo *cls,
- bool mayfree)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classcache_class_entry *clsenB;
- classcache_loader_entry *lden;
-#ifdef CLASSCACHE_VERBOSE
- char logbuffer[1024];
-#endif
-
- assert(cls);
- assert(cls->state & CLASS_LOADED);
-
- CLASSCACHE_LOCK();
-
-#ifdef CLASSCACHE_VERBOSE
- sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
- utf_cat_classname(logbuffer, cls->name);
- strcat(logbuffer,")");
- log_println(logbuffer);
-#endif
-
- en = classcache_new_name(cls->name);
-
- assert(en);
-
- /* iterate over all class entries */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
-
- /* check if this entry has already been loaded by initloader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == initloader) {
- if (clsen->classobj != cls) {
- /* A class with the same (initloader,name) pair has been stored already. */
- /* We free the given class and return the earlier one. */
-#ifdef CLASSCACHE_VERBOSE
- log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
-#endif
- assert(clsen->classobj);
- if (mayfree)
- class_free(cls);
- cls = clsen->classobj;
- }
- goto return_success;
- }
- }
-
- /* {This entry has not been resolved with initloader} */
-
- /* check if initloader is constrained to this entry */
- for (lden = clsen->constraints; lden; lden = lden->next) {
- if (lden->loader == initloader) {
- /* we have to use this entry. check if it has been resolved */
- if (clsen->classobj) {
- /* check if is has already been resolved to another class */
- if (clsen->classobj != cls) {
- /* a loading constraint is violated */
- exceptions_throw_linkageerror("loading constraint violated: ", cls);
- goto return_exception;
- }
-
- /* record initloader as initiating loader */
- clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
- goto return_success;
- }
-
- /* {this is the first resolution for this entry} */
- /* record initloader as initiating loader */
- clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
-
- /* maybe we can merge this entry with another one */
- for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
- /* we dont want the entry that we have already */
- if (clsenB->classobj == cls) {
- /* this entry has the same classobj. let's merge them */
- classcache_merge_class_entries(en,clsen,clsenB);
- goto return_success;
- }
- }
-
- /* record the loaded class object */
- clsen->classobj = cls;
- CLASSCACHE_COUNT(stat_classes_stored);
-
- /* done */
- goto return_success;
- }
- }
-
- }
-
- /* {There is no class entry containing initloader as initiating
- * or constrained loader.} */
-
- /* we look for a class entry with the same classobj we want to store */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
- if (clsen->classobj == cls) {
- /* this entry is about the same classobj. let's use it */
- /* check if this entry has already been loaded by initloader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == initloader)
- goto return_success;
- }
- clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
- goto return_success;
- }
- }
-
- /* create a new class entry for this class object with */
- /* initiating loader initloader */
-
- clsen = NEW(classcache_class_entry);
- clsen->classobj = cls;
- clsen->loaders = classcache_new_loader_entry(initloader, NULL);
- clsen->constraints = NULL;
-
- clsen->next = en->classes;
- en->classes = clsen;
- CLASSCACHE_COUNT(stat_classes_stored);
-
- return_success:
-#ifdef CLASSCACHE_VERBOSE
- classcache_debug_dump(stdout,cls->name);
-#endif
- CLASSCACHE_UNLOCK();
- return cls;
-
- return_exception:
- CLASSCACHE_UNLOCK();
- return NULL; /* exception */
-}
-
-/* classcache_store_unique *****************************************************
-
- Store a loaded class as loaded by the bootstrap loader. This is a wrapper
- aroung classcache_store that throws an exception if a class with the same
- name has already been loaded by the bootstrap loader.
-
- This function is used to register a few special classes during startup.
- It should not be used otherwise.
-
- IN:
- cls..............class object to cache
-
- RETURN VALUE:
- true.............everything ok, the class was stored.
- false............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-bool classcache_store_unique(classinfo *cls)
-{
- classinfo *result;
-
- result = classcache_store(NULL,cls,false);
- if (result == NULL)
- return false;
-
- if (result != cls) {
- exceptions_throw_internalerror("class already stored in the class cache");
- return false;
- }
-
- return true;
-}
-
-/* classcache_store_defined ****************************************************
-
- Store a loaded class after it has been defined. If the class has already
- been defined by the same defining loader in another thread, free the given
- class and returned the one which has been defined earlier.
-
- IN:
- cls..............class object to store. classloader must be set
- (classloader may be NULL, for bootloader)
-
- RETURN VALUE:
- cls..............everything ok, the class was stored the cache,
- other classinfo..the class had already been defined, CLS was freed, the
- class which was defined earlier is returned,
- NULL.............an exception has been thrown.
-
-*******************************************************************************/
-
-classinfo *classcache_store_defined(classinfo *cls)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
-#ifdef CLASSCACHE_VERBOSE
- char logbuffer[1024];
-#endif
-
- assert(cls);
- assert(cls->state & CLASS_LOADED);
-
- CLASSCACHE_LOCK();
-
-#ifdef CLASSCACHE_VERBOSE
- sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
- utf_cat_classname(logbuffer, cls->name);
- strcat(logbuffer,")");
- log_println(logbuffer);
-#endif
-
- en = classcache_new_name(cls->name);
-
- assert(en);
-
- /* iterate over all class entries */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
-
- /* check if this class has been defined by the same classloader */
- if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
- /* we found an earlier definition, delete the newer one */
- /* (if it is a different classinfo) */
- if (clsen->classobj != cls) {
-#ifdef CLASSCACHE_VERBOSE
- log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
-#endif
- class_free(cls);
- cls = clsen->classobj;
- }
- goto return_success;
- }
- }
-
- /* create a new class entry for this class object */
- /* the list of initiating loaders is empty at this point */
-
- clsen = NEW(classcache_class_entry);
- clsen->classobj = cls;
- clsen->loaders = NULL;
- clsen->constraints = NULL;
-
- clsen->next = en->classes;
- en->classes = clsen;
- CLASSCACHE_COUNT(stat_classes_stored);
-
-return_success:
-#ifdef CLASSCACHE_VERBOSE
- classcache_debug_dump(stdout,cls->name);
-#endif
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-/* classcache_find_loader ******************************************************
-
- Find the class entry loaded by or constrained to a given loader
- (internally used helper function)
-
- IN:
- entry............the classcache_name_entry
- loader...........the loader to look for
-
- RETURN VALUE:
- the classcache_class_entry for the given loader, or
- NULL if no entry was found
-
-*******************************************************************************/
-
-static classcache_class_entry * classcache_find_loader(
- classcache_name_entry * entry,
- classloader_t * loader)
-{
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
-
- assert(entry);
-
- /* iterate over all class entries */
- for (clsen = entry->classes; clsen; clsen = clsen->next) {
-
- /* check if this entry has already been loaded by initloader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == loader)
- return clsen; /* found */
- }
-
- /* check if loader is constrained to this entry */
- for (lden = clsen->constraints; lden; lden = lden->next) {
- if (lden->loader == loader)
- return clsen; /* found */
- }
- }
-
- /* not found */
- return NULL;
-}
-
-/* classcache_free_class_entry *************************************************
-
- Free the memory used by a class entry
-
- IN:
- clsen............the classcache_class_entry to free
-
-*******************************************************************************/
-
-static void classcache_free_class_entry(classcache_class_entry * clsen)
-{
- classcache_loader_entry *lden;
- classcache_loader_entry *next;
-
- assert(clsen);
-
- for (lden = clsen->loaders; lden; lden = next) {
- next = lden->next;
- FREE(lden, classcache_loader_entry);
- }
- for (lden = clsen->constraints; lden; lden = next) {
- next = lden->next;
- FREE(lden, classcache_loader_entry);
- }
-
- FREE(clsen, classcache_class_entry);
-}
-
-/* classcache_remove_class_entry ***********************************************
-
- Remove a classcache_class_entry from the list of possible resolution of
- a name entry
- (internally used helper function)
-
- IN:
- entry............the classcache_name_entry
- clsen............the classcache_class_entry to remove
-
-*******************************************************************************/
-
-static void classcache_remove_class_entry(classcache_name_entry * entry,
- classcache_class_entry * clsen)
-{
- classcache_class_entry **chain;
-
- assert(entry);
- assert(clsen);
-
- chain = &(entry->classes);
- while (*chain) {
- if (*chain == clsen) {
- *chain = clsen->next;
- classcache_free_class_entry(clsen);
- return;
- }
- chain = &((*chain)->next);
- }
-}
-
-/* classcache_free_name_entry **************************************************
-
- Free the memory used by a name entry
-
- IN:
- entry............the classcache_name_entry to free
-
-*******************************************************************************/
-
-static void classcache_free_name_entry(classcache_name_entry * entry)
-{
- classcache_class_entry *clsen;
- classcache_class_entry *next;
-
- assert(entry);
-
- for (clsen = entry->classes; clsen; clsen = next) {
- next = clsen->next;
- classcache_free_class_entry(clsen);
- }
-
- FREE(entry, classcache_name_entry);
-}
-
-/* classcache_free *************************************************************
-
- Free the memory used by the class cache
-
- NOTE:
- The class cache may not be used any more after this call, except
- when it is reinitialized with classcache_init.
-
- Note: NOT synchronized!
-
-*******************************************************************************/
-
-void classcache_free(void)
-{
- u4 slot;
- classcache_name_entry *entry;
- classcache_name_entry *next;
-
- for (slot = 0; slot < hashtable_classcache.size; ++slot) {
- for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
- next = entry->hashlink;
- classcache_free_name_entry(entry);
- }
- }
-
- MFREE(hashtable_classcache.ptr, voidptr, hashtable_classcache.size);
- hashtable_classcache.size = 0;
- hashtable_classcache.entries = 0;
- hashtable_classcache.ptr = NULL;
-}
-
-/* classcache_add_constraint ***************************************************
-
- Add a loading constraint
-
- IN:
- a................first initiating loader
- b................second initiating loader
- classname........class name
-
- RETURN VALUE:
- true.............everything ok, the constraint has been added,
- false............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraint(classloader_t * a,
- classloader_t * b,
- utf * classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsenA;
- classcache_class_entry *clsenB;
-
- assert(classname);
-
-#ifdef CLASSCACHE_VERBOSE
- log_start();
- log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
- utf_fprint_printable_ascii_classname(stdout, classname);
- log_print(")\n");
- log_finish();
-#endif
-
- /* a constraint with a == b is trivially satisfied */
- if (a == b) {
- CLASSCACHE_COUNT(stat_trivial_constraints);
- return true;
- }
-
- CLASSCACHE_LOCK();
-
- en = classcache_new_name(classname);
-
- assert(en);
- CLASSCACHE_COUNT(stat_nontriv_constraints);
-
- /* find the entry loaded by / constrained to each loader */
- clsenA = classcache_find_loader(en, a);
- clsenB = classcache_find_loader(en, b);
-
- if (clsenA && clsenB) {
- /* { both loaders have corresponding entries } */
- CLASSCACHE_COUNT(stat_nontriv_constraints_both);
-
- /* if the entries are the same, the constraint is already recorded */
- if (clsenA == clsenB)
- goto return_success;
-
- /* check if the entries can be merged */
- if (clsenA->classobj && clsenB->classobj
- && clsenA->classobj != clsenB->classobj) {
- /* no, the constraint is violated */
- exceptions_throw_linkageerror("loading constraint violated: ",
- clsenA->classobj);
- goto return_exception;
- }
-
- /* yes, merge the entries */
- classcache_merge_class_entries(en,clsenA,clsenB);
- CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
- }
- else {
- /* { at most one of the loaders has a corresponding entry } */
-
- /* set clsenA to the single class entry we have */
- if (!clsenA)
- clsenA = clsenB;
-
- if (!clsenA) {
- /* { no loader has a corresponding entry } */
- CLASSCACHE_COUNT(stat_nontriv_constraints_none);
-
- /* create a new class entry with the constraint (a,b,en->name) */
- clsenA = NEW(classcache_class_entry);
- clsenA->classobj = NULL;
- clsenA->loaders = NULL;
- clsenA->constraints = classcache_new_loader_entry(b, NULL);
- clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
-
- clsenA->next = en->classes;
- en->classes = clsenA;
- }
- else {
- CLASSCACHE_COUNT(stat_nontriv_constraints_one);
-
- /* make b the loader that has no corresponding entry */
- if (clsenB)
- b = a;
-
- /* loader b must be added to entry clsenA */
- clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
- }
- }
-
- return_success:
- CLASSCACHE_UNLOCK();
- return true;
-
- return_exception:
- CLASSCACHE_UNLOCK();
- return false; /* exception */
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-/* classcache_add_constraints_for_params ***************************************
-
- Add loading constraints for the parameters and return type of
- the given method.
-
- IN:
- a................first initiating loader
- b................second initiating loader
- m................methodinfo
-
- RETURN VALUE:
- true.............everything ok, the constraints have been added,
- false............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraints_for_params(classloader_t * a,
- classloader_t * b,
- methodinfo *m)
-{
- methoddesc *md;
- typedesc *td;
- s4 i;
-
- /* a constraint with a == b is trivially satisfied */
-
- if (a == b) {
- return true;
- }
-
- /* get the parsed descriptor */
-
- assert(m);
- md = m->parseddesc;
- assert(md);
-
- /* constrain the return type */
-
- if (md->returntype.type == TYPE_ADR) {
- if (!classcache_add_constraint(a, b, md->returntype.classref->name))
- return false; /* exception */
- }
-
- /* constrain each reference type used in the parameters */
-
- td = md->paramtypes;
- i = md->paramcount;
- for (; i--; td++) {
- if (td->type != TYPE_ADR)
- continue;
-
- if (!classcache_add_constraint(a, b, td->classref->name))
- return false; /* exception */
- }
-
- /* everything ok */
- return true;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* classcache_number_of_loaded_classes *****************************************
-
- Counts the number of loaded classes and returns it.
-
- Note: This function assumes that the CLASSCACHE_LOCK is held by the
- caller!
-
-*******************************************************************************/
-
-static s4 classcache_number_of_loaded_classes(void)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- s4 number;
- s4 i;
-
- /* initialize class counter */
-
- number = 0;
-
- for (i = 0; i < hashtable_classcache.size; i++) {
- /* iterate over hashlink */
-
- for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
- /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
-
- if (en->name->text[0] == '$')
- continue;
-
- /* iterate over classes with same name */
-
- for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
- /* get only loaded classes */
-
- if (clsen->classobj != NULL)
- number++;
- }
- }
- }
-
- return number;
-}
-
-
-/* classcache_get_loaded_class_count *******************************************
-
- Counts the number of loaded classes and returns it.
-
-*******************************************************************************/
-
-s4 classcache_get_loaded_class_count(void)
-{
- s4 count;
-
- CLASSCACHE_LOCK();
-
- count = classcache_number_of_loaded_classes();
-
- CLASSCACHE_UNLOCK();
-
- return count;
-}
-
-
-/* classcache_get_loaded_classes ***********************************************
-
- Returns an array of all loaded classes as array. The array is
- allocaed on the Java heap.
-
-*******************************************************************************/
-
-#if defined(ENABLE_JVMTI)
-void classcache_get_loaded_classes(s4 *class_count_ptr,
- classinfo ***classes_ptr)
-{
- classinfo **classes;
- s4 class_count;
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- s4 i;
- s4 j;
-
- CLASSCACHE_LOCK();
-
- /* get the number of loaded classes and allocate the array */
-
- class_count = classcache_number_of_loaded_classes();
-
- classes = GCMNEW(classinfo*, class_count);
-
- /* look in every slot of the hashtable */
-
- for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
- /* iterate over hashlink */
-
- for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
- /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
-
- if (en->name->text[0] == '$')
- continue;
-
- /* iterate over classes with same name */
-
- for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
- /* get only loaded classes */
-
- if (clsen->classobj != NULL) {
- classes[j] = clsen->classobj;
- j++;
- }
- }
- }
- }
-
- /* pass the return values */
-
- *class_count_ptr = class_count;
- *classes_ptr = classes;
-
- CLASSCACHE_UNLOCK();
-}
-#endif /* defined(ENABLE_JVMTI) */
-
-
-/* classcache_foreach_loaded_class *********************************************
-
- Calls the given function for each loaded class.
-
-*******************************************************************************/
-
-void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
- void *data)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- s4 i;
-
- CLASSCACHE_LOCK();
-
- /* look in every slot of the hashtable */
-
- for (i = 0; i < hashtable_classcache.size; i++) {
- /* iterate over hashlink */
-
- for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
- /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
-
- if (en->name->text[0] == '$')
- continue;
-
- /* iterate over classes with same name */
-
- for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
- /* get only loaded classes */
-
- if (clsen->classobj != NULL) {
- (*func)(clsen->classobj, data);
- }
- }
- }
- }
-
- CLASSCACHE_UNLOCK();
-}
-
-
-/*============================================================================*/
-/* DEBUG DUMPS */
-/*============================================================================*/
-
-/* classcache_debug_dump *******************************************************
-
- Print the contents of the loaded class cache to a stream
-
- IN:
- file.............output stream
- only.............if != NULL, only print entries for this name
- (Currently we print also the rest of the hash chain to
- get a feel for the average length of hash chains.)
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-#ifndef NDEBUG
-void classcache_debug_dump(FILE * file,utf *only)
-{
- classcache_name_entry *c;
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
- u4 slot;
-
- CLASSCACHE_LOCK();
-
- log_println("=== [loaded class cache] =====================================");
- log_println("hash size : %d", (int) hashtable_classcache.size);
- log_println("hash entries: %d", (int) hashtable_classcache.entries);
- log_println("");
-
- if (only) {
- c = classcache_lookup_name(only);
- slot = 0; /* avoid compiler warning */
- goto dump_it;
- }
-
- for (slot = 0; slot < hashtable_classcache.size; ++slot) {
- c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
-
-dump_it:
- for (; c; c = c->hashlink) {
- utf_fprint_printable_ascii_classname(file, c->name);
- fprintf(file, "\n");
-
- /* iterate over all class entries */
- for (clsen = c->classes; clsen; clsen = clsen->next) {
- if (clsen->classobj) {
- log_println(" loaded %p", (void *) clsen->classobj);
- }
- else {
- log_println(" unresolved");
- }
-
- log_start();
- log_print(" loaders: ");
- for (lden = clsen->loaders; lden; lden = lden->next) {
- log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
- }
- log_finish();
-
- log_start();
- log_print(" constraints: ");
- for (lden = clsen->constraints; lden; lden = lden->next) {
- log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
- }
- log_finish();
- }
- }
-
- if (only)
- break;
- }
- fprintf(file, "\n==============================================================\n\n");
-
- CLASSCACHE_UNLOCK();
-}
-#endif /* 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/vmcore/classcache.h - loaded class cache and loading constraints
-
- 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 _CLASSCACHE_H
-#define _CLASSCACHE_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include <stdio.h> /* for FILE */
-
-#if defined(ENABLE_JVMTI)
-# include "native/jni.h"
-#endif
-
-#include "toolbox/hashtable.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/references.h"
-
-
-/* forward declarations *******************************************************/
-
-typedef struct classcache_name_entry classcache_name_entry;
-typedef struct classcache_class_entry classcache_class_entry;
-typedef struct classcache_loader_entry classcache_loader_entry;
-
-/* global variables ***********************************************************/
-
-extern hashtable hashtable_classcache;
-
-
-/* structs ********************************************************************/
-
-/*----------------------------------------------------------------------------*/
-/* The Loaded Class Cache */
-/* */
-/* The loaded class cache is implemented as a two-level data structure. */
-/* */
-/* The first level is a hash table indexed by class names. For each class */
-/* name in the cache there is a classcache_name_entry, which collects all */
-/* information about classes with this class name. */
-/* */
-/* Second level: For each classcache_name_entry there is a list of */
-/* classcache_class_entry:s representing the possible different resolutions */
-/* of the class name. */
-/* */
-/* A classcache_class_entry records the following: */
-/* */
-/* - the loaded class object, if this entry has been resolved, otherwise NULL */
-/* - the list of initiating loaders which have resolved the class name to */
-/* this class object */
-/* - the list of initiating loaders which are constrained to resolve this */
-/* class name to this class object in the future */
-/* */
-/* The classcache_class_entry:s approximate the equivalence classes created */
-/* by the loading constraints and the equivalence of loaded classes. */
-/* */
-/* When a loading constraint (loaderA,loaderB,NAME) is added, then the */
-/* classcache_class_entry:s for NAME containing loaderA and loaderB resp. */
-/* must be merged into one entry. If this is impossible, because the entries */
-/* have already been resolved to different class objects, then the constraint */
-/* is violated and an expception must be thrown. */
-/*----------------------------------------------------------------------------*/
-
-
-/* classcache_name_entry
- *
- * For each classname a classcache_name_entry struct is created.
- */
-
-struct classcache_name_entry
-{
- utf *name; /* class name */
- classcache_name_entry *hashlink; /* link for external chaining */
- classcache_class_entry *classes; /* equivalence classes for this name*/
-};
-
-struct classcache_class_entry
-{
- classinfo *classobj; /* the loaded class object, or NULL */
- classcache_loader_entry *loaders;
- classcache_loader_entry *constraints;
- classcache_class_entry *next; /* next class entry for same name */
-};
-
-struct classcache_loader_entry
-{
- classloader_t *loader; /* class loader object */
- classcache_loader_entry *next; /* next loader entry in the list */
-};
-
-
-/* callback function type for classcache_foreach_loaded_class */
-
-typedef void (*classcache_foreach_functionptr_t)(classinfo *, void *);
-
-
-/* function prototypes ********************************************************/
-
-/* initialize the loaded class cache */
-bool classcache_init(void);
-void classcache_free(void);
-
-classinfo * classcache_lookup(classloader_t *initloader,utf *classname);
-classinfo * classcache_lookup_defined(classloader_t *defloader,utf *classname);
-classinfo * classcache_lookup_defined_or_initiated(classloader_t *loader,utf *classname);
-
-bool classcache_store_unique(classinfo *cls);
-classinfo * classcache_store(classloader_t *initloader,classinfo *cls,bool mayfree);
-classinfo * classcache_store_defined(classinfo *cls);
-
-#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraint(classloader_t *a,classloader_t *b,utf *classname);
-bool classcache_add_constraints_for_params(classloader_t *a,classloader_t *b,
- methodinfo *m);
-#endif
-
-s4 classcache_get_loaded_class_count(void);
-
-void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
- void *data);
-
-#if defined(ENABLE_JVMTI)
-void classcache_get_loaded_classes(s4 *class_count_ptr,
- classinfo ***classes_ptr);
-#endif
-
-#ifndef NDEBUG
-void classcache_debug_dump(FILE *file,utf *only);
-#endif
-
-#endif /* _CLASSCACHE_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:
- */
-
+++ /dev/null
-/* src/vmcore/descriptor.c - checking and parsing of field / method descriptors
-
- 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 "vm/types.h"
-
-#include "md-abi.h"
-
-#include "mm/memory.h"
-
-#include "vm/exceptions.h"
-#include "vm/jit_interface.h"
-#include "vm/primitive.h"
-#include "vm/vm.h"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/options.h"
-
-
-/* constants (private to descriptor.c) ****************************************/
-
-/* initial number of entries for the classrefhash of a descriptor_pool */
-/* (currently the hash is never grown!) */
-#define CLASSREFHASH_INIT_SIZE 64
-
-/* initial number of entries for the descriptorhash of a descriptor_pool */
-/* (currently the hash is never grown!) */
-#define DESCRIPTORHASH_INIT_SIZE 128
-
-/* data structures (private to descriptor.c) **********************************/
-
-typedef struct classref_hash_entry classref_hash_entry;
-typedef struct descriptor_hash_entry descriptor_hash_entry;
-
-/* entry struct for the classrefhash of descriptor_pool */
-struct classref_hash_entry {
- classref_hash_entry *hashlink; /* for hash chaining */
- utf *name; /* name of the class refered to */
- u2 index; /* index into classref table */
-};
-
-/* entry struct for the descriptorhash of descriptor_pool */
-struct descriptor_hash_entry {
- descriptor_hash_entry *hashlink;
- utf *desc;
- parseddesc_t parseddesc;
- s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
-};
-
-
-/****************************************************************************/
-/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
-/****************************************************************************/
-
-/* SKIP_FIELDDESCRIPTOR:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * CAUTION: This macro does not check for an unexpected end of the
- * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
- */
-#define SKIP_FIELDDESCRIPTOR(utf_ptr) \
- do { while (*(utf_ptr)=='[') (utf_ptr)++; \
- if (*(utf_ptr)++=='L') \
- while(*(utf_ptr)++ != ';') /* skip */; } while(0)
-
-/* SKIP_FIELDDESCRIPTOR_SAFE:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * Input:
- * utf_ptr....points to first char of descriptor
- * end_ptr....points to first char after the end of the string
- * errorflag..must be initialized (to false) by the caller!
- * Output:
- * utf_ptr....points to first char after the descriptor
- * errorflag..set to true if the string ended unexpectedly
- */
-#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
- do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
- if ((utf_ptr) == (end_ptr)) \
- (errorflag) = true; \
- else \
- if (*(utf_ptr)++=='L') { \
- while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
- /* skip */; \
- if ((utf_ptr)[-1] != ';') \
- (errorflag) = true; }} while(0)
-
-
-/****************************************************************************/
-/* DEBUG HELPERS */
-/****************************************************************************/
-
-/*#define DESCRIPTOR_VERBOSE*/
-
-/****************************************************************************/
-/* FUNCTIONS */
-/****************************************************************************/
-
-/* descriptor_to_basic_type ****************************************************
-
- Return the basic type to use for a value with this descriptor.
-
- IN:
- utf..............descriptor utf string
-
- OUT:
- A TYPE_* constant.
-
- PRECONDITIONS:
- This function assumes that the descriptor has passed
- descriptor_pool_add checks and that it does not start with '('.
-
-*******************************************************************************/
-
-int descriptor_to_basic_type(utf *descriptor)
-{
- assert(descriptor->blength >= 1);
-
- switch (descriptor->text[0]) {
- case 'Z':
- case 'B':
- case 'C':
- case 'S':
- case 'I':
- return TYPE_INT;
-
- case 'J':
- return TYPE_LNG;
-
- case 'F':
- return TYPE_FLT;
-
- case 'D':
- return TYPE_DBL;
-
- case 'L':
- case '[':
- return TYPE_ADR;
-
- default:
- vm_abort("descriptor_to_basic_type: invalid type %c",
- descriptor->text[0]);
- }
-
- /* keep the compiler happy */
-
- return 0;
-}
-
-
-/* descriptor_typesize *********************************************************
-
- Return the size in bytes needed for the given type.
-
- IN:
- td..............typedesc describing the type
-
- OUT:
- The number of bytes
-
-*******************************************************************************/
-
-int descriptor_typesize(typedesc *td)
-{
- assert(td);
-
- switch (td->type) {
- case TYPE_INT:
- case TYPE_FLT:
- return 4;
-
- case TYPE_LNG:
- case TYPE_DBL:
- return 8;
-
- case TYPE_ADR:
- return SIZEOF_VOID_P;
-
- default:
- vm_abort("descriptor_typesize: invalid type %d", td->type);
- }
-
- /* keep the compiler happy */
-
- return 0;
-}
-
-
-/* name_from_descriptor ********************************************************
-
- Return the class name indicated by the given descriptor
- (Internally used helper function)
-
- IN:
- c................class containing the descriptor
- utf_ptr..........first character of descriptor
- end_ptr..........first character after the end of the string
- mode.............a combination (binary or) of the following flags:
-
- (Flags marked with * are the default settings.)
-
- How to handle "V" descriptors:
-
- * DESCRIPTOR_VOID.....handle it like other primitive types
- DESCRIPTOR_NOVOID...treat it as an error
-
- How to deal with extra characters after the end of the
- descriptor:
-
- * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
- DESCRIPTOR_CHECKEND.....treat them as an error
-
- OUT:
- *next............if non-NULL, *next is set to the first character after
- the descriptor. (Undefined if an error occurs.)
- *name............set to the utf name of the class
-
- RETURN VALUE:
- true.............descriptor parsed successfully
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#define DESCRIPTOR_VOID 0 /* default */
-#define DESCRIPTOR_NOVOID 0x0040
-#define DESCRIPTOR_NOCHECKEND 0 /* default */
-#define DESCRIPTOR_CHECKEND 0x1000
-
-static bool
-name_from_descriptor(classinfo *c,
- char *utf_ptr, char *end_ptr,
- char **next, int mode, utf **name)
-{
- char *start = utf_ptr;
- bool error = false;
-
- assert(c);
- assert(utf_ptr);
- assert(end_ptr);
- assert(name);
-
- *name = NULL;
- SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
-
- if (mode & DESCRIPTOR_CHECKEND)
- error |= (utf_ptr != end_ptr);
-
- if (!error) {
- if (next) *next = utf_ptr;
-
- switch (*start) {
- case 'V':
- if (mode & DESCRIPTOR_NOVOID)
- break;
- /* FALLTHROUGH! */
- case 'I':
- case 'J':
- case 'F':
- case 'D':
- case 'B':
- case 'C':
- case 'S':
- case 'Z':
- return true;
-
- case 'L':
- start++;
- utf_ptr--;
- /* FALLTHROUGH! */
- case '[':
- *name = utf_new(start, utf_ptr - start);
- return true;
- }
- }
-
- exceptions_throw_classformaterror(c, "Invalid descriptor");
- return false;
-}
-
-
-/* descriptor_to_typedesc ******************************************************
-
- Parse the given type descriptor and fill a typedesc struct
- (Internally used helper function)
-
- IN:
- pool.............the descriptor pool
- utf_ptr..........points to first character of type descriptor
- end_pos..........points after last character of the whole descriptor
-
- OUT:
- *next............set to next character after type descriptor
- *d...............filled with parsed information
-
- RETURN VALUE:
- true.............parsing succeeded
- false............an exception has been thrown
-
-*******************************************************************************/
-
-static bool
-descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
- char **next, typedesc *td)
-{
- utf *name;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
- return false;
-
- if (name) {
- /* a reference type */
- td->type = TYPE_ADR;
- td->decltype = TYPE_ADR;
- td->arraydim = 0;
- for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
- td->arraydim++;
- td->classref = descriptor_pool_lookup_classref(pool, name);
-
- } else {
- /* a primitive type */
- switch (*utf_ptr) {
- case 'B':
- td->decltype = PRIMITIVETYPE_BYTE;
- td->type = TYPE_INT;
- break;
- case 'C':
- td->decltype = PRIMITIVETYPE_CHAR;
- td->type = TYPE_INT;
- break;
- case 'S':
- td->decltype = PRIMITIVETYPE_SHORT;
- td->type = TYPE_INT;
- break;
- case 'Z':
- td->decltype = PRIMITIVETYPE_BOOLEAN;
- td->type = TYPE_INT;
- break;
- case 'I':
- td->decltype = PRIMITIVETYPE_INT;
- td->type = TYPE_INT;
- break;
- case 'D':
- td->decltype = PRIMITIVETYPE_DOUBLE;
- td->type = TYPE_DBL;
- break;
- case 'F':
- td->decltype = PRIMITIVETYPE_FLOAT;
- td->type = TYPE_FLT;
- break;
- case 'J':
- td->decltype = PRIMITIVETYPE_LONG;
- td->type = TYPE_LNG;
- break;
- case 'V':
- td->decltype = PRIMITIVETYPE_VOID;
- td->type = TYPE_VOID;
- break;
- default:
- assert(false);
- }
-
- td->arraydim = 0;
- td->classref = NULL;
- }
-
- return true;
-}
-
-
-/* descriptor_pool_new *********************************************************
-
- Allocate a new descriptor_pool
-
- IN:
- referer..........class for which to create the pool
-
- RETURN VALUE:
- a pointer to the new descriptor_pool
-
-*******************************************************************************/
-
-descriptor_pool *
-descriptor_pool_new(classinfo *referer)
-{
- descriptor_pool *pool;
- u4 hashsize;
- u4 slot;
-
- pool = DNEW(descriptor_pool);
- assert(pool);
-
- pool->referer = referer;
- pool->fieldcount = 0;
- pool->methodcount = 0;
- pool->paramcount = 0;
- pool->descriptorsize = 0;
- pool->descriptors = NULL;
- pool->descriptors_next = NULL;
- pool->classrefs = NULL;
- pool->descriptor_kind = NULL;
- pool->descriptor_kind_next = NULL;
-
- hashsize = CLASSREFHASH_INIT_SIZE;
- pool->classrefhash.size = hashsize;
- pool->classrefhash.entries = 0;
- pool->classrefhash.ptr = DMNEW(voidptr,hashsize);
- for (slot=0; slot<hashsize; ++slot)
- pool->classrefhash.ptr[slot] = NULL;
-
- hashsize = DESCRIPTORHASH_INIT_SIZE;
- pool->descriptorhash.size = hashsize;
- pool->descriptorhash.entries = 0;
- pool->descriptorhash.ptr = DMNEW(voidptr,hashsize);
- for (slot=0; slot<hashsize; ++slot)
- pool->descriptorhash.ptr[slot] = NULL;
-
- return pool;
-}
-
-
-/* descriptor_pool_add_class ***************************************************
-
- Add the given class reference to the pool
-
- IN:
- pool.............the descriptor_pool
- name.............the class reference to add
-
- RETURN VALUE:
- true.............reference has been added
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool
-descriptor_pool_add_class(descriptor_pool *pool, utf *name)
-{
- u4 key,slot;
- classref_hash_entry *c;
-
- assert(pool);
- assert(name);
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
- utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
-#endif
-
- /* find a place in the hashtable */
-
- key = utf_hashkey(name->text, name->blength);
- slot = key & (pool->classrefhash.size - 1);
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
-
- while (c) {
- if (c->name == name)
- return true; /* already stored */
- c = c->hashlink;
- }
-
- /* check if the name is a valid classname */
-
- if (!is_valid_name(name->text,UTF_END(name))) {
- exceptions_throw_classformaterror(pool->referer, "Invalid class name");
- return false; /* exception */
- }
-
- /* XXX check maximum array dimension */
-
- c = DNEW(classref_hash_entry);
- c->name = name;
- c->index = pool->classrefhash.entries++;
- c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- pool->classrefhash.ptr[slot] = c;
-
- return true;
-}
-
-
-/* descriptor_pool_add *********************************************************
-
- Check the given descriptor and add it to the pool
-
- IN:
- pool.............the descriptor_pool
- desc.............the descriptor to add. Maybe a field or method desc.
-
- OUT:
- *paramslots......if non-NULL, set to the number of parameters.
- LONG and DOUBLE are counted twice
-
- RETURN VALUE:
- true.............descriptor has been added
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool
-descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
-{
- u4 key,slot;
- descriptor_hash_entry *d;
- char *utf_ptr;
- char *end_pos;
- utf *name;
- s4 argcount = 0;
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
- utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
-#endif
-
- assert(pool);
- assert(desc);
-
- /* find a place in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- /* Save all method descriptors in the hashtable, since the parsed */
- /* descriptor may vary between differenf methods (static vs. non-static). */
-
- utf_ptr = desc->text;
-
- if (*utf_ptr != '(') {
- while (d) {
- if (d->desc == desc) {
- if (paramslots)
- *paramslots = d->paramslots;
- return true; /* already stored */
- }
- d = d->hashlink;
- }
- }
-
- /* add the descriptor to the pool */
-
- d = DNEW(descriptor_hash_entry);
- d->desc = desc;
- d->parseddesc.any = NULL;
- d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
- pool->descriptorhash.ptr[slot] = d;
-
- /* now check the descriptor */
-
- end_pos = UTF_END(desc);
-
- if (*utf_ptr == '(') {
- /* a method descriptor */
-
- pool->methodcount++;
- utf_ptr++;
-
- /* check arguments */
-
- while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
- pool->paramcount++;
-
- /* We cannot count the `this' argument here because
- * we don't know if the method is static. */
-
- if (*utf_ptr == 'J' || *utf_ptr == 'D')
- argcount += 2;
- else
- argcount++;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
- DESCRIPTOR_NOVOID, &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool, name))
- return false;
- }
-
- if (utf_ptr == end_pos) {
- exceptions_throw_classformaterror(pool->referer,
- "Missing ')' in method descriptor");
- return false;
- }
-
- utf_ptr++; /* skip ')' */
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
- DESCRIPTOR_CHECKEND, &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool,name))
- return false;
-
- if (argcount > 255) {
- exceptions_throw_classformaterror(pool->referer,
- "Too many arguments in signature");
- return false;
- }
-
- } else {
- /* a field descriptor */
-
- pool->fieldcount++;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
- DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
- &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool,name))
- return false;
- }
-
- d->paramslots = argcount;
-
- if (paramslots)
- *paramslots = argcount;
-
- return true;
-}
-
-
-/* descriptor_pool_create_classrefs ********************************************
-
- Create a table containing all the classrefs which were added to the pool
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *count...........if count is non-NULL, this is set to the number
- of classrefs in the table
-
- RETURN VALUE:
- a pointer to the constant_classref table
-
-*******************************************************************************/
-
-constant_classref *
-descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
-{
- u4 nclasses;
- u4 slot;
- classref_hash_entry *c;
- constant_classref *ref;
-
- assert(pool);
-
- nclasses = pool->classrefhash.entries;
- pool->classrefs = MNEW(constant_classref,nclasses);
-
- /* fill the constant_classref structs */
-
- for (slot = 0; slot < pool->classrefhash.size; ++slot) {
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- while (c) {
- ref = pool->classrefs + c->index;
- CLASSREF_INIT(*ref, pool->referer, c->name);
- c = c->hashlink;
- }
- }
-
- if (count)
- *count = nclasses;
-
- return pool->classrefs;
-}
-
-
-/* descriptor_pool_lookup_classref *********************************************
-
- Return the constant_classref for the given class name
-
- IN:
- pool.............the descriptor_pool
- classname........name of the class to look up
-
- RETURN VALUE:
- a pointer to the constant_classref, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-constant_classref *
-descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
-{
- u4 key,slot;
- classref_hash_entry *c;
-
- assert(pool);
- assert(pool->classrefs);
- assert(classname);
-
- key = utf_hashkey(classname->text, classname->blength);
- slot = key & (pool->classrefhash.size - 1);
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
-
- while (c) {
- if (c->name == classname)
- return pool->classrefs + c->index;
- c = c->hashlink;
- }
-
- exceptions_throw_internalerror("Class reference not found in descriptor pool");
- return NULL;
-}
-
-
-/* descriptor_pool_alloc_parsed_descriptors ************************************
-
- Allocate space for the parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- NOTE:
- This function must be called after all descriptors have been added
- with descriptor_pool_add.
-
-*******************************************************************************/
-
-void
-descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
-{
- u4 size;
-
- assert(pool);
-
- /* TWISTI: paramcount + 1: we don't know if the method is static or */
- /* not, i have no better solution yet. */
-
- size =
- pool->fieldcount * sizeof(typedesc) +
- pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
- pool->paramcount * sizeof(typedesc) +
- pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
-
- pool->descriptorsize = size;
- if (size) {
- pool->descriptors = MNEW(u1, size);
- pool->descriptors_next = pool->descriptors;
- }
-
- size = pool->fieldcount + pool->methodcount;
- if (size) {
- pool->descriptor_kind = DMNEW(u1, size);
- pool->descriptor_kind_next = pool->descriptor_kind;
- }
-}
-
-
-/* descriptor_pool_parse_field_descriptor **************************************
-
- Parse the given field descriptor
-
- IN:
- pool.............the descriptor_pool
- desc.............the field descriptor
-
- RETURN VALUE:
- a pointer to the parsed field descriptor, or
- NULL if an exception has been thrown
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called (once)
- before this function is used.
-
-*******************************************************************************/
-
-typedesc *
-descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
-{
- u4 key,slot;
- descriptor_hash_entry *d;
- typedesc *td;
-
- assert(pool);
- assert(pool->descriptors);
- assert(pool->descriptors_next);
-
- /* lookup the descriptor in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- while (d) {
- if (d->desc == desc) {
- /* found */
- if (d->parseddesc.fd)
- return d->parseddesc.fd;
- break;
- }
- d = d->hashlink;
- }
-
- assert(d);
-
- if (desc->text[0] == '(') {
- exceptions_throw_classformaterror(pool->referer,
- "Method descriptor used in field reference");
- return NULL;
- }
-
- td = (typedesc *) pool->descriptors_next;
- pool->descriptors_next += sizeof(typedesc);
-
- if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
- return NULL;
-
- *(pool->descriptor_kind_next++) = 'f';
-
- d->parseddesc.fd = td;
-
- return td;
-}
-
-
-/* descriptor_pool_parse_method_descriptor *************************************
-
- Parse the given method descriptor
-
- IN:
- pool.............the descriptor_pool
- desc.............the method descriptor
- mflags...........the method flags
- thisclass........classref to the class containing the method.
- This is ignored if mflags contains ACC_STATIC.
- The classref is stored for inserting the 'this' argument.
-
- RETURN VALUE:
- a pointer to the parsed method descriptor, or
- NULL if an exception has been thrown
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called
- (once) before this function is used.
-
-*******************************************************************************/
-
-methoddesc *
-descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
- s4 mflags,constant_classref *thisclass)
-{
- u4 key, slot;
- descriptor_hash_entry *d;
- methoddesc *md;
- typedesc *td;
- char *utf_ptr;
- char *end_pos;
- s2 paramcount = 0;
- s2 paramslots = 0;
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
- (void*)pool,(int)mflags,(void*)thisclass);
- utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
-#endif
-
- assert(pool);
- assert(pool->descriptors);
- assert(pool->descriptors_next);
-
- /* check that it is a method descriptor */
-
- if (desc->text[0] != '(') {
- exceptions_throw_classformaterror(pool->referer,
- "Field descriptor used in method reference");
- return NULL;
- }
-
- /* lookup the descriptor in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- /* find an un-parsed descriptor */
-
- while (d) {
- if (d->desc == desc)
- if (!d->parseddesc.md)
- break;
- d = d->hashlink;
- }
-
- assert(d);
-
- md = (methoddesc *) pool->descriptors_next;
- pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
-
- utf_ptr = desc->text + 1; /* skip '(' */
- end_pos = UTF_END(desc);
-
- td = md->paramtypes;
-
- /* count the `this' pointer */
-
- if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
- td->type = TYPE_ADR;
- td->decltype = TYPE_ADR;
- td->arraydim = 0;
- td->classref = thisclass;
-
- td++;
- pool->descriptors_next += sizeof(typedesc);
- paramcount++;
- paramslots++;
- }
-
- while (*utf_ptr != ')') {
- /* parse a parameter type */
-
- if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
- return NULL;
-
- if (IS_2_WORD_TYPE(td->type))
- paramslots++;
-
- td++;
- pool->descriptors_next += sizeof(typedesc);
- paramcount++;
- paramslots++;
- }
- utf_ptr++; /* skip ')' */
-
- /* Skip possible `this' pointer in paramtypes array to allow a possible */
- /* memory move later in parse. */
- /* We store the thisclass reference, so we can later correctly fill in */
- /* the parameter slot of the 'this' argument. */
-
- if (mflags == ACC_UNDEF) {
- td->classref = thisclass;
- td++;
- pool->descriptors_next += sizeof(typedesc);
- }
-
- /* parse return type */
-
- if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
- &(md->returntype)))
- return NULL;
-
- md->paramcount = paramcount;
- md->paramslots = paramslots;
-
- /* If mflags != ACC_UNDEF we parse a real loaded method, so do
- param prealloc. Otherwise we do this in stack analysis. */
-
- if (mflags != ACC_UNDEF) {
- if (md->paramcount > 0) {
- /* allocate memory for params */
-
- md->params = MNEW(paramdesc, md->paramcount);
- }
- else {
- md->params = METHODDESC_NOPARAMS;
- }
-
- /* fill the paramdesc */
- /* md_param_alloc has to be called if md->paramcount == 0,
- too, so it can make the reservation for the Linkage Area,
- Return Register... */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- {
- /* As builtin-functions are native functions, we have
- to pre-allocate for the native ABI. */
-
- if (mflags & ACC_METHOD_BUILTIN)
- md_param_alloc_native(md);
- else
- md_param_alloc(md);
- }
-#endif
- }
- else {
- /* params will be allocated later by
- descriptor_params_from_paramtypes if necessary */
-
- md->params = NULL;
- }
-
- *(pool->descriptor_kind_next++) = 'm';
-
- d->parseddesc.md = md;
-
- return md;
-}
-
-/* descriptor_params_from_paramtypes *******************************************
-
- Create the paramdescs for a method descriptor. This function is called
- when we know whether the method is static or not. This function may only
- be called once for each methoddesc, and only if md->params == NULL.
-
- IN:
- md...............the parsed method descriptor
- md->params MUST be NULL.
- mflags...........the ACC_* access flags of the method. Only the
- ACC_STATIC bit is checked.
- The value ACC_UNDEF is NOT allowed.
-
- RETURN VALUE:
- true.............the paramdescs were created successfully
- false............an exception has been thrown
-
- POSTCONDITION:
- md->parms != NULL
-
-*******************************************************************************/
-
-bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
-{
- typedesc *td;
-
- assert(md);
- assert(md->params == NULL);
- assert(mflags != ACC_UNDEF);
-
- td = md->paramtypes;
-
- /* check for `this' pointer */
-
- if (!(mflags & ACC_STATIC)) {
- constant_classref *thisclass;
-
- /* fetch class reference from reserved param slot */
- thisclass = td[md->paramcount].classref;
- assert(thisclass);
-
- if (md->paramcount > 0) {
- /* shift param types by 1 argument */
- MMOVE(td + 1, td, typedesc, md->paramcount);
- }
-
- /* fill in first argument `this' */
-
- td->type = TYPE_ADR;
- td->decltype = TYPE_ADR;
- td->arraydim = 0;
- td->classref = thisclass;
-
- md->paramcount++;
- md->paramslots++;
- }
-
- /* if the method has params, process them */
-
- if (md->paramcount > 0) {
- /* allocate memory for params */
-
- md->params = MNEW(paramdesc, md->paramcount);
-
- } else {
- md->params = METHODDESC_NOPARAMS;
- }
-
- /* fill the paramdesc */
- /* md_param_alloc has to be called if md->paramcount == 0, too, so
- it can make the reservation for the Linkage Area, Return
- Register.. */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- {
- /* As builtin-functions are native functions, we have to
- pre-allocate for the native ABI. */
-
- if (mflags & ACC_METHOD_BUILTIN)
- md_param_alloc_native(md);
- else
- md_param_alloc(md);
- }
-#endif
-
- return true;
-}
-
-
-/* descriptor_pool_get_parsed_descriptors **************************************
-
- Return a pointer to the block of parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *size............if size is non-NULL, this is set to the size of the
- parsed descriptor block (in u1)
-
- RETURN VALUE:
- a pointer to the block of parsed descriptors
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called (once)
- before this function is used.
-
-*******************************************************************************/
-
-void *
-descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
-{
- assert(pool);
- assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
-
- if (size)
- *size = pool->descriptorsize;
-
- return pool->descriptors;
-}
-
-
-/* descriptor_pool_get_sizes ***************************************************
-
- Get the sizes of the class reference table and the parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *classrefsize....set to size of the class reference table
- *descsize........set to size of the parsed descriptors
-
- NOTE:
- This function may only be called after both
- descriptor_pool_create_classrefs, and
- descriptor_pool_alloc_parsed_descriptors
- have been called.
-
-*******************************************************************************/
-
-void
-descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
-{
- assert(pool);
- assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
- assert(pool->classrefs);
- assert(classrefsize);
- assert(descsize);
-
- *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
- *descsize = pool->descriptorsize;
-}
-
-
-/****************************************************************************/
-/* DEBUG HELPERS */
-/****************************************************************************/
-
-#ifndef NDEBUG
-/* descriptor_debug_print_typedesc *********************************************
-
- Print the given typedesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parsed descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_typedesc(FILE *file,typedesc *d)
-{
- int ch;
-
- if (!d) {
- fprintf(file,"(typedesc *)NULL");
- return;
- }
-
- if (d->type == TYPE_ADR) {
- if (d->classref)
- utf_fprint_printable_ascii(file,d->classref->name);
- else
- fprintf(file,"<class=NULL>");
- }
- else {
- switch (d->decltype) {
- case PRIMITIVETYPE_INT : ch='I'; break;
- case PRIMITIVETYPE_CHAR : ch='C'; break;
- case PRIMITIVETYPE_BYTE : ch='B'; break;
- case PRIMITIVETYPE_SHORT : ch='S'; break;
- case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
- case PRIMITIVETYPE_LONG : ch='J'; break;
- case PRIMITIVETYPE_FLOAT : ch='F'; break;
- case PRIMITIVETYPE_DOUBLE : ch='D'; break;
- case PRIMITIVETYPE_VOID : ch='V'; break;
- default : ch='!';
- }
- fputc(ch,file);
- }
- if (d->arraydim)
- fprintf(file,"[%d]",d->arraydim);
-}
-
-/* descriptor_debug_print_paramdesc ********************************************
-
- Print the given paramdesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parameter descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
-{
- if (!d) {
- fprintf(file,"(paramdesc *)NULL");
- return;
- }
-
- if (d->inmemory) {
- fprintf(file,"<m%d>",d->regoff);
- }
- else {
- fprintf(file,"<r%d>",d->regoff);
- }
-}
-
-/* descriptor_debug_print_methoddesc *******************************************
-
- Print the given methoddesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parsed descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
-{
- int i;
-
- if (!d) {
- fprintf(file,"(methoddesc *)NULL");
- return;
- }
-
- fputc('(',file);
- for (i=0; i<d->paramcount; ++i) {
- if (i)
- fputc(',',file);
- descriptor_debug_print_typedesc(file,d->paramtypes + i);
- if (d->params) {
- descriptor_debug_print_paramdesc(file,d->params + i);
- }
- }
- if (d->params == METHODDESC_NOPARAMS)
- fputs("<NOPARAMS>",file);
- fputc(')',file);
- descriptor_debug_print_typedesc(file,&(d->returntype));
-}
-
-/* descriptor_pool_debug_dump **************************************************
-
- Print the state of the descriptor_pool to the given stream
-
- IN:
- pool.............the descriptor_pool
- file.............stream to print to
-
-*******************************************************************************/
-
-void
-descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
-{
- u4 slot;
- u1 *pos;
- u1 *kind;
- u4 size;
-
- fprintf(file,"======[descriptor_pool for ");
- utf_fprint_printable_ascii(file,pool->referer->name);
- fprintf(file,"]======\n");
-
- fprintf(file,"fieldcount: %d\n",pool->fieldcount);
- fprintf(file,"methodcount: %d\n",pool->methodcount);
- fprintf(file,"paramcount: %d\n",pool->paramcount);
- fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
- fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
- fprintf(file,"classrefsize: %d bytes\n",
- (int)(pool->classrefhash.entries * sizeof(constant_classref)));
-
- fprintf(file,"class references:\n");
- for (slot=0; slot<pool->classrefhash.size; ++slot) {
- classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- while (c) {
- fprintf(file," %4d: ",c->index);
- utf_fprint_printable_ascii(file,c->name);
- fprintf(file,"\n");
- c = c->hashlink;
- }
- }
-
- fprintf(file,"hashed descriptors:\n");
- for (slot=0; slot<pool->descriptorhash.size; ++slot) {
- descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
- while (c) {
- fprintf(file," %p: ",c->parseddesc.any);
- utf_fprint_printable_ascii(file,c->desc);
- fprintf(file,"\n");
- c = c->hashlink;
- }
- }
-
- fprintf(file,"descriptors:\n");
- if (pool->descriptors) {
- pos = pool->descriptors;
- size = pool->descriptors_next - pool->descriptors;
- fprintf(file," size: %d bytes\n",size);
-
- if (pool->descriptor_kind) {
- kind = pool->descriptor_kind;
-
- while (pos < (pool->descriptors + size)) {
- fprintf(file," %p: ",pos);
- switch (*kind++) {
- case 'f':
- descriptor_debug_print_typedesc(file,(typedesc*)pos);
- pos += sizeof(typedesc);
- break;
- case 'm':
- descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
- pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
- pos += sizeof(methoddesc) - sizeof(typedesc);
- break;
- default:
- fprintf(file,"INVALID KIND");
- }
- fputc('\n',file);
- }
- }
- else {
- while (size >= sizeof(voidptr)) {
- fprintf(file," %p\n",*((voidptr*)pos));
- pos += sizeof(voidptr);
- size -= sizeof(voidptr);
- }
- }
- }
-
- fprintf(file,"==========================================================\n");
-}
-#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/vmcore/descriptor.h - checking and parsing of field / method descriptors
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _DESCRIPTOR_H
-#define _DESCRIPTOR_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct descriptor_pool descriptor_pool;
-typedef struct typedesc typedesc;
-typedef struct paramdesc paramdesc;
-typedef struct methoddesc methoddesc;
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vmcore/utf8.h"
-
-#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */
-
-/* data structures ************************************************************/
-
-/*----------------------------------------------------------------------------*/
-/* Descriptor Pools */
-/* */
-/* A descriptor_pool is a temporary data structure used during loading of */
-/* a class. The descriptor_pool is used to allocate the table of */
-/* constant_classrefs the class uses, and for parsing the field and method */
-/* descriptors which occurr within the class. The inner workings of */
-/* descriptor_pool are not important for outside code. */
-/* */
-/* You use a descriptor_pool as follows: */
-/* */
-/* 1. create one with descriptor_pool_new */
-/* 2. add all explicit class references with descriptor_pool_add_class */
-/* 3. add all field/method descriptors with descriptor_pool_add */
-/* 4. call descriptor_pool_create_classrefs */
-/* You can now lookup classrefs with descriptor_pool_lookup_classref */
-/* 5. call descriptor_pool_alloc_parsed_descriptors */
-/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */
-/* for each method descriptor call descriptor_pool_parse_method_descriptor */
-/* 7. call descriptor_pool_get_parsed_descriptors */
-/* */
-/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */
-/* memory which can be thrown away when the steps above have been */
-/* done. */
-/*----------------------------------------------------------------------------*/
-
-struct descriptor_pool {
- classinfo *referer;
- u4 fieldcount;
- u4 methodcount;
- u4 paramcount;
- u4 descriptorsize;
- u1 *descriptors;
- u1 *descriptors_next;
- hashtable descriptorhash;
- constant_classref *classrefs;
- hashtable classrefhash;
- u1 *descriptor_kind; /* useful for debugging */
- u1 *descriptor_kind_next; /* useful for debugging */
-};
-
-
-/* data structures for parsed field/method descriptors ************************/
-
-struct typedesc {
- constant_classref *classref; /* class reference for TYPE_ADR types */
- u1 type; /* TYPE_??? constant [1] */
- u1 decltype; /* (PRIMITIVE)TYPE_??? constant [2] */
- u1 arraydim; /* array dimension (0 if no array) */
-};
-
-/* [1]...the type field contains the basic type used within the VM. So ints, */
-/* shorts, chars, bytes, booleans all have TYPE_INT. */
-/* [2]...the decltype field contains the declared type. */
-/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */
-/* For non-primitive types decltype is TYPE_ADR. */
-
-struct paramdesc {
-#if defined(__MIPS__)
- u1 type; /* TYPE_??? of the register allocated */
-#endif
- bool inmemory; /* argument in register or on stack */
- uint32_t index; /* index into argument register array */
- uint32_t regoff; /* register index or stack offset */
-};
-
-struct methoddesc {
- s2 paramcount; /* number of parameters */
- s2 paramslots; /* like above but LONG,DOUBLE count twice */
- s4 argintreguse; /* number of used integer argument registers */
- s4 argfltreguse; /* number of used float argument registers */
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- s4 argadrreguse; /* number of used address registers */
-#endif
- s4 memuse; /* number of stack slots used */
- paramdesc *params; /* allocated parameter descriptions [3] */
- typedesc returntype; /* parsed descriptor of the return type */
- typedesc paramtypes[1]; /* parameter types, variable length! */
-};
-
-/* [3]...If params is NULL, the parameter descriptions have not yet been */
-/* allocated. In this case ___the possible 'this' pointer of the method */
-/* is NOT counted in paramcount/paramslots and it is NOT included in */
-/* the paramtypes array___. */
-/* If params != NULL, the parameter descriptions have been */
-/* allocated, and the 'this' pointer of the method, if any, IS included.*/
-/* In case the method has no parameters at all, the special value */
-/* METHODDESC_NO_PARAMS is used (see below). */
-
-/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */
-/* indicating that the method is a static method without any parameters. */
-/* This special value must be != NULL and it may only be set if */
-/* md->paramcount == 0. */
-
-#define METHODDESC_NOPARAMS ((paramdesc*)1)
-
-/* function prototypes ********************************************************/
-
-descriptor_pool * descriptor_pool_new(classinfo *referer);
-
-bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
-bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots);
-
-int descriptor_to_basic_type(utf *desc);
-int descriptor_typesize(typedesc *td);
-
-constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool,
- s4 *count);
-constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname);
-
-void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool);
-
-typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc);
-methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags,
- constant_classref *thisclass);
-
-bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags);
-
-void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size);
-void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize,
- u4 *descsize);
-
-#ifndef NDEBUG
-void descriptor_debug_print_typedesc(FILE *file,typedesc *d);
-void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d);
-void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d);
-void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
-#endif /* !defined(NDEBUG) */
-
-#endif /* _DESCRIPTOR_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:
- */
+++ /dev/null
-/* src/vmcore/field.c - field 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 <stdint.h>
-#include <stdio.h>
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "vm/types.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/primitive.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/annotation.h"
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/field.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-/* field_load ******************************************************************
-
- Load everything about a class field from the class file and fill a
- fieldinfo structure.
-
-*******************************************************************************/
-
-#define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
-
-bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
-{
- classinfo *c;
- u4 attrnum, i;
- u4 pindex = field_load_NOVALUE; /* constantvalue_index */
- utf *u;
-
- /* Get class. */
-
- c = cb->clazz;
-
- f->clazz = c;
-
- /* Get access flags. */
-
- if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
- return false;
-
- f->flags = suck_u2(cb);
-
- /* Get name. */
-
- if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
- return false;
-
- f->name = u;
-
- /* Get descriptor. */
-
- if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
- return false;
-
- f->descriptor = u;
- f->parseddesc = NULL;
-
- if (!descriptor_pool_add(descpool, u, NULL))
- return false;
-
- /* descriptor_pool_add accepts method descriptors, so we have to
- check against them here before the call of
- descriptor_to_basic_type below. */
-
- if (u->text[0] == '(') {
- exceptions_throw_classformaterror(c, "Method descriptor used for field");
- return false;
- }
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- /* check name */
- if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
- exceptions_throw_classformaterror(c,
- "Illegal Field name \"%s\"",
- f->name->text);
- return false;
- }
-
- /* check flag consistency */
- i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
-
- if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
- ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
- exceptions_throw_classformaterror(c,
- "Illegal field modifiers: 0x%X",
- f->flags);
- return false;
- }
-
- if (c->flags & ACC_INTERFACE) {
- if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
- != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
- f->flags & ACC_TRANSIENT) {
- exceptions_throw_classformaterror(c,
- "Illegal field modifiers: 0x%X",
- f->flags);
- return false;
- }
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- /* data type */
-
- f->type = descriptor_to_basic_type(f->descriptor);
-
- /* For static-fields allocate memory for the value and set the
- value to 0. */
-
- if (f->flags & ACC_STATIC) {
- switch (f->type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_FLT:
- case TYPE_DBL:
- f->value = NEW(imm_union);
- break;
-
- case TYPE_ADR:
-#if !defined(ENABLE_GC_BOEHM)
- f->value = NEW(imm_union);
-#else
- f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
-#endif
- break;
-
- default:
- vm_abort("field_load: invalid field type %d", f->type);
- }
-
- /* Set the field to zero, for float and double fields set the
- correct 0.0 value. */
-
- switch (f->type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_ADR:
- f->value->l = 0;
- break;
-
- case TYPE_FLT:
- f->value->f = 0.0;
- break;
-
- case TYPE_DBL:
- f->value->d = 0.0;
- break;
- }
- }
- else {
- /* For instance-fields set the offset to 0. */
-
- f->offset = 0;
-
- /* For final fields, which are not static, we need a value
- structure. */
-
- if (f->flags & ACC_FINAL) {
- f->value = NEW(imm_union);
- /* XXX hack */
- f->value->l = 0;
- }
-
- switch (f->type) {
- case TYPE_ADR:
- c->flags |= ACC_CLASS_HAS_POINTERS;
- break;
- }
- }
-
- /* read attributes */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- attrnum = suck_u2(cb);
-
- for (i = 0; i < attrnum; i++) {
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
- return false;
-
- if (u == utf_ConstantValue) {
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* check attribute length */
-
- if (suck_u4(cb) != 2) {
- exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
- return false;
- }
-
- /* constant value attribute */
-
- if (pindex != field_load_NOVALUE) {
- exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
- return false;
- }
-
- /* index of value in constantpool */
-
- pindex = suck_u2(cb);
-
- /* initialize field with value from constantpool */
-
- switch (f->type) {
- case TYPE_INT: {
- constant_integer *ci;
-
- if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
- return false;
-
- f->value->i = ci->value;
- }
- break;
-
- case TYPE_LNG: {
- constant_long *cl;
-
- if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
- return false;
-
- f->value->l = cl->value;
- }
- break;
-
- case TYPE_FLT: {
- constant_float *cf;
-
- if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
- return false;
-
- f->value->f = cf->value;
- }
- break;
-
- case TYPE_DBL: {
- constant_double *cd;
-
- if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
- return false;
-
- f->value->d = cd->value;
- }
- break;
-
- case TYPE_ADR:
- if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
- return false;
-
- /* Create Java-string from compressed UTF8-string. */
-
- f->value->a = literalstring_new(u);
- break;
-
- default:
- vm_abort("field_load: invalid field type %d", f->type);
- }
- }
-#if defined(ENABLE_JAVASE)
- else if (u == utf_Signature) {
- /* Signature */
-
- if (!loader_load_attribute_signature(cb, &(f->signature)))
- return false;
- }
-
-#if defined(ENABLE_ANNOTATIONS)
- else if (u == utf_RuntimeVisibleAnnotations) {
- /* RuntimeVisibleAnnotations */
- if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
- return false;
- }
- else if (u == utf_RuntimeInvisibleAnnotations) {
- /* RuntimeInvisibleAnnotations */
- if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
- return false;
- }
-#endif
-#endif
- else {
- /* unknown attribute */
-
- if (!loader_skip_attribute_body(cb))
- return false;
- }
- }
-
- /* everything was ok */
-
- return true;
-}
-
-
-/* field_get_type **************************************************************
-
- Returns the type of the field as class.
-
-*******************************************************************************/
-
-classinfo *field_get_type(fieldinfo *f)
-{
- typedesc *td;
- utf *u;
- classinfo *c;
-
- td = f->parseddesc;
-
- if (td->type == TYPE_ADR) {
- assert(td->classref);
-
- u = td->classref->name;
-
- /* load the class of the field-type with the field's
- classloader */
-
- c = load_class_from_classloader(u, f->clazz->classloader);
- }
- else {
- c = primitive_class_get_by_type(td->decltype);
- }
-
- return c;
-}
-
-
-/* field_free ******************************************************************
-
- Frees a fields' resources.
-
-*******************************************************************************/
-
-void field_free(fieldinfo *f)
-{
- /* free memory for fields which have a value */
-
- if (f->value)
-#if defined(ENABLE_GC_BOEHM)
- if (f->type != TYPE_ADR)
-#endif
- FREE(f->value, imm_union);
-}
-
-
-/* field_get_annotations ******************************************************
-
- Get a fields' unparsed annotations in a byte array.
-
- IN:
- f........the field of which the annotations should be returned
-
- RETURN VALUE:
- The unparsed annotations in a byte array (or NULL if there aren't any).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* declaring class */
- int slot; /* slot of this field */
- java_handle_bytearray_t *annotations; /* unparsed annotations */
- java_handle_t *field_annotations; /* array of unparsed */
- /* annotations of all fields of the declaring class */
-
- c = f->clazz;
- slot = f - c->fields;
- annotations = NULL;
-
- LLNI_classinfo_field_get(c, field_annotations, field_annotations);
-
- /* the field_annotations array might be shorter then the field
- * count if the fields above a certain index have no annotations.
- */
- if (field_annotations != NULL &&
- array_length_get(field_annotations) > slot) {
- annotations = (java_handle_bytearray_t*)array_objectarray_element_get(
- (java_handle_objectarray_t*)field_annotations, slot);
- }
-
- return annotations;
-#else
- return NULL;
-#endif
-}
-
-
-/* field_printflags ************************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_printflags(fieldinfo *f)
-{
- if (f == NULL) {
- printf("NULL");
- return;
- }
-
- if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
- if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
- if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
- if (f->flags & ACC_STATIC) printf(" STATIC");
- if (f->flags & ACC_FINAL) printf(" FINAL");
- if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
- if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
- if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
- if (f->flags & ACC_NATIVE) printf(" NATIVE");
- if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
- if (f->flags & ACC_ABSTRACT) printf(" ABSTRACT");
-}
-#endif
-
-
-/* field_print *****************************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_print(fieldinfo *f)
-{
- if (f == NULL) {
- printf("(fieldinfo*)NULL");
- return;
- }
-
- utf_display_printable_ascii_classname(f->clazz->name);
- printf(".");
- utf_display_printable_ascii(f->name);
- printf(" ");
- utf_display_printable_ascii(f->descriptor);
-
- field_printflags(f);
-
- if (!(f->flags & ACC_STATIC)) {
- printf(", offset: %d", f->offset);
- }
-}
-#endif
-
-
-/* field_println ***************************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_println(fieldinfo *f)
-{
- field_print(f);
- printf("\n");
-}
-#endif
-
-/* field_fieldref_print ********************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_fieldref_print(constant_FMIref *fr)
-{
- if (fr == NULL) {
- printf("(constant_FMIref *)NULL");
- return;
- }
-
- if (IS_FMIREF_RESOLVED(fr)) {
- printf("<field> ");
- field_print(fr->p.field);
- }
- else {
- printf("<fieldref> ");
- utf_display_printable_ascii_classname(fr->p.classref->name);
- printf(".");
- utf_display_printable_ascii(fr->name);
- printf(" ");
- utf_display_printable_ascii(fr->descriptor);
- }
-}
-#endif
-
-/* field_fieldref_println ******************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_fieldref_println(constant_FMIref *fr)
-{
- field_fieldref_print(fr);
- printf("\n");
-}
-#endif
-
-/*
- * 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/vmcore/field.h - field 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 _FIELD_H
-#define _FIELD_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct fieldinfo fieldinfo;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/references.h"
-#include "vmcore/utf8.h"
-
-
-/* fieldinfo ******************************************************************/
-
-struct fieldinfo { /* field of a class */
-
- /* CAUTION: The first field must be a pointer that is never the same */
- /* value as CLASSREF_PSEUDO_VFTBL! This is used to check whether */
- /* a constant_FMIref has been resolved. */
-
- classinfo *clazz; /* needed by typechecker. Could be optimized */
- /* away by using constant_FMIref instead of */
- /* fieldinfo throughout the compiler. */
-
- s4 flags; /* ACC flags */
- s4 type; /* basic data type */
- utf *name; /* name of field */
- utf *descriptor;/* JavaVM descriptor string of field */
- utf *signature; /* Signature attribute string */
- typedesc *parseddesc;/* parsed descriptor */
-
- int32_t offset; /* offset from start of object (instance variables) */
- imm_union *value; /* storage for static values (class variables) */
-};
-
-
-/* function prototypes ********************************************************/
-
-bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool);
-classinfo *field_get_type(fieldinfo *f);
-void field_free(fieldinfo *f);
-
-java_handle_bytearray_t *field_get_annotations(fieldinfo *f);
-
-#if !defined(NDEBUG)
-void field_printflags(fieldinfo *f);
-void field_print(fieldinfo *f);
-void field_println(fieldinfo *f);
-void field_fieldref_print(constant_FMIref *fr);
-void field_fieldref_println(constant_FMIref *fr);
-#endif
-
-#endif /* _FIELD_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/vmcore/linker.c - class linker 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 <stdint.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/native.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/access.h"
-#include "vm/array.h"
-#include "vm/exceptions.h"
-#include "vm/primitive.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit_interface.h"
-
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-
-
-/* debugging macros ***********************************************************/
-
-#if !defined(NDEBUG)
-# define TRACELINKCLASS(c) \
- do { \
- if (opt_TraceLinkClass) { \
- log_start(); \
- log_print("[Linking "); \
- class_print((c)); \
- log_print("]"); \
- log_finish(); \
- } \
- } while (0)
-#else
-# define TRACELINKCLASS(c)
-#endif
-
-
-/* #include "vm/resolve.h" */
-/* copied prototype to avoid bootstrapping problem: */
-classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
-#else
-#define INLINELOG(code)
-#endif
-
-
-/* global variables ***********************************************************/
-
-static s4 interfaceindex; /* sequential numbering of interfaces */
-static s4 classvalue;
-
-java_object_t *linker_classrenumber_lock;
-
-
-/* private functions **********************************************************/
-
-static classinfo *link_class_intern(classinfo *c);
-static arraydescriptor *link_array(classinfo *c);
-static void linker_compute_class_values(classinfo *c);
-static void linker_compute_subclasses(classinfo *c);
-static bool linker_addinterface(classinfo *c, classinfo *ic);
-static s4 class_highestinterface(classinfo *c);
-
-
-/* dummy structures for alinment checks ***************************************/
-
-typedef struct dummy_alignment_long_t dummy_alignment_long_t;
-typedef struct dummy_alignment_double_t dummy_alignment_double_t;
-
-struct dummy_alignment_long_t {
- int32_t i;
- int64_t l;
-};
-
-struct dummy_alignment_double_t {
- int32_t i;
- double d;
-};
-
-
-/* linker_init *****************************************************************
-
- Initializes the linker subsystem and links classes required for the
- primitive table.
-
-*******************************************************************************/
-
-void linker_preinit(void)
-{
- TRACESUBSYSTEMINITIALIZATION("linker_preinit");
-
- /* Check for if alignment for long and double matches what we
- assume for the current architecture. */
-
-#if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__)) || defined(__M68K__)
- /* Define a define here which is later checked when we use this
- offset. */
-
-# define LINKER_ALIGNMENT_LONG_DOUBLE 4
-
- if (OFFSET(dummy_alignment_long_t, l) != 4)
- vm_abort("linker_preinit: long alignment is different from what assumed: %d != %d",
- OFFSET(dummy_alignment_long_t, l), 4);
-
- if (OFFSET(dummy_alignment_double_t, d) != 4)
- vm_abort("linker_preinit: double alignment is different from what assumed: %d != %d",
- OFFSET(dummy_alignment_double_t, d), 4);
-#else
-
-# define LINKER_ALIGNMENT_LONG_DOUBLE 8
-
- if (OFFSET(dummy_alignment_long_t, l) != 8)
- vm_abort("linker_preinit: long alignment is different from what assumed: %d != %d",
- OFFSET(dummy_alignment_long_t, l), 8);
-
- if (OFFSET(dummy_alignment_double_t, d) != 8)
- vm_abort("linker_preinit: double alignment is different from what assumed: %d != %d",
- OFFSET(dummy_alignment_double_t, d), 8);
-#endif
-
- /* Reset interface index. */
-
- interfaceindex = 0;
-
-#if defined(ENABLE_THREADS)
- /* create the global lock object */
-
- linker_classrenumber_lock = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
-#endif
-
- /* Link the most basic classes. */
-
- if (!link_class(class_java_lang_Object))
- vm_abort("linker_preinit: linking java/lang/Object failed");
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_Cloneable))
- vm_abort("linker_preinit: linking java/lang/Cloneable failed");
-
- if (!link_class(class_java_io_Serializable))
- vm_abort("linker_preinit: linking java/io/Serializable failed");
-#endif
-}
-
-
-/* linker_init *****************************************************************
-
- Links all classes required in the VM.
-
-*******************************************************************************/
-
-void linker_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("linker_init");
-
- /* Link java.lang.Class as first class of the system, because we
- need it's vftbl for all other classes so we can use a class as
- object. */
-
- if (!link_class(class_java_lang_Class))
- vm_abort("linker_init: linking java/lang/Class failed");
-
- /* Now set the header.vftbl of all classes which were created
- before java.lang.Class was linked. */
-
- class_postset_header_vftbl();
-
- /* Link primitive-type wrapping classes. */
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_Void))
- vm_abort("linker_init: linking failed");
-#endif
-
- if (!link_class(class_java_lang_Boolean))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Byte))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Character))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Short))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Integer))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Long))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Float))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Double))
- vm_abort("linker_init: linking failed");
-
- /* Link important system classes. */
-
- if (!link_class(class_java_lang_String))
- vm_abort("linker_init: linking java/lang/String failed");
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_ClassLoader))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_SecurityManager))
- vm_abort("linker_init: linking failed");
-#endif
-
- if (!link_class(class_java_lang_System))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Thread))
- vm_abort("linker_init: linking failed");
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_ThreadGroup))
- vm_abort("linker_init: linking failed");
-#endif
-
- if (!link_class(class_java_lang_Throwable))
- vm_abort("linker_init: linking failed");
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- if (!link_class(class_java_lang_VMSystem))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_VMThread))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_VMThrowable))
- vm_abort("linker_init: linking failed");
-#endif
-
- /* Important system exceptions. */
-
- if (!link_class(class_java_lang_Exception))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_ClassNotFoundException))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_RuntimeException))
- vm_abort("linker_init: linking failed");
-
- /* some classes which may be used more often */
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_StackTraceElement))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_Constructor))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_Field))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_Method))
- vm_abort("linker_init: linking failed");
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- if (!link_class(class_java_lang_reflect_VMConstructor))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_VMField))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_VMMethod))
- vm_abort("linker_init: linking failed");
-# endif
-
- if (!link_class(class_java_security_PrivilegedAction))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_util_Vector))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_util_HashMap))
- vm_abort("linker_init: linking failed");
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- if (!link_class(class_sun_reflect_MagicAccessorImpl))
- vm_abort("linker_init: linking failed");
-# endif
-
- if (!link_class(arrayclass_java_lang_Object))
- vm_abort("linker_init: linking failed");
-#endif
-
-
- /* create pseudo classes used by the typechecker */
-
- /* pseudo class for Arraystubs (extends java.lang.Object) */
-
- pseudo_class_Arraystub =
- class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
- pseudo_class_Arraystub->state |= CLASS_LOADED;
- pseudo_class_Arraystub->super = class_java_lang_Object;
-
-#if defined(ENABLE_JAVASE)
-
- pseudo_class_Arraystub->interfacescount = 2;
- pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
- pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
- pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- pseudo_class_Arraystub->interfacescount = 0;
- pseudo_class_Arraystub->interfaces = NULL;
-
-#else
-# error unknown Java configuration
-#endif
-
- if (!classcache_store_unique(pseudo_class_Arraystub))
- vm_abort("linker_init: could not cache pseudo_class_Arraystub");
-
- if (!link_class(pseudo_class_Arraystub))
- vm_abort("linker_init: linking pseudo_class_Arraystub failed");
-
- /* pseudo class representing the null type */
-
- pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
- pseudo_class_Null->state |= CLASS_LOADED;
- pseudo_class_Null->super = class_java_lang_Object;
-
- if (!classcache_store_unique(pseudo_class_Null))
- vm_abort("linker_init: could not cache pseudo_class_Null");
-
- if (!link_class(pseudo_class_Null))
- vm_abort("linker_init: linking failed");
-
- /* pseudo class representing new uninitialized objects */
-
- pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
- pseudo_class_New->state |= CLASS_LOADED;
- pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
- pseudo_class_New->super = class_java_lang_Object;
-
- if (!classcache_store_unique(pseudo_class_New))
- vm_abort("linker_init: could not cache pseudo_class_New");
-
- /* Correct vftbl-entries (retarded loading and linking of class
- java/lang/String). */
-
- stringtable_update();
-}
-
-
-/* link_class ******************************************************************
-
- Wrapper function for link_class_intern to ease monitor enter/exit
- and exception handling.
-
-*******************************************************************************/
-
-classinfo *link_class(classinfo *c)
-{
- classinfo *r;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_end;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- if (c == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- LOCK_MONITOR_ENTER(c);
-
- /* Maybe the class is currently linking or is already linked.*/
-
- if ((c->state & CLASS_LINKING) || (c->state & CLASS_LINKED)) {
- LOCK_MONITOR_EXIT(c);
-
- return c;
- }
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- compilingtime_stop();
-
- if (opt_getloadingtime)
- loadingtime_start();
-#endif
-
- /* call the internal function */
-
- r = link_class_intern(c);
-
- /* If return value is NULL, we had a problem and the class is not
- linked. */
-
- if (r == NULL)
- c->state &= ~CLASS_LINKING;
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getloadingtime)
- loadingtime_stop();
-
- if (opt_getcompilingtime)
- compilingtime_start();
-#endif
-
- LOCK_MONITOR_EXIT(c);
-
- RT_TIMING_GET_TIME(time_end);
-
- RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
-
- return r;
-}
-
-
-/* linker_overwrite_method *****************************************************
-
- Overwrite a method with another one, update method flags and check
- assumptions.
-
- IN:
- mg................the general method being overwritten
- ms................the overwriting (more specialized) method
- wl................worklist where to add invalidated methods
-
- RETURN VALUE:
- true..............everything ok
- false.............an exception has been thrown
-
-*******************************************************************************/
-
-static bool linker_overwrite_method(methodinfo *mg,
- methodinfo *ms,
- method_worklist **wl)
-{
- classinfo *cg;
- classinfo *cs;
-
- cg = mg->clazz;
- cs = ms->clazz;
-
- /* overriding a final method is illegal */
-
- if (mg->flags & ACC_FINAL) {
- exceptions_throw_verifyerror(mg, "Overriding final method");
- return false;
- }
-
- /* method ms overwrites method mg */
-
-#if defined(ENABLE_VERIFIER)
- /* Add loading constraints (for the more general types of method mg). */
- /* Not for <init>, as it is not invoked virtually. */
-
- if ((ms->name != utf_init)
- && !classcache_add_constraints_for_params(
- cs->classloader, cg->classloader, mg))
- {
- return false;
- }
-#endif
-
- /* inherit the vftbl index, and record the overwriting */
-
- ms->vftblindex = mg->vftblindex;
- ms->overwrites = mg;
-
- /* update flags and check assumptions */
- /* <init> methods are a special case, as they are never dispatched dynamically */
-
- if ((ms->flags & ACC_METHOD_IMPLEMENTED) && ms->name != utf_init) {
- do {
- if (mg->flags & ACC_METHOD_IMPLEMENTED) {
- /* this adds another implementation */
-
- mg->flags &= ~ACC_METHOD_MONOMORPHIC;
-
- INLINELOG( printf("becomes polymorphic: "); method_println(mg); );
-
- method_break_assumption_monomorphic(mg, wl);
- }
- else {
- /* this is the first implementation */
-
- mg->flags |= ACC_METHOD_IMPLEMENTED;
-
- INLINELOG( printf("becomes implemented: "); method_println(mg); );
- }
-
- ms = mg;
- mg = mg->overwrites;
- } while (mg != NULL);
- }
-
- return true;
-}
-
-
-/* link_class_intern ***********************************************************
-
- Tries to link a class. The function calculates the length in bytes
- that an instance of this class requires as well as the VTBL for
- methods and interface methods.
-
-*******************************************************************************/
-
-static classinfo *link_class_intern(classinfo *c)
-{
- classinfo *super; /* super class */
- classinfo *tc; /* temporary class variable */
- s4 supervftbllength; /* vftbllegnth of super class */
- s4 vftbllength; /* vftbllength of current class */
- s4 interfacetablelength; /* interface table length */
- vftbl_t *v; /* vftbl of current class */
- s4 i; /* interface/method/field counter */
- arraydescriptor *arraydesc; /* descriptor for array classes */
- method_worklist *worklist; /* worklist for recompilation */
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_resolving, time_compute_vftbl,
- time_abstract, time_compute_iftbl, time_fill_vftbl,
- time_offsets, time_fill_iftbl, time_finalizer,
- time_subclasses;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- TRACELINKCLASS(c);
-
- /* the class must be loaded */
-
- /* XXX should this be a specific exception? */
- assert(c->state & CLASS_LOADED);
-
- /* This is check in link_class. */
-
- assert(!(c->state & CLASS_LINKED));
-
- /* cache the self-reference of this class */
- /* we do this for cases where the defining loader of the class */
- /* has not yet been recorded as an initiating loader for the class */
- /* this is needed so subsequent code can assume that self-refs */
- /* will always resolve lazily */
- /* No need to do it for the bootloader - it is always registered */
- /* as initiating loader for the classes it loads. */
- if (c->classloader)
- classcache_store(c->classloader,c,false);
-
- /* this class is currently linking */
-
- c->state |= CLASS_LINKING;
-
- arraydesc = NULL;
- worklist = NULL;
-
- /* Link the super interfaces. */
-
- for (i = 0; i < c->interfacescount; i++) {
- tc = c->interfaces[i];
-
- if (!(tc->state & CLASS_LINKED))
- if (!link_class(tc))
- return NULL;
- }
-
- /* check super class */
-
- super = NULL;
-
- /* Check for java/lang/Object. */
-
- if (c->super == NULL) {
- c->index = 0;
- c->instancesize = sizeof(java_object_t);
-
- vftbllength = supervftbllength = 0;
-
- c->finalizer = NULL;
- }
- else {
- /* Get super class. */
-
- super = c->super;
-
- /* Link the super class if necessary. */
-
- if (!(super->state & CLASS_LINKED))
- if (!link_class(super))
- return NULL;
-
- /* OR the ACC_CLASS_HAS_POINTERS and the ACC_CLASS_REFERENCE_*
- flags. */
-
- c->flags |= (super->flags &
- (ACC_CLASS_HAS_POINTERS | ACC_CLASS_REFERENCE_MASK));
-
- /* handle array classes */
-
- if (c->name->text[0] == '[')
- if (!(arraydesc = link_array(c)))
- return NULL;
-
- if (c->flags & ACC_INTERFACE)
- c->index = interfaceindex++;
- else
- c->index = super->index + 1;
-
- c->instancesize = super->instancesize;
-
- vftbllength = supervftbllength = super->vftbl->vftbllength;
-
- c->finalizer = super->finalizer;
- }
- RT_TIMING_GET_TIME(time_resolving);
-
-
- /* compute vftbl length */
-
- for (i = 0; i < c->methodscount; i++) {
- methodinfo *m = &(c->methods[i]);
-
- if (!(m->flags & ACC_STATIC)) { /* is instance method */
- tc = super;
-
- while (tc) {
- s4 j;
-
- for (j = 0; j < tc->methodscount; j++) {
- if (method_canoverwrite(m, &(tc->methods[j]))) {
- if (tc->methods[j].flags & ACC_PRIVATE)
- goto notfoundvftblindex;
-
- /* package-private methods in other packages */
- /* must not be overridden */
- /* (see Java Language Specification 8.4.8.1) */
- if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
- && !SAME_PACKAGE(c,tc) )
- {
- goto notfoundvftblindex;
- }
-
- if (!linker_overwrite_method(&(tc->methods[j]), m, &worklist))
- return NULL;
-
- goto foundvftblindex;
- }
- }
-
- tc = tc->super;
- }
-
- notfoundvftblindex:
- m->vftblindex = (vftbllength++);
- foundvftblindex:
- ;
- }
- }
- RT_TIMING_GET_TIME(time_compute_vftbl);
-
-
- /* Check all interfaces of an abstract class (maybe be an
- interface too) for unimplemented methods. Such methods are
- called miranda-methods and are marked with the ACC_MIRANDA
- flag. VMClass.getDeclaredMethods does not return such
- methods. */
-
- if (c->flags & ACC_ABSTRACT) {
- classinfo *ic;
- methodinfo *im;
- s4 abstractmethodscount;
- s4 j;
- s4 k;
-
- abstractmethodscount = 0;
-
- /* check all interfaces of the abstract class */
-
- for (i = 0; i < c->interfacescount; i++) {
- ic = c->interfaces[i];
-
- for (j = 0; j < ic->methodscount; j++) {
- im = &(ic->methods[j]);
-
- /* skip `<clinit>' and `<init>' */
-
- if ((im->name == utf_clinit) || (im->name == utf_init))
- continue;
-
- for (tc = c; tc != NULL; tc = tc->super) {
- for (k = 0; k < tc->methodscount; k++) {
- if (method_canoverwrite(im, &(tc->methods[k])))
- goto noabstractmethod;
- }
- }
-
- abstractmethodscount++;
-
- noabstractmethod:
- ;
- }
- }
-
- if (abstractmethodscount > 0) {
- methodinfo *am;
-
- /* reallocate methods memory */
-
- c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
- c->methodscount + abstractmethodscount);
-
- for (i = 0; i < c->interfacescount; i++) {
- ic = c->interfaces[i];
-
- for (j = 0; j < ic->methodscount; j++) {
- im = &(ic->methods[j]);
-
- /* skip `<clinit>' and `<init>' */
-
- if ((im->name == utf_clinit) || (im->name == utf_init))
- continue;
-
- for (tc = c; tc != NULL; tc = tc->super) {
- for (k = 0; k < tc->methodscount; k++) {
- if (method_canoverwrite(im, &(tc->methods[k])))
- goto noabstractmethod2;
- }
- }
-
- /* Copy the method found into the new c->methods
- array and tag it as miranda-method. */
-
- am = &(c->methods[c->methodscount]);
- c->methodscount++;
-
- MCOPY(am, im, methodinfo, 1);
-
- am->vftblindex = (vftbllength++);
- am->clazz = c;
- am->flags |= ACC_MIRANDA;
-
- noabstractmethod2:
- ;
- }
- }
- }
- }
- RT_TIMING_GET_TIME(time_abstract);
-
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_vftbl_len +=
- sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
-#endif
-
- /* compute interfacetable length */
-
- interfacetablelength = 0;
-
- for (tc = c; tc != NULL; tc = tc->super) {
- for (i = 0; i < tc->interfacescount; i++) {
- s4 h = class_highestinterface(tc->interfaces[i]) + 1;
-
- if (h > interfacetablelength)
- interfacetablelength = h;
- }
- }
- RT_TIMING_GET_TIME(time_compute_iftbl);
-
- /* allocate virtual function table */
-
- v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
- sizeof(methodptr) * (vftbllength - 1) +
- sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
- v = (vftbl_t *) (((methodptr *) v) +
- (interfacetablelength - 1) * (interfacetablelength > 1));
-
- c->vftbl = v;
- v->clazz = c;
- v->vftbllength = vftbllength;
- v->interfacetablelength = interfacetablelength;
- v->arraydesc = arraydesc;
-
- /* store interface index in vftbl */
-
- if (c->flags & ACC_INTERFACE)
- v->baseval = -(c->index);
-
- /* copy virtual function table of super class */
-
- for (i = 0; i < supervftbllength; i++)
- v->table[i] = super->vftbl->table[i];
-
- /* Fill the remaining vftbl slots with the AbstractMethodError
- stub (all after the super class slots, because they are already
- initialized). */
-
- for (; i < vftbllength; i++) {
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
- else
-# endif
- v->table[i] = (methodptr) (ptrint) &asm_abstractmethoderror;
-#else
- v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
-#endif
- }
-
- /* add method stubs into virtual function table */
-
- for (i = 0; i < c->methodscount; i++) {
- methodinfo *m = &(c->methods[i]);
-
- assert(m->stubroutine == NULL);
-
- /* Don't create a compiler stub for abstract methods as they
- throw an AbstractMethodError with the default stub in the
- vftbl. This entry is simply copied by sub-classes. */
-
- if (m->flags & ACC_ABSTRACT)
- continue;
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- m->stubroutine = intrp_createcompilerstub(m);
- else
-#endif
- m->stubroutine = codegen_generate_stub_compiler(m);
-#else
- m->stubroutine = intrp_createcompilerstub(m);
-#endif
-
- /* static methods are not in the vftbl */
-
- if (m->flags & ACC_STATIC)
- continue;
-
- /* insert the stubroutine into the vftbl */
-
- v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
- }
- RT_TIMING_GET_TIME(time_fill_vftbl);
-
- /* compute instance size and offset of each field */
-
- for (i = 0; i < c->fieldscount; i++) {
- s4 dsize;
- fieldinfo *f = &(c->fields[i]);
-
- if (!(f->flags & ACC_STATIC)) {
- dsize = descriptor_typesize(f->parseddesc);
-
-#if defined(__I386__) || (defined(__ARM__) && !defined(__ARM_EABI__)) || (defined(__POWERPC__) && defined(__DARWIN__)) || defined(__M68K__)
- /* On some architectures and configurations we need to
- align long (int64_t) and double fields to 4-bytes to
- match what GCC does for struct members. We must do the
- same as GCC here because the offsets in native header
- structs like java_lang_Double must match the offsets of
- the Java fields (eg. java.lang.Double.value). */
-
-# if LINKER_ALIGNMENT_LONG_DOUBLE != 4
-# error alignment of long and double is not 4
-# endif
-
- c->instancesize = MEMORY_ALIGN(c->instancesize, 4);
-#else
-
-# if LINKER_ALIGNMENT_LONG_DOUBLE != 8
-# error alignment of long and double is not 8
-# endif
-
- c->instancesize = MEMORY_ALIGN(c->instancesize, dsize);
-#endif
-
- f->offset = c->instancesize;
- c->instancesize += dsize;
- }
- }
- RT_TIMING_GET_TIME(time_offsets);
-
- /* initialize interfacetable and interfacevftbllength */
-
- v->interfacevftbllength = MNEW(s4, interfacetablelength);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
-#endif
-
- for (i = 0; i < interfacetablelength; i++) {
- v->interfacevftbllength[i] = 0;
- v->interfacetable[-i] = NULL;
- }
-
- /* add interfaces */
-
- for (tc = c; tc != NULL; tc = tc->super)
- for (i = 0; i < tc->interfacescount; i++)
- if (!linker_addinterface(c, tc->interfaces[i]))
- return NULL;
-
- RT_TIMING_GET_TIME(time_fill_iftbl);
-
- /* add finalizer method (not for java.lang.Object) */
-
- if (super) {
- methodinfo *fi;
-
- fi = class_findmethod(c, utf_finalize, utf_void__void);
-
- if (fi)
- if (!(fi->flags & ACC_STATIC))
- c->finalizer = fi;
- }
- RT_TIMING_GET_TIME(time_finalizer);
-
- /* final tasks */
-
- linker_compute_subclasses(c);
-
- RT_TIMING_GET_TIME(time_subclasses);
-
- /* revert the linking state and class is linked */
-
- c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
-
- /* check worklist */
-
- /* XXX must this also be done in case of exception? */
-
- while (worklist != NULL) {
- method_worklist *wi = worklist;
-
- worklist = worklist->next;
-
- INLINELOG( printf("MUST BE RECOMPILED: "); method_println(wi->m); );
- jit_invalidate_code(wi->m);
-
- /* XXX put worklist into dump memory? */
- FREE(wi, method_worklist);
- }
-
- RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
- RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
- RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
- RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
- RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
- RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
- RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
- RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
- RT_TIMING_TIME_DIFF(time_finalizer ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
-
- /* just return c to show that we didn't had a problem */
-
- return c;
-}
-
-
-/* link_array ******************************************************************
-
- This function is called by link_class to create the arraydescriptor
- for an array class.
-
- This function returns NULL if the array cannot be linked because
- the component type has not been linked yet.
-
-*******************************************************************************/
-
-static arraydescriptor *link_array(classinfo *c)
-{
- classinfo *comp;
- s4 namelen;
- arraydescriptor *desc;
- vftbl_t *compvftbl;
- utf *u;
-
- comp = NULL;
- namelen = c->name->blength;
-
- /* Check the component type */
-
- switch (c->name->text[1]) {
- case '[':
- /* c is an array of arrays. */
- u = utf_new(c->name->text + 1, namelen - 1);
- if (!(comp = load_class_from_classloader(u, c->classloader)))
- return NULL;
- break;
-
- case 'L':
- /* c is an array of objects. */
- u = utf_new(c->name->text + 2, namelen - 3);
- if (!(comp = load_class_from_classloader(u, c->classloader)))
- return NULL;
- break;
- }
-
- /* If the component type has not been linked, link it now */
-
- assert(!comp || (comp->state & CLASS_LOADED));
-
- if (comp && !(comp->state & CLASS_LINKED))
- if (!link_class(comp))
- return NULL;
-
- /* Allocate the arraydescriptor */
-
- desc = NEW(arraydescriptor);
-
- if (comp) {
- /* c is an array of references */
- desc->arraytype = ARRAYTYPE_OBJECT;
- desc->componentsize = sizeof(void*);
- desc->dataoffset = OFFSET(java_objectarray_t, data);
-
- compvftbl = comp->vftbl;
-
- if (!compvftbl) {
- log_text("Component class has no vftbl");
- assert(0);
- }
-
- desc->componentvftbl = compvftbl;
-
- if (compvftbl->arraydesc) {
- desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
-
- if (compvftbl->arraydesc->dimension >= 255) {
- log_text("Creating array of dimension >255");
- assert(0);
- }
-
- desc->dimension = compvftbl->arraydesc->dimension + 1;
- desc->elementtype = compvftbl->arraydesc->elementtype;
-
- } else {
- desc->elementvftbl = compvftbl;
- desc->dimension = 1;
- desc->elementtype = ARRAYTYPE_OBJECT;
- }
-
- } else {
- /* c is an array of a primitive type */
- switch (c->name->text[1]) {
- case 'Z':
- desc->arraytype = ARRAYTYPE_BOOLEAN;
- desc->dataoffset = OFFSET(java_booleanarray_t,data);
- desc->componentsize = sizeof(u1);
- break;
-
- case 'B':
- desc->arraytype = ARRAYTYPE_BYTE;
- desc->dataoffset = OFFSET(java_bytearray_t,data);
- desc->componentsize = sizeof(u1);
- break;
-
- case 'C':
- desc->arraytype = ARRAYTYPE_CHAR;
- desc->dataoffset = OFFSET(java_chararray_t,data);
- desc->componentsize = sizeof(u2);
- break;
-
- case 'D':
- desc->arraytype = ARRAYTYPE_DOUBLE;
- desc->dataoffset = OFFSET(java_doublearray_t,data);
- desc->componentsize = sizeof(double);
- break;
-
- case 'F':
- desc->arraytype = ARRAYTYPE_FLOAT;
- desc->dataoffset = OFFSET(java_floatarray_t,data);
- desc->componentsize = sizeof(float);
- break;
-
- case 'I':
- desc->arraytype = ARRAYTYPE_INT;
- desc->dataoffset = OFFSET(java_intarray_t,data);
- desc->componentsize = sizeof(s4);
- break;
-
- case 'J':
- desc->arraytype = ARRAYTYPE_LONG;
- desc->dataoffset = OFFSET(java_longarray_t,data);
- desc->componentsize = sizeof(s8);
- break;
-
- case 'S':
- desc->arraytype = ARRAYTYPE_SHORT;
- desc->dataoffset = OFFSET(java_shortarray_t,data);
- desc->componentsize = sizeof(s2);
- break;
-
- default:
- exceptions_throw_noclassdeffounderror(c->name);
- return NULL;
- }
-
- desc->componentvftbl = NULL;
- desc->elementvftbl = NULL;
- desc->dimension = 1;
- desc->elementtype = desc->arraytype;
- }
-
- return desc;
-}
-
-
-/* linker_compute_subclasses ***************************************************
-
- XXX
-
- ATTENTION: DO NOT REMOVE ANY OF THE LOCKING MECHANISMS BELOW:
- This function needs to take the class renumber lock and stop the
- world during class renumbering. The lock is used in C code which
- is not that performance critical. Whereas JIT code uses critical
- sections to atomically access the class values.
-
-*******************************************************************************/
-
-static void linker_compute_subclasses(classinfo *c)
-{
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
-#if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
- threads_stopworld();
-#endif
-
- if (!(c->flags & ACC_INTERFACE)) {
- c->nextsub = NULL;
- c->sub = NULL;
- }
-
- if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
- c->nextsub = c->super->sub;
- c->super->sub = c;
- }
-
- classvalue = 0;
-
- /* compute class values */
-
- linker_compute_class_values(class_java_lang_Object);
-
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
-#if 0 && defined(ENABLE_THREADS) && !defined(DISABLE_GC)
- threads_startworld();
-#endif
-}
-
-
-/* linker_compute_class_values *************************************************
-
- XXX
-
-*******************************************************************************/
-
-static void linker_compute_class_values(classinfo *c)
-{
- classinfo *subs;
-
- c->vftbl->baseval = ++classvalue;
-
- subs = c->sub;
-
- while (subs) {
- linker_compute_class_values(subs);
-
- subs = subs->nextsub;
- }
-
- c->vftbl->diffval = classvalue - c->vftbl->baseval;
-}
-
-
-/* linker_addinterface *********************************************************
-
- Is needed by link_class for adding a VTBL to a class. All
- interfaces implemented by ic are added as well.
-
- RETURN VALUE:
- true.........everything ok
- false........an exception has been thrown
-
-*******************************************************************************/
-
-static bool linker_addinterface(classinfo *c, classinfo *ic)
-{
- s4 j, k;
- vftbl_t *v;
- s4 i;
- classinfo *sc;
- methodinfo *m;
-
- v = c->vftbl;
- i = ic->index;
-
- if (i >= v->interfacetablelength)
- vm_abort("Internal error: interfacetable overflow");
-
- /* if this interface has already been added, return immediately */
-
- if (v->interfacetable[-i] != NULL)
- return true;
-
- if (ic->methodscount == 0) { /* fake entry needed for subtype test */
- v->interfacevftbllength[i] = 1;
- v->interfacetable[-i] = MNEW(methodptr, 1);
- v->interfacetable[-i][0] = NULL;
- }
- else {
- v->interfacevftbllength[i] = ic->methodscount;
- v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_vftbl_len += sizeof(methodptr) *
- (ic->methodscount + (ic->methodscount == 0));
-#endif
-
- for (j = 0; j < ic->methodscount; j++) {
- for (sc = c; sc != NULL; sc = sc->super) {
- for (k = 0; k < sc->methodscount; k++) {
- m = &(sc->methods[k]);
-
- if (method_canoverwrite(m, &(ic->methods[j]))) {
- /* method m overwrites the (abstract) method */
-#if defined(ENABLE_VERIFIER)
- /* Add loading constraints (for the more
- general types of the method
- ic->methods[j]). */
- if (!classcache_add_constraints_for_params(
- c->classloader, ic->classloader,
- &(ic->methods[j])))
- {
- return false;
- }
-#endif
-
- /* XXX taken from gcj */
- /* check for ACC_STATIC: IncompatibleClassChangeError */
-
- /* check for !ACC_PUBLIC: IllegalAccessError */
-
- /* check for ACC_ABSTRACT: AbstracMethodError,
- not sure about that one */
-
- v->interfacetable[-i][j] = v->table[m->vftblindex];
- goto foundmethod;
- }
- }
- }
-
- /* If no method was found, insert the AbstractMethodError
- stub. */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- v->interfacetable[-i][j] =
- (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
- else
-# endif
- v->interfacetable[-i][j] =
- (methodptr) (ptrint) &asm_abstractmethoderror;
-#else
- v->interfacetable[-i][j] =
- (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
-#endif
-
- foundmethod:
- ;
- }
- }
-
- /* add superinterfaces of this interface */
-
- for (j = 0; j < ic->interfacescount; j++)
- if (!linker_addinterface(c, ic->interfaces[j]))
- return false;
-
- /* everything ok */
-
- return true;
-}
-
-
-/* class_highestinterface ******************************************************
-
- Used by the function link_class to determine the amount of memory
- needed for the interface table.
-
-*******************************************************************************/
-
-static s4 class_highestinterface(classinfo *c)
-{
- s4 h;
- s4 h2;
- s4 i;
-
- /* check for ACC_INTERFACE bit already done in link_class_intern */
-
- h = c->index;
-
- for (i = 0; i < c->interfacescount; i++) {
- h2 = class_highestinterface(c->interfaces[i]);
-
- if (h2 > h)
- h = h2;
- }
-
- return 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:
- */
+++ /dev/null
-/* src/vmcore/linker.h - class linker header
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _LINKER_H
-#define _LINKER_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct _vftbl vftbl_t;
-typedef struct arraydescriptor arraydescriptor;
-typedef struct primitivetypeinfo primitivetypeinfo;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vmcore/class.h"
-#include "vmcore/references.h"
-
-
-/* virtual function table ******************************************************
-
- The vtbl has a bidirectional layout with open ends at both sides.
- interfacetablelength gives the number of entries of the interface
- table at the start of the vftbl. The vftbl pointer points to
- &interfacetable[0]. vftbllength gives the number of entries of
- table at the end of the vftbl.
-
- runtime type check (checkcast):
-
- Different methods are used for runtime type check depending on the
- argument of checkcast/instanceof.
-
- A check against a class is implemented via relative numbering on
- the class hierachy tree. The tree is numbered in a depth first
- traversal setting the base field and the diff field. The diff field
- gets the result of (high - base) so that a range check can be
- implemented by an unsigned compare. A sub type test is done by
- checking the inclusion of base of the sub class in the range of the
- superclass.
-
- A check against an interface is implemented via the
- interfacevftbl. If the interfacevftbl contains a nonnull value a
- class is a subclass of this interface.
-
- interfacetable:
-
- Like standard virtual methods interface methods are called using
- virtual function tables. All interfaces are numbered sequentially
- (starting with zero). For each class there exist an interface table
- of virtual function tables for each implemented interface. The
- length of the interface table is determined by the highest number
- of an implemented interface.
-
- The following example assumes a class which implements interface 0 and 3:
-
- interfacetablelength = 4
-
- | ... | +----------+
- +-----------+ | method 2 |---> method z
- | class | | method 1 |---> method y
- +-----------+ | method 0 |---> method x
- | ivftbl 0 |----------> +----------+
- vftblptr ---> +-----------+
- | ivftbl -1 |--> NULL +----------+
- | ivftbl -2 |--> NULL | method 1 |---> method x
- | ivftbl -3 |-----+ | method 0 |---> method a
- +-----------+ +----> +----------+
-
- +---------------+
- | length 3 = 2 |
- | length 2 = 0 |
- | length 1 = 0 |
- | length 0 = 3 |
- interfacevftbllength ---> +---------------+
-
-*******************************************************************************/
-
-struct _vftbl {
- methodptr *interfacetable[1]; /* interface table (access via macro) */
- classinfo *clazz; /* class, the vtbl belongs to */
- arraydescriptor *arraydesc; /* for array classes, otherwise NULL */
- s4 vftbllength; /* virtual function table length */
- s4 interfacetablelength; /* interface table length */
- s4 baseval; /* base for runtime type check */
- /* (-index for interfaces) */
- s4 diffval; /* high - base for runtime type check */
- s4 *interfacevftbllength; /* length of interface vftbls */
- methodptr table[1]; /* class vftbl */
-};
-
-
-/* arraydescriptor *************************************************************
-
- For every array class an arraydescriptor is allocated which
- describes the array class. The arraydescriptor is referenced from
- the vftbl of the array class.
-
-*******************************************************************************/
-
-struct arraydescriptor {
- vftbl_t *componentvftbl; /* vftbl of the component type, NULL for primit. */
- vftbl_t *elementvftbl; /* vftbl of the element type, NULL for primitive */
- s2 arraytype; /* ARRAYTYPE_* constant */
- s2 dimension; /* dimension of the array (always >= 1) */
- s4 dataoffset; /* offset of the array data from object pointer */
- s4 componentsize; /* size of a component in bytes */
- s2 elementtype; /* ARRAYTYPE_* constant */
-};
-
-
-/* global variables ***********************************************************/
-
-/* This lock must be taken while renumbering classes or while atomically */
-/* accessing classes. */
-
-extern java_object_t *linker_classrenumber_lock;
-
-
-/* function prototypes ********************************************************/
-
-void linker_preinit(void);
-void linker_init(void);
-classinfo *link_class(classinfo *c);
-
-#endif /* _LINKER_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/vmcore/loader.c - class loader 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 <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/package.hpp"
-#include "vm/primitive.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit_interface.h"
-
-#if defined(ENABLE_JAVASE)
-# include "vmcore/annotation.h"
-# include "vmcore/stackmap.h"
-#endif
-
-#include "vmcore/classcache.h"
-#include "vmcore/field.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/suck.h"
-
-#if defined(ENABLE_ZLIB)
-# include "vmcore/zip.h"
-#endif
-
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
-
-/* global variables ***********************************************************/
-
-static hashtable *hashtable_classloader;
-
-
-/* loader_preinit **************************************************************
-
- Initializes the classpath list and loads classes required for the
- primitive table.
-
- NOTE: Exceptions thrown during VM initialization are caught in the
- exception functions themselves.
-
-*******************************************************************************/
-
-void loader_preinit(void)
-{
-#if defined(ENABLE_THREADS)
- list_classpath_entry *lce;
-#endif
-
- TRACESUBSYSTEMINITIALIZATION("loader_preinit");
-
-#if defined(ENABLE_THREADS)
- /* Initialize the monitor pointer for zip/jar file locking. */
-
- for (lce = list_first(list_classpath_entries); lce != NULL;
- lce = list_next(list_classpath_entries, lce)) {
- if (lce->type == CLASSPATH_ARCHIVE)
- LOCK_INIT_OBJECT_LOCK(lce);
- }
-#endif
-
- /* initialize classloader hashtable, 10 entries should be enough */
-
- hashtable_classloader = NEW(hashtable);
- hashtable_create(hashtable_classloader, 10);
-
- /* Load the most basic classes. */
-
- assert(vm_initializing == true);
-
- class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object);
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_Cloneable = load_class_bootstrap(utf_java_lang_Cloneable);
- class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable);
-#endif
-}
-
-
-/* loader_init *****************************************************************
-
- Loads all classes required in the VM.
-
- NOTE: Exceptions thrown during VM initialization are caught in the
- exception functions themselves.
-
-*******************************************************************************/
-
-void loader_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("loader_init");
-
- /* Load primitive-type wrapping classes. */
-
- assert(vm_initializing == true);
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void);
-#endif
-
- class_java_lang_Boolean = load_class_bootstrap(utf_java_lang_Boolean);
- class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte);
- class_java_lang_Character = load_class_bootstrap(utf_java_lang_Character);
- class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short);
- class_java_lang_Integer = load_class_bootstrap(utf_java_lang_Integer);
- class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long);
- class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float);
- class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double);
-
- /* Load important system classes. */
-
- class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class);
- class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_ClassLoader =
- load_class_bootstrap(utf_java_lang_ClassLoader);
-
- class_java_lang_SecurityManager =
- load_class_bootstrap(utf_java_lang_SecurityManager);
-#endif
-
- class_java_lang_System =
- load_class_bootstrap(utf_new_char("java/lang/System"));
-
- class_java_lang_Thread =
- load_class_bootstrap(utf_new_char("java/lang/Thread"));
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_ThreadGroup =
- load_class_bootstrap(utf_java_lang_ThreadGroup);
-#endif
-
- class_java_lang_Throwable = load_class_bootstrap(utf_java_lang_Throwable);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- class_java_lang_VMSystem =
- load_class_bootstrap(utf_new_char("java/lang/VMSystem"));
-
- class_java_lang_VMThread =
- load_class_bootstrap(utf_new_char("java/lang/VMThread"));
-
- class_java_lang_VMThrowable =
- load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
-#endif
-
- /* Important system exceptions. */
-
- class_java_lang_Exception = load_class_bootstrap(utf_java_lang_Exception);
-
- class_java_lang_ClassNotFoundException =
- load_class_bootstrap(utf_java_lang_ClassNotFoundException);
-
- class_java_lang_RuntimeException =
- load_class_bootstrap(utf_java_lang_RuntimeException);
-
- /* Some classes which may be used often. */
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_StackTraceElement = load_class_bootstrap(utf_java_lang_StackTraceElement);
-
- class_java_lang_reflect_Constructor = load_class_bootstrap(utf_java_lang_reflect_Constructor);
- class_java_lang_reflect_Field = load_class_bootstrap(utf_java_lang_reflect_Field);
- class_java_lang_reflect_Method = load_class_bootstrap(utf_java_lang_reflect_Method);
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- class_java_lang_reflect_VMConstructor = load_class_bootstrap(utf_java_lang_reflect_VMConstructor);
- class_java_lang_reflect_VMField = load_class_bootstrap(utf_java_lang_reflect_VMField);
- class_java_lang_reflect_VMMethod = load_class_bootstrap(utf_java_lang_reflect_VMMethod);
-# endif
-
- class_java_security_PrivilegedAction = load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
-
- class_java_util_HashMap = load_class_bootstrap(utf_new_char("java/util/HashMap"));
- class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- class_sun_reflect_MagicAccessorImpl =
- load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
-# endif
-
- arrayclass_java_lang_Object =
- load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
-
-# if defined(ENABLE_ANNOTATIONS)
- /* needed by annotation support */
- class_sun_reflect_ConstantPool =
- load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* needed by GNU Classpaths annotation support */
- class_sun_reflect_annotation_AnnotationParser =
- load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
-# endif
-# endif
-#endif
-}
-
-
-/* loader_hashtable_classloader_add ********************************************
-
- Adds an entry to the classloader hashtable.
-
- REMEMBER: Also use this to register native loaders!
-
-*******************************************************************************/
-
-classloader_t *loader_hashtable_classloader_add(java_handle_t *cl)
-{
- hashtable_classloader_entry *cle;
- u4 key;
- u4 slot;
-
- if (cl == NULL)
- return NULL;
-
- LOCK_MONITOR_ENTER(hashtable_classloader->header);
-
- LLNI_CRITICAL_START;
-
- /* key for entry is the hashcode of the classloader;
- aligned to 16-byte boundaries */
-
- key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
- slot = key & (hashtable_classloader->size - 1);
- cle = hashtable_classloader->ptr[slot];
-
- /* search hashchain for existing entry */
-
- while (cle) {
- if (cle->object == LLNI_DIRECT(cl))
- break;
-
- cle = cle->hashlink;
- }
-
- LLNI_CRITICAL_END;
-
- /* if no classloader was found, we create a new entry here */
-
- if (cle == NULL) {
- cle = NEW(hashtable_classloader_entry);
-
-#if defined(ENABLE_GC_CACAO)
- /* register the classloader object with the GC */
-
- gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
-#endif
-
- LLNI_CRITICAL_START;
-
- cle->object = LLNI_DIRECT(cl);
-
- LLNI_CRITICAL_END;
-
-/*#define LOADER_DEBUG_CLASSLOADER*/
-#ifdef LOADER_DEBUG_CLASSLOADER
- printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
- class_print(LLNI_vftbl_direct(cl)->class);
- printf("\n");
- fflush(stdout);
-#endif
-
- /* insert entry into hashtable */
-
- cle->hashlink = hashtable_classloader->ptr[slot];
- hashtable_classloader->ptr[slot] = cle;
-
- /* update number of entries */
-
- hashtable_classloader->entries++;
- }
-
-
- LOCK_MONITOR_EXIT(hashtable_classloader->header);
-
-#if defined(ENABLE_HANDLES)
- return cle;
-#else
- return cl;
-#endif
-}
-
-
-/* loader_hashtable_classloader_find *******************************************
-
- Find an entry in the classloader hashtable.
-
-*******************************************************************************/
-
-classloader_t *loader_hashtable_classloader_find(java_handle_t *cl)
-{
- hashtable_classloader_entry *cle;
- u4 key;
- u4 slot;
-
- if (cl == NULL)
- return NULL;
-
- LLNI_CRITICAL_START;
-
- /* key for entry is the hashcode of the classloader;
- aligned to 16-byte boundaries */
-
- key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
- slot = key & (hashtable_classloader->size - 1);
- cle = hashtable_classloader->ptr[slot];
-
- /* search hashchain for existing entry */
-
- while (cle) {
- if (cle->object == LLNI_DIRECT(cl))
- break;
-
- cle = cle->hashlink;
- }
-
-#ifdef LOADER_DEBUG_CLASSLOADER
- if (cle == NULL) {
- printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
- class_print(LLNI_vftbl_direct(cl)->class);
- printf("\n");
- fflush(stdout);
- }
-#endif
-
- LLNI_CRITICAL_END;
-
-#if defined(ENABLE_HANDLES)
- return cle;
-#else
- return cl;
-#endif
-}
-
-
-/* loader_load_all_classes *****************************************************
-
- Loads all classes specified in the BOOTCLASSPATH.
-
-*******************************************************************************/
-
-void loader_load_all_classes(void)
-{
- list_classpath_entry *lce;
-#if defined(ENABLE_ZLIB)
- hashtable *ht;
- s4 slot;
- hashtable_zipfile_entry *htzfe;
- utf *u;
-#endif
-
- for (lce = list_first(list_classpath_entries); lce != NULL;
- lce = list_next(list_classpath_entries, lce)) {
-#if defined(ENABLE_ZLIB)
- if (lce->type == CLASSPATH_ARCHIVE) {
- /* get the classes hashtable */
-
- ht = lce->htclasses;
-
- for (slot = 0; slot < ht->size; slot++) {
- htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
-
- for (; htzfe; htzfe = htzfe->hashlink) {
- u = htzfe->filename;
-
- /* skip all entries in META-INF and .properties,
- .png files */
-
- if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
- strstr(u->text, ".properties") ||
- strstr(u->text, ".png"))
- continue;
-
- /* load class from bootstrap classloader */
-
- if (!load_class_bootstrap(u)) {
- fprintf(stderr, "Error loading: ");
- utf_fprint_printable_ascii_classname(stderr, u);
- fprintf(stderr, "\n");
-
-#if !defined(NDEBUG)
- /* print out exception and cause */
-
- exceptions_print_current_exception();
-#endif
- }
- }
- }
-
- } else {
-#endif
-#if defined(ENABLE_ZLIB)
- }
-#endif
- }
-}
-
-
-/* loader_skip_attribute_body **************************************************
-
- Skips an attribute the attribute_name_index has already been read.
-
- attribute_info {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
-
-*******************************************************************************/
-
-bool loader_skip_attribute_body(classbuffer *cb)
-{
- u4 attribute_length;
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- attribute_length = suck_u4(cb);
-
- if (!suck_check_classbuffer_size(cb, attribute_length))
- return false;
-
- suck_skip_nbytes(cb, attribute_length);
-
- return true;
-}
-
-
-/* load_constantpool ***********************************************************
-
- Loads the constantpool of a class, the entries are transformed into
- a simpler format by resolving references (a detailed overview of
- the compact structures can be found in global.h).
-
-*******************************************************************************/
-
-static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
-{
-
- /* The following structures are used to save information which cannot be
- processed during the first pass. After the complete constantpool has
- been traversed the references can be resolved.
- (only in specific order) */
-
- /* CONSTANT_Class entries */
- typedef struct forward_class {
- struct forward_class *next;
- u2 thisindex;
- u2 name_index;
- } forward_class;
-
- /* CONSTANT_String */
- typedef struct forward_string {
- struct forward_string *next;
- u2 thisindex;
- u2 string_index;
- } forward_string;
-
- /* CONSTANT_NameAndType */
- typedef struct forward_nameandtype {
- struct forward_nameandtype *next;
- u2 thisindex;
- u2 name_index;
- u2 sig_index;
- } forward_nameandtype;
-
- /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
- typedef struct forward_fieldmethint {
- struct forward_fieldmethint *next;
- u2 thisindex;
- u1 tag;
- u2 class_index;
- u2 nameandtype_index;
- } forward_fieldmethint;
-
-
- classinfo *c;
- u4 idx;
-
- forward_class *forward_classes = NULL;
- forward_string *forward_strings = NULL;
- forward_nameandtype *forward_nameandtypes = NULL;
- forward_fieldmethint *forward_fieldmethints = NULL;
-
- forward_class *nfc;
- forward_string *nfs;
- forward_nameandtype *nfn;
- forward_fieldmethint *nff;
-
- u4 cpcount;
- u1 *cptags;
- voidptr *cpinfos;
-
- c = cb->clazz;
-
- /* number of entries in the constant_pool table plus one */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- cpcount = c->cpcount = suck_u2(cb);
-
- /* allocate memory */
- cptags = c->cptags = MNEW(u1, cpcount);
- cpinfos = c->cpinfos = MNEW(voidptr, cpcount);
-
- if (cpcount < 1) {
- exceptions_throw_classformaterror(c, "Illegal constant pool size");
- return false;
- }
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += (sizeof(u1) + sizeof(voidptr)) * cpcount;
-#endif
-
- /* initialize constantpool */
- for (idx = 0; idx < cpcount; idx++) {
- cptags[idx] = CONSTANT_UNUSED;
- cpinfos[idx] = NULL;
- }
-
-
- /******* first pass *******/
- /* entries which cannot be resolved now are written into
- temporary structures and traversed again later */
-
- idx = 1;
- while (idx < cpcount) {
- u4 t;
-
- /* get constant type */
- if (!suck_check_classbuffer_size(cb, 1))
- return false;
-
- t = suck_u1(cb);
-
- switch (t) {
- case CONSTANT_Class:
- nfc = DNEW(forward_class);
-
- nfc->next = forward_classes;
- forward_classes = nfc;
-
- nfc->thisindex = idx;
- /* reference to CONSTANT_NameAndType */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- nfc->name_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_String:
- nfs = DNEW(forward_string);
-
- nfs->next = forward_strings;
- forward_strings = nfs;
-
- nfs->thisindex = idx;
-
- /* reference to CONSTANT_Utf8_info with string characters */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- nfs->string_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_NameAndType:
- nfn = DNEW(forward_nameandtype);
-
- nfn->next = forward_nameandtypes;
- forward_nameandtypes = nfn;
-
- nfn->thisindex = idx;
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* reference to CONSTANT_Utf8_info containing simple name */
- nfn->name_index = suck_u2(cb);
-
- /* reference to CONSTANT_Utf8_info containing field or method
- descriptor */
- nfn->sig_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- nff = DNEW(forward_fieldmethint);
-
- nff->next = forward_fieldmethints;
- forward_fieldmethints = nff;
-
- nff->thisindex = idx;
- /* constant type */
- nff->tag = t;
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* class or interface type that contains the declaration of the
- field or method */
- nff->class_index = suck_u2(cb);
-
- /* name and descriptor of the field or method */
- nff->nameandtype_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_Integer: {
- constant_integer *ci = NEW(constant_integer);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_integer);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- ci->value = suck_s4(cb);
- cptags[idx] = CONSTANT_Integer;
- cpinfos[idx] = ci;
-
- idx++;
- break;
- }
-
- case CONSTANT_Float: {
- constant_float *cf = NEW(constant_float);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_float);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- cf->value = suck_float(cb);
- cptags[idx] = CONSTANT_Float;
- cpinfos[idx] = cf;
-
- idx++;
- break;
- }
-
- case CONSTANT_Long: {
- constant_long *cl = NEW(constant_long);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_long);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 8))
- return false;
-
- cl->value = suck_s8(cb);
- cptags[idx] = CONSTANT_Long;
- cpinfos[idx] = cl;
- idx += 2;
- if (idx > cpcount) {
- exceptions_throw_classformaterror(c, "Invalid constant pool entry");
- return false;
- }
- break;
- }
-
- case CONSTANT_Double: {
- constant_double *cd = NEW(constant_double);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_double);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 8))
- return false;
-
- cd->value = suck_double(cb);
- cptags[idx] = CONSTANT_Double;
- cpinfos[idx] = cd;
- idx += 2;
- if (idx > cpcount) {
- exceptions_throw_classformaterror(c, "Invalid constant pool entry");
- return false;
- }
- break;
- }
-
- case CONSTANT_Utf8: {
- u4 length;
-
- /* number of bytes in the bytes array (not string-length) */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- length = suck_u2(cb);
- cptags[idx] = CONSTANT_Utf8;
-
- /* validate the string */
- if (!suck_check_classbuffer_size(cb, length))
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify &&
- !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
- {
- exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
- return false;
- }
-#endif /* ENABLE_VERIFIER */
- /* insert utf-string into the utf-symboltable */
- cpinfos[idx] = utf_new((char *) cb->pos, length);
-
- /* skip bytes of the string (buffer size check above) */
- suck_skip_nbytes(cb, length);
- idx++;
- break;
- }
-
- default:
- exceptions_throw_classformaterror(c, "Illegal constant pool type");
- return false;
- } /* end switch */
- } /* end while */
-
-
- /* resolve entries in temporary structures */
-
- while (forward_classes) {
- utf *name =
- class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
- if (!name)
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify && !is_valid_name_utf(name)) {
- exceptions_throw_classformaterror(c, "Class reference with invalid name");
- return false;
- }
-#endif /* ENABLE_VERIFIER */
-
- /* add all class references to the descriptor_pool */
-
- if (!descriptor_pool_add_class(descpool, name))
- return false;
-
- cptags[forward_classes->thisindex] = CONSTANT_Class;
-
- /* the classref is created later */
- cpinfos[forward_classes->thisindex] = name;
-
- nfc = forward_classes;
- forward_classes = forward_classes->next;
- }
-
- while (forward_strings) {
- utf *text =
- class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
- if (!text)
- return false;
-
- /* resolve utf-string */
- cptags[forward_strings->thisindex] = CONSTANT_String;
- cpinfos[forward_strings->thisindex] = text;
-
- nfs = forward_strings;
- forward_strings = forward_strings->next;
- }
-
- while (forward_nameandtypes) {
- constant_nameandtype *cn = NEW(constant_nameandtype);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_nameandtype);
-#endif
-
- /* resolve simple name and descriptor */
- cn->name = class_getconstant(c,
- forward_nameandtypes->name_index,
- CONSTANT_Utf8);
- if (!cn->name)
- return false;
-
- cn->descriptor = class_getconstant(c,
- forward_nameandtypes->sig_index,
- CONSTANT_Utf8);
- if (!cn->descriptor)
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- /* check name */
- if (!is_valid_name_utf(cn->name)) {
- exceptions_throw_classformaterror(c,
- "Illegal Field name \"%s\"",
- cn->name->text);
-
- return false;
- }
-
- /* disallow referencing <clinit> among others */
- if (cn->name->text[0] == '<' && cn->name != utf_init) {
- exceptions_throw_classformaterror(c, "Illegal reference to special method");
- return false;
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
- cpinfos[forward_nameandtypes->thisindex] = cn;
-
- nfn = forward_nameandtypes;
- forward_nameandtypes = forward_nameandtypes->next;
- }
-
- while (forward_fieldmethints) {
- constant_nameandtype *nat;
- constant_FMIref *fmi = NEW(constant_FMIref);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_FMIref);
-#endif
- /* resolve simple name and descriptor */
-
- nat = class_getconstant(c,
- forward_fieldmethints->nameandtype_index,
- CONSTANT_NameAndType);
- if (!nat)
- return false;
-
- /* add all descriptors in {Field,Method}ref to the descriptor_pool */
-
- if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
- return false;
-
- /* the classref is created later */
-
- fmi->p.index = forward_fieldmethints->class_index;
- fmi->name = nat->name;
- fmi->descriptor = nat->descriptor;
-
- cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
- cpinfos[forward_fieldmethints->thisindex] = fmi;
-
- nff = forward_fieldmethints;
- forward_fieldmethints = forward_fieldmethints->next;
- }
-
- /* everything was ok */
-
- return true;
-}
-
-
-/* loader_load_attribute_signature *********************************************
-
- Signature_attribute {
- u2 attribute_name_index;
- u4 atrribute_length;
- u2 signature_index;
- }
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
-{
- classinfo *c;
- u4 attribute_length;
- u2 signature_index;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- /* check remaining bytecode */
-
- 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;
- }
-
- if (*signature != NULL) {
- exceptions_throw_classformaterror(c, "Multiple Signature attributes");
- return false;
- }
-
- /* get signature */
-
- signature_index = suck_u2(cb);
-
- if (!(*signature = class_getconstant(c, signature_index, CONSTANT_Utf8)))
- return false;
-
- return true;
-}
-#endif /* defined(ENABLE_JAVASE) */
-
-
-/* load_class_from_sysloader ***************************************************
-
- Load the class with the given name using the system class loader
-
- IN:
- name.............the classname
-
- RETURN VALUE:
- the loaded class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-classinfo *load_class_from_sysloader(utf *name)
-{
- methodinfo *m;
- java_handle_t *clo;
- classloader_t *cl;
- classinfo *c;
-
- assert(class_java_lang_Object);
- assert(class_java_lang_ClassLoader);
- assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
-
- m = class_resolveclassmethod(class_java_lang_ClassLoader,
- utf_getSystemClassLoader,
- utf_void__java_lang_ClassLoader,
- class_java_lang_Object,
- false);
-
- if (!m)
- return false;
-
- clo = vm_call_method(m, NULL);
-
- if (!clo)
- return false;
-
- cl = loader_hashtable_classloader_add(clo);
-
- c = load_class_from_classloader(name, cl);
-
- return c;
-}
-
-
-/* load_class_from_classloader *************************************************
-
- Load the class with the given name using the given user-defined class loader.
-
- IN:
- name.............the classname
- cl...............user-defined class loader
-
- RETURN VALUE:
- the loaded class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
-{
- java_handle_t *o;
- classinfo *c;
- classinfo *tmpc;
- java_handle_t *string;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_lookup, time_prepare, time_java,
- time_cache;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- assert(name);
-
- /* lookup if this class has already been loaded */
-
- c = classcache_lookup(cl, name);
-
- RT_TIMING_GET_TIME(time_lookup);
- RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
-
- if (c != NULL)
- return c;
-
- /* if other class loader than bootstrap, call it */
-
- if (cl != NULL) {
- methodinfo *lc;
- char *text;
- s4 namelen;
-
- text = name->text;
- namelen = name->blength;
-
- /* handle array classes */
- if (text[0] == '[') {
- classinfo *comp;
- utf *u;
-
- switch (text[1]) {
- case 'L':
- /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
- if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
- exceptions_throw_classnotfoundexception(name);
- return false;
- }
-
- u = utf_new(text + 2, namelen - 3);
-
- if (!(comp = load_class_from_classloader(u, cl)))
- return false;
-
- /* create the array class */
-
- c = class_array_of(comp, false);
-
- tmpc = classcache_store(cl, c, true);
-
- if (tmpc == NULL) {
- /* exception, free the loaded class */
- c->state &= ~CLASS_LOADING;
- class_free(c);
- }
-
- return tmpc;
-
- case '[':
- /* load the component class */
-
- u = utf_new(text + 1, namelen - 1);
-
- if (!(comp = load_class_from_classloader(u, cl)))
- return false;
-
- /* create the array class */
-
- c = class_array_of(comp, false);
-
- tmpc = classcache_store(cl, c, true);
-
- if (tmpc == NULL) {
- /* exception, free the loaded class */
- c->state &= ~CLASS_LOADING;
- class_free(c);
- }
-
- return tmpc;
-
- default:
- /* primitive array classes are loaded by the bootstrap loader */
-
- c = load_class_bootstrap(name);
-
- return c;
- }
- }
-
- LLNI_class_get(cl, c);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* OpenJDK uses this internal function because it's
- synchronized. */
-
- lc = class_resolveclassmethod(c,
- utf_loadClassInternal,
- utf_java_lang_String__java_lang_Class,
- NULL,
- true);
-#else
- lc = class_resolveclassmethod(c,
- utf_loadClass,
- utf_java_lang_String__java_lang_Class,
- NULL,
- true);
-#endif
-
- if (lc == NULL)
- return false; /* exception */
-
- /* move return value into `o' and cast it afterwards to a classinfo* */
-
- string = javastring_new_slash_to_dot(name);
-
- RT_TIMING_GET_TIME(time_prepare);
-
- o = vm_call_method(lc, (java_handle_t *) cl, string);
-
- RT_TIMING_GET_TIME(time_java);
-
- c = LLNI_classinfo_unwrap(o);
-
- if (c != NULL) {
- /* Store this class in the loaded class cache. If another
- class with the same (initloader,name) pair has been
- stored earlier it will be returned by classcache_store
- In this case classcache_store may not free the class
- because it has already been exposed to Java code which
- may have kept references to that class. */
-
- tmpc = classcache_store(cl, c, false);
-
- if (tmpc == NULL) {
- /* exception, free the loaded class */
- c->state &= ~CLASS_LOADING;
- class_free(c);
- }
-
- c = tmpc;
- }
-
- RT_TIMING_GET_TIME(time_cache);
-
- RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
- RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
- RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
-
- /* SUN compatible -verbose:class output */
-
- if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
- printf("[Loaded ");
- utf_display_printable_ascii_classname(name);
- printf("]\n");
- }
-
-#if defined(ENABLE_JVMTI)
- /* fire Class Load JVMTI event */
- if (jvmti) jvmti_ClassLoadPrepare(false, c);
-#endif
-
-
- return c;
- }
-
- c = load_class_bootstrap(name);
-
- return c;
-}
-
-
-/* load_class_bootstrap ********************************************************
-
- Load the class with the given name using the bootstrap class loader.
-
- IN:
- name.............the classname
-
- RETURN VALUE:
- loaded classinfo, or
- NULL if an exception has been thrown
-
- SYNCHRONIZATION:
- load_class_bootstrap is synchronized. It can be treated as an
- atomic operation.
-
-*******************************************************************************/
-
-classinfo *load_class_bootstrap(utf *name)
-{
- classbuffer *cb;
- classinfo *c;
- classinfo *r;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_lookup, time_array, time_suck,
- time_load, time_cache;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- /* for debugging */
-
- assert(name);
-
- /* lookup if this class has already been loaded */
-
- r = classcache_lookup(NULL, name);
-
- if (r != NULL) {
- RT_TIMING_GET_TIME(time_lookup);
- RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
-
- return r;
- }
-
- RT_TIMING_GET_TIME(time_lookup);
- RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
-
- /* create the classinfo */
-
- c = class_create_classinfo(name);
-
- /* handle array classes */
-
- if (name->text[0] == '[') {
- c = load_newly_created_array(c, NULL);
-
- if (c == NULL)
- return NULL;
-
- assert(c->state & CLASS_LOADED);
-
- RT_TIMING_GET_TIME(time_array);
- RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
-
- return c;
- }
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- compilingtime_stop();
-
- if (opt_getloadingtime)
- loadingtime_start();
-#endif
-
- /* load classdata, throw exception on error */
-
- cb = suck_start(c);
-
- if (cb == NULL) {
- exceptions_throw_classnotfoundexception(name);
- return NULL;
- }
-
- RT_TIMING_GET_TIME(time_suck);
-
- /* load the class from the buffer */
-
- r = load_class_from_classbuffer(cb);
-
- RT_TIMING_GET_TIME(time_load);
-
- if (r == NULL) {
- /* the class could not be loaded, free the classinfo struct */
-
- class_free(c);
- }
- else {
- /* Store this class in the loaded class cache this step also
- checks the loading constraints. If the class has been
- loaded before, the earlier loaded class is returned. */
-
- classinfo *res = classcache_store(NULL, c, true);
-
- if (res == NULL) {
- /* exception */
- class_free(c);
- }
- else {
- /* Add the package name to the boot packages. */
-
- Package_add(c->packagename);
- }
-
- r = res;
- }
-
- RT_TIMING_GET_TIME(time_cache);
-
- /* SUN compatible -verbose:class output */
-
- if (opt_verboseclass && r) {
- printf("[Loaded ");
- utf_display_printable_ascii_classname(name);
- printf(" from %s]\n", cb->path);
- }
-
- /* free memory */
-
- suck_stop(cb);
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getloadingtime)
- loadingtime_stop();
-
- if (opt_getcompilingtime)
- compilingtime_start();
-#endif
-
- RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
- RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
- RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
- RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
-
- return r;
-}
-
-
-/* load_class_from_classbuffer_intern ******************************************
-
- Loads a class from a classbuffer into a given classinfo structure.
- Super-classes are also loaded at this point and some verfication
- checks are done.
-
- SYNCHRONIZATION:
- This function is NOT synchronized!
-
-*******************************************************************************/
-
-static bool load_class_from_classbuffer_intern(classbuffer *cb)
-{
- classinfo *c;
- classinfo *tc;
- utf *name;
- utf *supername;
- utf **interfacesnames;
- utf *u;
- constant_classref *cr;
- int16_t index;
-
- u4 i,j;
- u4 ma, mi;
- descriptor_pool *descpool;
-#if defined(ENABLE_STATISTICS)
- u4 classrefsize;
- u4 descsize;
-#endif
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_checks, time_ndpool, time_cpool,
- time_setup, time_fields, time_methods, time_classrefs,
- time_descs, time_setrefs, time_parsefds, time_parsemds,
- time_parsecpool, time_verify, time_attrs;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- /* Get the classbuffer's class. */
-
- c = cb->clazz;
-
- if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
- return false;
-
- /* check signature */
-
- if (suck_u4(cb) != MAGIC) {
- exceptions_throw_classformaterror(c, "Bad magic number");
- return false;
- }
-
- /* check version */
-
- mi = suck_u2(cb);
- ma = suck_u2(cb);
-
- if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
- exceptions_throw_unsupportedclassversionerror(c, ma, mi);
- return false;
- }
-
- RT_TIMING_GET_TIME(time_checks);
-
- /* create a new descriptor pool */
-
- descpool = descriptor_pool_new(c);
-
- RT_TIMING_GET_TIME(time_ndpool);
-
- /* load the constant pool */
-
- if (!load_constantpool(cb, descpool))
- return false;
-
- RT_TIMING_GET_TIME(time_cpool);
-
- /* ACC flags */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* We OR the flags here, as we set already some flags in
- class_create_classinfo. */
-
- c->flags |= suck_u2(cb);
-
- /* check ACC flags consistency */
-
- if (c->flags & ACC_INTERFACE) {
- if (!(c->flags & ACC_ABSTRACT)) {
- /* We work around this because interfaces in JDK 1.1 are
- * not declared abstract. */
-
- c->flags |= ACC_ABSTRACT;
- }
-
- if (c->flags & ACC_FINAL) {
- exceptions_throw_classformaterror(c,
- "Illegal class modifiers: 0x%X",
- c->flags);
- return false;
- }
-
- if (c->flags & ACC_SUPER) {
- c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
- }
- }
-
- if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
- exceptions_throw_classformaterror(c,
- "Illegal class modifiers: 0x%X",
- c->flags);
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* This class. */
-
- index = suck_u2(cb);
-
- name = (utf *) class_getconstant(c, index, CONSTANT_Class);
-
- if (name == NULL)
- return false;
-
- if (c->name == utf_not_named_yet) {
- /* we finally have a name for this class */
- c->name = name;
- class_set_packagename(c);
- }
- else if (name != c->name) {
- exceptions_throw_noclassdeffounderror_wrong_name(c, name);
- return false;
- }
-
- /* Retrieve superclass. */
-
- c->super = NULL;
-
- index = suck_u2(cb);
-
- if (index == 0) {
- supername = NULL;
-
- /* This is only allowed for java.lang.Object. */
-
- if (c->name != utf_java_lang_Object) {
- exceptions_throw_classformaterror(c, "Bad superclass index");
- return false;
- }
- }
- else {
- supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
-
- if (supername == NULL)
- return false;
-
- /* java.lang.Object may not have a super class. */
-
- if (c->name == utf_java_lang_Object) {
- exceptions_throw_classformaterror(NULL, "java.lang.Object with superclass");
- return false;
- }
-
- /* Detect circularity. */
-
- if (supername == c->name) {
- exceptions_throw_classcircularityerror(c);
- return false;
- }
-
- /* Interfaces must have java.lang.Object as super class. */
-
- if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
- exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
- return false;
- }
- }
-
- /* Parse the super interfaces. */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- c->interfacescount = suck_u2(cb);
-
- if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
- return false;
-
- c->interfaces = MNEW(classinfo*, c->interfacescount);
-
- /* Get the names of the super interfaces. */
-
- interfacesnames = DMNEW(utf*, c->interfacescount);
-
- for (i = 0; i < c->interfacescount; i++) {
- index = suck_u2(cb);
-
- u = (utf *) class_getconstant(c, index, CONSTANT_Class);
-
- if (u == NULL)
- return false;
-
- interfacesnames[i] = u;
- }
-
- RT_TIMING_GET_TIME(time_setup);
-
- /* Parse fields. */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- c->fieldscount = suck_u2(cb);
- c->fields = MNEW(fieldinfo, c->fieldscount);
-
- MZERO(c->fields, fieldinfo, c->fieldscount);
-
- for (i = 0; i < c->fieldscount; i++) {
- if (!field_load(cb, &(c->fields[i]), descpool))
- return false;
- }
-
- RT_TIMING_GET_TIME(time_fields);
-
- /* Parse methods. */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- c->methodscount = suck_u2(cb);
- c->methods = MNEW(methodinfo, c->methodscount);
-
- MZERO(c->methods, methodinfo, c->methodscount);
-
- for (i = 0; i < c->methodscount; i++) {
- if (!method_load(cb, &(c->methods[i]), descpool))
- return false;
- }
-
- RT_TIMING_GET_TIME(time_methods);
-
- /* create the class reference table */
-
- c->classrefs =
- descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
-
- RT_TIMING_GET_TIME(time_classrefs);
-
- /* allocate space for the parsed descriptors */
-
- descriptor_pool_alloc_parsed_descriptors(descpool);
- c->parseddescs =
- descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
- count_classref_len += classrefsize;
- count_parsed_desc_len += descsize;
- }
-#endif
-
- RT_TIMING_GET_TIME(time_descs);
-
- /* put the classrefs in the constant pool */
-
- for (i = 0; i < c->cpcount; i++) {
- if (c->cptags[i] == CONSTANT_Class) {
- utf *name = (utf *) c->cpinfos[i];
- c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
- }
- }
-
- /* Resolve the super class. */
-
- if (supername != NULL) {
- cr = descriptor_pool_lookup_classref(descpool, supername);
-
- if (cr == NULL)
- return false;
-
- /* XXX This should be done better. */
- tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
-
- if (tc == NULL) {
- resolve_handle_pending_exception(true);
- return false;
- }
-
- /* Interfaces are not allowed as super classes. */
-
- if (tc->flags & ACC_INTERFACE) {
- exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
- return false;
- }
-
- /* Don't allow extending final classes */
-
- if (tc->flags & ACC_FINAL) {
- exceptions_throw_verifyerror(NULL,
- "Cannot inherit from final class");
- return false;
- }
-
- /* Store the super class. */
-
- c->super = tc;
- }
-
- /* Resolve the super interfaces. */
-
- for (i = 0; i < c->interfacescount; i++) {
- u = interfacesnames[i];
- cr = descriptor_pool_lookup_classref(descpool, u);
-
- if (cr == NULL)
- return false;
-
- /* XXX This should be done better. */
- tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
-
- if (tc == NULL) {
- resolve_handle_pending_exception(true);
- return false;
- }
-
- /* Detect circularity. */
-
- if (tc == c) {
- exceptions_throw_classcircularityerror(c);
- return false;
- }
-
- if (!(tc->flags & ACC_INTERFACE)) {
- exceptions_throw_incompatibleclasschangeerror(tc,
- "Implementing class");
- return false;
- }
-
- /* Store the super interface. */
-
- c->interfaces[i] = tc;
- }
-
- RT_TIMING_GET_TIME(time_setrefs);
-
- /* Parse the field descriptors. */
-
- for (i = 0; i < c->fieldscount; i++) {
- c->fields[i].parseddesc =
- descriptor_pool_parse_field_descriptor(descpool,
- c->fields[i].descriptor);
- if (!c->fields[i].parseddesc)
- return false;
- }
-
- RT_TIMING_GET_TIME(time_parsefds);
-
- /* parse method descriptors */
-
- for (i = 0; i < c->methodscount; i++) {
- methodinfo *m = &c->methods[i];
- m->parseddesc =
- descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
- m->flags, class_get_self_classref(m->clazz));
- if (!m->parseddesc)
- return false;
-
- for (j = 0; j < m->rawexceptiontablelength; j++) {
- if (!m->rawexceptiontable[j].catchtype.any)
- continue;
-
- if ((m->rawexceptiontable[j].catchtype.ref =
- descriptor_pool_lookup_classref(descpool,
- (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL)
- return false;
- }
-
- for (j = 0; j < m->thrownexceptionscount; j++) {
- if (!m->thrownexceptions[j].any)
- continue;
-
- if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
- (utf *) m->thrownexceptions[j].any)) == NULL)
- return false;
- }
- }
-
- RT_TIMING_GET_TIME(time_parsemds);
-
- /* parse the loaded descriptors */
-
- for (i = 0; i < c->cpcount; i++) {
- constant_FMIref *fmi;
- s4 index;
-
- switch (c->cptags[i]) {
- case CONSTANT_Fieldref:
- fmi = (constant_FMIref *) c->cpinfos[i];
- fmi->parseddesc.fd =
- descriptor_pool_parse_field_descriptor(descpool,
- fmi->descriptor);
- if (!fmi->parseddesc.fd)
- return false;
-
- index = fmi->p.index;
- fmi->p.classref =
- (constant_classref *) class_getconstant(c, index,
- CONSTANT_Class);
- if (!fmi->p.classref)
- return false;
- break;
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- fmi = (constant_FMIref *) c->cpinfos[i];
- index = fmi->p.index;
- fmi->p.classref =
- (constant_classref *) class_getconstant(c, index,
- CONSTANT_Class);
- if (!fmi->p.classref)
- return false;
- fmi->parseddesc.md =
- descriptor_pool_parse_method_descriptor(descpool,
- fmi->descriptor,
- ACC_UNDEF,
- fmi->p.classref);
- if (!fmi->parseddesc.md)
- return false;
- break;
- }
- }
-
- RT_TIMING_GET_TIME(time_parsecpool);
-
-#ifdef ENABLE_VERIFIER
- /* Check if all fields and methods can be uniquely
- * identified by (name,descriptor). */
-
- if (opt_verify) {
- /* We use a hash table here to avoid making the
- * average case quadratic in # of methods, fields.
- */
- static int shift = 0;
- u2 *hashtab;
- u2 *next; /* for chaining colliding hash entries */
- size_t len;
- size_t hashlen;
- u2 index;
- u2 old;
-
- /* Allocate hashtable */
- len = c->methodscount;
- if (len < c->fieldscount) len = c->fieldscount;
- hashlen = 5 * len;
- hashtab = MNEW(u2,(hashlen + len));
- next = hashtab + hashlen;
-
- /* Determine bitshift (to get good hash values) */
- if (!shift) {
- len = sizeof(utf);
- while (len) {
- len >>= 1;
- shift++;
- }
- }
-
- /* Check fields */
- memset(hashtab, 0, sizeof(u2) * (hashlen + len));
-
- for (i = 0; i < c->fieldscount; ++i) {
- fieldinfo *fi = c->fields + i;
-
- /* It's ok if we lose bits here */
- index = ((((size_t) fi->name) +
- ((size_t) fi->descriptor)) >> shift) % hashlen;
-
- if ((old = hashtab[index])) {
- old--;
- next[i] = old;
- do {
- if (c->fields[old].name == fi->name &&
- c->fields[old].descriptor == fi->descriptor) {
- exceptions_throw_classformaterror(c, "Repetitive field name/signature");
- return false;
- }
- } while ((old = next[old]));
- }
- hashtab[index] = i + 1;
- }
-
- /* Check methods */
- memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
-
- for (i = 0; i < c->methodscount; ++i) {
- methodinfo *mi = c->methods + i;
-
- /* It's ok if we lose bits here */
- index = ((((size_t) mi->name) +
- ((size_t) mi->descriptor)) >> shift) % hashlen;
-
- if ((old = hashtab[index])) {
- old--;
- next[i] = old;
- do {
- if (c->methods[old].name == mi->name &&
- c->methods[old].descriptor == mi->descriptor) {
- exceptions_throw_classformaterror(c, "Repetitive method name/signature");
- return false;
- }
- } while ((old = next[old]));
- }
- hashtab[index] = i + 1;
- }
-
- MFREE(hashtab, u2, (hashlen + len));
- }
-#endif /* ENABLE_VERIFIER */
-
- RT_TIMING_GET_TIME(time_verify);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- size_classinfo += sizeof(classinfo*) * c->interfacescount;
- size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
- size_methodinfo += sizeof(methodinfo) * c->methodscount;
- }
-#endif
-
- /* load attribute structures */
-
- if (!class_load_attributes(cb))
- return false;
-
- /* Pre Java 1.5 version don't check this. This implementation is
- like Java 1.5 do it: for class file version 45.3 we don't check
- it, older versions are checked. */
-
- if (((ma == 45) && (mi > 3)) || (ma > 45)) {
- /* check if all data has been read */
- s4 classdata_left = ((cb->data + cb->size) - cb->pos);
-
- if (classdata_left > 0) {
- exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
- return false;
- }
- }
-
- RT_TIMING_GET_TIME(time_attrs);
-
- RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
- RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
- RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
- RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
- RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
- RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
- RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
- RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
- RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
- RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
- RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
- RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
- RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
- RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
- RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
-
- return true;
-}
-
-
-/* load_class_from_classbuffer *************************************************
-
- Convenience wrapper for load_class_from_classbuffer.
-
- SYNCHRONIZATION:
- This function is NOT synchronized!
-
-*******************************************************************************/
-
-classinfo *load_class_from_classbuffer(classbuffer *cb)
-{
- classinfo *c;
- bool result;
- int32_t dumpmarker;
-
- /* Get the classbuffer's class. */
-
- c = cb->clazz;
-
- /* Check if the class is already loaded. */
-
- if (c->state & CLASS_LOADED)
- return c;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_class_loads++;
-#endif
-
-#if !defined(NDEBUG)
- if (loadverbose)
- log_message_class("Loading class: ", c);
-#endif
-
- /* Mark start of dump memory area. */
-
- DMARKER;
-
- /* Class is currently loading. */
-
- c->state |= CLASS_LOADING;
-
- /* Parse the classbuffer. */
-
- result = load_class_from_classbuffer_intern(cb);
-
- /* Release dump area. */
-
- DRELEASE;
-
- /* An error occurred. */
-
- if (result == false) {
- /* Revert loading state. */
-
- c->state = (c->state & ~CLASS_LOADING);
-
- return NULL;
- }
-
- /* Revert loading state and set loaded. */
-
- c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
-
-#if defined(ENABLE_JVMTI)
- /* fire Class Prepare JVMTI event */
-
- if (jvmti)
- jvmti_ClassLoadPrepare(true, c);
-#endif
-
-#if !defined(NDEBUG)
- if (loadverbose)
- log_message_class("Loading done class: ", c);
-#endif
-
- return c;
-}
-
-
-/* load_newly_created_array ****************************************************
-
- Load a newly created array class.
-
- RETURN VALUE:
- c....................the array class C has been loaded
- other classinfo......the array class was found in the class cache,
- C has been freed
- NULL.................an exception has been thrown
-
- Note:
- This is an internal function. Do not use it unless you know exactly
- what you are doing!
-
- Use one of the load_class_... functions for general array class loading.
-
-*******************************************************************************/
-
-classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
-{
- classinfo *comp = NULL;
- methodinfo *clone;
- methoddesc *clonedesc;
- constant_classref *classrefs;
- char *text;
- s4 namelen;
- utf *u;
-
- text = c->name->text;
- namelen = c->name->blength;
-
- /* Check array class name */
-
- if ((namelen < 2) || (text[0] != '[')) {
- exceptions_throw_classnotfoundexception(c->name);
- return NULL;
- }
-
- /* Check the element type */
-
- switch (text[1]) {
- case '[':
- /* c is an array of arrays. We have to create the component class. */
-
- u = utf_new(text + 1, namelen - 1);
-
- comp = load_class_from_classloader(u, loader);
-
- if (comp == NULL)
- return NULL;
-
- assert(comp->state & CLASS_LOADED);
-
- /* the array's flags are that of the component class */
- c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
- c->classloader = comp->classloader;
- break;
-
- case 'L':
- /* c is an array of objects. */
-
- /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
- if ((namelen < 4) || (text[2] == '[') || (text[namelen - 1] != ';')) {
- exceptions_throw_classnotfoundexception(c->name);
- return NULL;
- }
-
- u = utf_new(text + 2, namelen - 3);
-
- if (!(comp = load_class_from_classloader(u, loader)))
- return NULL;
-
- assert(comp->state & CLASS_LOADED);
-
- /* the array's flags are that of the component class */
- c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
- c->classloader = comp->classloader;
- break;
-
- default:
- /* c is an array of a primitive type */
-
- /* check for cases like `[II' and whether the character is a
- valid primitive type */
-
- if ((namelen > 2) || (primitive_class_get_by_char(text[1]) == NULL)) {
- exceptions_throw_classnotfoundexception(c->name);
- return NULL;
- }
-
- /* the accessibility of the array class is public (VM Spec 5.3.3) */
- c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
- c->classloader = NULL;
- }
-
- assert(class_java_lang_Object);
-#if defined(ENABLE_JAVASE)
- assert(class_java_lang_Cloneable);
- assert(class_java_io_Serializable);
-#endif
-
- /* Setup the array class. */
-
- c->super = class_java_lang_Object;
-
-#if defined(ENABLE_JAVASE)
-
- c->interfacescount = 2;
- c->interfaces = MNEW(classinfo*, 2);
- c->interfaces[0] = class_java_lang_Cloneable;
- c->interfaces[1] = class_java_io_Serializable;
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- c->interfacescount = 0;
- c->interfaces = NULL;
-
-#else
-# error unknow Java configuration
-#endif
-
- c->methodscount = 1;
- c->methods = MNEW(methodinfo, c->methodscount);
-
- MZERO(c->methods, methodinfo, c->methodscount);
-
- classrefs = MNEW(constant_classref, 2);
-
- CLASSREF_INIT(classrefs[0], c, c->name);
- CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
-
- /* create descriptor for clone method */
- /* we need one paramslot which is reserved for the 'this' parameter */
- clonedesc = NEW(methoddesc);
- clonedesc->returntype.type = TYPE_ADR;
- clonedesc->returntype.classref = classrefs + 1;
- clonedesc->returntype.arraydim = 0;
- /* initialize params to "empty", add real params below in
- descriptor_params_from_paramtypes */
- clonedesc->paramcount = 0;
- clonedesc->paramslots = 0;
- clonedesc->paramtypes[0].classref = classrefs + 0;
- clonedesc->params = NULL;
-
- /* create methodinfo */
-
- clone = c->methods;
- MSET(clone, 0, methodinfo, 1);
-
-#if defined(ENABLE_THREADS)
- lock_init_object_lock(&clone->header);
-#endif
-
- /* ATTENTION: if you delete the ACC_NATIVE below, set
- clone->maxlocals=1 (interpreter related) */
-
- clone->flags = ACC_PUBLIC | ACC_NATIVE;
- clone->name = utf_clone;
- clone->descriptor = utf_void__java_lang_Object;
- clone->parseddesc = clonedesc;
- clone->clazz = c;
-
- /* parse the descriptor to get the register allocation */
-
- if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
- return false;
-
- clone->code = codegen_generate_stub_native(clone, BUILTIN_clone);
-
- /* XXX: field: length? */
-
- /* array classes are not loaded from class files */
-
- c->state |= CLASS_LOADED;
- c->parseddescs = (u1 *) clonedesc;
- c->parseddescsize = sizeof(methodinfo);
- c->classrefs = classrefs;
- c->classrefcount = 1;
-
- /* insert class into the loaded class cache */
- /* XXX free classinfo if NULL returned? */
-
- return classcache_store(loader, c, true);
-}
-
-
-/* loader_close ****************************************************************
-
- Frees all resources.
-
-*******************************************************************************/
-
-void loader_close(void)
-{
- /* empty */
-}
-
-
-/*
- * 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/vmcore/loader.h - class loader 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 _LOADER_H
-#define _LOADER_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct classbuffer classbuffer;
-
-
-#include "config.h"
-
-#include <stdio.h>
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vmcore/utf8.h"
-
-
-/* constant pool entries *******************************************************
-
- All constant pool entries need a data structure which contain the entrys
- value. In some cases this structure exist already, in the remaining cases
- this structure must be generated:
-
- kind structure generated?
- ----------------------------------------------------------------------
- CONSTANT_Class constant_classref yes
- CONSTANT_Fieldref constant_FMIref yes
- CONSTANT_Methodref constant_FMIref yes
- CONSTANT_InterfaceMethodref constant_FMIref yes
- CONSTANT_String unicode no
- CONSTANT_Integer constant_integer yes
- CONSTANT_Float constant_float yes
- CONSTANT_Long constant_long yes
- CONSTANT_Double constant_double yes
- CONSTANT_NameAndType constant_nameandtype yes
- CONSTANT_Utf8 unicode no
- CONSTANT_UNUSED -
-
-*******************************************************************************/
-
-typedef struct { /* Integer */
- s4 value;
-} constant_integer;
-
-
-typedef struct { /* Float */
- float value;
-} constant_float;
-
-
-typedef struct { /* Long */
- s8 value;
-} constant_long;
-
-
-typedef struct { /* Double */
- double value;
-} constant_double;
-
-
-typedef struct { /* NameAndType (Field or Method) */
- utf *name; /* field/method name */
- utf *descriptor; /* field/method type descriptor string */
-} constant_nameandtype;
-
-
-/* classbuffer ****************************************************************/
-
-struct classbuffer {
- classinfo *clazz; /* pointer to classinfo structure */
- uint8_t *data; /* pointer to byte code */
- int32_t size; /* size of the byte code */
- uint8_t *pos; /* current read position */
- char *path; /* path to file (for debugging) */
-};
-
-
-/* hashtable_classloader_entry *************************************************
-
- ATTENTION: The pointer to the classloader object needs to be the
- first field of the entry, so that it can be used as an indirection
- cell. This is checked by gc_init() during startup.
-
-*******************************************************************************/
-
-typedef struct hashtable_classloader_entry hashtable_classloader_entry;
-
-struct hashtable_classloader_entry {
- java_object_t *object;
- hashtable_classloader_entry *hashlink;
-};
-
-
-/* classloader *****************************************************************
-
- [!ENABLE_HANDLES]: The classloader is a Java Object which cannot move.
- [ENABLE_HANDLES] : The classloader entry itself is a static handle for a
- given classloader (use loader_hashtable_classloader_foo).
-
-*******************************************************************************/
-
-#if defined(ENABLE_HANDLES)
-typedef hashtable_classloader_entry classloader_t;
-#else
-typedef java_object_t classloader_t;
-#endif
-
-
-/* function prototypes ********************************************************/
-
-void loader_preinit(void);
-void loader_init(void);
-
-/* classloader management functions */
-classloader_t *loader_hashtable_classloader_add(java_handle_t *cl);
-classloader_t *loader_hashtable_classloader_find(java_handle_t *cl);
-
-void loader_load_all_classes(void);
-
-bool loader_skip_attribute_body(classbuffer *cb);
-
-#if defined(ENABLE_JAVASE)
-bool loader_load_attribute_signature(classbuffer *cb, utf **signature);
-#endif
-
-/* free resources */
-void loader_close(void);
-
-/* class loading functions */
-classinfo *load_class_from_sysloader(utf *name);
-classinfo *load_class_from_classloader(utf *name, classloader_t *cl);
-classinfo *load_class_bootstrap(utf *name);
-
-/* (don't use the following directly) */
-classinfo *load_class_from_classbuffer(classbuffer *cb);
-classinfo *load_newly_created_array(classinfo *c, classloader_t *loader);
-
-#endif /* _LOADER_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:
- */
+++ /dev/null
-/* src/vmcore/method.c - method 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 <stdint.h>
-#include <stdio.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/resolve.h"
-#include "vm/vm.h"
-
-#include "vm/jit/code.h"
-#include "vm/jit/methodheader.h"
-
-#include "vm/jit_interface.h"
-
-#include "vmcore/class.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
-#else
-#define INLINELOG(code)
-#endif
-
-
-/* global variables ***********************************************************/
-
-methodinfo *method_java_lang_reflect_Method_invoke;
-
-
-/* method_init *****************************************************************
-
- Initialize method subsystem.
-
-*******************************************************************************/
-
-void method_init(void)
-{
-#if defined(ENABLE_JAVASE)
- /* Sanity check. */
-
- if (class_java_lang_reflect_Method == NULL)
- vm_abort("method_init: class_java_lang_reflect_Method is NULL");
-
- /* Cache java.lang.reflect.Method.invoke() */
-
- method_java_lang_reflect_Method_invoke =
- class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
-
- if (method_java_lang_reflect_Method_invoke == NULL)
- vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
-#endif
-}
-
-
-/* method_load *****************************************************************
-
- Loads a method from the class file and fills an existing methodinfo
- structure.
-
- method_info {
- u2 access_flags;
- u2 name_index;
- u2 descriptor_index;
- u2 attributes_count;
- attribute_info attributes[attribute_count];
- }
-
- attribute_info {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
-
- LineNumberTable_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 line_number_table_length;
- {
- u2 start_pc;
- u2 line_number;
- } line_number_table[line_number_table_length];
- }
-
-*******************************************************************************/
-
-bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
-{
- classinfo *c;
- int argcount;
- s4 i, j, k, l;
- utf *u;
- u2 name_index;
- u2 descriptor_index;
- u2 attributes_count;
- u2 attribute_name_index;
- utf *attribute_name;
- u2 code_attributes_count;
- u2 code_attribute_name_index;
- utf *code_attribute_name;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- LOCK_INIT_OBJECT_LOCK(&(m->header));
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_all_methods++;
-#endif
-
- /* all fields of m have been zeroed in load_class_from_classbuffer */
-
- m->clazz = c;
-
- if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
- return false;
-
- /* access flags */
-
- m->flags = suck_u2(cb);
-
- /* name */
-
- name_index = suck_u2(cb);
-
- if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8)))
- return false;
-
- m->name = u;
-
- /* descriptor */
-
- descriptor_index = suck_u2(cb);
-
- if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
- return false;
-
- m->descriptor = u;
-
- if (!descriptor_pool_add(descpool, u, &argcount))
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (!is_valid_name_utf(m->name)) {
- exceptions_throw_classformaterror(c, "Method with invalid name");
- return false;
- }
-
- if (m->name->text[0] == '<' &&
- m->name != utf_init && m->name != utf_clinit) {
- exceptions_throw_classformaterror(c, "Method with invalid special name");
- return false;
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- if (!(m->flags & ACC_STATIC))
- argcount++; /* count the 'this' argument */
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (argcount > 255) {
- exceptions_throw_classformaterror(c, "Too many arguments in signature");
- return false;
- }
-
- /* check flag consistency */
- if (m->name != utf_clinit) {
- i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
-
- if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
- exceptions_throw_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
- return false;
- }
-
- if (m->flags & ACC_ABSTRACT) {
- if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
- ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
- exceptions_throw_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
- return false;
- }
- }
-
- if (c->flags & ACC_INTERFACE) {
- if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
- exceptions_throw_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
- return false;
- }
- }
-
- if (m->name == utf_init) {
- if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
- ACC_NATIVE | ACC_ABSTRACT)) {
- exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
- return false;
- }
- }
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- /* mark the method as monomorphic until further notice */
-
- m->flags |= ACC_METHOD_MONOMORPHIC;
-
- /* non-abstract methods have an implementation in this class */
-
- if (!(m->flags & ACC_ABSTRACT))
- m->flags |= ACC_METHOD_IMPLEMENTED;
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* attributes count */
-
- attributes_count = suck_u2(cb);
-
- for (i = 0; i < attributes_count; i++) {
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* attribute name index */
-
- 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_Code) {
- /* Code */
-
- if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
- exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
- return false;
- }
-
- if (m->jcode) {
- exceptions_throw_classformaterror(c, "Multiple Code attributes");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
- return false;
-
- suck_u4(cb);
- m->maxstack = suck_u2(cb);
- m->maxlocals = suck_u2(cb);
-
- if (m->maxlocals < argcount) {
- exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- m->jcodelength = suck_u4(cb);
-
- if (m->jcodelength == 0) {
- exceptions_throw_classformaterror(c, "Code of a method has length 0");
- return false;
- }
-
- if (m->jcodelength > 65535) {
- exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, m->jcodelength))
- return false;
-
- m->jcode = MNEW(u1, m->jcodelength);
- suck_nbytes(m->jcode, cb, m->jcodelength);
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- m->rawexceptiontablelength = suck_u2(cb);
- if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
- return false;
-
- m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- count_vmcode_len += m->jcodelength + 18;
- count_extable_len +=
- m->rawexceptiontablelength * sizeof(raw_exception_entry);
- }
-#endif
-
- for (j = 0; j < m->rawexceptiontablelength; j++) {
- u4 idx;
- m->rawexceptiontable[j].startpc = suck_u2(cb);
- m->rawexceptiontable[j].endpc = suck_u2(cb);
- m->rawexceptiontable[j].handlerpc = suck_u2(cb);
-
- idx = suck_u2(cb);
-
- if (!idx) {
- m->rawexceptiontable[j].catchtype.any = NULL;
- }
- else {
- /* the classref is created later */
- if (!(m->rawexceptiontable[j].catchtype.any =
- (utf *) class_getconstant(c, idx, CONSTANT_Class)))
- return false;
- }
- }
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* code attributes count */
-
- code_attributes_count = suck_u2(cb);
-
- for (k = 0; k < code_attributes_count; k++) {
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* code attribute name index */
-
- code_attribute_name_index = suck_u2(cb);
-
- code_attribute_name =
- class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
-
- if (code_attribute_name == NULL)
- return false;
-
- /* check which code attribute */
-
- if (code_attribute_name == utf_LineNumberTable) {
- /* LineNumberTable */
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* attribute length */
-
- (void) suck_u4(cb);
-
- /* line number table length */
-
- m->linenumbercount = suck_u2(cb);
-
- if (!suck_check_classbuffer_size(cb,
- (2 + 2) * m->linenumbercount))
- return false;
-
- m->linenumbers = MNEW(lineinfo, m->linenumbercount);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
-#endif
-
- for (l = 0; l < m->linenumbercount; l++) {
- m->linenumbers[l].start_pc = suck_u2(cb);
- m->linenumbers[l].line_number = suck_u2(cb);
- }
- }
-#if defined(ENABLE_JAVASE)
- else if (code_attribute_name == utf_StackMapTable) {
- /* StackTableMap */
-
- if (!stackmap_load_attribute_stackmaptable(cb, m))
- return false;
- }
-#endif
- else {
- /* unknown code attribute */
-
- if (!loader_skip_attribute_body(cb))
- return false;
- }
- }
- }
- else if (attribute_name == utf_Exceptions) {
- /* Exceptions */
-
- if (m->thrownexceptions != NULL) {
- exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* attribute length */
-
- (void) suck_u4(cb);
-
- m->thrownexceptionscount = suck_u2(cb);
-
- if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
- return false;
-
- m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
-
- for (j = 0; j < m->thrownexceptionscount; j++) {
- /* the classref is created later */
- if (!((m->thrownexceptions)[j].any =
- (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
- return false;
- }
- }
-#if defined(ENABLE_JAVASE)
- else if (attribute_name == utf_Signature) {
- /* Signature */
-
- if (!loader_load_attribute_signature(cb, &(m->signature)))
- return false;
- }
-
-#if defined(ENABLE_ANNOTATIONS)
- else if (attribute_name == utf_RuntimeVisibleAnnotations) {
- /* RuntimeVisibleAnnotations */
- if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
- /* RuntimeInvisibleAnnotations */
- if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
- /* RuntimeVisibleParameterAnnotations */
- if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
- /* RuntimeInvisibleParameterAnnotations */
- if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_AnnotationDefault) {
- /* AnnotationDefault */
- if (!annotation_load_method_attribute_annotationdefault(cb, m))
- return false;
- }
-#endif
-#endif
- else {
- /* unknown attribute */
-
- if (!loader_skip_attribute_body(cb))
- return false;
- }
- }
-
- if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
- exceptions_throw_classformaterror(c, "Missing Code attribute");
- return false;
- }
-
-#if defined(ENABLE_REPLACEMENT)
- /* initialize the hit countdown field */
-
- m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
-#endif
-
- /* everything was ok */
-
- return true;
-}
-
-
-/* method_free *****************************************************************
-
- Frees all memory that was allocated for this method.
-
-*******************************************************************************/
-
-void method_free(methodinfo *m)
-{
- if (m->jcode)
- MFREE(m->jcode, u1, m->jcodelength);
-
- if (m->rawexceptiontable)
- MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
-
- code_free_code_of_method(m);
-
- if (m->stubroutine) {
- if (m->flags & ACC_NATIVE) {
- removenativestub(m->stubroutine);
-
- } else {
- removecompilerstub(m->stubroutine);
- }
- }
-}
-
-
-/* method_canoverwrite *********************************************************
-
- Check if m and old are identical with respect to type and
- name. This means that old can be overwritten with m.
-
-*******************************************************************************/
-
-bool method_canoverwrite(methodinfo *m, methodinfo *old)
-{
- if (m->name != old->name)
- return false;
-
- if (m->descriptor != old->descriptor)
- return false;
-
- if (m->flags & ACC_STATIC)
- return false;
-
- return true;
-}
-
-
-/* method_new_builtin **********************************************************
-
- Creates a minimal methodinfo structure for builtins. This comes handy
- when dealing with builtin stubs or stacktraces.
-
-*******************************************************************************/
-
-methodinfo *method_new_builtin(builtintable_entry *bte)
-{
- methodinfo *m;
-
- /* allocate the methodinfo structure */
-
- m = NEW(methodinfo);
-
- /* initialize methodinfo structure */
-
- MZERO(m, methodinfo, 1);
- LOCK_INIT_OBJECT_LOCK(&(m->header));
-
- m->flags = ACC_METHOD_BUILTIN;
- m->parseddesc = bte->md;
- m->name = bte->name;
- m->descriptor = bte->descriptor;
-
- /* return the newly created methodinfo */
-
- return m;
-}
-
-
-/* method_vftbl_lookup *********************************************************
-
- Does a method lookup in the passed virtual function table. This
- function does exactly the same thing as JIT, but additionally
- relies on the fact, that the methodinfo pointer is at the first
- data segment slot (even for compiler stubs).
-
-*******************************************************************************/
-
-methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
-{
- methodptr mptr;
- methodptr *pmptr;
- methodinfo *resm; /* pointer to new resolved method */
-
- /* If the method is not an instance method, just return it. */
-
- if (m->flags & ACC_STATIC)
- return m;
-
- assert(vftbl);
-
- /* Get the method from the virtual function table. Is this an
- interface method? */
-
- if (m->clazz->flags & ACC_INTERFACE) {
- pmptr = vftbl->interfacetable[-(m->clazz->index)];
- mptr = pmptr[(m - m->clazz->methods)];
- }
- else {
- mptr = vftbl->table[m->vftblindex];
- }
-
- /* and now get the codeinfo pointer from the first data segment slot */
-
- resm = code_get_methodinfo_for_pv(mptr);
-
- return resm;
-}
-
-
-/* method_get_parametercount **************************************************
-
- Use the descriptor of a method to determine the number of parameters
- of the method. The this pointer of non-static methods is not counted.
-
- IN:
- m........the method of which the parameters should be counted
-
- RETURN VALUE:
- The parameter count or -1 on error.
-
-*******************************************************************************/
-
-int32_t method_get_parametercount(methodinfo *m)
-{
- methoddesc *md; /* method descriptor of m */
- int32_t paramcount = 0; /* the parameter count of m */
-
- md = m->parseddesc;
-
- /* is the descriptor fully parsed? */
-
- if (md->params == NULL) {
- if (!descriptor_params_from_paramtypes(md, m->flags)) {
- return -1;
- }
- }
-
- paramcount = md->paramcount;
-
- /* skip `this' pointer */
-
- if (!(m->flags & ACC_STATIC)) {
- --paramcount;
- }
-
- return paramcount;
-}
-
-
-/* method_get_parametertypearray ***********************************************
-
- Use the descriptor of a method to generate a java.lang.Class array
- which contains the classes of the parametertypes of the method.
-
- This function is called by java.lang.reflect.{Constructor,Method}.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
-{
- methoddesc *md;
- typedesc *paramtypes;
- int32_t paramcount;
- java_handle_objectarray_t *oa;
- int32_t i;
- classinfo *c;
-
- md = m->parseddesc;
-
- /* is the descriptor fully parsed? */
-
- if (m->parseddesc->params == NULL)
- if (!descriptor_params_from_paramtypes(md, m->flags))
- return NULL;
-
- paramtypes = md->paramtypes;
- paramcount = md->paramcount;
-
- /* skip `this' pointer */
-
- if (!(m->flags & ACC_STATIC)) {
- paramtypes++;
- paramcount--;
- }
-
- /* create class-array */
-
- oa = builtin_anewarray(paramcount, class_java_lang_Class);
-
- if (oa == NULL)
- return NULL;
-
- /* get classes */
-
- for (i = 0; i < paramcount; i++) {
- if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
- return NULL;
-
- LLNI_array_direct(oa, i) = (java_object_t *) c;
- }
-
- return oa;
-}
-
-
-/* method_get_exceptionarray ***************************************************
-
- Get the exceptions which can be thrown by a method.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
-{
- java_handle_objectarray_t *oa;
- classinfo *c;
- s4 i;
-
- /* create class-array */
-
- oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
-
- if (oa == NULL)
- return NULL;
-
- /* iterate over all exceptions and store the class in the array */
-
- for (i = 0; i < m->thrownexceptionscount; i++) {
- c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
-
- if (c == NULL)
- return NULL;
-
- LLNI_array_direct(oa, i) = (java_object_t *) c;
- }
-
- return oa;
-}
-
-
-/* method_returntype_get *******************************************************
-
- Get the return type of the method.
-
-*******************************************************************************/
-
-classinfo *method_returntype_get(methodinfo *m)
-{
- typedesc *td;
- classinfo *c;
-
- td = &(m->parseddesc->returntype);
-
- if (!resolve_class_from_typedesc(td, true, false, &c))
- return NULL;
-
- return c;
-}
-
-
-/* method_count_implementations ************************************************
-
- Count the implementations of a method in a class cone (a class and all its
- subclasses.)
-
- IN:
- m................the method to count
- c................class at which to start the counting (this class and
- all its subclasses will be searched)
-
- OUT:
- *found...........if found != NULL, *found receives the method
- implementation that was found. This value is only
- meaningful if the return value is 1.
-
- RETURN VALUE:
- the number of implementations found
-
-*******************************************************************************/
-
-s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
-{
- s4 count;
- methodinfo *mp;
- methodinfo *mend;
- classinfo *child;
-
- count = 0;
-
- mp = c->methods;
- mend = mp + c->methodscount;
-
- for (; mp < mend; ++mp) {
- if (method_canoverwrite(mp, m)) {
- if (found)
- *found = mp;
- count++;
- break;
- }
- }
-
- for (child = c->sub; child != NULL; child = child->nextsub) {
- count += method_count_implementations(m, child, found);
- }
-
- return count;
-}
-
-
-/* method_get_annotations ******************************************************
-
- Get a methods' unparsed annotations in a byte array.
-
- IN:
- m........the method of which the annotations should be returned
-
- RETURN VALUE:
- The unparsed annotations in a byte array (or NULL if there aren't any).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *method_get_annotations(methodinfo *m)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* methods' declaring class */
- int slot; /* methods' slot */
- java_handle_t *annotations; /* methods' unparsed annotations */
- java_handle_t *method_annotations; /* all methods' unparsed annotations */
- /* of the declaring class */
-
- c = m->clazz;
- slot = m - c->methods;
- annotations = NULL;
-
- LLNI_classinfo_field_get(c, method_annotations, method_annotations);
-
- /* the method_annotations array might be shorter then the method
- * count if the methods above a certain index have no annotations.
- */
- if (method_annotations != NULL &&
- array_length_get(method_annotations) > slot) {
- annotations = array_objectarray_element_get(
- (java_handle_objectarray_t*)method_annotations, slot);
- }
-
- return (java_handle_bytearray_t*)annotations;
-#else
- return NULL;
-#endif
-}
-
-
-/* method_get_parameterannotations ********************************************
-
- Get a methods' unparsed parameter annotations in an array of byte
- arrays.
-
- IN:
- m........the method of which the parameter annotations should be
- returned
-
- RETURN VALUE:
- The unparsed parameter annotations in a byte array (or NULL if
- there aren't any).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* methods' declaring class */
- int slot; /* methods' slot */
- java_handle_t *parameterAnnotations; /* methods' unparsed */
- /* parameter annotations */
- java_handle_t *method_parameterannotations; /* all methods' unparsed */
- /* parameter annotations of */
- /* the declaring class */
-
- c = m->clazz;
- slot = m - c->methods;
- parameterAnnotations = NULL;
-
- LLNI_classinfo_field_get(
- c, method_parameterannotations, method_parameterannotations);
-
- /* the method_annotations array might be shorter then the method
- * count if the methods above a certain index have no annotations.
- */
- if (method_parameterannotations != NULL &&
- array_length_get(method_parameterannotations) > slot) {
- parameterAnnotations = array_objectarray_element_get(
- (java_handle_objectarray_t*)method_parameterannotations,
- slot);
- }
-
- return (java_handle_bytearray_t*)parameterAnnotations;
-#else
- return NULL;
-#endif
-}
-
-
-/* method_get_annotationdefault ***********************************************
-
- Get a methods' unparsed annotation default value in a byte array.
-
- IN:
- m........the method of which the annotation default value should be
- returned
-
- RETURN VALUE:
- The unparsed annotation default value in a byte array (or NULL if
- there isn't one).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* methods' declaring class */
- int slot; /* methods' slot */
- java_handle_t *annotationDefault; /* methods' unparsed */
- /* annotation default value */
- java_handle_t *method_annotationdefaults; /* all methods' unparsed */
- /* annotation default values of */
- /* the declaring class */
-
- c = m->clazz;
- slot = m - c->methods;
- annotationDefault = NULL;
-
- LLNI_classinfo_field_get(
- c, method_annotationdefaults, method_annotationdefaults);
-
- /* the method_annotations array might be shorter then the method
- * count if the methods above a certain index have no annotations.
- */
- if (method_annotationdefaults != NULL &&
- array_length_get(method_annotationdefaults) > slot) {
- annotationDefault = array_objectarray_element_get(
- (java_handle_objectarray_t*)method_annotationdefaults, slot);
- }
-
- return (java_handle_bytearray_t*)annotationDefault;
-#else
- return NULL;
-#endif
-}
-
-
-/* method_add_to_worklist ******************************************************
-
- Add the method to the given worklist. If the method already occurs in
- the worklist, the worklist remains unchanged.
-
-*******************************************************************************/
-
-static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
-{
- method_worklist *wi;
-
- for (wi = *wl; wi != NULL; wi = wi->next)
- if (wi->m == m)
- return;
-
- wi = NEW(method_worklist);
- wi->next = *wl;
- wi->m = m;
-
- *wl = wi;
-}
-
-
-/* method_add_assumption_monomorphic *******************************************
-
- Record the assumption that the method is monomorphic.
-
- IN:
- m.................the method
- caller............the caller making the assumption
-
-*******************************************************************************/
-
-void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
-{
- method_assumption *as;
-
- /* XXX LOCKING FOR THIS FUNCTION? */
-
- /* check if we already have registered this assumption */
-
- for (as = m->assumptions; as != NULL; as = as->next) {
- if (as->context == caller)
- return;
- }
-
- /* register the assumption */
-
- as = NEW(method_assumption);
- as->next = m->assumptions;
- as->context = caller;
-
- m->assumptions = as;
-}
-
-
-/* method_break_assumption_monomorphic *****************************************
-
- Break the assumption that this method is monomorphic. All callers that
- have registered this assumption are added to the worklist.
-
- IN:
- m.................the method
- wl................worklist where to add invalidated callers
-
-*******************************************************************************/
-
-void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
-{
- method_assumption *as;
-
- /* XXX LOCKING FOR THIS FUNCTION? */
-
- for (as = m->assumptions; as != NULL; as = as->next) {
- INLINELOG(
- printf("ASSUMPTION BROKEN (monomorphism): ");
- method_print(m);
- printf(" in ");
- method_println(as->context);
- );
-
- method_add_to_worklist(as->context, wl);
- }
-}
-
-
-/* method_printflags ***********************************************************
-
- Prints the flags of a method to stdout like.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_printflags(methodinfo *m)
-{
- if (m == NULL) {
- printf("NULL");
- return;
- }
-
- if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
- if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
- if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
- if (m->flags & ACC_STATIC) printf(" STATIC");
- if (m->flags & ACC_FINAL) printf(" FINAL");
- if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
- if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
- if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
- if (m->flags & ACC_NATIVE) printf(" NATIVE");
- if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
- if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
- if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
- if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
- if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_print ****************************************************************
-
- Prints a method to stdout like:
-
- java.lang.Object.<init>()V
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_print(methodinfo *m)
-{
- if (m == NULL) {
- printf("NULL");
- return;
- }
-
- if (m->clazz != NULL)
- utf_display_printable_ascii_classname(m->clazz->name);
- else
- printf("NULL");
- printf(".");
- utf_display_printable_ascii(m->name);
- utf_display_printable_ascii(m->descriptor);
-
- method_printflags(m);
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_println **************************************************************
-
- Prints a method plus new line to stdout like:
-
- java.lang.Object.<init>()V
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_println(methodinfo *m)
-{
- if (opt_debugcolor) printf("\033[31m"); /* red */
- method_print(m);
- if (opt_debugcolor) printf("\033[m");
- printf("\n");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_methodref_print ******************************************************
-
- Prints a method reference to stdout.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_methodref_print(constant_FMIref *mr)
-{
- if (!mr) {
- printf("(constant_FMIref *)NULL");
- return;
- }
-
- if (IS_FMIREF_RESOLVED(mr)) {
- printf("<method> ");
- method_print(mr->p.method);
- }
- else {
- printf("<methodref> ");
- utf_display_printable_ascii_classname(mr->p.classref->name);
- printf(".");
- utf_display_printable_ascii(mr->name);
- utf_display_printable_ascii(mr->descriptor);
- }
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_methodref_println ****************************************************
-
- Prints a method reference to stdout, followed by a newline.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_methodref_println(constant_FMIref *mr)
-{
- method_methodref_print(mr);
- printf("\n");
-}
-#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/vmcore/method.h - method 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 _METHOD_H
-#define _METHOD_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct methodinfo methodinfo;
-typedef struct raw_exception_entry raw_exception_entry;
-typedef struct lineinfo lineinfo;
-typedef struct method_assumption method_assumption;
-typedef struct method_worklist method_worklist;
-typedef struct codeinfo codeinfo;
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/builtin.h"
-#include "vm/global.h"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/references.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-
-#if defined(ENABLE_JAVASE)
-# include "vmcore/stackmap.h"
-#endif
-
-#include "vmcore/utf8.h"
-
-
-#if defined(ENABLE_REPLACEMENT)
-/* Initial value for the hit countdown field of each method. */
-#define METHOD_INITIAL_HIT_COUNTDOWN 1000
-#endif
-
-
-/* methodinfo *****************************************************************/
-
-struct methodinfo { /* method structure */
- java_object_t header; /* we need this in jit's monitorenter */
- s4 flags; /* ACC flags */
- utf *name; /* name of method */
- utf *descriptor; /* JavaVM descriptor string of method */
-#if defined(ENABLE_JAVASE)
- utf *signature; /* Signature attribute */
- stack_map_t *stack_map; /* StackMapTable attribute */
-#endif
-
- methoddesc *parseddesc; /* parsed descriptor */
-
- classinfo *clazz; /* class, the method belongs to */
- s4 vftblindex; /* index of method in virtual function */
- /* table (if it is a virtual method) */
- s4 maxstack; /* maximum stack depth of method */
- s4 maxlocals; /* maximum number of local variables */
- s4 jcodelength; /* length of JavaVM code */
- u1 *jcode; /* pointer to JavaVM code */
-
- s4 rawexceptiontablelength; /* exceptiontable length */
- raw_exception_entry *rawexceptiontable; /* the exceptiontable */
-
- u2 thrownexceptionscount; /* number of exceptions attribute */
- classref_or_classinfo *thrownexceptions; /* except. a method may throw */
-
- u2 linenumbercount; /* number of linenumber attributes */
- lineinfo *linenumbers; /* array of lineinfo items */
-
- u1 *stubroutine; /* stub for compiling or calling natives */
- codeinfo *code; /* current code of this method */
-
-#if defined(ENABLE_LSRA)
- s4 maxlifetimes; /* helper for lsra */
-#endif
-
- methodinfo *overwrites; /* method that is directly overwritten */
- method_assumption *assumptions; /* list of assumptions about this method */
-
-#if defined(ENABLE_REPLACEMENT)
- s4 hitcountdown; /* decreased for each hit */
-#endif
-
-#if defined(ENABLE_DEBUG_FILTER)
- u1 filtermatches; /* flags indicating which filters the method matches */
-#endif
-
-#if defined(ENABLE_ESCAPE)
- u1 *paramescape;
-#endif
-};
-
-/* method_assumption ***********************************************************
-
- This struct is used for registering assumptions about methods.
-
-*******************************************************************************/
-
-struct method_assumption {
- method_assumption *next;
- methodinfo *context;
-};
-
-
-/* method_worklist *************************************************************
-
- List node used for method worklists.
-
-*******************************************************************************/
-
-struct method_worklist {
- method_worklist *next;
- methodinfo *m;
-};
-
-
-/* raw_exception_entry ********************************************************/
-
-/* exception table entry read by the loader */
-
-struct raw_exception_entry { /* exceptiontable entry in a method */
- classref_or_classinfo catchtype; /* catchtype of exc. (0 == catchall) */
- u2 startpc; /* start pc of guarded area (inclusive) */
- u2 endpc; /* end pc of guarded area (exklusive) */
- u2 handlerpc; /* pc of exception handler */
-};
-
-
-/* lineinfo *******************************************************************/
-
-struct lineinfo {
- u2 start_pc;
- u2 line_number;
-};
-
-
-/* global variables ***********************************************************/
-
-extern methodinfo *method_java_lang_reflect_Method_invoke;
-
-
-/* inline functions ***********************************************************/
-
-inline static bool method_is_builtin(methodinfo* m)
-{
- return m->flags & ACC_METHOD_BUILTIN;
-}
-
-
-/* function prototypes ********************************************************/
-
-void method_init(void);
-
-bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool);
-void method_free(methodinfo *m);
-bool method_canoverwrite(methodinfo *m, methodinfo *old);
-
-methodinfo *method_new_builtin(builtintable_entry *bte);
-
-methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m);
-
-int32_t method_get_parametercount(methodinfo *m);
-java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m);
-java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m);
-classinfo *method_returntype_get(methodinfo *m);
-
-void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller);
-void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl);
-
-s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found);
-
-java_handle_bytearray_t *method_get_annotations(methodinfo *m);
-java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m);
-java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m);
-
-#if !defined(NDEBUG)
-void method_printflags(methodinfo *m);
-void method_print(methodinfo *m);
-void method_println(methodinfo *m);
-void method_methodref_print(constant_FMIref *mr);
-void method_methodref_println(constant_FMIref *mr);
-#endif
-
-#endif /* _METHOD_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:
- */
+++ /dev/null
-/* src/vmcore/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/vm.h"
-
-#include "vmcore/options.h"
-#include "vmcore/system.h"
-
-
-/* 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_JITCACHE)
-bool opt_jitcache = false;
-bool opt_jitcache_details = 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_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_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_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 = system_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 = system_strlen(opts[i].name);
-
- if (system_strlen(option + 1) > l) {
- if (memcmp(option + 1, opts[i].name, l) == 0) {
- opt_index++;
- opt_arg = system_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;
- 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 = system_strlen(" -XX:+") + system_strlen(opt->name);
- break;
-
- case OPT_TYPE_VALUE:
- printf("%s=<value>", opt->name);
- length = system_strlen(" -XX:") + system_strlen(opt->name) +
- system_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 = system_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 = system_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 = system_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_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 = system_atoi(value);
- break;
-
- case OPT_InlineMaxSize:
- if (value != NULL)
- opt_InlineMaxSize = system_atoi(value);
- break;
-
- case OPT_InlineMinSize:
- if (value != NULL)
- opt_InlineMinSize = system_atoi(value);
- break;
-#endif
-#endif
-
- case OPT_PrintConfig:
- opt_PrintConfig = enable;
- break;
-
- case OPT_ProfileGCMemoryUsage:
- if (value == NULL)
- opt_ProfileGCMemoryUsage = 5;
- else
- opt_ProfileGCMemoryUsage = system_atoi(value);
- break;
-
- case OPT_ProfileMemoryUsage:
- if (value == NULL)
- opt_ProfileMemoryUsage = 5;
- else
- opt_ProfileMemoryUsage = system_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 = system_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 = system_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/vmcore/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"
-
-#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 {
- char *name;
- bool arg;
- int value;
-};
-
-
-typedef struct option_t option_t;
-
-struct option_t {
- char *name;
- int value;
- int type;
- 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_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
-
-#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/vmcore/primitivecore.c - core functions for primitive types
-
- 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.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "vm/global.h"
-#include "vm/primitive.h"
-#include "vm/vm.h"
-
-#include "vmcore/class.h"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
-
-/* primitivetype_table *********************************************************
-
- Structure for primitive classes: contains the class for wrapping
- the primitive type, the primitive class, the name of the class for
- wrapping, the one character type signature and the name of the
- primitive class.
-
- CAUTION: Don't change the order of the types. This table is indexed
- by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
-
-*******************************************************************************/
-
-primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
- { "int" , NULL, NULL, NULL, "java/lang/Integer", 'I', "[I", NULL },
- { "long" , NULL, NULL, NULL, "java/lang/Long", 'J', "[J", NULL },
- { "float" , NULL, NULL, NULL, "java/lang/Float", 'F', "[F", NULL },
- { "double" , NULL, NULL, NULL, "java/lang/Double", 'D', "[D", NULL },
- { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
- { "byte" , NULL, NULL, NULL, "java/lang/Byte", 'B', "[B", NULL },
- { "char" , NULL, NULL, NULL, "java/lang/Character", 'C', "[C", NULL },
- { "short" , NULL, NULL, NULL, "java/lang/Short", 'S', "[S", NULL },
- { "boolean" , NULL, NULL, NULL, "java/lang/Boolean", 'Z', "[Z", NULL },
- { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
-#if defined(ENABLE_JAVASE)
- { "void" , NULL, NULL, NULL, "java/lang/Void", 'V', NULL, NULL }
-#else
- { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
-#endif
-};
-
-
-/* primitive_init **************************************************************
-
- Fill the primitive type table with the primitive-type classes,
- array-classes and wrapper classes. This is important in the VM
- startup.
-
- We split this primitive-type table initialization because of
- annotations in the bootstrap classes.
-
- But we may get a problem if we have annotations in:
-
- java/lang/Object
- java/lang/Cloneable
- java/io/Serializable
-
- Also see: loader_preinit and linker_preinit.
-
-*******************************************************************************/
-
-void primitive_init(void)
-{
- utf *name;
- classinfo *c;
- utf *u;
- classinfo *ac;
- int i;
-
- TRACESUBSYSTEMINITIALIZATION("primitive_init");
-
- /* Load and link primitive-type classes and array-classes. */
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
- /* Skip dummy entries. */
-
- if (primitivetype_table[i].cname == NULL)
- continue;
-
- /* create UTF-8 name */
-
- name = utf_new_char(primitivetype_table[i].cname);
-
- primitivetype_table[i].name = name;
-
- /* create primitive class */
-
- c = class_create_classinfo(name);
-
- /* Primitive type classes don't have a super class. */
-
- c->super = NULL;
-
- /* set flags and mark it as primitive class */
-
- c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT | ACC_CLASS_PRIMITIVE;
-
- /* prevent loader from loading primitive class */
-
- c->state |= CLASS_LOADED;
-
- /* INFO: don't put primitive classes into the classcache */
-
- if (!link_class(c))
- vm_abort("linker_init: linking failed");
-
- /* Just to be sure. */
-
- assert(c->state & CLASS_LOADED);
- assert(c->state & CLASS_LINKED);
-
- primitivetype_table[i].class_primitive = c;
-
- /* Create primitive array class. */
-
- if (primitivetype_table[i].arrayname != NULL) {
- u = utf_new_char(primitivetype_table[i].arrayname);
- ac = class_create_classinfo(u);
- ac = load_newly_created_array(ac, NULL);
-
- if (ac == NULL)
- vm_abort("primitive_init: loading failed");
-
- assert(ac->state & CLASS_LOADED);
-
- if (!link_class(ac))
- vm_abort("primitive_init: linking failed");
-
- /* Just to be sure. */
-
- assert(ac->state & CLASS_LOADED);
- assert(ac->state & CLASS_LINKED);
-
- primitivetype_table[i].arrayclass = ac;
- }
- }
-
- /* We use two for-loops to have the array-classes already in the
- primitive-type table (hint: annotations in wrapper-classes). */
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
- /* Skip dummy entries. */
-
- if (primitivetype_table[i].cname == NULL)
- continue;
-
- /* Create class for wrapping the primitive type. */
-
- u = utf_new_char(primitivetype_table[i].wrapname);
- c = load_class_bootstrap(u);
-
- if (c == NULL)
- vm_abort("primitive_init: loading failed");
-
- if (!link_class(c))
- vm_abort("primitive_init: linking failed");
-
- /* Just to be sure. */
-
- assert(c->state & CLASS_LOADED);
- assert(c->state & CLASS_LINKED);
-
- primitivetype_table[i].class_wrap = c;
- }
-}
-
-
-/* primitive_postinit **********************************************************
-
- Finish the primitive-type table initialization. In this step we
- set the vftbl of the primitive-type classes.
-
- This is necessary because java/lang/Class is loaded and linked
- after the primitive types have been linked.
-
- We have to do that in an extra function, as the primitive types are
- not stored in the classcache.
-
-*******************************************************************************/
-
-void primitive_postinit(void)
-{
- classinfo *c;
- int i;
-
- TRACESUBSYSTEMINITIALIZATION("primitive_postinit");
-
- assert(class_java_lang_Class);
- assert(class_java_lang_Class->vftbl);
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
- /* Skip dummy entries. */
-
- if (primitivetype_table[i].cname == NULL)
- continue;
-
- c = primitivetype_table[i].class_primitive;
-
- c->object.header.vftbl = class_java_lang_Class->vftbl;
- }
-}
-
-
-/*
- * 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/vmcore/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/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
-#include "vmcore/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:
- */
-
+++ /dev/null
-/* src/vmcore/rt-timing.c - POSIX real-time timing utilities
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 <errno.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "vm/global.h"
-
-#include "vmcore/rt-timing.h"
-
-
-struct rt_timing_stat {
- int index;
- int totalindex;
- const char *name;
-};
-
-static struct rt_timing_stat rt_timing_stat_defs[] = {
- { RT_TIMING_JIT_CHECKS ,RT_TIMING_JIT_TOTAL , "checks at beginning" },
- { RT_TIMING_JIT_PARSE ,RT_TIMING_JIT_TOTAL , "parse" },
- { RT_TIMING_JIT_STACK ,RT_TIMING_JIT_TOTAL , "analyse_stack" },
- { RT_TIMING_JIT_TYPECHECK ,RT_TIMING_JIT_TOTAL , "typecheck" },
- { RT_TIMING_JIT_LOOP ,RT_TIMING_JIT_TOTAL , "loop" },
- { RT_TIMING_JIT_IFCONV ,RT_TIMING_JIT_TOTAL , "if conversion" },
- { RT_TIMING_JIT_ALLOC ,RT_TIMING_JIT_TOTAL , "register allocation" },
- { RT_TIMING_JIT_RPLPOINTS ,RT_TIMING_JIT_TOTAL , "replacement point generation" },
- { RT_TIMING_JIT_CODEGEN ,RT_TIMING_JIT_TOTAL , "codegen" },
- { RT_TIMING_JIT_TOTAL ,-1 , "total compile time" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_LINK_RESOLVE ,RT_TIMING_LINK_TOTAL, "link: resolve superclass/superinterfaces"},
- { RT_TIMING_LINK_C_VFTBL ,RT_TIMING_LINK_TOTAL, "link: compute vftbl length"},
- { RT_TIMING_LINK_ABSTRACT ,RT_TIMING_LINK_TOTAL, "link: handle abstract methods"},
- { RT_TIMING_LINK_C_IFTBL ,RT_TIMING_LINK_TOTAL, "link: compute interface table"},
- { RT_TIMING_LINK_F_VFTBL ,RT_TIMING_LINK_TOTAL, "link: fill vftbl"},
- { RT_TIMING_LINK_OFFSETS ,RT_TIMING_LINK_TOTAL, "link: set offsets"},
- { RT_TIMING_LINK_F_IFTBL ,RT_TIMING_LINK_TOTAL, "link: fill interface table"},
- { RT_TIMING_LINK_FINALIZER ,RT_TIMING_LINK_TOTAL, "link: set finalizer"},
- { RT_TIMING_LINK_EXCEPTS ,RT_TIMING_LINK_TOTAL, "link: resolve exception classes"},
- { RT_TIMING_LINK_SUBCLASS ,RT_TIMING_LINK_TOTAL, "link: re-calculate subclass indices"},
- { RT_TIMING_LINK_TOTAL ,-1 , "total link time" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_LOAD_CHECKS ,RT_TIMING_LOAD_TOTAL, "load: initial checks"},
- { RT_TIMING_LOAD_NDPOOL ,RT_TIMING_LOAD_TOTAL, "load: new descriptor pool"},
- { RT_TIMING_LOAD_CPOOL ,RT_TIMING_LOAD_TOTAL, "load: load constant pool"},
- { RT_TIMING_LOAD_SETUP ,RT_TIMING_LOAD_TOTAL, "load: class setup"},
- { RT_TIMING_LOAD_FIELDS ,RT_TIMING_LOAD_TOTAL, "load: load fields"},
- { RT_TIMING_LOAD_METHODS ,RT_TIMING_LOAD_TOTAL, "load: load methods"},
- { RT_TIMING_LOAD_CLASSREFS ,RT_TIMING_LOAD_TOTAL, "load: create classrefs"},
- { RT_TIMING_LOAD_DESCS ,RT_TIMING_LOAD_TOTAL, "load: allocate descriptors"},
- { RT_TIMING_LOAD_SETREFS ,RT_TIMING_LOAD_TOTAL, "load: set classrefs"},
- { RT_TIMING_LOAD_PARSEFDS ,RT_TIMING_LOAD_TOTAL, "load: parse field descriptors"},
- { RT_TIMING_LOAD_PARSEMDS ,RT_TIMING_LOAD_TOTAL, "load: parse method descriptors"},
- { RT_TIMING_LOAD_PARSECP ,RT_TIMING_LOAD_TOTAL, "load: parse descriptors in constant pool"},
- { RT_TIMING_LOAD_VERIFY ,RT_TIMING_LOAD_TOTAL, "load: verifier checks"},
- { RT_TIMING_LOAD_ATTRS ,RT_TIMING_LOAD_TOTAL, "load: load attributes"},
- { RT_TIMING_LOAD_TOTAL ,-1 , "total load time (from classbuffer)"},
- { -1 ,-1 , "" },
-
- { RT_TIMING_LOAD_BOOT_LOOKUP,-1 , "boot: lookup in classcache"},
- { RT_TIMING_LOAD_BOOT_ARRAY ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load array classes"},
- { RT_TIMING_LOAD_BOOT_SUCK ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: suck class files"},
- { RT_TIMING_LOAD_BOOT_LOAD ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load from class buffer"},
- { RT_TIMING_LOAD_BOOT_CACHE ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: store in classcache"},
- { RT_TIMING_LOAD_BOOT_TOTAL ,-1 , "total bootstrap loader time"},
- { -1 ,-1 , "" },
-
- { RT_TIMING_LOAD_CL_LOOKUP ,-1 , "classloader: lookup in classcache" },
- { RT_TIMING_LOAD_CL_PREPARE ,-1 , "classloader: prepare loader call" },
- { RT_TIMING_LOAD_CL_JAVA ,-1 , "classloader: loader Java code" },
- { RT_TIMING_LOAD_CL_CACHE ,-1 , "classloader: store in classcache" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_NEW_OBJECT ,-1 , "builtin_new time" },
- { RT_TIMING_NEW_ARRAY ,-1 , "builtin_newarray time" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_GC_ALLOC ,-1 , "heap allocation time" },
-#if defined(ENABLE_GC_CACAO)
- { RT_TIMING_GC_SUSPEND ,RT_TIMING_GC_TOTAL , "gc: suspending threads" },
- { RT_TIMING_GC_ROOTSET1 ,RT_TIMING_GC_TOTAL , "gc: rootset finding" },
- { RT_TIMING_GC_MARK ,RT_TIMING_GC_TOTAL , "gc: marking phase" },
- { RT_TIMING_GC_COMPACT ,RT_TIMING_GC_TOTAL , "gc: compaction phase" },
- { RT_TIMING_GC_ROOTSET2 ,RT_TIMING_GC_TOTAL , "gc: rootset writeback" },
- { RT_TIMING_GC_TOTAL ,-1 , "total garbage collection time" },
- { -1 ,-1 , "" },
-#endif
-
- { 0 ,-1 , NULL }
-};
-
-static long long rt_timing_sum[RT_TIMING_N] = { 0 };
-
-void rt_timing_gettime(struct timespec *ts)
-{
- if (clock_gettime(CLOCK_THREAD_CPUTIME_ID,ts) != 0) {
- fprintf(stderr,"could not get time by clock_gettime: %s\n",strerror(errno));
- abort();
- }
-}
-
-long rt_timing_diff_usec(struct timespec *a,struct timespec *b)
-{
- long diff;
- time_t atime;
-
- diff = (b->tv_nsec - a->tv_nsec) / 1000;
- atime = a->tv_sec;
- while (atime < b->tv_sec) {
- atime++;
- diff += 1000000;
- }
- return diff;
-}
-
-void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index)
-{
- long diff;
-
- diff = rt_timing_diff_usec(a,b);
- rt_timing_sum[index] += diff;
-}
-
-void rt_timing_print_time_stats(FILE *file)
-{
- struct rt_timing_stat *stats;
- double total;
-
- for (stats = rt_timing_stat_defs; stats->name; ++stats) {
- if (stats->index < 0) {
- fprintf(file,"%s\n",stats->name);
- continue;
- }
-
- if (stats->totalindex >= 0) {
- total = rt_timing_sum[stats->totalindex];
- fprintf(file,"%12lld usec %3.0f%% %s\n",
- rt_timing_sum[stats->index],
- (total != 0.0) ? rt_timing_sum[stats->index] / total * 100.0 : 0.0,
- stats->name);
- }
- else {
- fprintf(file,"%12lld usec %s\n",
- rt_timing_sum[stats->index],
- stats->name);
- }
- }
-}
-
-/*
- * 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/vmcore/rt-timing.h - POSIX real-time timing utilities
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _RT_TIMING_H
-#define _RT_TIMING_H
-
-#include "config.h"
-
-#if defined(ENABLE_RT_TIMING)
-
-#include <time.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "vm/global.h"
-
-
-#define RT_TIMING_GET_TIME(ts) \
- rt_timing_gettime(&(ts));
-
-#define RT_TIMING_TIME_DIFF(a,b,index) \
- rt_timing_time_diff(&(a),&(b),(index));
-
-#define RT_TIMING_JIT_CHECKS 0
-#define RT_TIMING_JIT_PARSE 1
-#define RT_TIMING_JIT_STACK 2
-#define RT_TIMING_JIT_TYPECHECK 3
-#define RT_TIMING_JIT_LOOP 4
-#define RT_TIMING_JIT_IFCONV 5
-#define RT_TIMING_JIT_ALLOC 6
-#define RT_TIMING_JIT_RPLPOINTS 7
-#define RT_TIMING_JIT_CODEGEN 8
-#define RT_TIMING_JIT_TOTAL 9
-
-#define RT_TIMING_LINK_RESOLVE 10
-#define RT_TIMING_LINK_C_VFTBL 11
-#define RT_TIMING_LINK_ABSTRACT 12
-#define RT_TIMING_LINK_C_IFTBL 13
-#define RT_TIMING_LINK_F_VFTBL 14
-#define RT_TIMING_LINK_OFFSETS 15
-#define RT_TIMING_LINK_F_IFTBL 16
-#define RT_TIMING_LINK_FINALIZER 17
-#define RT_TIMING_LINK_EXCEPTS 18
-#define RT_TIMING_LINK_SUBCLASS 19
-#define RT_TIMING_LINK_TOTAL 20
-
-#define RT_TIMING_LOAD_CHECKS 21
-#define RT_TIMING_LOAD_NDPOOL 22
-#define RT_TIMING_LOAD_CPOOL 23
-#define RT_TIMING_LOAD_SETUP 24
-#define RT_TIMING_LOAD_FIELDS 25
-#define RT_TIMING_LOAD_METHODS 26
-#define RT_TIMING_LOAD_CLASSREFS 27
-#define RT_TIMING_LOAD_DESCS 28
-#define RT_TIMING_LOAD_SETREFS 29
-#define RT_TIMING_LOAD_PARSEFDS 30
-#define RT_TIMING_LOAD_PARSEMDS 31
-#define RT_TIMING_LOAD_PARSECP 32
-#define RT_TIMING_LOAD_VERIFY 33
-#define RT_TIMING_LOAD_ATTRS 34
-#define RT_TIMING_LOAD_TOTAL 35
-
-#define RT_TIMING_LOAD_BOOT_LOOKUP 36
-#define RT_TIMING_LOAD_BOOT_ARRAY 37
-#define RT_TIMING_LOAD_BOOT_SUCK 38
-#define RT_TIMING_LOAD_BOOT_LOAD 39
-#define RT_TIMING_LOAD_BOOT_CACHE 40
-#define RT_TIMING_LOAD_BOOT_TOTAL 41
-
-#define RT_TIMING_LOAD_CL_LOOKUP 42
-#define RT_TIMING_LOAD_CL_PREPARE 43
-#define RT_TIMING_LOAD_CL_JAVA 44
-#define RT_TIMING_LOAD_CL_CACHE 45
-
-#define RT_TIMING_NEW_OBJECT 46
-#define RT_TIMING_NEW_ARRAY 47
-
-#define RT_TIMING_GC_ALLOC 48
-#define RT_TIMING_GC_SUSPEND 49
-#define RT_TIMING_GC_ROOTSET1 50
-#define RT_TIMING_GC_MARK 51
-#define RT_TIMING_GC_COMPACT 52
-#define RT_TIMING_GC_ROOTSET2 53
-#define RT_TIMING_GC_TOTAL 54
-
-#define RT_TIMING_N 55
-
-void rt_timing_gettime(struct timespec *ts);
-
-void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index);
-
-long rt_timing_diff_usec(struct timespec *a,struct timespec *b);
-
-void rt_timing_print_time_stats(FILE *file);
-
-#else /* !defined(ENABLE_RT_TIMING) */
-
-#define RT_TIMING_GET_TIME(ts)
-#define RT_TIMING_TIME_DIFF(a,b,index)
-
-#endif /* defined(ENABLE_RT_TIMING) */
-
-#endif /* _RT_TIMING_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:
- */
+++ /dev/null
-/* src/vmcore/stackmap.c - class attribute StackMapTable
-
- Copyright (C) 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 "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "vm/exceptions.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/stackmap.h"
-#include "vmcore/statistics.h"
-#include "vmcore/suck.h"
-
-
-/* stackmap_get_verification_type_info *****************************************
-
- union verification_type_info {
- Top_variable_info;
- Integer_variable_info;
- Float_variable_info;
- Long_variable_info;
- Double_variable_info;
- Null_variable_info;
- UninitializedThis_variable_info;
- Object_variable_info;
- Uninitialized_variable_info;
- }
-
- Top_variable_info {
- u1 tag = ITEM_Top; // 0
- }
-
- Integer_variable_info {
- u1 tag = ITEM_Integer; // 1
- }
-
- Float_variable_info {
- u1 tag = ITEM_Float; // 2
- }
-
- Long_variable_info {
- u1 tag = ITEM_Long; // 4
- }
-
- Double_variable_info {
- u1 tag = ITEM_Double; // 3
- }
-
- Null_variable_info {
- u1 tag = ITEM_Null; // 5
- }
-
- UninitializedThis_variable_info {
- u1 tag = ITEM_UninitializedThis; // 6
- }
-
- Object_variable_info {
- u1 tag = ITEM_Object; // 7
- u2 cpool_index;
- }
-
- Uninitialized_variable_info {
- u1 tag = ITEM_Uninitialized; // 8
- u2 offset;
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
-{
- /* get verification type */
-
- if (!suck_check_classbuffer_size(cb, 1))
- return false;
-
- verification_type_info->tag = suck_u1(cb);
-
- /* process the tag */
-
- switch (verification_type_info->tag) {
- case ITEM_Top:
- case ITEM_Integer:
- case ITEM_Float:
- case ITEM_Long:
- case ITEM_Double:
- case ITEM_Null:
- case ITEM_UninitializedThis:
- break;
-
- case ITEM_Object:
- /* get constant pool index */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
- break;
-
- case ITEM_Uninitialized:
- /* get offset */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
- break;
- }
-
- return true;
-}
-
-
-/* stackmap_get_same_locals_1_stack_item_frame *********************************
-
- same_locals_1_stack_item_frame {
- u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
- verification_type_info stack[1];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
-{
- same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
-
- /* for convenience */
-
- same_locals_1_stack_item_frame =
- &(stack_map_frame->same_locals_1_stack_item_frame);
-
- if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_get_same_locals_1_stack_item_frame_extended ************************
-
- same_locals_1_stack_item_frame_extended {
- u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
- u2 offset_delta;
- verification_type_info stack[1];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
-{
- same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
-
- /* for convenience */
-
- same_locals_1_stack_item_frame_extended =
- &(stack_map_frame->same_locals_1_stack_item_frame_extended);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
-
- /* process stack */
-
- if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_get_chop_frame *****************************************************
-
- chop_frame {
- u1 frame_type = CHOP_FRAME; // 248-250
- u2 offset_delta;
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_chop_frame(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- chop_frame_t *chop_frame;
-
- /* for convenience */
-
- chop_frame = &(stack_map_frame->chop_frame);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- chop_frame->offset_delta = suck_u2(cb);
-
- return true;
-}
-
-
-/* stackmap_get_same_frame_extended ********************************************
-
- same_frame_extended {
- u1 frame_type = SAME_FRAME_EXTENDED; // 251
- u2 offset_delta;
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_same_frame_extended(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- same_frame_extended_t *same_frame_extended;
-
- /* for convenience */
-
- same_frame_extended = &(stack_map_frame->same_frame_extended);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- same_frame_extended->offset_delta = suck_u2(cb);
-
- return true;
-}
-
-
-/* stackmap_get_append_frame ***************************************************
-
- append_frame {
- u1 frame_type = APPEND_FRAME; // 252-254
- u2 offset_delta;
- verification_type_info locals[frame_Type - 251];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_append_frame(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- append_frame_t *append_frame;
- s4 number_of_locals;
- s4 i;
-
- /* for convenience */
-
- append_frame = &(stack_map_frame->append_frame);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- append_frame->offset_delta = suck_u2(cb);
-
- /* allocate locals array */
-
- number_of_locals = append_frame->frame_type - 251;
-
- append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
-
- /* process all locals */
-
- for (i = 0; i < number_of_locals; i++)
- if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_get_full_frame *****************************************************
-
- full_frame {
- u1 frame_type = FULL_FRAME;
- u2 offset_delta;
- u2 number_of_locals;
- verification_type_info locals[number_of_locals];
- u2 number_of_stack_items;
- verification_type_info stack[number_of_stack_items];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_full_frame(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- full_frame_t *full_frame;
- s4 i;
-
- /* for convenience */
-
- full_frame = &(stack_map_frame->full_frame);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* get offset delta */
-
- stack_map_frame->full_frame.offset_delta = suck_u2(cb);
-
- /* get number of locals */
-
- full_frame->number_of_locals = suck_u2(cb);
-
- /* allocate locals array */
-
- full_frame->locals =
- DMNEW(verification_type_info_t, full_frame->number_of_locals);
-
- /* process all locals */
-
- for (i = 0; i < full_frame->number_of_locals; i++)
- if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
- return false;
-
- /* get number of stack items */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- full_frame->number_of_stack_items = suck_u2(cb);
-
- /* allocate stack array */
-
- full_frame->stack =
- DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
-
- /* process all stack items */
-
- for (i = 0; i < full_frame->number_of_stack_items; i++)
- if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_load_attribute_stackmaptable ***************************************
-
- stack_map {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 number_of_entries;
- stack_map_frame entries[number_of_entries];
- }
-
- union stack_map_frame {
- same_frame;
- same_locals_1_stack_item_frame;
- same_locals_1_stack_item_frame_extended;
- chop_frame;
- same_frame_extended;
- append_frame;
- full_frame;
- }
-
- same_frame {
- u1 frame_type = SAME; // 0-63
- }
-
-*******************************************************************************/
-
-bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
-{
- classinfo *c;
- stack_map_t *stack_map;
- s4 i;
- u1 frame_type;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- /* allocate stack map structure */
-
- stack_map = DNEW(stack_map_t);
-
- STATISTICS(size_stack_map += sizeof(stack_map_t));
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* attribute_length */
-
- stack_map->attribute_length = suck_u4(cb);
-
- if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
- return false;
-
- /* get number of entries */
-
- stack_map->number_of_entries = suck_u2(cb);
-
- /* process all entries */
-
- stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
-
- for (i = 0; i < stack_map->number_of_entries; i++) {
- /* get the frame type */
-
- frame_type = suck_u1(cb);
-
- stack_map->entries[i].frame_type = frame_type;
-
- /* process frame */
-
- if (frame_type <= FRAME_TYPE_SAME) {
- /* same_frame */
- }
- else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
- /* same_locals_1_stack_item_frame */
-
- if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type <= FRAME_TYPE_RESERVED) {
- /* reserved */
-
- exceptions_throw_classformaterror(c, "reserved frame type");
- return false;
- }
- else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
- /* same_locals_1_stack_item_frame_extended */
-
- if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type <= FRAME_TYPE_CHOP) {
- /* chop_frame */
-
- if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
- /* same_frame_extended */
-
- if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type <= FRAME_TYPE_APPEND) {
- /* append_frame */
-
- if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type == FRAME_TYPE_FULL_FRAME) {
- /* full_frame */
-
- if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- }
-
- /* store stack map in method structure */
-
-#if 0
- /* currently not used */
-
- m->stack_map = stack_map;
-#endif
-
- return true;
-}
-
-
-/*
- * 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/vmcore/stackmap.h - class attribute StackMapTable
-
- Copyright (C) 2006, 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
-
- 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 _STACKMAP_H
-#define _STACKMAP_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct stack_map_t stack_map_t;
-typedef union stack_map_frame_t stack_map_frame_t;
-typedef struct same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame_t;
-typedef struct same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended_t;
-typedef struct chop_frame_t chop_frame_t;
-typedef struct same_frame_extended_t same_frame_extended_t;
-typedef struct append_frame_t append_frame_t;
-typedef struct full_frame_t full_frame_t;
-
-typedef union verification_type_info_t verification_type_info_t;
-typedef struct Top_variable_info_t Top_variable_info_t;
-typedef struct Integer_variable_info_t Integer_variable_info_t;
-typedef struct Float_variable_info_t Float_variable_info_t;
-typedef struct Long_variable_info_t Long_variable_info_t;
-typedef struct Double_variable_info_t Double_variable_info_t;
-typedef struct Null_variable_info_t Null_variable_info_t;
-typedef struct UninitializedThis_variable_info_t UninitializedThis_variable_info_t;
-typedef struct Object_variable_info_t Object_variable_info_t;
-typedef struct Uninitialized_variable_info_t Uninitialized_variable_info_t;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-
-
-/* verification_type_info *****************************************************/
-
-#define ITEM_Top 0
-#define ITEM_Integer 1
-#define ITEM_Float 2
-#define ITEM_Double 3
-#define ITEM_Long 4
-#define ITEM_Null 5
-#define ITEM_UninitializedThis 6
-#define ITEM_Object 7
-#define ITEM_Uninitialized 8
-
-struct Top_variable_info_t {
- u1 tag;
-};
-
-struct Integer_variable_info_t {
- u1 tag;
-};
-
-struct Float_variable_info_t {
- u1 tag;
-};
-
-struct Long_variable_info_t {
- u1 tag;
-};
-
-struct Double_variable_info_t {
- u1 tag;
-};
-
-struct Null_variable_info_t {
- u1 tag;
-};
-
-struct UninitializedThis_variable_info_t {
- u1 tag;
-};
-
-struct Object_variable_info_t {
- u1 tag;
- u2 cpool_index;
-};
-
-struct Uninitialized_variable_info_t {
- u1 tag;
- u2 offset;
-};
-
-union verification_type_info_t {
- u1 tag;
- Top_variable_info_t Top_variable_info;
- Integer_variable_info_t Integer_variable_info;
- Float_variable_info_t Float_variable_info;
- Long_variable_info_t Long_variable_info;
- Double_variable_info_t Double_variable_info;
- Null_variable_info_t Null_variable_info;
- UninitializedThis_variable_info_t UninitializedThis_variable_info;
- Object_variable_info_t Object_variable_info;
- Uninitialized_variable_info_t Uninitialized_variable_info;
-};
-
-
-/* stack_map_t ****************************************************************/
-
-struct stack_map_t {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 number_of_entries;
- stack_map_frame_t *entries;
-};
-
-
-/* same_locals_1_stack_item_frame_t *******************************************/
-
-struct same_locals_1_stack_item_frame_t {
- u1 frame_type;
- verification_type_info_t stack[1];
-};
-
-
-/* same_locals_1_stack_item_frame_extended_t **********************************/
-
-struct same_locals_1_stack_item_frame_extended_t {
- u1 frame_type;
- u2 offset_delta;
- verification_type_info_t stack[1];
-};
-
-
-/* chop_frame_t ***************************************************************/
-
-struct chop_frame_t {
- u1 frame_type;
- u2 offset_delta;
-};
-
-
-/* same_frame_extended_t ******************************************************/
-
-struct same_frame_extended_t {
- u1 frame_type;
- u2 offset_delta;
-};
-
-
-/* append_frame_t *************************************************************/
-
-struct append_frame_t {
- u1 frame_type;
- u2 offset_delta;
- verification_type_info_t *locals;
-};
-
-
-/* full_frame_t ***************************************************************/
-
-struct full_frame_t {
- u1 frame_type;
- u2 offset_delta;
- u2 number_of_locals;
- verification_type_info_t *locals;
- u2 number_of_stack_items;
- verification_type_info_t *stack;
-};
-
-
-/* stack_map_frame_t **********************************************************/
-
-#define FRAME_TYPE_SAME 63 /* 0-63 */
-#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM 127 /* 0-127 */
-#define FRAME_TYPE_RESERVED 246 /* 128-246 */
-#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED 247 /* 247 */
-#define FRAME_TYPE_CHOP 250 /* 248-250 */
-#define FRAME_TYPE_SAME_FRAME_EXTENDED 251 /* 251 */
-#define FRAME_TYPE_APPEND 254 /* 252-254 */
-#define FRAME_TYPE_FULL_FRAME 255 /* 255 */
-
-union stack_map_frame_t {
- u1 frame_type;
- same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame;
- same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended;
- chop_frame_t chop_frame;
- same_frame_extended_t same_frame_extended;
- append_frame_t append_frame;
- full_frame_t full_frame;
-};
-
-
-/* function prototypes ********************************************************/
-
-bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m);
-
-#endif /* _STACKMAP_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:
- */
+++ /dev/null
-/* src/vmcore/statistics.c - global varables for statistics
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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-common.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/global.h"
-
-#include "vm/jit/code.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.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/vmcore/statistics.h - exports global varables for statistics
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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/vmcore/suck.c - functions to read LE ordered types from a buffer
-
- 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 <stdlib.h>
-
-#include "vm/types.h"
-
-#include "arch.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/list.h"
-#include "toolbox/logging.h"
-#include "toolbox/util.h"
-
-#include "vm/exceptions.h"
-#include "vm/properties.h"
-#include "vm/vm.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/suck.h"
-#include "vmcore/system.h"
-#include "vmcore/zip.h"
-
-
-/* global variables ***********************************************************/
-
-list_t *list_classpath_entries;
-
-
-/* suck_init *******************************************************************
-
- Initializes the suck subsystem like initializing the classpath
- entries list.
-
-*******************************************************************************/
-
-bool suck_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("suck_init");
-
- list_classpath_entries = list_create(OFFSET(list_classpath_entry, linkage));
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* scandir_filter **************************************************************
-
- Filters for zip/jar files.
-
-*******************************************************************************/
-
-#if defined(__LINUX__)
-static int scandir_filter(const struct dirent *a)
-#else
-static int scandir_filter(struct dirent *a)
-#endif
-{
- s4 namlen;
-
-#if defined(_DIRENT_HAVE_D_NAMLEN)
- namlen = a->d_namlen;
-#else
- namlen = strlen(a->d_name);
-#endif
-
- if ((strncasecmp(a->d_name + namlen - 4, ".zip", 4) == 0) ||
- (strncasecmp(a->d_name + namlen - 4, ".jar", 4) == 0))
- return 1;
-
- return 0;
-}
-
-
-/* suck_add ********************************************************************
-
- Adds a classpath to the global classpath entries list.
-
-*******************************************************************************/
-
-void suck_add(char *classpath)
-{
- list_classpath_entry *lce;
- char *start;
- char *end;
- char *filename;
- s4 filenamelen;
- bool is_zip;
- char *cwd;
- s4 cwdlen;
-#if defined(ENABLE_ZLIB)
- hashtable *ht;
-#endif
-
- /* parse the classpath string */
-
- for (start = classpath; (*start) != '\0'; ) {
-
- /* search for ':' delimiter to get the end of the current entry */
- for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
-
- if (start != end) {
- is_zip = false;
- filenamelen = end - start;
-
- if (filenamelen > 4) {
- if ((strncasecmp(end - 4, ".zip", 4) == 0) ||
- (strncasecmp(end - 4, ".jar", 4) == 0)) {
- is_zip = true;
- }
- }
-
- /* save classpath entries as absolute pathnames */
-
- cwd = NULL;
- cwdlen = 0;
-
- if (*start != '/') { /* XXX fix me for win32 */
- cwd = _Jv_getcwd();
- cwdlen = strlen(cwd) + strlen("/");
- }
-
- /* allocate memory for filename and fill it */
-
- filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
- strlen("0"));
-
- if (cwd) {
- strcpy(filename, cwd);
- strcat(filename, "/");
- strncat(filename, start, filenamelen);
-
- /* add cwd length to file length */
- filenamelen += cwdlen;
-
- } else {
- strncpy(filename, start, filenamelen);
- filename[filenamelen] = '\0';
- }
-
- lce = NULL;
-
- if (is_zip) {
-#if defined(ENABLE_ZLIB)
- ht = zip_open(filename);
-
- if (ht != NULL) {
- lce = NEW(list_classpath_entry);
-
- lce->type = CLASSPATH_ARCHIVE;
- lce->htclasses = ht;
- lce->path = filename;
- lce->pathlen = filenamelen;
-
- /* SUN compatible -verbose:class output */
-
- if (opt_verboseclass)
- printf("[Opened %s]\n", filename);
- }
-
-#else
- vm_abort("suck_add: zip/jar files not supported");
-#endif
- }
- else {
- if (filename[filenamelen - 1] != '/') {/* XXX fixme for win32 */
- filename[filenamelen] = '/';
- filename[filenamelen + 1] = '\0';
- filenamelen++;
- }
-
- lce = NEW(list_classpath_entry);
-
- lce->type = CLASSPATH_PATH;
- lce->path = filename;
- lce->pathlen = filenamelen;
- }
-
- /* add current classpath entry, if no error */
-
- if (lce != NULL)
- list_add_last(list_classpath_entries, lce);
- }
-
- /* goto next classpath entry, skip ':' delimiter */
-
- if ((*end) == ':')
- start = end + 1;
- else
- start = end;
- }
-}
-
-
-/* suck_add_from_property ******************************************************
-
- Adds a classpath form a property entry to the global classpath
- entries list.
-
-*******************************************************************************/
-
-void suck_add_from_property(char *key)
-{
- char *value;
- char *start;
- char *end;
- char *path;
- s4 pathlen;
- struct dirent **namelist;
- s4 n;
- s4 i;
- s4 namlen;
- char *boot_class_path;
- char *p;
-
- /* get the property value */
-
- value = properties_get(key);
-
- if (value == NULL)
- return;
-
- /* get the directory entries of the property */
-
- for (start = value; (*start) != '\0'; ) {
-
- /* search for ':' delimiter to get the end of the current entry */
-
- for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
-
- /* found an entry */
-
- if (start != end) {
- /* allocate memory for the path entry */
-
- pathlen = end - start;
- path = MNEW(char, pathlen + strlen("0"));
-
- /* copy and terminate the string */
-
- strncpy(path, start, pathlen);
- path[pathlen] = '\0';
-
- /* Reset namelist to NULL for the freeing in an error case
- (see below). */
-
- namelist = NULL;
-
- /* scan the directory found for zip/jar files */
-
- n = system_scandir(path, &namelist, scandir_filter, alphasort);
-
- /* On error, just continue, this should be ok. */
-
- if (n > 0) {
- for (i = 0; i < n; i++) {
-#if defined(_DIRENT_HAVE_D_NAMLEN)
- namlen = namelist[i]->d_namlen;
-#else
- namlen = strlen(namelist[i]->d_name);
-#endif
-
- /* Allocate memory for bootclasspath. */
-
- boot_class_path = properties_get("sun.boot.class.path");
-
- p = MNEW(char,
- pathlen + strlen("/") + namlen +
- strlen(":") +
- strlen(boot_class_path) +
- strlen("0"));
-
- /* Prepend the file found to the bootclasspath. */
-
- strcpy(p, path);
- strcat(p, "/");
- strcat(p, namelist[i]->d_name);
- 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, strlen(boot_class_path));
-
- /* free the memory allocated by scandir */
- /* (We use `free` as the memory came from the C library.) */
-
- free(namelist[i]);
- }
- }
-
- /* On some systems (like Linux) when n == 0, then namelist
- returned from scnadir is NULL, thus we don't have to
- free it.
- (Use `free` as the memory came from the C library.) */
-
- if (namelist != NULL)
- free(namelist);
-
- MFREE(path, char, pathlen + strlen("0"));
- }
-
- /* goto next entry, skip ':' delimiter */
-
- if ((*end) == ':')
- start = end + 1;
- else
- start = end;
- }
-}
-
-
-/* suck_check_classbuffer_size *************************************************
-
- Assert that at least <len> bytes are left to read <len> is limited
- to the range of non-negative s4 values.
-
-*******************************************************************************/
-
-bool suck_check_classbuffer_size(classbuffer *cb, s4 len)
-{
-#ifdef ENABLE_VERIFIER
- if (len < 0 || ((cb->data + cb->size) - cb->pos) < len) {
- exceptions_throw_classformaterror(cb->clazz, "Truncated class file");
- return false;
- }
-#endif /* ENABLE_VERIFIER */
-
- return true;
-}
-
-
-u1 suck_u1(classbuffer *cb)
-{
- u1 a;
-
- a = SUCK_BE_U1(cb->pos);
- cb->pos++;
-
- return a;
-}
-
-
-u2 suck_u2(classbuffer *cb)
-{
- u2 a;
-
- a = SUCK_BE_U2(cb->pos);
- cb->pos += 2;
-
- return a;
-}
-
-
-u4 suck_u4(classbuffer *cb)
-{
- u4 a;
-
- a = SUCK_BE_U4(cb->pos);
- cb->pos += 4;
-
- return a;
-}
-
-
-u8 suck_u8(classbuffer *cb)
-{
-#if U8_AVAILABLE == 1
- u8 a;
-
- a = SUCK_BE_U8(cb->pos);
- cb->pos += 8;
-
- return a;
-#else
- u8 v;
-
- v.high = suck_u4(cb);
- v.low = suck_u4(cb);
-
- return v;
-#endif
-}
-
-
-float suck_float(classbuffer *cb)
-{
- float f;
-
-#if WORDS_BIGENDIAN == 0
- u1 buffer[4];
- u2 i;
-
- for (i = 0; i < 4; i++)
- buffer[3 - i] = suck_u1(cb);
-
- MCOPY((u1 *) (&f), buffer, u1, 4);
-#else
- suck_nbytes((u1*) (&f), cb, 4);
-#endif
-
- assert(sizeof(float) == 4);
-
- return f;
-}
-
-
-double suck_double(classbuffer *cb)
-{
- double d;
-
-#if WORDS_BIGENDIAN == 0
- u1 buffer[8];
- u2 i;
-
-# if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
- /*
- * On little endian ARM processors when using FPA, word order
- * of doubles is still big endian. So take that into account
- * here. When using VFP, word order of doubles follows byte
- * order. (michi 2005/07/24)
- */
- for (i = 0; i < 4; i++)
- buffer[3 - i] = suck_u1(cb);
- for (i = 0; i < 4; i++)
- buffer[7 - i] = suck_u1(cb);
-# else
- for (i = 0; i < 8; i++)
- buffer[7 - i] = suck_u1(cb);
-# endif /* defined(__ARM__) && ... */
-
- MCOPY((u1 *) (&d), buffer, u1, 8);
-#else
- suck_nbytes((u1*) (&d), cb, 8);
-#endif
-
- assert(sizeof(double) == 8);
-
- return d;
-}
-
-
-/* suck_nbytes *****************************************************************
-
- Transfer block of classfile data into a buffer.
-
-*******************************************************************************/
-
-void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
-{
- MCOPY(buffer, cb->pos, u1, len);
- cb->pos += len;
-}
-
-
-/* suck_skip_nbytes ************************************************************
-
- Skip block of classfile data.
-
-*******************************************************************************/
-
-void suck_skip_nbytes(classbuffer *cb, s4 len)
-{
- cb->pos += len;
-}
-
-
-/* suck_start ******************************************************************
-
- Returns true if classbuffer is already loaded or a file for the
- specified class has succussfully been read in. All directories of
- the searchpath are used to find the classfile (<classname>.class).
- Returns NULL if no classfile is found and writes an error message.
-
-*******************************************************************************/
-
-classbuffer *suck_start(classinfo *c)
-{
- list_classpath_entry *lce;
- char *filename;
- s4 filenamelen;
- char *path;
- FILE *classfile;
- s4 len;
- struct stat buffer;
- classbuffer *cb;
-
- /* initialize return value */
-
- cb = NULL;
-
- /* get the classname as char string (do it here for the warning at
- the end of the function) */
-
- filenamelen = utf_bytes(c->name) + strlen(".class") + strlen("0");
- filename = MNEW(char, filenamelen);
-
- utf_copy(filename, c->name);
- strcat(filename, ".class");
-
- /* walk through all classpath entries */
-
- for (lce = list_first(list_classpath_entries); lce != NULL && cb == NULL;
- lce = list_next(list_classpath_entries, lce)) {
-#if defined(ENABLE_ZLIB)
- if (lce->type == CLASSPATH_ARCHIVE) {
-
- /* enter a monitor on zip/jar archives */
-
- LOCK_MONITOR_ENTER(lce);
-
- /* try to get the file in current archive */
-
- cb = zip_get(lce, c);
-
- /* leave the monitor */
-
- LOCK_MONITOR_EXIT(lce);
-
- } else {
-#endif /* defined(ENABLE_ZLIB) */
- path = MNEW(char, lce->pathlen + filenamelen);
- strcpy(path, lce->path);
- strcat(path, filename);
-
- classfile = system_fopen(path, "r");
-
- if (classfile) { /* file exists */
- if (!system_stat(path, &buffer)) { /* read classfile data */
- cb = NEW(classbuffer);
- cb->clazz = c;
- cb->size = buffer.st_size;
- cb->data = MNEW(u1, cb->size);
- cb->pos = cb->data;
- cb->path = lce->path;
-
- /* read class data */
-
- len = system_fread((void *) cb->data, 1, cb->size,
- classfile);
-
- if (len != buffer.st_size) {
- suck_stop(cb);
-/* if (ferror(classfile)) { */
-/* } */
- }
-
- /* close the class file */
-
- system_fclose(classfile);
- }
- }
-
- MFREE(path, char, lce->pathlen + filenamelen);
-#if defined(ENABLE_ZLIB)
- }
-#endif
- }
-
- if (opt_verbose)
- if (cb == NULL)
- dolog("Warning: Can not open class file '%s'", filename);
-
- MFREE(filename, char, filenamelen);
-
- return cb;
-}
-
-
-/* suck_stop *******************************************************************
-
- Frees memory for buffer with classfile data.
-
- CAUTION: This function may only be called if buffer has been
- allocated by suck_start with reading a file.
-
-*******************************************************************************/
-
-void suck_stop(classbuffer *cb)
-{
- /* free memory */
-
- MFREE(cb->data, u1, cb->size);
- FREE(cb, classbuffer);
-}
-
-
-/*
- * 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/vmcore/suck.h - functions to read LE ordered types from a buffer
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _SUCK_H
-#define _SUCK_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-
-
-/* list_classpath_entry *******************************************************/
-
-enum {
- CLASSPATH_PATH,
- CLASSPATH_ARCHIVE
-};
-
-typedef struct list_classpath_entry list_classpath_entry;
-
-struct list_classpath_entry {
-#if defined(ENABLE_THREADS)
- java_object_t header; /* monitor locking on zip/jar files */
-#endif
- s4 type;
- char *path;
- s4 pathlen;
-#if defined(ENABLE_ZLIB)
- hashtable *htclasses;
-#endif
- listnode_t linkage;
-};
-
-
-/* macros to read LE and BE types from a buffer ********************************
-
- BE macros are for Java class file loading.
- LE macros are for ZIP file loading.
-
-*******************************************************************************/
-
-/* LE macros (for ZIP files ) *************************************************/
-
-#if defined(__I386__) || defined(__X86_64__)
-
-/* we can optimize the LE access on little endian machines without alignment */
-
-#define SUCK_LE_U1(p) *((u1 *) (p))
-#define SUCK_LE_U2(p) *((u2 *) (p))
-#define SUCK_LE_U4(p) *((u4 *) (p))
-
-#if U8_AVAILABLE == 1
-#define SUCK_LE_U8(p) *((u8 *) (p))
-#endif
-
-#else /* defined(__I386__) || defined(__X86_64__) */
-
-#define SUCK_LE_U1(p) \
- ((u1) (p)[0])
-
-#define SUCK_LE_U2(p) \
- ((((u2) (p)[1]) << 8) + \
- ((u2) (p)[0]))
-
-#define SUCK_LE_U4(p) \
- ((((u4) (p)[3]) << 24) + \
- (((u4) (p)[2]) << 16) + \
- (((u4) (p)[1]) << 8) + \
- ((u4) (p)[0]))
-
-#if U8_AVAILABLE == 1
-#define SUCK_LE_U8(p) \
- ((((u8) (p)[7]) << 56) + \
- (((u8) (p)[6]) << 48) + \
- (((u8) (p)[5]) << 40) + \
- (((u8) (p)[4]) << 32) + \
- (((u8) (p)[3]) << 24) + \
- (((u8) (p)[2]) << 16) + \
- (((u8) (p)[1]) << 8) + \
- ((u8) (p)[0]))
-#endif
-
-#endif /* defined(__I386__) || defined(__X86_64__) */
-
-
-/* BE macros (for Java class files ) ******************************************/
-
-#define SUCK_BE_U1(p) \
- ((u1) (p)[0])
-
-#define SUCK_BE_U2(p) \
- ((((u2) (p)[0]) << 8) + \
- ((u2) (p)[1]))
-
-#define SUCK_BE_U4(p) \
- ((((u4) (p)[0]) << 24) + \
- (((u4) (p)[1]) << 16) + \
- (((u4) (p)[2]) << 8) + \
- ((u4) (p)[3]))
-
-#if U8_AVAILABLE == 1
-#define SUCK_BE_U8(p) \
- ((((u8) (p)[0]) << 56) + \
- (((u8) (p)[1]) << 48) + \
- (((u8) (p)[2]) << 40) + \
- (((u8) (p)[3]) << 32) + \
- (((u8) (p)[4]) << 24) + \
- (((u8) (p)[5]) << 16) + \
- (((u8) (p)[6]) << 8) + \
- ((u8) (p)[7]))
-#endif
-
-
-#define SUCK_BE_S1(p) (s1) SUCK_BE_U1(p)
-#define SUCK_BE_S2(p) (s2) SUCK_BE_U2(p)
-#define SUCK_BE_S4(p) (s4) SUCK_BE_U4(p)
-#define SUCK_BE_S8(p) (s8) SUCK_BE_U8(p)
-
-
-/* signed suck defines ********************************************************/
-
-#define suck_s1(a) (s1) suck_u1((a))
-#define suck_s2(a) (s2) suck_u2((a))
-#define suck_s4(a) (s4) suck_u4((a))
-#define suck_s8(a) (s8) suck_u8((a))
-
-
-/* export variables ***********************************************************/
-
-extern list_t *list_classpath_entries;
-
-
-/* function prototypes ********************************************************/
-
-bool suck_init(void);
-
-void suck_add(char *classpath);
-void suck_add_from_property(char *key);
-
-bool suck_check_classbuffer_size(classbuffer *cb, s4 len);
-
-u1 suck_u1(classbuffer *cb);
-u2 suck_u2(classbuffer *cb);
-u4 suck_u4(classbuffer *cb);
-u8 suck_u8(classbuffer *cb);
-
-float suck_float(classbuffer *cb);
-double suck_double(classbuffer *cb);
-
-void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len);
-void suck_skip_nbytes(classbuffer *cb, s4 len);
-
-classbuffer *suck_start(classinfo *c);
-
-void suck_stop(classbuffer *cb);
-
-#endif /* _SUCK_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/vmcore/system.c - system (OS) functions
-
- Copyright (C) 2007
- 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"
-
-/* NOTE: In this file we check for all system headers, because we wrap
- all system calls into functions for better portability. */
-
-#if defined(HAVE_ERRNO_H)
-# include <errno.h>
-#endif
-
-#if defined(HAVE_STDINT_H)
-# include <stdint.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(__DARWIN__)
-# include <mach/mach.h>
-# include <mach/mach_host.h>
-# include <mach/host_info.h>
-#endif
-
-/* this should work on BSD */
-/* #include <sys/sysctl.h> */
-
-#include "vm/vm.h"
-
-
-/* system_mmap_anonymous *******************************************************
-
- Maps anonymous memory, even on systems not defining
- MAP_ANON(YMOUS).
-
-*******************************************************************************/
-
-void *system_mmap_anonymous(void *addr, size_t len, int prot, int flags)
-{
- void *p;
-
-#if defined(MAP_ANON) || defined(MAP_ANONYMOUS)
- p = mmap(addr, len, prot,
-# if defined(MAP_ANON)
- MAP_ANON | flags,
-# else
- MAP_ANONYMOUS | flags,
-# endif
- -1, 0);
-#else
- int fd;
-
- fd = open("/dev/zero", O_RDONLY, 0);
-
- if (fd == -1)
- vm_abort("system_mmap_anonymous: open failed: %s", strerror(errno));
-
- p = mmap(addr, len, prot, flags, fd, 0);
-#endif
-
-#if defined(MAP_FAILED)
- if (p == MAP_FAILED)
-#else
- if (p == (void *) -1)
-#endif
- vm_abort("system_mmap_anonymous: mmap failed: %s", strerror(errno));
-
- return p;
-}
-
-
-/* system_processors_online ****************************************************
-
- Returns the number of online processors in the system.
-
- RETURN:
- online processor count
-
-*******************************************************************************/
-
-int system_processors_online(void)
-{
-#if defined(_SC_NPROC_ONLN)
-
- return (int) sysconf(_SC_NPROC_ONLN);
-
-#elif defined(_SC_NPROCESSORS_ONLN)
-
- return (int) sysconf(_SC_NPROCESSORS_ONLN);
-
-#elif defined(__DARWIN__)
-
- host_basic_info_data_t hinfo;
- mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
- kern_return_t rc;
-
- rc = host_info(mach_host_self(), HOST_BASIC_INFO,
- (host_info_t) &hinfo, &hinfo_count);
-
- if (rc != KERN_SUCCESS) {
- return -1;
- }
-
- /* XXX michi: according to my infos this should be
- hinfo.max_cpus, can someone please confirm or deny that? */
- return (int) hinfo.avail_cpus;
-
-#elif defined(__FREEBSD__)
-# error IMPLEMENT ME!
-
- /* this should work in BSD */
- /*
- int ncpu, mib[2], rc;
- size_t len;
-
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(ncpu);
- rc = sysctl(mib, 2, &ncpu, &len, NULL, 0);
-
- return (int32_t) ncpu;
- */
-
-#else
-
- return 1;
-
-#endif
-}
-
-
-/*
- * 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/vmcore/system.h - 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 _VMCORE_SYSTEM_H
-#define _VMCORE_SYSTEM_H
-
-#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_FCNTL_H)
-# include <fcntl.h>
-#endif
-
-#if defined(ENABLE_JRE_LAYOUT)
-# if defined(HAVE_LIBGEN_H)
-# include <libgen.h>
-# endif
-#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
-
-
-/* inline functions ***********************************************************/
-
-inline static void system_abort(void)
-{
-#if defined(HAVE_ABORT)
- abort();
-#else
-# error abort not available
-#endif
-}
-
-inline static int system_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 static int system_access(const char *pathname, int mode)
-{
-#if defined(HAVE_ACCESS)
- return access(pathname, mode);
-#else
-# error access not available
-#endif
-}
-
-inline static int system_atoi(const char *nptr)
-{
-#if defined(HAVE_ATOI)
- return atoi(nptr);
-#else
-# error atoi not available
-#endif
-}
-
-inline static void *system_calloc(size_t nmemb, size_t size)
-{
-#if defined(HAVE_CALLOC)
- return calloc(nmemb, size);
-#else
-# error calloc not available
-#endif
-}
-
-inline static int system_close(int fd)
-{
-#if defined(HAVE_CLOSE)
- return close(fd);
-#else
-# error close not available
-#endif
-}
-
-inline static int system_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 static char *system_dirname(char *path)
-{
-#if defined(HAVE_DIRNAME)
- return dirname(path);
-#else
-# error dirname not available
-#endif
-}
-#endif
-
-inline static int system_dlclose(void* handle)
-{
-#if defined(HAVE_DLCLOSE)
- return dlclose(handle);
-#else
-# error dlclose not available
-#endif
-}
-
-inline static char* system_dlerror(void)
-{
-#if defined(HAVE_DLERROR)
- return dlerror();
-#else
-# error dlerror not available
-#endif
-}
-
-inline static void* system_dlopen(const char* filename, int flag)
-{
-#if defined(HAVE_DLOPEN)
- return dlopen(filename, flag);
-#else
-# error dlopen not available
-#endif
-}
-
-inline static void* system_dlsym(void* handle, const char* symbol)
-{
-#if defined(HAVE_DLSYM)
- return dlsym(handle, symbol);
-#else
-# error dlsym not available
-#endif
-}
-
-inline static FILE *system_fopen(const char *path, const char *mode)
-{
-#if defined(HAVE_FOPEN)
- return fopen(path, mode);
-#else
-# error fopen not available
-#endif
-}
-
-inline static int system_fclose(FILE *fp)
-{
-#if defined(HAVE_FCLOSE)
- return fclose(fp);
-#else
-# error fclose not available
-#endif
-}
-
-inline static size_t system_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 static void system_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 static int system_gethostname(char *name, size_t len)
-{
-#if defined(HAVE_GETHOSTNAME)
- return gethostname(name, len);
-#else
-# error gethostname not available
-#endif
-}
-
-inline static int system_getpagesize(void)
-{
-#if defined(HAVE_GETPAGESIZE)
- return getpagesize();
-#else
-# error getpagesize not available
-#endif
-}
-
-inline static int system_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 static int system_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 static int system_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 static void *system_malloc(size_t size)
-{
-#if defined(HAVE_MALLOC)
- return malloc(size);
-#else
-# error malloc not available
-#endif
-}
-
-inline static void *system_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 static void *system_memset(void *s, int c, size_t n)
-{
-#if defined(HAVE_MEMSET)
- return memset(s, c, n);
-#else
-# error memset not available
-#endif
-}
-
-inline static int system_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
-}
-
-#if defined(__LINUX__)
-inline static int system_scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
-#elif defined(__IRIX__)
-inline static int system_scandir(const char *dir, struct dirent ***namelist, int(*filter)(dirent_t *), int(*compar)(dirent_t **, dirent_t **))
-#else
-inline static int system_scandir(const char *dir, struct dirent ***namelist, int(*filter)(struct dirent *), int(*compar)(const void *, const void *))
-#endif
-{
-#if defined(HAVE_SCANDIR)
- return scandir(dir, namelist, filter, compar);
-#else
-# error scandir not available
-#endif
-}
-
-inline static int system_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 static int system_shutdown(int s, int how)
-{
-#if defined(HAVE_SHUTDOWN)
- return shutdown(s, how);
-#else
-# error shutdown not available
-#endif
-}
-
-inline static int system_socket(int domain, int type, int protocol)
-{
-#if defined(HAVE_SOCKET)
- return socket(domain, type, protocol);
-#else
-# error socket not available
-#endif
-}
-
-inline static int system_stat(const char *path, struct stat *buf)
-{
-#if defined(HAVE_STAT)
- return stat(path, buf);
-#else
-# error stat not available
-#endif
-}
-
-inline static char *system_strcat(char *dest, const char *src)
-{
-#if defined(HAVE_STRCAT)
- return strcat(dest, src);
-#else
-# error strcat not available
-#endif
-}
-
-inline static char *system_strcpy(char *dest, const char *src)
-{
-#if defined(HAVE_STRCPY)
- return strcpy(dest, src);
-#else
-# error strcpy not available
-#endif
-}
-
-inline static char *system_strdup(const char *s)
-{
-#if defined(HAVE_STRDUP)
- return strdup(s);
-#else
-# error strdup not available
-#endif
-}
-
-inline static char *system_strerror(int errnum)
-{
-#if defined(HAVE_STRERROR)
- return strerror(errnum);
-#else
-# error strerror not available
-#endif
-}
-
-inline static size_t system_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
-}
-
-
-/* function prototypes ********************************************************/
-
-void *system_mmap_anonymous(void *addr, size_t len, int prot, int flags);
-int system_processors_online(void);
-
-#endif /* _VMCORE_SYSTEM_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:
- */
+++ /dev/null
-/* src/vmcore/utf8.c - utf8 string 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 <string.h>
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/exceptions.h"
-
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/utf8.h"
-
-
-/* global variables ***********************************************************/
-
-/* hashsize must be power of 2 */
-
-#define HASHTABLE_UTF_SIZE 16384 /* initial size of utf-hash */
-
-hashtable *hashtable_utf; /* hashtable for utf8-symbols */
-
-
-/* utf-symbols for pointer comparison of frequently used strings **************/
-
-utf *utf_java_lang_Object;
-
-utf *utf_java_lang_Class;
-utf *utf_java_lang_ClassLoader;
-utf *utf_java_lang_Cloneable;
-utf *utf_java_lang_SecurityManager;
-utf *utf_java_lang_String;
-utf *utf_java_lang_ThreadGroup;
-utf *utf_java_lang_ref_SoftReference;
-utf *utf_java_lang_ref_WeakReference;
-utf *utf_java_lang_ref_PhantomReference;
-utf *utf_java_io_Serializable;
-
-utf *utf_java_lang_Throwable;
-utf *utf_java_lang_Error;
-
-utf *utf_java_lang_AbstractMethodError;
-utf *utf_java_lang_ClassCircularityError;
-utf *utf_java_lang_ClassFormatError;
-utf *utf_java_lang_ExceptionInInitializerError;
-utf *utf_java_lang_IncompatibleClassChangeError;
-utf *utf_java_lang_InstantiationError;
-utf *utf_java_lang_InternalError;
-utf *utf_java_lang_LinkageError;
-utf *utf_java_lang_NoClassDefFoundError;
-utf *utf_java_lang_NoSuchFieldError;
-utf *utf_java_lang_NoSuchMethodError;
-utf *utf_java_lang_OutOfMemoryError;
-utf *utf_java_lang_UnsatisfiedLinkError;
-utf *utf_java_lang_UnsupportedClassVersionError;
-utf *utf_java_lang_VerifyError;
-utf *utf_java_lang_VirtualMachineError;
-
-utf *utf_java_lang_Exception;
-
-utf *utf_java_lang_ArithmeticException;
-utf *utf_java_lang_ArrayIndexOutOfBoundsException;
-utf *utf_java_lang_ArrayStoreException;
-utf *utf_java_lang_ClassCastException;
-utf *utf_java_lang_ClassNotFoundException;
-utf *utf_java_lang_CloneNotSupportedException;
-utf *utf_java_lang_IllegalAccessException;
-utf *utf_java_lang_IllegalArgumentException;
-utf *utf_java_lang_IllegalMonitorStateException;
-utf *utf_java_lang_InstantiationException;
-utf *utf_java_lang_InterruptedException;
-utf *utf_java_lang_NegativeArraySizeException;
-utf *utf_java_lang_NullPointerException;
-utf *utf_java_lang_RuntimeException;
-utf *utf_java_lang_StringIndexOutOfBoundsException;
-
-utf *utf_java_lang_reflect_InvocationTargetException;
-
-utf *utf_java_security_PrivilegedActionException;
-
-#if defined(ENABLE_JAVASE)
-utf* utf_java_lang_Void;
-#endif
-
-utf* utf_java_lang_Boolean;
-utf* utf_java_lang_Byte;
-utf* utf_java_lang_Character;
-utf* utf_java_lang_Short;
-utf* utf_java_lang_Integer;
-utf* utf_java_lang_Long;
-utf* utf_java_lang_Float;
-utf* utf_java_lang_Double;
-
-#if defined(ENABLE_JAVASE)
-utf *utf_java_lang_StackTraceElement;
-utf *utf_java_lang_reflect_Constructor;
-utf *utf_java_lang_reflect_Field;
-utf *utf_java_lang_reflect_Method;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-utf *utf_java_lang_reflect_VMConstructor;
-utf *utf_java_lang_reflect_VMField;
-utf *utf_java_lang_reflect_VMMethod;
-# endif
-
-utf *utf_java_util_Vector;
-#endif
-
-utf *utf_InnerClasses; /* InnerClasses */
-utf *utf_ConstantValue; /* ConstantValue */
-utf *utf_Code; /* Code */
-utf *utf_Exceptions; /* Exceptions */
-utf *utf_LineNumberTable; /* LineNumberTable */
-utf *utf_SourceFile; /* SourceFile */
-
-#if defined(ENABLE_JAVASE)
-utf *utf_EnclosingMethod;
-utf *utf_Signature;
-utf *utf_StackMapTable;
-
-#if defined(ENABLE_ANNOTATIONS)
-utf *utf_RuntimeVisibleAnnotations; /* RuntimeVisibleAnnotations */
-utf *utf_RuntimeInvisibleAnnotations; /* RuntimeInvisibleAnnotations */
-utf *utf_RuntimeVisibleParameterAnnotations; /* RuntimeVisibleParameterAnnotations */
-utf *utf_RuntimeInvisibleParameterAnnotations; /* RuntimeInvisibleParameterAnnotations */
-utf *utf_AnnotationDefault; /* AnnotationDefault */
-#endif
-#endif
-
-utf *utf_init; /* <init> */
-utf *utf_clinit; /* <clinit> */
-utf *utf_clone; /* clone */
-utf *utf_finalize; /* finalize */
-utf *utf_invoke;
-utf *utf_main;
-utf *utf_run; /* run */
-
-utf *utf_add;
-utf *utf_remove;
-utf *utf_addThread;
-utf *utf_removeThread;
-utf *utf_put;
-utf *utf_get;
-utf *utf_uncaughtException;
-utf *utf_value;
-
-utf *utf_fillInStackTrace;
-utf *utf_findNative;
-utf *utf_getSystemClassLoader;
-utf *utf_initCause;
-utf *utf_loadClass;
-utf *utf_loadClassInternal;
-utf *utf_printStackTrace;
-
-utf *utf_division_by_zero;
-
-utf *utf_Z; /* Z */
-utf *utf_B; /* B */
-utf *utf_C; /* C */
-utf *utf_S; /* S */
-utf *utf_I; /* I */
-utf *utf_J; /* J */
-utf *utf_F; /* F */
-utf *utf_D; /* D */
-
-utf *utf_void__void; /* ()V */
-utf *utf_boolean__void; /* (Z)V */
-utf *utf_byte__void; /* (B)V */
-utf *utf_char__void; /* (C)V */
-utf *utf_short__void; /* (S)V */
-utf *utf_int__void; /* (I)V */
-utf *utf_long__void; /* (J)V */
-utf *utf_float__void; /* (F)V */
-utf *utf_double__void; /* (D)V */
-
-utf *utf_void__java_lang_ClassLoader; /* ()Ljava/lang/ClassLoader; */
-utf *utf_void__java_lang_Object; /* ()Ljava/lang/Object; */
-utf *utf_void__java_lang_Throwable; /* ()Ljava/lang/Throwable; */
-utf *utf_java_lang_ClassLoader_java_lang_String__J;
-utf *utf_java_lang_Exception__V; /* (Ljava/lang/Exception;)V */
-utf *utf_java_lang_Object__java_lang_Object;
-utf *utf_java_lang_String__void; /* (Ljava/lang/String;)V */
-utf *utf_java_lang_String__java_lang_Class;
-utf *utf_java_lang_Thread__V; /* (Ljava/lang/Thread;)V */
-utf *utf_java_lang_Thread_java_lang_Throwable__V;
-utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
-utf *utf_java_lang_Throwable__void; /* (Ljava/lang/Throwable;)V */
-utf *utf_java_lang_Throwable__java_lang_Throwable;
-
-utf *utf_not_named_yet; /* special name for unnamed classes */
-utf *utf_null;
-utf *array_packagename;
-
-
-/* utf_init ********************************************************************
-
- Initializes the utf8 subsystem.
-
-*******************************************************************************/
-
-void utf8_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("utf8_init");
-
- /* create utf8 hashtable */
-
- hashtable_utf = NEW(hashtable);
-
- hashtable_create(hashtable_utf, HASHTABLE_UTF_SIZE);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_len += sizeof(utf*) * hashtable_utf->size;
-#endif
-
- /* create utf-symbols for pointer comparison of frequently used strings */
-
- utf_java_lang_Object = utf_new_char("java/lang/Object");
-
- utf_java_lang_Class = utf_new_char("java/lang/Class");
- utf_java_lang_ClassLoader = utf_new_char("java/lang/ClassLoader");
- utf_java_lang_Cloneable = utf_new_char("java/lang/Cloneable");
- utf_java_lang_SecurityManager = utf_new_char("java/lang/SecurityManager");
- utf_java_lang_String = utf_new_char("java/lang/String");
- utf_java_lang_ThreadGroup = utf_new_char("java/lang/ThreadGroup");
-
- utf_java_lang_ref_SoftReference =
- utf_new_char("java/lang/ref/SoftReference");
-
- utf_java_lang_ref_WeakReference =
- utf_new_char("java/lang/ref/WeakReference");
-
- utf_java_lang_ref_PhantomReference =
- utf_new_char("java/lang/ref/PhantomReference");
-
- utf_java_io_Serializable = utf_new_char("java/io/Serializable");
-
- utf_java_lang_Throwable = utf_new_char("java/lang/Throwable");
- utf_java_lang_Error = utf_new_char("java/lang/Error");
-
- utf_java_lang_ClassCircularityError =
- utf_new_char("java/lang/ClassCircularityError");
-
- utf_java_lang_ClassFormatError = utf_new_char("java/lang/ClassFormatError");
-
- utf_java_lang_ExceptionInInitializerError =
- utf_new_char("java/lang/ExceptionInInitializerError");
-
- utf_java_lang_IncompatibleClassChangeError =
- utf_new_char("java/lang/IncompatibleClassChangeError");
-
- utf_java_lang_InstantiationError =
- utf_new_char("java/lang/InstantiationError");
-
- utf_java_lang_InternalError = utf_new_char("java/lang/InternalError");
- utf_java_lang_LinkageError = utf_new_char("java/lang/LinkageError");
-
- utf_java_lang_NoClassDefFoundError =
- utf_new_char("java/lang/NoClassDefFoundError");
-
- utf_java_lang_OutOfMemoryError = utf_new_char("java/lang/OutOfMemoryError");
-
- utf_java_lang_UnsatisfiedLinkError =
- utf_new_char("java/lang/UnsatisfiedLinkError");
-
- utf_java_lang_UnsupportedClassVersionError =
- utf_new_char("java/lang/UnsupportedClassVersionError");
-
- utf_java_lang_VerifyError = utf_new_char("java/lang/VerifyError");
-
- utf_java_lang_VirtualMachineError =
- utf_new_char("java/lang/VirtualMachineError");
-
-#if defined(ENABLE_JAVASE)
- utf_java_lang_AbstractMethodError =
- utf_new_char("java/lang/AbstractMethodError");
-
- utf_java_lang_NoSuchFieldError =
- utf_new_char("java/lang/NoSuchFieldError");
-
- utf_java_lang_NoSuchMethodError =
- utf_new_char("java/lang/NoSuchMethodError");
-#endif
-
- utf_java_lang_Exception = utf_new_char("java/lang/Exception");
-
- utf_java_lang_ArithmeticException =
- utf_new_char("java/lang/ArithmeticException");
-
- utf_java_lang_ArrayIndexOutOfBoundsException =
- utf_new_char("java/lang/ArrayIndexOutOfBoundsException");
-
- utf_java_lang_ArrayStoreException =
- utf_new_char("java/lang/ArrayStoreException");
-
- utf_java_lang_ClassCastException =
- utf_new_char("java/lang/ClassCastException");
-
- utf_java_lang_ClassNotFoundException =
- utf_new_char("java/lang/ClassNotFoundException");
-
- utf_java_lang_CloneNotSupportedException =
- utf_new_char("java/lang/CloneNotSupportedException");
-
- utf_java_lang_IllegalAccessException =
- utf_new_char("java/lang/IllegalAccessException");
-
- utf_java_lang_IllegalArgumentException =
- utf_new_char("java/lang/IllegalArgumentException");
-
- utf_java_lang_IllegalMonitorStateException =
- utf_new_char("java/lang/IllegalMonitorStateException");
-
- utf_java_lang_InstantiationException =
- utf_new_char("java/lang/InstantiationException");
-
- utf_java_lang_InterruptedException =
- utf_new_char("java/lang/InterruptedException");
-
- utf_java_lang_NegativeArraySizeException =
- utf_new_char("java/lang/NegativeArraySizeException");
-
- utf_java_lang_NullPointerException =
- utf_new_char("java/lang/NullPointerException");
-
- utf_java_lang_RuntimeException =
- utf_new_char("java/lang/RuntimeException");
-
- utf_java_lang_StringIndexOutOfBoundsException =
- utf_new_char("java/lang/StringIndexOutOfBoundsException");
-
- utf_java_lang_reflect_InvocationTargetException =
- utf_new_char("java/lang/reflect/InvocationTargetException");
-
- utf_java_security_PrivilegedActionException =
- utf_new_char("java/security/PrivilegedActionException");
-
-#if defined(ENABLE_JAVASE)
- utf_java_lang_Void = utf_new_char("java/lang/Void");
-#endif
-
- utf_java_lang_Boolean = utf_new_char("java/lang/Boolean");
- utf_java_lang_Byte = utf_new_char("java/lang/Byte");
- utf_java_lang_Character = utf_new_char("java/lang/Character");
- utf_java_lang_Short = utf_new_char("java/lang/Short");
- utf_java_lang_Integer = utf_new_char("java/lang/Integer");
- utf_java_lang_Long = utf_new_char("java/lang/Long");
- utf_java_lang_Float = utf_new_char("java/lang/Float");
- utf_java_lang_Double = utf_new_char("java/lang/Double");
-
-#if defined(ENABLE_JAVASE)
- utf_java_lang_StackTraceElement =
- utf_new_char("java/lang/StackTraceElement");
-
- utf_java_lang_reflect_Constructor =
- utf_new_char("java/lang/reflect/Constructor");
-
- utf_java_lang_reflect_Field = utf_new_char("java/lang/reflect/Field");
- utf_java_lang_reflect_Method = utf_new_char("java/lang/reflect/Method");
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- utf_java_lang_reflect_VMConstructor = utf_new_char("java/lang/reflect/VMConstructor");
- utf_java_lang_reflect_VMField = utf_new_char("java/lang/reflect/VMField");
- utf_java_lang_reflect_VMMethod = utf_new_char("java/lang/reflect/VMMethod");
-# endif
-
- utf_java_util_Vector = utf_new_char("java/util/Vector");
-#endif
-
- utf_InnerClasses = utf_new_char("InnerClasses");
- utf_ConstantValue = utf_new_char("ConstantValue");
- utf_Code = utf_new_char("Code");
- utf_Exceptions = utf_new_char("Exceptions");
- utf_LineNumberTable = utf_new_char("LineNumberTable");
- utf_SourceFile = utf_new_char("SourceFile");
-
-#if defined(ENABLE_JAVASE)
- utf_EnclosingMethod = utf_new_char("EnclosingMethod");
- utf_Signature = utf_new_char("Signature");
- utf_StackMapTable = utf_new_char("StackMapTable");
-
-# if defined(ENABLE_ANNOTATIONS)
- utf_RuntimeVisibleAnnotations = utf_new_char("RuntimeVisibleAnnotations");
- utf_RuntimeInvisibleAnnotations = utf_new_char("RuntimeInvisibleAnnotations");
- utf_RuntimeVisibleParameterAnnotations = utf_new_char("RuntimeVisibleParameterAnnotations");
- utf_RuntimeInvisibleParameterAnnotations = utf_new_char("RuntimeInvisibleParameterAnnotations");
- utf_AnnotationDefault = utf_new_char("AnnotationDefault");
-# endif
-#endif
-
- utf_init = utf_new_char("<init>");
- utf_clinit = utf_new_char("<clinit>");
- utf_clone = utf_new_char("clone");
- utf_finalize = utf_new_char("finalize");
- utf_invoke = utf_new_char("invoke");
- utf_main = utf_new_char("main");
- utf_run = utf_new_char("run");
-
- utf_add = utf_new_char("add");
- utf_remove = utf_new_char("remove");
- utf_addThread = utf_new_char("addThread");
- utf_removeThread = utf_new_char("removeThread");
- utf_put = utf_new_char("put");
- utf_get = utf_new_char("get");
- utf_uncaughtException = utf_new_char("uncaughtException");
- utf_value = utf_new_char("value");
-
- utf_fillInStackTrace = utf_new_char("fillInStackTrace");
- utf_findNative = utf_new_char("findNative");
- utf_getSystemClassLoader = utf_new_char("getSystemClassLoader");
- utf_initCause = utf_new_char("initCause");
- utf_loadClass = utf_new_char("loadClass");
- utf_loadClassInternal = utf_new_char("loadClassInternal");
- utf_printStackTrace = utf_new_char("printStackTrace");
-
- utf_division_by_zero = utf_new_char("/ by zero");
-
- utf_Z = utf_new_char("Z");
- utf_B = utf_new_char("B");
- utf_C = utf_new_char("C");
- utf_S = utf_new_char("S");
- utf_I = utf_new_char("I");
- utf_J = utf_new_char("J");
- utf_F = utf_new_char("F");
- utf_D = utf_new_char("D");
-
- utf_void__void = utf_new_char("()V");
- utf_boolean__void = utf_new_char("(Z)V");
- utf_byte__void = utf_new_char("(B)V");
- utf_char__void = utf_new_char("(C)V");
- utf_short__void = utf_new_char("(S)V");
- utf_int__void = utf_new_char("(I)V");
- utf_long__void = utf_new_char("(J)V");
- utf_float__void = utf_new_char("(F)V");
- utf_double__void = utf_new_char("(D)V");
- utf_void__java_lang_Object = utf_new_char("()Ljava/lang/Object;");
- utf_void__java_lang_Throwable = utf_new_char("()Ljava/lang/Throwable;");
-
- utf_void__java_lang_ClassLoader =
- utf_new_char("()Ljava/lang/ClassLoader;");
-
- utf_java_lang_ClassLoader_java_lang_String__J =
- utf_new_char("(Ljava/lang/ClassLoader;Ljava/lang/String;)J");
-
- utf_java_lang_Exception__V = utf_new_char("(Ljava/lang/Exception;)V");
-
- utf_java_lang_Object__java_lang_Object =
- utf_new_char("(Ljava/lang/Object;)Ljava/lang/Object;");
-
- utf_java_lang_String__void = utf_new_char("(Ljava/lang/String;)V");
-
- utf_java_lang_String__java_lang_Class =
- utf_new_char("(Ljava/lang/String;)Ljava/lang/Class;");
-
- utf_java_lang_Thread__V = utf_new_char("(Ljava/lang/Thread;)V");
-
- utf_java_lang_Thread_java_lang_Throwable__V =
- utf_new_char("(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
-
- utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V =
- utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
-
- utf_java_lang_Throwable__void = utf_new_char("(Ljava/lang/Throwable;)V");
-
- utf_java_lang_Throwable__java_lang_Throwable =
- utf_new_char("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
-
- utf_null = utf_new_char("null");
- utf_not_named_yet = utf_new_char("\t<not_named_yet>");
- array_packagename = utf_new_char("\t<the array package>");
-}
-
-
-/* utf_hashkey *****************************************************************
-
- The hashkey is computed from the utf-text by using up to 8
- characters. For utf-symbols longer than 15 characters 3 characters
- are taken from the beginning and the end, 2 characters are taken
- from the middle.
-
-*******************************************************************************/
-
-#define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
-#define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
-
-u4 utf_hashkey(const char *text, u4 length)
-{
- const char *start_pos = text; /* pointer to utf text */
- u4 a;
-
- switch (length) {
- case 0: /* empty string */
- return 0;
-
- case 1: return fbs(0);
- case 2: return fbs(0) ^ nbs(3);
- case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
- case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
- case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
- case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
- case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
- case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
-
- case 9:
- a = fbs(0);
- a ^= nbs(1);
- a ^= nbs(2);
- text++;
- return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
-
- case 10:
- a = fbs(0);
- text++;
- a ^= nbs(2);
- a ^= nbs(3);
- a ^= nbs(4);
- text++;
- return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
-
- case 11:
- a = fbs(0);
- text++;
- a ^= nbs(2);
- a ^= nbs(3);
- a ^= nbs(4);
- text++;
- return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
-
- case 12:
- a = fbs(0);
- text += 2;
- a ^= nbs(2);
- a ^= nbs(3);
- text++;
- a ^= nbs(5);
- a ^= nbs(6);
- a ^= nbs(7);
- text++;
- return a ^ nbs(9) ^ nbs(10);
-
- case 13:
- a = fbs(0);
- a ^= nbs(1);
- text++;
- a ^= nbs(3);
- a ^= nbs(4);
- text += 2;
- a ^= nbs(7);
- a ^= nbs(8);
- text += 2;
- return a ^ nbs(9) ^ nbs(10);
-
- case 14:
- a = fbs(0);
- text += 2;
- a ^= nbs(3);
- a ^= nbs(4);
- text += 2;
- a ^= nbs(7);
- a ^= nbs(8);
- text += 2;
- return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
-
- case 15:
- a = fbs(0);
- text += 2;
- a ^= nbs(3);
- a ^= nbs(4);
- text += 2;
- a ^= nbs(7);
- a ^= nbs(8);
- text += 2;
- return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
-
- default: /* 3 characters from beginning */
- a = fbs(0);
- text += 2;
- a ^= nbs(3);
- a ^= nbs(4);
-
- /* 2 characters from middle */
- text = start_pos + (length / 2);
- a ^= fbs(5);
- text += 2;
- a ^= nbs(6);
-
- /* 3 characters from end */
- text = start_pos + length - 4;
-
- a ^= fbs(7);
- text++;
-
- return a ^ nbs(10) ^ nbs(11);
- }
-}
-
-/* utf_full_hashkey ************************************************************
-
- This function computes a hash value using all bytes in the string.
-
- The algorithm is the "One-at-a-time" algorithm as published
- by Bob Jenkins on http://burtleburtle.net/bob/hash/doobs.html.
-
-*******************************************************************************/
-
-u4 utf_full_hashkey(const char *text, u4 length)
-{
- register const unsigned char *p = (const unsigned char *) text;
- register u4 hash;
- register u4 i;
-
- hash = 0;
- for (i=length; i--;)
- {
- hash += *p++;
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- return hash;
-}
-
-/* unicode_hashkey *************************************************************
-
- Compute the hashkey of a unicode string.
-
-*******************************************************************************/
-
-u4 unicode_hashkey(u2 *text, u2 len)
-{
- return utf_hashkey((char *) text, len);
-}
-
-
-/* utf_new *********************************************************************
-
- Creates a new utf-symbol, the text of the symbol is passed as a
- u1-array. The function searches the utf-hashtable for a utf-symbol
- with this text. On success the element returned, otherwise a new
- hashtable element is created.
-
- If the number of entries in the hashtable exceeds twice the size of
- the hashtable slots a reorganization of the hashtable is done and
- the utf symbols are copied to a new hashtable with doubled size.
-
-*******************************************************************************/
-
-utf *utf_new(const char *text, u2 length)
-{
- u4 key; /* hashkey computed from utf-text */
- u4 slot; /* slot in hashtable */
- utf *u; /* hashtable element */
- u2 i;
-
- LOCK_MONITOR_ENTER(hashtable_utf->header);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_new++;
-#endif
-
- key = utf_hashkey(text, length);
- slot = key & (hashtable_utf->size - 1);
- u = hashtable_utf->ptr[slot];
-
- /* search external hash chain for utf-symbol */
-
- while (u) {
- if (u->blength == length) {
- /* compare text of hashtable elements */
-
- for (i = 0; i < length; i++)
- if (text[i] != u->text[i])
- goto nomatch;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_new_found++;
-#endif
-
- /* symbol found in hashtable */
-
- LOCK_MONITOR_EXIT(hashtable_utf->header);
-
- return u;
- }
-
- nomatch:
- u = u->hashlink; /* next element in external chain */
- }
-
- /* location in hashtable found, create new utf element */
-
- u = NEW(utf);
-
- u->blength = length; /* length in bytes of utfstring */
- u->hashlink = hashtable_utf->ptr[slot]; /* link in external hashchain */
- u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
-
- memcpy(u->text, text, length); /* copy utf-text */
- u->text[length] = '\0';
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_len += sizeof(utf) + length + 1;
-#endif
-
- hashtable_utf->ptr[slot] = u; /* insert symbol into table */
- hashtable_utf->entries++; /* update number of entries */
-
- if (hashtable_utf->entries > (hashtable_utf->size * 2)) {
-
- /* reorganization of hashtable, average length of the external
- chains is approx. 2 */
-
- hashtable *newhash; /* the new hashtable */
- u4 i;
- utf *u;
- utf *nextu;
- u4 slot;
-
- /* create new hashtable, double the size */
-
- newhash = hashtable_resize(hashtable_utf, hashtable_utf->size * 2);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_len += sizeof(utf*) * hashtable_utf->size;
-#endif
-
- /* transfer elements to new hashtable */
-
- for (i = 0; i < hashtable_utf->size; i++) {
- u = hashtable_utf->ptr[i];
-
- while (u) {
- nextu = u->hashlink;
- slot = utf_hashkey(u->text, u->blength) & (newhash->size - 1);
-
- u->hashlink = (utf *) newhash->ptr[slot];
- newhash->ptr[slot] = u;
-
- /* follow link in external hash chain */
-
- u = nextu;
- }
- }
-
- /* dispose old table */
-
- hashtable_free(hashtable_utf);
-
- hashtable_utf = newhash;
- }
-
- LOCK_MONITOR_EXIT(hashtable_utf->header);
-
- return u;
-}
-
-
-/* utf_new_u2 ******************************************************************
-
- Make utf symbol from u2 array, if isclassname is true '.' is
- replaced by '/'.
-
-*******************************************************************************/
-
-utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
-{
- char *buffer; /* memory buffer for unicode characters */
- char *pos; /* pointer to current position in buffer */
- u4 left; /* unicode characters left */
- u4 buflength; /* utf length in bytes of the u2 array */
- utf *result; /* resulting utf-string */
- int i;
-
- /* determine utf length in bytes and allocate memory */
-
- buflength = u2_utflength(unicode_pos, unicode_length);
- buffer = MNEW(char, buflength);
-
- left = buflength;
- pos = buffer;
-
- for (i = 0; i++ < unicode_length; unicode_pos++) {
- /* next unicode character */
- u2 c = *unicode_pos;
-
- if ((c != 0) && (c < 0x80)) {
- /* 1 character */
- left--;
- if ((int) left < 0) break;
- /* convert classname */
- if (isclassname && c == '.')
- *pos++ = '/';
- else
- *pos++ = (char) c;
-
- } else if (c < 0x800) {
- /* 2 characters */
- unsigned char high = c >> 6;
- unsigned char low = c & 0x3F;
- left = left - 2;
- if ((int) left < 0) break;
- *pos++ = high | 0xC0;
- *pos++ = low | 0x80;
-
- } else {
- /* 3 characters */
- char low = c & 0x3f;
- char mid = (c >> 6) & 0x3F;
- char high = c >> 12;
- left = left - 3;
- if ((int) left < 0) break;
- *pos++ = high | 0xE0;
- *pos++ = mid | 0x80;
- *pos++ = low | 0x80;
- }
- }
-
- /* insert utf-string into symbol-table */
- result = utf_new(buffer,buflength);
-
- MFREE(buffer, char, buflength);
-
- return result;
-}
-
-
-/* utf_new_char ****************************************************************
-
- Creates a new utf symbol, the text for this symbol is passed as a
- c-string ( = char* ).
-
-*******************************************************************************/
-
-utf *utf_new_char(const char *text)
-{
- return utf_new(text, strlen(text));
-}
-
-
-/* utf_new_char_classname ******************************************************
-
- Creates a new utf symbol, the text for this symbol is passed as a
- c-string ( = char* ) "." characters are going to be replaced by
- "/". Since the above function is used often, this is a separte
- function, instead of an if.
-
-*******************************************************************************/
-
-utf *utf_new_char_classname(const char *text)
-{
- if (strchr(text, '.')) {
- char *txt = strdup(text);
- char *end = txt + strlen(txt);
- char *c;
- utf *tmpRes;
-
- for (c = txt; c < end; c++)
- if (*c == '.') *c = '/';
-
- tmpRes = utf_new(txt, strlen(txt));
- FREE(txt, 0);
-
- return tmpRes;
-
- } else
- return utf_new(text, strlen(text));
-}
-
-
-/* utf_nextu2 ******************************************************************
-
- Read the next unicode character from the utf string and increment
- the utf-string pointer accordingly.
-
- CAUTION: This function is unsafe for input that was not checked
- by is_valid_utf!
-
-*******************************************************************************/
-
-u2 utf_nextu2(char **utf_ptr)
-{
- /* uncompressed unicode character */
- u2 unicode_char = 0;
- /* current position in utf text */
- unsigned char *utf = (unsigned char *) (*utf_ptr);
- /* bytes representing the unicode character */
- unsigned char ch1, ch2, ch3;
- /* number of bytes used to represent the unicode character */
- int len = 0;
-
- switch ((ch1 = utf[0]) >> 4) {
- default: /* 1 byte */
- (*utf_ptr)++;
- return (u2) ch1;
- case 0xC:
- case 0xD: /* 2 bytes */
- if (((ch2 = utf[1]) & 0xC0) == 0x80) {
- unsigned char high = ch1 & 0x1F;
- unsigned char low = ch2 & 0x3F;
- unicode_char = (high << 6) + low;
- len = 2;
- }
- break;
-
- case 0xE: /* 2 or 3 bytes */
- if (((ch2 = utf[1]) & 0xC0) == 0x80) {
- if (((ch3 = utf[2]) & 0xC0) == 0x80) {
- unsigned char low = ch3 & 0x3f;
- unsigned char mid = ch2 & 0x3f;
- unsigned char high = ch1 & 0x0f;
- unicode_char = (((high << 6) + mid) << 6) + low;
- len = 3;
- } else
- len = 2;
- }
- break;
- }
-
- /* update position in utf-text */
- *utf_ptr = (char *) (utf + len);
-
- return unicode_char;
-}
-
-
-/* utf_bytes *******************************************************************
-
- Determine number of bytes (aka. octets) in the utf string.
-
- IN:
- u............utf string
-
- OUT:
- The number of octets of this utf string.
- There is _no_ terminating zero included in this count.
-
-*******************************************************************************/
-
-u4 utf_bytes(utf *u)
-{
- return u->blength;
-}
-
-
-/* utf_get_number_of_u2s_for_buffer ********************************************
-
- Determine number of UTF-16 u2s in the given UTF-8 buffer
-
- CAUTION: This function is unsafe for input that was not checked
- by is_valid_utf!
-
- CAUTION: Use this function *only* when you want to convert an UTF-8 buffer
- to an array of u2s (UTF-16) and want to know how many of them you will get.
- All other uses of this function are probably wrong.
-
- IN:
- buffer........points to first char in buffer
- blength.......number of _bytes_ in the buffer
-
- OUT:
- the number of u2s needed to hold this string in UTF-16 encoding.
- There is _no_ terminating zero included in this count.
-
- NOTE: Unlike utf_get_number_of_u2s, this function never throws an
- exception.
-
-*******************************************************************************/
-
-u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength)
-{
- const char *endpos; /* points behind utf string */
- const char *utf_ptr; /* current position in utf text */
- u4 len = 0; /* number of unicode characters */
-
- utf_ptr = buffer;
- endpos = utf_ptr + blength;
-
- while (utf_ptr < endpos) {
- len++;
- /* next unicode character */
- utf_nextu2((char **)&utf_ptr);
- }
-
- assert(utf_ptr == endpos);
-
- return len;
-}
-
-
-/* utf_get_number_of_u2s *******************************************************
-
- Determine number of UTF-16 u2s in the utf string.
-
- CAUTION: This function is unsafe for input that was not checked
- by is_valid_utf!
-
- CAUTION: Use this function *only* when you want to convert a utf string
- to an array of u2s and want to know how many of them you will get.
- All other uses of this function are probably wrong.
-
- IN:
- u............utf string
-
- OUT:
- the number of u2s needed to hold this string in UTF-16 encoding.
- There is _no_ terminating zero included in this count.
- XXX 0 if a NullPointerException has been thrown (see below)
-
-*******************************************************************************/
-
-u4 utf_get_number_of_u2s(utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
- u4 len = 0; /* number of unicode characters */
-
- /* XXX this is probably not checked by most callers! Review this after */
- /* the invalid uses of this function have been eliminated */
- if (u == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- len++;
- /* next unicode character */
- utf_nextu2(&utf_ptr);
- }
-
- if (utf_ptr != endpos) {
- /* string ended abruptly */
- exceptions_throw_internalerror("Illegal utf8 string");
- return 0;
- }
-
- return len;
-}
-
-
-/* utf8_safe_number_of_u2s *****************************************************
-
- Determine number of UTF-16 u2s needed for decoding the given UTF-8 string.
- (For invalid UTF-8 the U+fffd replacement character will be counted.)
-
- This function is safe even for invalid UTF-8 strings.
-
- IN:
- text..........zero-terminated(!) UTF-8 string (may be invalid)
- must NOT be NULL
- nbytes........strlen(text). (This is needed to completely emulate
- the RI).
-
- OUT:
- the number of u2s needed to hold this string in UTF-16 encoding.
- There is _no_ terminating zero included in this count.
-
-*******************************************************************************/
-
-s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes) {
- register const unsigned char *t;
- register s4 byte;
- register s4 len;
- register const unsigned char *tlimit;
- s4 byte1;
- s4 byte2;
- s4 byte3;
- s4 value;
- s4 skip;
-
- assert(text);
- assert(nbytes >= 0);
-
- len = 0;
- t = (const unsigned char *) text;
- tlimit = t + nbytes;
-
- /* CAUTION: Keep this code in sync with utf8_safe_convert_to_u2s! */
-
- while (1) {
- byte = *t++;
-
- if (byte & 0x80) {
- /* highest bit set, non-ASCII character */
-
- if ((byte & 0xe0) == 0xc0) {
- /* 2-byte: should be 110..... 10...... ? */
-
- if ((*t++ & 0xc0) == 0x80)
- ; /* valid 2-byte */
- else
- t--; /* invalid */
- }
- else if ((byte & 0xf0) == 0xe0) {
- /* 3-byte: should be 1110.... 10...... 10...... */
- /* ^t */
-
- if (t + 2 > tlimit)
- return len + 1; /* invalid, stop here */
-
- if ((*t++ & 0xc0) == 0x80) {
- if ((*t++ & 0xc0) == 0x80)
- ; /* valid 3-byte */
- else
- t--; /* invalid */
- }
- else
- t--; /* invalid */
- }
- else if ((byte & 0xf8) == 0xf0) {
- /* 4-byte: should be 11110... 10...... 10...... 10...... */
- /* ^t */
-
- if (t + 3 > tlimit)
- return len + 1; /* invalid, stop here */
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- if (((byte2 = *t++) & 0xc0) == 0x80) {
- if (((byte3 = *t++) & 0xc0) == 0x80) {
- /* valid 4-byte UTF-8? */
- value = ((byte & 0x07) << 18)
- | ((byte1 & 0x3f) << 12)
- | ((byte2 & 0x3f) << 6)
- | ((byte3 & 0x3f) );
-
- if (value > 0x10FFFF)
- ; /* invalid */
- else if (value > 0xFFFF)
- len += 1; /* we need surrogates */
- else
- ; /* 16bit suffice */
- }
- else
- t--; /* invalid */
- }
- else
- t--; /* invalid */
- }
- else
- t--; /* invalid */
- }
- else if ((byte & 0xfc) == 0xf8) {
- /* invalid 5-byte */
- if (t + 4 > tlimit)
- return len + 1; /* invalid, stop here */
-
- skip = 4;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- }
- else if ((byte & 0xfe) == 0xfc) {
- /* invalid 6-byte */
- if (t + 5 > tlimit)
- return len + 1; /* invalid, stop here */
-
- skip = 5;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- }
- else
- ; /* invalid */
- }
- else {
- /* NUL */
-
- if (byte == 0)
- break;
-
- /* ASCII character, common case */
- }
-
- len++;
- }
-
- return len;
-}
-
-
-/* utf8_safe_convert_to_u2s ****************************************************
-
- Convert the given UTF-8 string to UTF-16 into a pre-allocated buffer.
- (Invalid UTF-8 will be replaced with the U+fffd replacement character.)
- Use utf8_safe_number_of_u2s to determine the number of u2s to allocate.
-
- This function is safe even for invalid UTF-8 strings.
-
- IN:
- text..........zero-terminated(!) UTF-8 string (may be invalid)
- must NOT be NULL
- nbytes........strlen(text). (This is needed to completely emulate
- the RI).
- buffer........a preallocated array of u2s to receive the decoded
- string. Use utf8_safe_number_of_u2s to get the
- required number of u2s for allocating this.
-
-*******************************************************************************/
-
-#define UNICODE_REPLACEMENT 0xfffd
-
-void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer) {
- register const unsigned char *t;
- register s4 byte;
- register const unsigned char *tlimit;
- s4 byte1;
- s4 byte2;
- s4 byte3;
- s4 value;
- s4 skip;
-
- assert(text);
- assert(nbytes >= 0);
-
- t = (const unsigned char *) text;
- tlimit = t + nbytes;
-
- /* CAUTION: Keep this code in sync with utf8_safe_number_of_u2s! */
-
- while (1) {
- byte = *t++;
-
- if (byte & 0x80) {
- /* highest bit set, non-ASCII character */
-
- if ((byte & 0xe0) == 0xc0) {
- /* 2-byte: should be 110..... 10...... */
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- /* valid 2-byte UTF-8 */
- *buffer++ = ((byte & 0x1f) << 6)
- | ((byte1 & 0x3f) );
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else if ((byte & 0xf0) == 0xe0) {
- /* 3-byte: should be 1110.... 10...... 10...... */
-
- if (t + 2 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- if (((byte2 = *t++) & 0xc0) == 0x80) {
- /* valid 3-byte UTF-8 */
- *buffer++ = ((byte & 0x0f) << 12)
- | ((byte1 & 0x3f) << 6)
- | ((byte2 & 0x3f) );
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else if ((byte & 0xf8) == 0xf0) {
- /* 4-byte: should be 11110... 10...... 10...... 10...... */
-
- if (t + 3 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- if (((byte2 = *t++) & 0xc0) == 0x80) {
- if (((byte3 = *t++) & 0xc0) == 0x80) {
- /* valid 4-byte UTF-8? */
- value = ((byte & 0x07) << 18)
- | ((byte1 & 0x3f) << 12)
- | ((byte2 & 0x3f) << 6)
- | ((byte3 & 0x3f) );
-
- if (value > 0x10FFFF) {
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else if (value > 0xFFFF) {
- /* we need surrogates */
- *buffer++ = 0xd800 | ((value >> 10) - 0x40);
- *buffer++ = 0xdc00 | (value & 0x03ff);
- }
- else
- *buffer++ = value; /* 16bit suffice */
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else if ((byte & 0xfc) == 0xf8) {
- if (t + 4 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- skip = 4;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else if ((byte & 0xfe) == 0xfc) {
- if (t + 5 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- skip = 5;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else {
- /* NUL */
-
- if (byte == 0)
- break;
-
- /* ASCII character, common case */
-
- *buffer++ = byte;
- }
- }
-}
-
-
-/* u2_utflength ****************************************************************
-
- Returns the utf length in bytes of a u2 array.
-
-*******************************************************************************/
-
-u4 u2_utflength(u2 *text, u4 u2_length)
-{
- u4 result_len = 0; /* utf length in bytes */
- u2 ch; /* current unicode character */
- u4 len;
-
- for (len = 0; len < u2_length; len++) {
- /* next unicode character */
- ch = *text++;
-
- /* determine bytes required to store unicode character as utf */
- if (ch && (ch < 0x80))
- result_len++;
- else if (ch < 0x800)
- result_len += 2;
- else
- result_len += 3;
- }
-
- return result_len;
-}
-
-
-/* utf_copy ********************************************************************
-
- Copy the given utf string byte-for-byte to a buffer.
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_copy(char *buffer, utf *u)
-{
- /* our utf strings are zero-terminated (done by utf_new) */
- MCOPY(buffer, u->text, char, u->blength + 1);
-}
-
-
-/* utf_cat *********************************************************************
-
- Append the given utf string byte-for-byte to a buffer.
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_cat(char *buffer, utf *u)
-{
- /* our utf strings are zero-terminated (done by utf_new) */
- MCOPY(buffer + strlen(buffer), u->text, char, u->blength + 1);
-}
-
-
-/* utf_copy_classname **********************************************************
-
- Copy the given utf classname byte-for-byte to a buffer.
- '/' is replaced by '.'
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_copy_classname(char *buffer, utf *u)
-{
- char *bufptr;
- char *srcptr;
- char *endptr;
- char ch;
-
- bufptr = buffer;
- srcptr = u->text;
- endptr = UTF_END(u) + 1; /* utfs are zero-terminared by utf_new */
-
- while (srcptr != endptr) {
- ch = *srcptr++;
- if (ch == '/')
- ch = '.';
- *bufptr++ = ch;
- }
-}
-
-
-/* utf_cat *********************************************************************
-
- Append the given utf classname byte-for-byte to a buffer.
- '/' is replaced by '.'
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_cat_classname(char *buffer, utf *u)
-{
- utf_copy_classname(buffer + strlen(buffer), u);
-}
-
-/* utf_display_printable_ascii *************************************************
-
- Write utf symbol to stdout (for debugging purposes).
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_display_printable_ascii(utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (u == NULL) {
- printf("NULL");
- fflush(stdout);
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
-
- u2 c = utf_nextu2(&utf_ptr);
-
- if ((c >= 32) && (c <= 127))
- printf("%c", c);
- else
- printf("?");
- }
-
- fflush(stdout);
-}
-
-
-/* utf_display_printable_ascii_classname ***************************************
-
- Write utf symbol to stdout with `/' converted to `.' (for debugging
- purposes).
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_display_printable_ascii_classname(utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (u == NULL) {
- printf("NULL");
- fflush(stdout);
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
-
- u2 c = utf_nextu2(&utf_ptr);
-
- if (c == '/')
- c = '.';
-
- if ((c >= 32) && (c <= 127))
- printf("%c", c);
- else
- printf("?");
- }
-
- fflush(stdout);
-}
-
-
-/* utf_sprint_convert_to_latin1 ************************************************
-
- Write utf symbol into c-string (for debugging purposes).
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_sprint_convert_to_latin1(char *buffer, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
- u2 pos = 0; /* position in c-string */
-
- if (!u) {
- strcpy(buffer, "NULL");
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos)
- /* copy next unicode character */
- buffer[pos++] = utf_nextu2(&utf_ptr);
-
- /* terminate string */
- buffer[pos] = '\0';
-}
-
-
-/* utf_sprint_convert_to_latin1_classname **************************************
-
- Write utf symbol into c-string with `/' converted to `.' (for debugging
- purposes).
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
- u2 pos = 0; /* position in c-string */
-
- if (!u) {
- strcpy(buffer, "NULL");
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* copy next unicode character */
- u2 c = utf_nextu2(&utf_ptr);
- if (c == '/') c = '.';
- buffer[pos++] = c;
- }
-
- /* terminate string */
- buffer[pos] = '\0';
-}
-
-
-/* utf_strcat_convert_to_latin1 ************************************************
-
- Like libc strcat, but uses an utf8 string.
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_strcat_convert_to_latin1(char *buffer, utf *u)
-{
- utf_sprint_convert_to_latin1(buffer + strlen(buffer), u);
-}
-
-
-/* utf_strcat_convert_to_latin1_classname **************************************
-
- Like libc strcat, but uses an utf8 string.
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u)
-{
- utf_sprint_convert_to_latin1_classname(buffer + strlen(buffer), u);
-}
-
-
-/* utf_fprint_printable_ascii **************************************************
-
- Write utf symbol into file.
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_fprint_printable_ascii(FILE *file, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (!u)
- return;
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
- u2 c = utf_nextu2(&utf_ptr);
-
- if (c >= 32 && c <= 127) fprintf(file, "%c", c);
- else fprintf(file, "?");
- }
-}
-
-
-/* utf_fprint_printable_ascii_classname ****************************************
-
- Write utf symbol into file with `/' converted to `.'.
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_fprint_printable_ascii_classname(FILE *file, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (!u)
- return;
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
- u2 c = utf_nextu2(&utf_ptr);
- if (c == '/') c = '.';
-
- if (c >= 32 && c <= 127) fprintf(file, "%c", c);
- else fprintf(file, "?");
- }
-}
-
-
-/* is_valid_utf ****************************************************************
-
- Return true if the given string is a valid UTF-8 string.
-
- utf_ptr...points to first character
- end_pos...points after last character
-
-*******************************************************************************/
-
-/* static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26}; */
-
-bool is_valid_utf(char *utf_ptr, char *end_pos)
-{
- int bytes;
- int len,i;
- char c;
- unsigned long v;
-
- if (end_pos < utf_ptr) return false;
- bytes = end_pos - utf_ptr;
- while (bytes--) {
- c = *utf_ptr++;
-
- if (!c) return false; /* 0x00 is not allowed */
- if ((c & 0x80) == 0) continue; /* ASCII */
-
- if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
- else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
- else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
- else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
- else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
- else return false; /* invalid leading byte */
-
- if (len > 2) return false; /* Java limitation */
-
- v = (unsigned long)c & (0x3f >> len);
-
- if ((bytes -= len) < 0) return false; /* missing bytes */
-
- for (i = len; i--; ) {
- c = *utf_ptr++;
- if ((c & 0xc0) != 0x80) /* 10xx xxxx */
- return false;
- v = (v << 6) | (c & 0x3f);
- }
-
- if (v == 0) {
- if (len != 1) return false; /* Java special */
-
- } else {
- /* Sun Java seems to allow overlong UTF-8 encodings */
-
- /* if (v < min_codepoint[len]) */
- /* XXX throw exception? */
- }
-
- /* surrogates in UTF-8 seem to be allowed in Java classfiles */
- /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
-
- /* even these seem to be allowed */
- /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
- }
-
- return true;
-}
-
-
-/* is_valid_name ***************************************************************
-
- Return true if the given string may be used as a class/field/method
- name. (Currently this only disallows empty strings and control
- characters.)
-
- NOTE: The string is assumed to have passed is_valid_utf!
-
- utf_ptr...points to first character
- end_pos...points after last character
-
-*******************************************************************************/
-
-bool is_valid_name(char *utf_ptr, char *end_pos)
-{
- if (end_pos <= utf_ptr) return false; /* disallow empty names */
-
- while (utf_ptr < end_pos) {
- unsigned char c = *utf_ptr++;
-
- if (c < 0x20) return false; /* disallow control characters */
- if (c == 0xc0 && (unsigned char) *utf_ptr == 0x80) /* disallow zero */
- return false;
- }
-
- return true;
-}
-
-bool is_valid_name_utf(utf *u)
-{
- return is_valid_name(u->text, UTF_END(u));
-}
-
-
-/* utf_show ********************************************************************
-
- Writes the utf symbols in the utfhash to stdout and displays the
- number of external hash chains grouped according to the chainlength
- (for debugging purposes).
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void utf_show(void)
-{
-
-#define CHAIN_LIMIT 20 /* limit for seperated enumeration */
-
- u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
- u4 max_chainlength = 0; /* maximum length of the chains */
- u4 sum_chainlength = 0; /* sum of the chainlengths */
- u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
- u4 i;
-
- printf("UTF-HASH:\n");
-
- /* show element of utf-hashtable */
-
- for (i = 0; i < hashtable_utf->size; i++) {
- utf *u = hashtable_utf->ptr[i];
-
- if (u) {
- printf("SLOT %d: ", (int) i);
-
- while (u) {
- printf("'");
- utf_display_printable_ascii(u);
- printf("' ");
- u = u->hashlink;
- }
- printf("\n");
- }
- }
-
- printf("UTF-HASH: %d slots for %d entries\n",
- (int) hashtable_utf->size, (int) hashtable_utf->entries );
-
- if (hashtable_utf->entries == 0)
- return;
-
- printf("chains:\n chainlength number of chains %% of utfstrings\n");
-
- for (i=0;i<CHAIN_LIMIT;i++)
- chain_count[i]=0;
-
- /* count numbers of hashchains according to their length */
- for (i=0; i<hashtable_utf->size; i++) {
-
- utf *u = (utf*) hashtable_utf->ptr[i];
- u4 chain_length = 0;
-
- /* determine chainlength */
- while (u) {
- u = u->hashlink;
- chain_length++;
- }
-
- /* update sum of all chainlengths */
- sum_chainlength+=chain_length;
-
- /* determine the maximum length of the chains */
- if (chain_length>max_chainlength)
- max_chainlength = chain_length;
-
- /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
- if (chain_length>=CHAIN_LIMIT) {
- beyond_limit+=chain_length;
- chain_length=CHAIN_LIMIT-1;
- }
-
- /* update number of hashchains of current length */
- chain_count[chain_length]++;
- }
-
- /* display results */
- for (i=1;i<CHAIN_LIMIT-1;i++)
- printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/hashtable_utf->entries));
-
- printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/hashtable_utf->entries);
-
-
- printf("max. chainlength:%5d\n",max_chainlength);
-
- /* avg. chainlength = sum of chainlengths / number of chains */
- printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (hashtable_utf->size-chain_count[0]));
-}
-#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/vmcore/utf8.h - utf8 string 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.
-
-*/
-
-
-#ifndef _UTF_H
-#define _UTF_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct utf utf;
-
-#include "config.h"
-
-#include <stdio.h>
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* data structure for utf8 symbols ********************************************/
-
-struct utf {
- utf *hashlink; /* link for external hash chain */
- s4 blength; /* text length in bytes */
- char *text; /* pointer to text */
-};
-
-/* to determine the end of utf strings */
-
-#define UTF_END(u) ((char *) u->text + u->blength)
-
-
-/* utf-symbols for pointer comparison of frequently used strings **************/
-
-extern utf *utf_java_lang_Object;
-
-extern utf *utf_java_lang_Class;
-extern utf *utf_java_lang_ClassLoader;
-extern utf *utf_java_lang_Cloneable;
-extern utf *utf_java_lang_SecurityManager;
-extern utf *utf_java_lang_String;
-extern utf *utf_java_lang_ThreadGroup;
-extern utf *utf_java_lang_ref_SoftReference;
-extern utf *utf_java_lang_ref_WeakReference;
-extern utf *utf_java_lang_ref_PhantomReference;
-extern utf *utf_java_io_Serializable;
-
-extern utf *utf_java_lang_Throwable;
-extern utf *utf_java_lang_Error;
-
-extern utf *utf_java_lang_AbstractMethodError;
-extern utf *utf_java_lang_ClassCircularityError;
-extern utf *utf_java_lang_ClassFormatError;
-extern utf *utf_java_lang_ExceptionInInitializerError;
-extern utf *utf_java_lang_IncompatibleClassChangeError;
-extern utf *utf_java_lang_InstantiationError;
-extern utf *utf_java_lang_InternalError;
-extern utf *utf_java_lang_LinkageError;
-extern utf *utf_java_lang_NoClassDefFoundError;
-extern utf *utf_java_lang_NoSuchFieldError;
-extern utf *utf_java_lang_NoSuchMethodError;
-extern utf *utf_java_lang_OutOfMemoryError;
-extern utf *utf_java_lang_UnsatisfiedLinkError;
-extern utf *utf_java_lang_UnsupportedClassVersionError;
-extern utf *utf_java_lang_VerifyError;
-extern utf *utf_java_lang_VirtualMachineError;
-
-extern utf *utf_java_lang_Exception;
-
-extern utf *utf_java_lang_ArithmeticException;
-extern utf *utf_java_lang_ArrayIndexOutOfBoundsException;
-extern utf *utf_java_lang_ArrayStoreException;
-extern utf *utf_java_lang_ClassCastException;
-extern utf *utf_java_lang_ClassNotFoundException;
-extern utf *utf_java_lang_CloneNotSupportedException;
-extern utf *utf_java_lang_IllegalAccessException;
-extern utf *utf_java_lang_IllegalArgumentException;
-extern utf *utf_java_lang_IllegalMonitorStateException;
-extern utf *utf_java_lang_InstantiationException;
-extern utf *utf_java_lang_InterruptedException;
-extern utf *utf_java_lang_NegativeArraySizeException;
-extern utf *utf_java_lang_NullPointerException;
-extern utf *utf_java_lang_RuntimeException;
-extern utf *utf_java_lang_StringIndexOutOfBoundsException;
-
-extern utf *utf_java_lang_reflect_InvocationTargetException;
-
-extern utf *utf_java_security_PrivilegedActionException;
-
-#if defined(ENABLE_JAVASE)
-extern utf* utf_java_lang_Void;
-#endif
-
-extern utf* utf_java_lang_Boolean;
-extern utf* utf_java_lang_Byte;
-extern utf* utf_java_lang_Character;
-extern utf* utf_java_lang_Short;
-extern utf* utf_java_lang_Integer;
-extern utf* utf_java_lang_Long;
-extern utf* utf_java_lang_Float;
-extern utf* utf_java_lang_Double;
-
-#if defined(ENABLE_JAVASE)
-extern utf *utf_java_lang_StackTraceElement;
-extern utf *utf_java_lang_reflect_Constructor;
-extern utf *utf_java_lang_reflect_Field;
-extern utf *utf_java_lang_reflect_Method;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern utf *utf_java_lang_reflect_VMConstructor;
-extern utf *utf_java_lang_reflect_VMField;
-extern utf *utf_java_lang_reflect_VMMethod;
-# endif
-
-extern utf *utf_java_util_Vector;
-#endif
-
-extern utf *utf_InnerClasses;
-extern utf *utf_ConstantValue;
-extern utf *utf_Code;
-extern utf *utf_Exceptions;
-extern utf *utf_LineNumberTable;
-extern utf *utf_SourceFile;
-
-#if defined(ENABLE_JAVASE)
-extern utf *utf_EnclosingMethod;
-extern utf *utf_Signature;
-extern utf *utf_StackMapTable;
-
-#if defined(ENABLE_ANNOTATIONS)
-extern utf *utf_RuntimeVisibleAnnotations;
-extern utf *utf_RuntimeInvisibleAnnotations;
-extern utf *utf_RuntimeVisibleParameterAnnotations;
-extern utf *utf_RuntimeInvisibleParameterAnnotations;
-extern utf *utf_AnnotationDefault;
-#endif
-#endif
-
-extern utf *utf_init;
-extern utf *utf_clinit;
-extern utf *utf_clone;
-extern utf *utf_finalize;
-extern utf *utf_invoke;
-extern utf *utf_main;
-extern utf *utf_run;
-
-extern utf *utf_add;
-extern utf *utf_remove;
-extern utf *utf_addThread;
-extern utf *utf_removeThread;
-extern utf *utf_put;
-extern utf *utf_get;
-extern utf *utf_uncaughtException;
-extern utf *utf_value;
-
-extern utf *utf_fillInStackTrace;
-extern utf *utf_findNative;
-extern utf *utf_getSystemClassLoader;
-extern utf *utf_initCause;
-extern utf *utf_loadClass;
-extern utf *utf_loadClassInternal;
-extern utf *utf_printStackTrace;
-
-extern utf *utf_division_by_zero;
-
-extern utf *utf_Z;
-extern utf *utf_B;
-extern utf *utf_C;
-extern utf *utf_S;
-extern utf *utf_I;
-extern utf *utf_J;
-extern utf *utf_F;
-extern utf *utf_D;
-
-extern utf *utf_void__void;
-extern utf *utf_boolean__void;
-extern utf *utf_byte__void;
-extern utf *utf_char__void;
-extern utf *utf_short__void;
-extern utf *utf_int__void;
-extern utf *utf_long__void;
-extern utf *utf_float__void;
-extern utf *utf_double__void;
-
-extern utf *utf_void__java_lang_ClassLoader;
-extern utf *utf_void__java_lang_Object;
-extern utf *utf_void__java_lang_Throwable;
-extern utf *utf_java_lang_ClassLoader_java_lang_String__J;
-extern utf *utf_java_lang_Exception__V;
-extern utf *utf_java_lang_Object__java_lang_Object;
-extern utf *utf_java_lang_String__void;
-extern utf *utf_java_lang_String__java_lang_Class;
-extern utf *utf_java_lang_Thread__V;
-extern utf *utf_java_lang_Thread_java_lang_Throwable__V;
-extern utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
-extern utf *utf_java_lang_Throwable__void;
-extern utf *utf_java_lang_Throwable__java_lang_Throwable;
-
-extern utf *utf_not_named_yet;
-extern utf *utf_null;
-extern utf *array_packagename;
-
-
-/* function prototypes ********************************************************/
-
-/* initialize the utf8 subsystem */
-void utf8_init(void);
-
-u4 utf_hashkey(const char *text, u4 length);
-u4 utf_full_hashkey(const char *text, u4 length);
-
-/* determine hashkey of a unicode-symbol */
-u4 unicode_hashkey(u2 *text, u2 length);
-
-/* create new utf-symbol */
-utf *utf_new(const char *text, u2 length);
-
-/* make utf symbol from u2 array */
-utf *utf_new_u2(u2 *unicodedata, u4 unicodelength, bool isclassname);
-
-utf *utf_new_char(const char *text);
-utf *utf_new_char_classname(const char *text);
-
-/* get number of bytes */
-u4 utf_bytes(utf *u);
-
-/* get next unicode character of a utf-string */
-u2 utf_nextu2(char **utf);
-
-/* get (number of) unicode characters of a utf string (safe) */
-s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes);
-void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer);
-
-/* get (number of) unicode characters of a utf string (UNSAFE!) */
-u4 utf_get_number_of_u2s(utf *u);
-u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength);
-
-/* determine utf length in bytes of a u2 array */
-u4 u2_utflength(u2 *text, u4 u2_length);
-
-void utf_copy(char *buffer, utf *u);
-void utf_cat(char *buffer, utf *u);
-void utf_copy_classname(char *buffer, utf *u);
-void utf_cat_classname(char *buffer, utf *u);
-
-/* write utf symbol to file/buffer */
-void utf_display_printable_ascii(utf *u);
-void utf_display_printable_ascii_classname(utf *u);
-
-void utf_sprint_convert_to_latin1(char *buffer, utf *u);
-void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u);
-
-void utf_strcat_convert_to_latin1(char *buffer, utf *u);
-void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u);
-
-void utf_fprint_printable_ascii(FILE *file, utf *u);
-void utf_fprint_printable_ascii_classname(FILE *file, utf *u);
-
-/* check if a UTF-8 string is valid */
-bool is_valid_utf(char *utf_ptr, char *end_pos);
-
-/* check if a UTF-8 string may be used as a class/field/method name */
-bool is_valid_name(char *utf_ptr, char *end_pos);
-bool is_valid_name_utf(utf *u);
-
-/* show utf-table */
-void utf_show(void);
-
-#endif /* _UTF_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:
- */
+++ /dev/null
-/* src/vmcore/zip.c - ZIP file handling for bootstrap classloader
-
- 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 <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <zlib.h>
-#include <sys/mman.h>
-
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "mm/memory.h"
-
-#include "vm/global.h"
-#include "vm/vm.h"
-
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-#include "vmcore/zip.h"
-
-
-/* start size for classes hashtable *******************************************/
-
-#define HASHTABLE_CLASSES_SIZE (1 << 10)
-
-
-/* info taken from:
- http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
-*/
-
-/* all signatures in the ZIP file have a length of 4 bytes ********************/
-
-#define SIGNATURE_LENGTH 4
-
-/* Central directory structure *************************************************
-
- [file header 1]
- .
- .
- .
- [file header n]
- [digital signature]
-
- File header:
-
- central file header signature 4 bytes (0x02014b50)
- version made by 2 bytes
- version needed to extract 2 bytes
- general purpose bit flag 2 bytes
- compression method 2 bytes
- last mod file time 2 bytes
- last mod file date 2 bytes
- crc-32 4 bytes
- compressed size 4 bytes
- uncompressed size 4 bytes
- file name length 2 bytes
- extra field length 2 bytes
- file comment length 2 bytes
- disk number start 2 bytes
- internal file attributes 2 bytes
- external file attributes 4 bytes
- relative offset of local header 4 bytes
-
- file name (variable size)
- extra field (variable size)
- file comment (variable size)
-
- Digital signature:
-
- header signature 4 bytes (0x05054b50)
- size of data 2 bytes
- signature data (variable size)
-
-*******************************************************************************/
-
-#define CDSFH_HEADER_SIZE 46
-
-#define CDSFH_SIGNATURE 0x02014b50
-#define CDSFH_COMPRESSION_METHOD 10
-#define CDSFH_COMPRESSED_SIZE 20
-#define CDSFH_UNCOMPRESSED_SIZE 24
-#define CDSFH_FILE_NAME_LENGTH 28
-#define CDSFH_EXTRA_FIELD_LENGTH 30
-#define CDSFH_FILE_COMMENT_LENGTH 32
-#define CDSFH_RELATIVE_OFFSET 42
-#define CDSFH_FILENAME 46
-
-typedef struct cdsfh cdsfh;
-
-struct cdsfh {
- u2 compressionmethod;
- u4 compressedsize;
- u4 uncompressedsize;
- u2 filenamelength;
- u2 extrafieldlength;
- u2 filecommentlength;
- u4 relativeoffset;
-};
-
-
-/* End of central directory record *********************************************
-
- end of central dir signature 4 bytes (0x06054b50)
- number of this disk 2 bytes
- number of the disk with the
- start of the central directory 2 bytes
- total number of entries in the
- central directory on this disk 2 bytes
- total number of entries in
- the central directory 2 bytes
- size of the central directory 4 bytes
- offset of start of central
- directory with respect to
- the starting disk number 4 bytes
- .ZIP file comment length 2 bytes
- .ZIP file comment (variable size)
-
-*******************************************************************************/
-
-#define EOCDR_SIGNATURE 0x06054b50
-#define EOCDR_ENTRIES 10
-#define EOCDR_OFFSET 16
-
-typedef struct eocdr eocdr;
-
-struct eocdr {
- u2 entries;
- u4 offset;
-};
-
-
-/* zip_open ********************************************************************
-
- XXX
-
-*******************************************************************************/
-
-hashtable *zip_open(char *path)
-{
- hashtable *ht;
- hashtable_zipfile_entry *htzfe;
- int fd;
- u1 lfh_signature[SIGNATURE_LENGTH];
- off_t len;
- u1 *filep;
- s4 i;
- u1 *p;
- eocdr eocdr;
- cdsfh cdsfh;
- const char *filename;
- const char *classext;
- utf *u;
- u4 key; /* hashkey computed from utf-text */
- u4 slot; /* slot in hashtable */
-
- /* first of all, open the file */
-
- if ((fd = open(path, O_RDONLY)) == -1)
- return NULL;
-
- /* check for signature in first local file header */
-
- if (read(fd, lfh_signature, SIGNATURE_LENGTH) != SIGNATURE_LENGTH)
- return NULL;
-
- if (SUCK_LE_U4(lfh_signature) != LFH_SIGNATURE)
- return NULL;
-
- /* get the file length */
-
- if ((len = lseek(fd, 0, SEEK_END)) == -1)
- return NULL;
-
- /* we better mmap the file */
-
- filep = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
-
- /* some older compilers, like DEC OSF cc, don't like comparisons
- on void* types */
-
- if ((ptrint) filep == (ptrint) MAP_FAILED)
- return NULL;
-
- /* find end of central directory record */
-
- for (p = filep + len; p >= filep; p--)
- if (SUCK_LE_U4(p) == EOCDR_SIGNATURE)
- break;
-
- /* get number of entries in central directory */
-
- eocdr.entries = SUCK_LE_U2(p + EOCDR_ENTRIES);
- eocdr.offset = SUCK_LE_U4(p + EOCDR_OFFSET);
-
- /* create hashtable for filenames */
-
- ht = NEW(hashtable);
-
- hashtable_create(ht, HASHTABLE_CLASSES_SIZE);
-
- /* add all file entries into the hashtable */
-
- for (i = 0, p = filep + eocdr.offset; i < eocdr.entries; i++) {
- /* check file header signature */
-
- if (SUCK_LE_U4(p) != CDSFH_SIGNATURE)
- return NULL;
-
- /* we found an entry */
-
- cdsfh.compressionmethod = SUCK_LE_U2(p + CDSFH_COMPRESSION_METHOD);
- cdsfh.compressedsize = SUCK_LE_U4(p + CDSFH_COMPRESSED_SIZE);
- cdsfh.uncompressedsize = SUCK_LE_U4(p + CDSFH_UNCOMPRESSED_SIZE);
- cdsfh.filenamelength = SUCK_LE_U2(p + CDSFH_FILE_NAME_LENGTH);
- cdsfh.extrafieldlength = SUCK_LE_U2(p + CDSFH_EXTRA_FIELD_LENGTH);
- cdsfh.filecommentlength = SUCK_LE_U2(p + CDSFH_FILE_COMMENT_LENGTH);
- cdsfh.relativeoffset = SUCK_LE_U4(p + CDSFH_RELATIVE_OFFSET);
-
- /* create utf8 string of filename, strip .class from classes */
-
- filename = (const char *) (p + CDSFH_FILENAME);
- classext = filename + cdsfh.filenamelength - strlen(".class");
-
- /* skip directory entries */
-
- if (filename[cdsfh.filenamelength - 1] != '/') {
- if (strncmp(classext, ".class", strlen(".class")) == 0)
- u = utf_new(filename, cdsfh.filenamelength - strlen(".class"));
- else
- u = utf_new(filename, cdsfh.filenamelength);
-
- /* insert class into hashtable */
-
- htzfe = NEW(hashtable_zipfile_entry);
-
- htzfe->filename = u;
- htzfe->compressionmethod = cdsfh.compressionmethod;
- htzfe->compressedsize = cdsfh.compressedsize;
- htzfe->uncompressedsize = cdsfh.uncompressedsize;
- htzfe->data = filep + cdsfh.relativeoffset;
-
- /* get hashtable slot */
-
- key = utf_hashkey(u->text, u->blength);
- slot = key & (ht->size - 1);
-
- /* insert into external chain */
-
- htzfe->hashlink = ht->ptr[slot];
-
- /* insert hashtable zipfile entry */
-
- ht->ptr[slot] = htzfe;
- ht->entries++;
- }
-
- /* move to next central directory structure file header */
-
- p = p +
- CDSFH_HEADER_SIZE +
- cdsfh.filenamelength +
- cdsfh.extrafieldlength +
- cdsfh.filecommentlength;
- }
-
- /* return pointer to hashtable */
-
- return ht;
-}
-
-
-/* zip_find ********************************************************************
-
- Search for the given filename in the classpath entries of a zip file.
-
- NOTE: The '.class' extension is stripped when reading a zip file, so if
- you want to find a .class file, you must search for its name _without_
- the '.class' extension.
- XXX I dont like that, it makes foo and foo.class ambiguous. -Edwin
-
- IN:
- lce..........the classpath entries for the zip file
- u............the filename to look for
-
- RETURN VALUE:
- hashtable_zipfile_entry * of the entry if found, or
- NULL if not found
-
-*******************************************************************************/
-
-hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u)
-{
- hashtable *ht;
- u4 key; /* hashkey computed from utf-text */
- u4 slot; /* slot in hashtable */
- hashtable_zipfile_entry *htzfe; /* hashtable element */
-
- /* get classes hashtable from the classpath entry */
-
- ht = lce->htclasses;
-
- /* get the hashtable slot of the name searched */
-
- key = utf_hashkey(u->text, u->blength);
- slot = key & (ht->size - 1);
- htzfe = ht->ptr[slot];
-
- /* search external hash chain for utf-symbol */
-
- while (htzfe) {
- if (htzfe->filename == u)
- return htzfe;
-
- /* next element in external chain */
-
- htzfe = htzfe->hashlink;
- }
-
- /* file not found in this archive */
-
- return NULL;
-}
-
-
-/* zip_get ********************************************************************
-
- XXX
-
-*******************************************************************************/
-
-classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
-{
- hashtable_zipfile_entry *htzfe;
- lfh lfh;
- u1 *indata;
- u1 *outdata;
- z_stream zs;
- int err;
- classbuffer *cb;
-
- /* try to find the class in the current archive */
-
- htzfe = zip_find(lce, c->name);
-
- if (htzfe == NULL)
- return NULL;
-
- /* read stuff from local file header */
-
- lfh.filenamelength = SUCK_LE_U2(htzfe->data + LFH_FILE_NAME_LENGTH);
- lfh.extrafieldlength = SUCK_LE_U2(htzfe->data + LFH_EXTRA_FIELD_LENGTH);
-
- indata = htzfe->data +
- LFH_HEADER_SIZE +
- lfh.filenamelength +
- lfh.extrafieldlength;
-
- /* allocate buffer for uncompressed data */
-
- outdata = MNEW(u1, htzfe->uncompressedsize);
-
- /* how is the file stored? */
-
- switch (htzfe->compressionmethod) {
- case Z_DEFLATED:
- /* fill z_stream structure */
-
- zs.next_in = indata;
- zs.avail_in = htzfe->compressedsize;
- zs.next_out = outdata;
- zs.avail_out = htzfe->uncompressedsize;
-
- zs.zalloc = Z_NULL;
- zs.zfree = Z_NULL;
- zs.opaque = Z_NULL;
-
- /* initialize this inflate run */
-
- if (inflateInit2(&zs, -MAX_WBITS) != Z_OK)
- vm_abort("zip_get: inflateInit2 failed: %s", strerror(errno));
-
- /* decompress the file into buffer */
-
- err = inflate(&zs, Z_SYNC_FLUSH);
-
- if ((err != Z_STREAM_END) && (err != Z_OK))
- vm_abort("zip_get: inflate failed: %s", strerror(errno));
-
- /* finish this inflate run */
-
- if (inflateEnd(&zs) != Z_OK)
- vm_abort("zip_get: inflateEnd failed: %s", strerror(errno));
- break;
-
- case 0:
- /* uncompressed file, just copy the data */
- MCOPY(outdata, indata, u1, htzfe->compressedsize);
- break;
-
- default:
- vm_abort("zip_get: unknown compression method %d",
- htzfe->compressionmethod);
- }
-
- /* allocate classbuffer */
-
- cb = NEW(classbuffer);
-
- cb->clazz = c;
- cb->size = htzfe->uncompressedsize;
- cb->data = outdata;
- cb->pos = outdata;
- cb->path = lce->path;
-
- /* return the filled classbuffer structure */
-
- return cb;
-}
-
-
-/*
- * 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/vmcore/zip.c - ZIP file handling for bootstrap classloader
-
- Copyright (C) 1996-2005, 2006, 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
-
- 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 _ZIP_H
-#define _ZIP_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-/* Local file header ***********************************************************
-
- local file header signature 4 bytes (0x04034b50)
- version needed to extract 2 bytes
- general purpose bit flag 2 bytes
- compression method 2 bytes
- last mod file time 2 bytes
- last mod file date 2 bytes
- crc-32 4 bytes
- compressed size 4 bytes
- uncompressed size 4 bytes
- file name length 2 bytes
- extra field length 2 bytes
-
- file name (variable size)
- extra field (variable size)
-
-*******************************************************************************/
-
-#define LFH_HEADER_SIZE 30
-
-#define LFH_SIGNATURE 0x04034b50
-#define LFH_FILE_NAME_LENGTH 26
-#define LFH_EXTRA_FIELD_LENGTH 28
-
-typedef struct lfh lfh;
-
-struct lfh {
- u2 compressionmethod;
- u4 compressedsize;
- u4 uncompressedsize;
- u2 filenamelength;
- u2 extrafieldlength;
-};
-
-/* hashtable_zipfile_entry ****************************************************/
-
-typedef struct hashtable_zipfile_entry hashtable_zipfile_entry;
-
-struct hashtable_zipfile_entry {
- utf *filename;
- u2 compressionmethod;
- u4 compressedsize;
- u4 uncompressedsize;
- u1 *data;
- hashtable_zipfile_entry *hashlink;
-};
-
-
-/* function prototypes ********************************************************/
-
-hashtable *zip_open(char *path);
-hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u);
-classbuffer *zip_get(list_classpath_entry *lce, classinfo *c);
-
-#endif /* _ZIP_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:
- */
PR57.class,
PR58.class,
PR65.class,
-PR80.class
+PR80.class,
+PR89.class
})
public class All {
--- /dev/null
+/* tests/regression/bugzilla/PR89.java
+
+ Copyright (C) 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.
+
+*/
+
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import java.lang.reflect.*;
+
+public class PR89 {
+ final static float f = 123.456f;
+ final static double d = 789.012;
+
+ @Test
+ public void testFloat() throws Exception {
+ FloatReflect floatReflect = new FloatReflect();
+ Method m = FloatReflect.class.getMethod("returnFloat", null);
+ Float ret = (Float) m.invoke(floatReflect, null);
+ assertEquals(f, ret, 0.0);
+ }
+
+ @Test
+ public void testDouble() throws Exception {
+ DoubleReflect doubleReflect = new DoubleReflect();
+ Method m = DoubleReflect.class.getMethod("returnDouble", null);
+ Double ret = (Double) m.invoke(doubleReflect, null);
+ assertEquals(d, ret, 0.0);
+ }
+
+ class FloatReflect {
+ public float returnFloat() {
+ return f;
+ }
+ }
+
+ class DoubleReflect {
+ public double returnDouble() {
+ return d;
+ }
+ }
+}