the same distribution terms as the rest of that program.
-* m4/{ac_prog_javac.m4,ac_prog_javac_works.m4}
+* m4/{ac_prog_jar.m4,ac_prog_javac.m4,ac_prog_javac_works.m4,ax_compiler_vendor.m4}
The http://ac-archive.sourceforge.net/ website states this about the
copyright:
AC_PREFIX_DEFAULT(/usr/local/cacao)
-dnl Set optimization and debugging for all architectures and systems.
-if test x"$CFLAGS" = "x"; then
- OPT_CFLAGS="-g -O0"
-else
- OPT_CFLAGS=$CFLAGS
-fi
-
-if test x"$CXXFLAGS" = "x"; then
- OPT_CXXFLAGS="-g -O0"
-else
- OPT_CXXFLAGS=$CXXFLAGS
-fi
-
-dnl system type
+dnl Host CPU type.
case "$host_cpu" in
alpha | alphaev56 | alphapca56 )
ARCH_DIR="alpha"
;;
* )
- AC_MSG_ERROR($host_cpu systems are not supported at this time)
+ AC_MSG_ERROR([$host_cpu systems are currently not supported.])
;;
esac
-dnl host type
+
+dnl Host operating system type.
case "$host_os" in
*cygwin* )
OS_DIR="cygwin"
OS_FLAGS="-D__WINDOWS__ -D__CYGWIN__"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
*darwin* )
OS_DIR="darwin"
OS_FLAGS="-D__DARWIN__"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
*kfreebsd*-gnu)
OS_DIR="freebsd"
OS_FLAGS="-D__FREEBSD__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
*freebsd* )
OS_DIR="freebsd"
OS_FLAGS="-D__FREEBSD__ -D_XOPEN_SOURCE_EXTENDED"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
*irix* )
OS_DIR="irix"
OS_FLAGS="-D__IRIX__"
- CC_FLAGS=""
- CXX_FLAGS=""
INTRP_CFLAGS="$ARCH_FLAGS $OS_FLAGS"
;;
*uclinux | *elf )
OS_DIR="uclinux"
OS_FLAGS="-D__LINUX__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
*linux* | *Linux* )
OS_DIR="linux"
OS_FLAGS="-D__LINUX__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
*netbsd* )
OS_DIR="netbsd"
OS_FLAGS="-D__NETBSD__ -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D_BSD_SOURCE"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
dnl not set when cpp is called with -std=c99, therefore we add them
dnl here.
OS_FLAGS="-D__SOLARIS__ -D_POSIX_C_SOURCE=200112L -D__EXTENSIONS__ -D_BSD_SOURCE"
- CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long -D_XOPEN_SOURCE=600"
- CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long"
+ CC_FLAGS="-D_XOPEN_SOURCE=600"
+ CXX_FLAGS="-D_XOPEN_SOURCE=500"
INTRP_CFLAGS="-Wall -Wno-long-long $ARCH_FLAGS $OS_FLAGS"
;;
* )
+ AC_MSG_ERROR([$host_os operating systems are currently not supported.])
;;
esac
-dnl temporary set the CFLAGS for configure tests (e.g. inline keyword)
-dnl we set it properly at the end of this file
+dnl Set optimization and debugging for all architectures and systems.
+dnl NOTE: Setting the CFLAGS/CXXFLAGS only works before calling AC_PROG_CC/AC_PROG_CXX.
+if test x"$CFLAGS" = "x"; then
+ OPT_CFLAGS="-g -O0"
+else
+ OPT_CFLAGS=$CFLAGS
+fi
+
+if test x"$CXXFLAGS" = "x"; then
+ OPT_CXXFLAGS="-g -O0"
+else
+ OPT_CXXFLAGS=$CXXFLAGS
+fi
+
+dnl Check for compiler.
+AC_PROG_CC
+AC_PROG_CXX
+
+dnl Check compiler vendor.
+AX_COMPILER_VENDOR
+
+dnl Set compiler flags depending on the compiler vendor.
+case "$ax_cv_c_compiler_vendor" in
+gnu )
+ CC_FLAGS="-std=c99 -pedantic -Wall -Wno-long-long $CC_FLAGS"
+ CXX_FLAGS="-std=c++98 -pedantic -Wall -Wno-long-long $CXX_FLAGS"
+ ;;
+
+sgi )
+ CC_FLAGS="-c99 $CC_FLAGS"
+ CXX_FLAGS="$CXX_FLAGS"
+ ;;
+
+sun )
+ CC_FLAGS="-xc99 $CC_FLAGS"
+ CXX_FLAGS="$CXX_FLAGS"
+ ;;
+
+* )
+ AC_MSG_ERROR([$ax_cv_c_compiler_vendor compilers are currently not supported.])
+ ;;
+esac
+
+dnl Temporary set the CFLAGS for configure tests (e.g. inline keyword)
+dnl we set it properly at the end of this file.
CFLAGS="$OPT_CFLAGS $ARCH_FLAGS $OS_FLAGS $CC_FLAGS"
CXXFLAGS="$OPT_CXXFLAGS $ARCH_FLAGS $OS_FLAGS $CXX_FLAGS"
AC_SUBST(OS_DIR)
AC_SUBST(USE_SCHEDULER)
-
dnl Checks for programs.
-AC_PROG_CC
-AC_PROG_CXX
AM_PROG_AS
AC_PROG_LD
AC_PROG_LD_GNU
dnl keep them alpha-sorted!
AC_CHECK_HEADERS([assert.h])
AC_CHECK_HEADERS([errno.h])
+AC_CHECK_HEADERS([execinfo.h])
AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([libgen.h])
AC_CHECK_HEADERS([netdb.h])
AC_CHECK_HEADERS([signal.h])
+AC_CHECK_HEADERS([stdarg.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)])
AC_CHECK_FUNCS([access])
AC_CHECK_FUNCS([atoi])
AC_CHECK_FUNCS([atol])
+AC_CHECK_FUNCS([backtrace])
+AC_CHECK_FUNCS([backtrace_symbols])
AC_CHECK_FUNCS([calloc])
AC_CHECK_FUNCS([close])
AC_CHECK_FUNCS([confstr])
AC_CHECK_FUNCS([fsync])
AC_CHECK_FUNCS([ftruncate])
AC_CHECK_FUNCS([getcwd])
+AC_CHECK_FUNCS([getenv])
AC_CHECK_FUNCS([gethostbyname])
AC_CHECK_FUNCS([gethostname])
AC_CHECK_FUNCS([getpagesize])
AC_CHECK_FUNCS([mmap])
AC_CHECK_FUNCS([mprotect])
AC_CHECK_FUNCS([open])
+AC_CHECK_FUNCS([printf])
AC_CHECK_FUNCS([read])
AC_CHECK_FUNCS([readlink])
AC_CHECK_FUNCS([realloc])
AC_CHECK_FUNCS([strcat])
AC_CHECK_FUNCS([strchr])
AC_CHECK_FUNCS([strcpy])
+AC_CHECK_FUNCS([strcmp])
AC_CHECK_FUNCS([strdup])
AC_CHECK_FUNCS([strerror])
AC_CHECK_FUNCS([strlen])
AC_CHECK_FUNCS([strncmp])
AC_CHECK_FUNCS([strstr])
AC_CHECK_FUNCS([time])
+AC_CHECK_FUNCS([va_end])
+AC_CHECK_FUNCS([va_start])
AC_CHECK_FUNCS([write])
AC_CHECK_ENABLE_ANNOTATIONS
AC_CHECK_ENABLE_ASSERTION
-
-dnl where is CACAO's vm.zip
-AC_MSG_CHECKING(where CACAO's vm.zip is installed)
-AC_ARG_WITH([vm-zip],
- [AS_HELP_STRING(--with-vm-zip=<path>,path to CACAO's vm.zip (includes the name of the file and may be flat) [[default=/usr/local/cacao/share/cacao/vm.zip]])],
- [CACAO_VM_ZIP=${withval}],
- [CACAO_VM_ZIP=${CACAO_PREFIX}/share/cacao/vm.zip])
-AC_MSG_RESULT(${CACAO_VM_ZIP})
-AC_DEFINE_UNQUOTED([CACAO_VM_ZIP], "${CACAO_VM_ZIP}", [CACAO's vm.zip])
-AC_SUBST(CACAO_VM_ZIP)
-
+dnl This one depends on AC_CHECK_ENABLE_ZLIB.
+AC_CHECK_WITH_VM_ZIP
AC_CHECK_WITH_JAVA_RUNTIME_LIBRARY
AC_CHECK_WITH_JNI_MD_H
AC_CHECK_WITH_JNI_H
-dnl HPI is only required for OpenJDK
+dnl JVM, HPI, and JMM is only required for OpenJDK.
case "${WITH_JAVA_RUNTIME_LIBRARY}" in
openjdk)
+ AC_CHECK_WITH_JVM_MD_H
+ AC_CHECK_WITH_JVM_H
AC_CHECK_WITH_HPI_MD_H
AC_CHECK_WITH_HPI_H
+ AC_CHECK_WITH_JMM_H
;;
*)
;;
--- /dev/null
+dnl Taken from http://ac-archive.sourceforge.net/
+
+dnl @synopsis AX_COMPILER_VENDOR
+dnl
+dnl @summary find the vendor (gnu, intel, etc.) of the C/C++ compiler
+dnl
+dnl Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm,
+dnl sun, hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi,
+dnl microsoft, watcom, etc. The vendor is returned in the cache
+dnl variable $ax_cv_c_compiler_vendor for C and
+dnl $ax_cv_cxx_compiler_vendor for C++.
+dnl
+dnl @category C
+dnl @category Cxx
+dnl @author Steven G. Johnson <stevenj@alum.mit.edu> with Matteo Frigo
+dnl @version 2005-05-30
+dnl @license GPLWithACException
+
+AC_DEFUN([AX_COMPILER_VENDOR],
+[
+AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
+ [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
+ # note: don't check for gcc first since some other compilers define __GNUC__
+ for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
+ vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
+#if !($vencpp)
+ thisisanerror;
+#endif
+])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break])
+ done
+ ])
+])
if test x"${ENABLE_DL}" = "xyes"; then
AC_CHECK_HEADERS([dlfcn.h],, [AC_MSG_ERROR(cannot find dlfcn.h)])
- AC_CHECK_LIB([dl], [dlopen],, [AC_MSG_ERROR(cannot find libdl)])
+
+ case "${OS_DIR}" in
+ freebsd | netbsd )
+ dnl There is no libdl on FreeBSD, and NetBSD (see PR96).
+ ;;
+ *)
+ AC_CHECK_LIB([dl], [dlopen],, [AC_MSG_ERROR(cannot find libdl)])
+ ;;
+ esac
+
AC_CHECK_FUNCS([dlclose])
AC_CHECK_FUNCS([dlerror])
AC_CHECK_FUNCS([dlopen])
--- /dev/null
+dnl m4/jmm.m4
+dnl
+dnl Copyright (C) 2008 Theobroma Systems Ltd.
+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 for jmm.h
+
+AC_DEFUN([AC_CHECK_WITH_JMM_H],[
+AC_MSG_CHECKING(where jmm.h is installed)
+AC_ARG_WITH([jmm_h],
+ [AS_HELP_STRING(--with-jmm_h=<dir>,path to jmm.h (only with --with-java-runtime-library=openjdk) [[default=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export]])],
+ [WITH_JMM_H=${withval}],
+ [case "${WITH_JAVA_RUNTIME_LIBRARY}" in
+ openjdk)
+ WITH_JMM_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export
+ ;;
+ *)
+ ;;
+ esac])
+AC_MSG_RESULT(${WITH_JMM_H})
+
+AC_CHECK_HEADER([${WITH_JMM_H}/jmm.h],
+ [AC_DEFINE_UNQUOTED([INCLUDE_JMM_H], "${WITH_JMM_H}/jmm.h", [Java runtime library jmm.h header])],
+ [AC_MSG_ERROR(cannot find jmm.h)])
+])
--- /dev/null
+dnl m4/jvm.m4
+dnl
+dnl Copyright (C) 2008 Theobroma Systems Ltd.
+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 for jvm_md.h
+
+AC_DEFUN([AC_CHECK_WITH_JVM_MD_H],[
+AC_MSG_CHECKING(where jvm_md.h is installed)
+AC_ARG_WITH([jvm_md_h],
+ [AS_HELP_STRING(--with-jvm_md_h=<dir>,path to jvm_md.h (only with --with-java-runtime-library=openjdk) [[default=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/solaris/javavm/export]])],
+ [WITH_JVM_MD_H=${withval}],
+ [case "${WITH_JAVA_RUNTIME_LIBRARY}" in
+ openjdk)
+ WITH_JVM_MD_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/solaris/javavm/export
+ ;;
+ *)
+ ;;
+ esac])
+AC_MSG_RESULT(${WITH_JVM_MD_H})
+
+AC_CHECK_HEADER([${WITH_JVM_MD_H}/jvm_md.h],
+ [AC_DEFINE_UNQUOTED([INCLUDE_JVM_MD_H], "${WITH_JVM_MD_H}/jvm_md.h", [Java runtime library jvm_md.h header])],
+ [AC_MSG_ERROR(cannot find jvm_md.h)])
+
+dnl Add the path to jvm_md.h to the CPPFLAGS so jvm.h can find it.
+CPPFLAGS="${CPPFLAGS} -I${WITH_JVM_MD_H}"
+])
+
+
+dnl Check for jvm.h
+
+AC_DEFUN([AC_CHECK_WITH_JVM_H],[
+AC_MSG_CHECKING(where jvm.h is installed)
+AC_ARG_WITH([jvm_h],
+ [AS_HELP_STRING(--with-jvm_h=<dir>,path to jvm.h (only with --with-java-runtime-library=openjdk) [[default=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export]])],
+ [WITH_JVM_H=${withval}],
+ [case "${WITH_JAVA_RUNTIME_LIBRARY}" in
+ openjdk)
+ WITH_JVM_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export
+ ;;
+ *)
+ ;;
+ esac])
+AC_MSG_RESULT(${WITH_JVM_H})
+
+AC_CHECK_HEADER([${WITH_JVM_H}/jvm.h],
+ [AC_DEFINE_UNQUOTED([INCLUDE_JVM_H], "${WITH_JVM_H}/jvm.h", [Java runtime library jvm.h header])],
+ [AC_MSG_ERROR(cannot find jvm.h)])
+])
--- /dev/null
+dnl m4/vm-zip.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 where is CACAO's vm.zip
+
+AC_DEFUN([AC_CHECK_WITH_VM_ZIP],[
+AC_MSG_CHECKING(where CACAO's vm.zip is installed)
+AC_ARG_WITH([vm-zip],
+ [AS_HELP_STRING(--with-vm-zip=<path>,path to CACAO's vm.zip (includes the name of the file and may be flat) [[default=(--enable-zlib:${CACAO_PREFIX}/share/cacao/vm.zip,--disable-zlib:${CACAO_PREFIX}/share/cacao/classes)]])],
+ [CACAO_VM_ZIP=${withval}],
+ [case "${ENABLE_ZLIB}" in
+ no)
+ CACAO_VM_ZIP=${CACAO_PREFIX}/share/cacao/classes
+ ;;
+ *)
+ CACAO_VM_ZIP=${CACAO_PREFIX}/share/cacao/vm.zip
+ ;;
+ esac
+ ])
+AC_MSG_RESULT(${CACAO_VM_ZIP})
+AC_DEFINE_UNQUOTED([CACAO_VM_ZIP], "${CACAO_VM_ZIP}", [CACAO's vm.zip])
+AC_SUBST(CACAO_VM_ZIP)
+])
#include "config.h"
-#include <assert.h>
-
#if defined(ENABLE_JRE_LAYOUT)
# include <errno.h>
# include <libgen.h>
# include <unistd.h>
#endif
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JVMTI)
# include "native/jvmti/jvmti.h"
void* libjvm_vm_run;
const char* lterror;
- bool (*VM_create)(JavaVM **, void **, void *);
- void (*vm_run)(JavaVM *, JavaVMInitArgs *);
+ 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);
+ // Prepare the options.
+ JavaVMInitArgs* vm_args = prepare_options(argc, argv);
/* load and initialize a Java VM, return a JNI interface pointer in env */
os::abort();
}
- /* concatinate the library name */
+ /* concatenate the library name */
strcat(path, "/../lib/"LIBJVM_NAME);
# else
os::abort();
}
- /* free the error string */
-
- free((void *) lterror);
+ // Free the error string.
+ os::free((void*) lterror);
}
libjvm_VM_create = os::dlsym(libjvm_handle, "VM_create");
os::abort();
}
- VM_create =
- (bool (*)(JavaVM **, void **, void *)) (ptrint) libjvm_VM_create;
+ VM_create = (bool (*)(JavaVM**, void**, void*)) (uintptr_t) libjvm_VM_create;
#endif
- /* create the Java VM */
+ // Create the Java VM.
+ JavaVM* vm;
+ void* env; // We use a void* instead of a JNIEnv* here to prevent a compiler warning.
- (void) VM_create(&vm, (void**) &env, vm_args);
+ (void) VM_create(&vm, &env, vm_args);
#if defined(ENABLE_JVMTI)
# error This should be a JVMTI function.
os::abort();
}
- vm_run = (void (*)(JavaVM *, JavaVMInitArgs *)) (ptrint) libjvm_vm_run;
+ vm_run = (void (*)(JavaVM*, JavaVMInitArgs*)) (uintptr_t) libjvm_vm_run;
#endif
- /* run the VM */
-
+ // Run the VM.
vm_run(vm, vm_args);
- /* keep compiler happy */
-
+ // Keep compiler happy.
return 0;
}
if ENABLE_ZLIB
pkgdata_DATA = vm.zip
else
-pkgdata_DATA = nozip
+noinst_DATA = nozip
endif
endif
if ENABLE_ZLIB
pkgdata_DATA = vm.zip
else
-pkgdata_DATA = nozip
+noinst_DATA = nozip
endif
endif
nozip: $(VM_JAVA_FILES)
$(mkdir_p) classes
$(JAVAC) -bootclasspath $(BOOTCLASSPATH) -source 1.5 -target 1.5 -d classes $(VM_JAVA_FILES)
+
+install-data-local: nozip
+ $(mkinstalldirs) $(DESTDIR)$(pkgdatadir)
+ cp -R classes $(DESTDIR)$(pkgdatadir)
+
+uninstall-local:
+ rm -rf $(DESTDIR)$(pkgdatadir)/classes
+
endif
clean-local:
libmm_la_SOURCES = \
codememory.c \
codememory.h \
- dumpmemory.c \
- dumpmemory.h \
+ dumpmemory.cpp \
+ dumpmemory.hpp \
$(GC_FILE) \
gc.hpp \
memory.c \
#include "config.h"
#include "vm/types.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#include "vm/method.h"
#include "vm/types.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "threads/thread.hpp"
#include "compact.h"
#include "threads/thread.hpp"
-#include "toolbox/list.h"
-#include "vm/jit/replace.h"
+#include "toolbox/list.hpp"
+#include "vm/jit/replace.hpp"
/* Configuration Switches *****************************************************/
#include "config.h"
#include "vm/types.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "gc.h"
#include "final.h"
#include "gc.h"
#include "region.h"
-#include "vm/array.h" /* needed for ARRAYTYPE_OBJECT */
+#include "vm/array.hpp" /* needed for ARRAYTYPE_OBJECT */
#define GC_SIZE_DUMMY 0xff
#include "toolbox/logging.h"
#include "vm/global.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/method.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
/* Structures *****************************************************************/
#include <stdlib.h>
#include <sys/mman.h> /* REMOVEME */
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
#include "threads/thread.hpp"
#include "mm/codememory.h"
#define DEFAULT_CODE_MEMORY_SIZE 128 * 1024 /* defaulting to 128kB */
#if defined(ENABLE_THREADS)
-static java_object_t *lock_code_memory = NULL;
+static Mutex *code_memory_mutex = NULL;
#endif
-static void *code_memory = NULL;
-static int code_memory_size = 0;
-static int pagesize = 0;
+static void *code_memory = NULL;
+static int code_memory_size = 0;
+static int pagesize = 0;
/* codememory_init *************************************************************
TRACESUBSYSTEMINITIALIZATION("codememory_init");
#if defined(ENABLE_THREADS)
- /* create lock for code memory */
+ /* create mutex for code memory */
- lock_code_memory = NEW(java_object_t);
-
- lock_init_object_lock(lock_code_memory);
+ code_memory_mutex = Mutex_new();
#endif
/* Get the pagesize of this architecture. */
{
void *p;
- LOCK_MONITOR_ENTER(lock_code_memory);
+ Mutex_lock(code_memory_mutex);
size = MEMORY_ALIGN(size, ALIGNSIZE);
code_memory = (void *) ((ptrint) code_memory + size);
code_memory_size -= size;
- LOCK_MONITOR_EXIT(lock_code_memory);
+ Mutex_unlock(code_memory_mutex);
return p;
}
+++ /dev/null
-/* src/mm/dumpmemory.c - dump memory management
-
- 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/dumpmemory.h"
-#include "mm/memory.h"
-
-#include "threads/thread.hpp"
-
-#include "vm/options.h"
-#include "vm/os.hpp"
-
-#if defined(ENABLE_STATISTICS)
-# include "vm/statistics.h"
-#endif
-
-#include "vm/vm.hpp"
-
-
-/*******************************************************************************
-
- This structure is used for dump memory allocation if cacao
- runs without threads.
-
-*******************************************************************************/
-
-#if !defined(ENABLE_THREADS)
-static dumpinfo_t _no_threads_dumpinfo;
-#endif
-
-#if defined(ENABLE_THREADS)
-#define DUMPINFO &((threadobject *) THREADOBJECT)->dumpinfo
-#else
-#define DUMPINFO &_no_threads_dumpinfo
-#endif
-
-
-/* dump_check_canaries *********************************************************
-
- Check canaries in dump memory.
-
- IN:
- di...........dumpinfo_t * of the dump area to check
- bottomsize...dump size down to which the dump area should be checked
- (specify 0 to check the whole dump area)
-
- ERROR HANDLING:
- If any canary has been changed, this function aborts the VM with
- an error message.
-
-*******************************************************************************/
-
-#if defined(ENABLE_MEMCHECK)
-static void dump_check_canaries(dumpinfo_t *di, s4 bottomsize)
-{
- dump_allocation_t *da;
- uint8_t *pm;
- int i, j;
-
- /* iterate over all dump memory allocations above bottomsize */
-
- da = di->allocations;
-
- while (da && da->used >= bottomsize) {
- /* check canaries */
-
- pm = ((uint8_t *) da->mem) - MEMORY_CANARY_SIZE;
-
- for (i = 0; i < MEMORY_CANARY_SIZE; ++i) {
- if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
- fprintf(stderr, "canary bytes:");
-
- for (j = 0; j < MEMORY_CANARY_SIZE; ++j)
- fprintf(stderr, " %02x", pm[j]);
-
- fprintf(stderr,"\n");
-
- vm_abort("error: dump memory bottom canary killed: "
- "%p (%d bytes allocated at %p)\n",
- pm + i, da->size, da->mem);
- }
- }
-
- pm = ((uint8_t *) da->mem) + da->size;
-
- for (i = 0; i < MEMORY_CANARY_SIZE; ++i) {
- if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
- fprintf(stderr, "canary bytes:");
-
- for (j = 0; j < MEMORY_CANARY_SIZE; ++j)
- fprintf(stderr, " %02x", pm[j]);
-
- fprintf(stderr, "\n");
-
- vm_abort("error: dump memory top canary killed: "
- "%p (%d bytes allocated at %p)\n",
- pm + i, da->size, da->mem);
- }
- }
-
- da = da->next;
- }
-}
-#endif /* defined(ENABLE_MEMCHECK) */
-
-
-/* dumpmemory_alloc ************************************************************
-
- ATTENTION: This function must only be called from dumpmemory_get!
-
- Allocate a new dump memory block.
-
- IN:
- di ..... dumpinfo_t of the current thread
- size ... required memory size
-
-*******************************************************************************/
-
-void dumpmemory_alloc(dumpinfo_t *di, size_t size)
-{
- dumpblock_t *db;
- size_t newblocksize;
-
- /* Allocate a new dumpblock_t structure. */
-
- db = memory_checked_alloc(sizeof(dumpblock_t));
-
- /* If requested size is greater than the default, make the new
- dump block as big as the size requested. Else use the default
- size. */
-
- if (size > DUMPBLOCKSIZE) {
- newblocksize = size;
- }
- else {
- newblocksize = DUMPBLOCKSIZE;
- }
-
- /* allocate dumpblock memory */
-
- db->dumpmem = memory_checked_alloc(newblocksize);
-
- db->size = newblocksize;
- db->prev = di->block;
- di->block = db;
-
- /* Used dump size is previously allocated dump size, because the
- remaining free memory of the previous dump block cannot be
- used. */
-
- di->used = di->allocated;
-
- /* Increase the allocated dump size by the size of the new dump
- block. */
-
- di->allocated += newblocksize;
-
-#if defined(ENABLE_STATISTICS)
- /* The amount of globally allocated dump memory (thread save). */
-
- if (opt_stat)
- globalallocateddumpsize += newblocksize;
-#endif
-}
-
-
-/* dumpmemory_get **************************************************************
-
- Allocate memory in the dump area.
-
- IN:
- size.........size of block to allocate, in bytes
- may be zero, in which case NULL is returned
-
- RETURN VALUE:
- pointer to allocated memory, or
- NULL iff `size` was zero
-
- ERROR HANDLING:
- XXX This function uses `memory_checked_alloc`, which *exits* if
- no memory could be allocated.
-
- THREADS:
- dumpmemory_get is thread safe. Each thread has its own dump
- memory area.
-
- This function is a fast allocator suitable for scratch memory that
- can be collectively freed when the current activity (eg. compiling)
- is done.
-
- You cannot selectively free dump memory. Before you start
- allocating it, you remember the current size returned by
- `dumpmemory_marker`. Later, when you no longer need the memory,
- call `dumpmemory_release` with the remembered size and all dump
- memory allocated since the call to `dumpmemory_marker` will be
- freed.
-
-*******************************************************************************/
-
-void *dumpmemory_get(size_t size)
-{
-#if defined(DISABLE_DUMP)
-
- /* use malloc memory for dump memory (for debugging only!) */
-
- return mem_alloc(size);
-
-#else /* !defined(DISABLE_DUMP) */
-
- void *p;
- dumpinfo_t *di;
-#if defined(ENABLE_MEMCHECK)
- s4 origsize = size; /* needed for the canary system */
-#endif
-
- di = DUMPINFO;
-
- if (size == 0)
- return NULL;
-
-#if defined(ENABLE_MEMCHECK)
- size += 2 * MEMORY_CANARY_SIZE;
-#endif
-
- size = MEMORY_ALIGN(size, ALIGNSIZE);
-
- /* Check if we have enough memory in the current memory block. */
-
- if (di->used + size > di->allocated) {
- /* If not, allocate a new one. */
-
- dumpmemory_alloc(di, size);
- }
-
- /* current dump block base address + the size of the current dump
- block - the size of the unused memory = new start address */
-
- p = ((uint8_t *) di->block->dumpmem) + di->block->size -
- (di->allocated - di->used);
-
-#if defined(ENABLE_MEMCHECK)
- {
- dump_allocation_t *da = NEW(dump_allocation_t);
- uint8_t *pm;
- int i;
-
- /* add the allocation to our linked list of allocations */
-
- da->next = di->allocations;
- da->mem = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
- da->size = origsize;
- da->used = di->used;
-
- di->allocations = da;
-
- /* write the canaries */
-
- pm = (uint8_t *) p;
-
- for (i = 0; i < MEMORY_CANARY_SIZE; ++i)
- pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
-
- pm = ((uint8_t *) da->mem) + da->size;
-
- for (i = 0; i < MEMORY_CANARY_SIZE; ++i)
- pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
-
- /* make m point after the bottom canary */
-
- p = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
-
- /* clear the memory */
-
- (void) os_memset(p, MEMORY_CLEAR_BYTE, da->size);
- }
-#endif /* defined(ENABLE_MEMCHECK) */
-
- /* Increase used dump size by the allocated memory size. */
-
- di->used += size;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- if (di->used > maxdumpsize)
- maxdumpsize = di->used;
-#endif
-
- return p;
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/* dumpmemory_realloc **********************************************************
-
- Stupid realloc implementation for dump memory. Avoid, if possible.
-
-*******************************************************************************/
-
-void *dumpmemory_realloc(void *src, s4 len1, s4 len2)
-{
-#if defined(DISABLE_DUMP)
- /* use malloc memory for dump memory (for debugging only!) */
-
- return mem_realloc(src, len1, len2);
-#else
- void *dst;
-
- dst = dumpmemory_get(len2);
-
- (void) os_memcpy(dst, src, len1);
-
-#if defined(ENABLE_MEMCHECK)
- /* destroy the source */
-
- (void) os_memset(src, MEMORY_CLEAR_BYTE, len1);
-#endif
-
- return dst;
-#endif
-}
-
-
-/* dumpmemory_release **********************************************************
-
- Release dump memory above the given size.
-
- IN:
- size........All dump memory above this mark will be freed. Usually
- `size` will be the return value of a `dumpmemory_marker`
- call made earlier.
-
- ERROR HANDLING:
- XXX If the given size is invalid, this function *exits* with an
- error message.
-
- See `dump_alloc`.
-
-*******************************************************************************/
-
-void dumpmemory_release(s4 size)
-{
-#if defined(DISABLE_DUMP)
-
- /* use malloc memory for dump memory (for debugging only!) */
-
- /* do nothing */
-
-#else /* !defined(DISABLE_DUMP) */
-
- dumpinfo_t *di;
-
- di = DUMPINFO;
-
- if ((size < 0) || (size > di->used))
- vm_abort("dump_release: Illegal dump release size: %d", size);
-
-#if defined(ENABLE_MEMCHECK)
- {
- dump_allocation_t *da, *next;
-
- /* check canaries */
-
- dump_check_canaries(di, size);
-
- /* iterate over all dump memory allocations about to be released */
-
- da = di->allocations;
-
- while ((da != NULL) && (da->used >= size)) {
- next = da->next;
-
- /* invalidate the freed memory */
-
- (void) os_memset(da->mem, MEMORY_CLEAR_BYTE, da->size);
-
- FREE(da, dump_allocation_t);
-
- da = next;
- }
- di->allocations = da;
- }
-#endif /* defined(ENABLE_MEMCHECK) */
-
- /* Reset the used dump size to the size specified. */
-
- di->used = size;
-
- while ((di->block != NULL) && di->allocated - di->block->size >= di->used) {
- dumpblock_t *tmp = di->block;
-
- di->allocated -= tmp->size;
- di->block = tmp->prev;
-
-#if defined(ENABLE_STATISTICS)
- /* the amount of globally allocated dump memory (thread save) */
-
- if (opt_stat)
- globalallocateddumpsize -= tmp->size;
-#endif
-
- /* Release the dump memory and the dumpinfo structure. */
-
- os_free(tmp->dumpmem);
- os_free(tmp);
- }
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/* dumpmemory_marker ***********************************************************
-
- Returns a marker of the dump memory area. This marker is actually
- the used size of the dump memory area.
-
- RETURN VALUE:
- marker of the current dump memory status
-
-*******************************************************************************/
-
-int32_t dumpmemory_marker(void)
-{
-#if defined(DISABLE_DUMP)
- /* use malloc memory for dump memory (for debugging only!) */
-
- return 0;
-
-#else /* !defined(DISABLE_DUMP) */
-
- dumpinfo_t *di;
-
- di = DUMPINFO;
-
- if (di == NULL)
- return 0;
-
- return di->used;
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/*
- * These 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/dumpmemory.cpp - dump memory management
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ 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 "mm/dumpmemory.hpp"
+#include "mm/memory.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/options.h"
+#include "vm/os.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/vm.hpp"
+
+
+/*******************************************************************************
+
+ This structure is used for dump memory allocation if cacao
+ runs without threads.
+
+*******************************************************************************/
+
+#if !defined(ENABLE_THREADS)
+static dumpinfo_t _no_threads_dumpinfo;
+#endif
+
+
+/**
+ * Allocate a new thread-local dump memory structure.
+ */
+DumpMemory::DumpMemory() : _size(0), _used(0)
+{
+}
+
+
+/**
+ * Stupid realloc implementation for dump memory. Avoid, if possible.
+ */
+void* DumpMemory::reallocate(void* src, size_t len1, size_t len2)
+{
+ void* dst = allocate(len2);
+
+ (void) os::memcpy(dst, src, len1);
+
+#if defined(ENABLE_MEMCHECK)
+ // Destroy the source.
+ (void) os::memset(src, MEMORY_CLEAR_BYTE, len1);
+#endif
+
+ return dst;
+}
+
+
+/**
+ * Add the given dump area to the area list.
+ *
+ * @param dm Pointer to dump area.
+ */
+void DumpMemory::add_area(DumpMemoryArea* dma)
+{
+ _areas.push_back(dma);
+
+ // Increase the size count of the dump memory.
+ _size += dma->get_size();
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ if (_size > (size_t) maxdumpsize)
+ maxdumpsize = _size;
+ }
+#endif
+}
+
+
+/**
+ * Remove the given dump area from the area list.
+ *
+ * @param dm Pointer to dump area.
+ */
+void DumpMemory::remove_area(DumpMemoryArea* dma)
+{
+ // Sanity check.
+ assert(_areas.back() == dma);
+
+ // Remove the last area from the list. The check above guarantees
+ // we are removing the correct area.
+ _areas.pop_back();
+
+ // Decrease the size and used count.
+ _size -= dma->get_size();
+ _used -= dma->get_used();
+}
+
+
+/**
+ * Allocate a new dump memory area.
+ *
+ * @ param size Required memory size.
+ */
+DumpMemoryArea::DumpMemoryArea(size_t size) : _size(0), _used(0)
+{
+ // Get the DumpMemory object of the current thread.
+ DumpMemory* dm = DumpMemory::get_current();
+
+ // Add this area to the areas list.
+ dm->add_area(this);
+}
+
+
+/**
+ * Release all dump memory blocks in the current dump area.
+ */
+DumpMemoryArea::~DumpMemoryArea()
+{
+ // Get the DumpMemory object of the current thread.
+ DumpMemory* dm = DumpMemory::get_current();
+
+#if defined(ENABLE_MEMCHECK)
+ // Check canaries.
+
+ check_canaries();
+
+ // Iterate over all dump memory allocations about to be released.
+
+ for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
+ DumpMemoryAllocation* dma = *it;
+
+ // Invalidate the freed memory.
+ (void) os::memset(dma->get_mem(), MEMORY_CLEAR_BYTE, dma->get_size());
+
+ // Call the destructor of the current allocation.
+ delete dma;
+ }
+#endif /* defined(ENABLE_MEMCHECK) */
+
+ // Free all memory blocks.
+ for (std::vector<DumpMemoryBlock*>::iterator it = _blocks.begin(); it != _blocks.end(); it++) {
+ // Call the destructor of the current block.
+ delete *it;
+ }
+
+ // Remove this area for the area list.
+ dm->remove_area(this);
+}
+
+
+/**
+ * Allocate a dump memory block for the current dump memory area.
+ *
+ * @param size Required memory size.
+ *
+ * @return Pointer to the newly allocated block.
+ */
+DumpMemoryBlock* DumpMemoryArea::allocate_new_block(size_t size)
+{
+ DumpMemoryBlock* dmb = new DumpMemoryBlock(size);
+ _blocks.push_back(dmb);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ DumpMemory* dm = DumpMemory::get_current();
+ dm->add_size(dmb->get_size());
+
+ if (dm->get_size() > (size_t) maxdumpsize)
+ maxdumpsize = dm->get_size();
+ }
+#endif
+
+ return dmb;
+}
+
+
+/**
+ * Checks canaries in this dump memory area. If any canary has been changed,
+ * this function aborts the VM with an error message.
+ */
+#if defined(ENABLE_MEMCHECK)
+void DumpMemoryArea::check_canaries()
+{
+ uint8_t* pm;
+
+ // Iterate over all dump memory allocations.
+
+ for (std::vector<DumpMemoryAllocation*>::iterator it = _allocs.begin(); it != _allocs.end(); it++) {
+ DumpMemoryAllocation* dma = *it;
+
+ // Check canaries.
+
+ pm = ((uint8_t *) dma->get_mem()) - MEMORY_CANARY_SIZE;
+
+ for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
+ if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
+ fprintf(stderr, "canary bytes:");
+
+ for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
+ fprintf(stderr, " %02x", pm[j]);
+
+ fprintf(stderr,"\n");
+
+ vm_abort("error: dump memory bottom canary killed: "
+ "%p (%d bytes allocated at %p)\n",
+ pm + i, dma->get_size(), dma->get_mem());
+ }
+ }
+
+ pm = ((uint8_t *) dma->get_mem()) + dma->get_size();
+
+ for (int i = 0; i < MEMORY_CANARY_SIZE; ++i) {
+ if (pm[i] != i + MEMORY_CANARY_FIRST_BYTE) {
+ fprintf(stderr, "canary bytes:");
+
+ for (int j = 0; j < MEMORY_CANARY_SIZE; ++j)
+ fprintf(stderr, " %02x", pm[j]);
+
+ fprintf(stderr, "\n");
+
+ vm_abort("error: dump memory top canary killed: "
+ "%p (%d bytes allocated at %p)\n",
+ pm + i, dma->get_size(), dma->get_mem());
+ }
+ }
+ }
+}
+#endif /* defined(ENABLE_MEMCHECK) */
+
+
+/**
+ * Allocate a memory block for the current dump memory block.
+ *
+ * @param size Required memory size.
+ */
+DumpMemoryBlock::DumpMemoryBlock(size_t size) : _size(0), _used(0), _block(0)
+{
+ // If requested size is greater than the default, make the new
+ // memory block as big as the requested size. Otherwise use the
+ // default size.
+ _size = (size > DEFAULT_SIZE) ? size : DEFAULT_SIZE;
+
+ // Allocate a memory block.
+ _block = memory_checked_alloc(_size);
+
+#if defined(ENABLE_STATISTICS)
+ // The amount of globally allocated dump memory (thread safe).
+ if (opt_stat)
+ globalallocateddumpsize += _size;
+#endif
+}
+
+
+/**
+ * Release the memory block for the dump memory block.
+ *
+ * @param size Required memory size.
+ */
+DumpMemoryBlock::~DumpMemoryBlock()
+{
+ // Release the memory block.
+ mem_free(_block, /* XXX */ 1);
+
+#if defined(ENABLE_STATISTICS)
+ // The amount of globally allocated dump memory (thread safe).
+ if (opt_stat)
+ globalallocateddumpsize -= _size;
+#endif
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+ void* DumpMemory_allocate(size_t size) { return DumpMemory::allocate(size); }
+ void* DumpMemory_reallocate(void* src, size_t len1, size_t len2) { return DumpMemory::reallocate(src, len1, len2); }
+}
+
+
+/*
+ * These 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/dumpmemory.h - dump memory management
-
- 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 _DUMPMEMORY_H
-#define _DUMPMEMORY_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct dumpblock_t dumpblock_t;
-typedef struct dumpinfo_t dumpinfo_t;
-
-#include "config.h"
-
-#include <stdint.h>
-#include <string.h>
-
-
-/* ATTENTION: We need to define dumpblock_t and dumpinfo_t before
- internal includes, as we need dumpinfo_t as nested structure in
- threadobject. */
-
-/* dumpblock ******************************************************************/
-
-#define DUMPBLOCKSIZE 2 << 13 /* 2 * 8192 bytes */
-#define ALIGNSIZE 8
-
-struct dumpblock_t {
- dumpblock_t *prev;
- void *dumpmem;
- int32_t size;
-};
-
-
-/* dump_allocation *************************************************************
-
- This struct is used to record dump memory allocations for ENABLE_MEMCHECK.
-
-*******************************************************************************/
-
-#if defined(ENABLE_MEMCHECK)
-typedef struct dump_allocation_t dump_allocation_t;
-
-struct dump_allocation_t {
- dump_allocation_t *next;
- void *mem;
- int32_t used;
- int32_t size;
-};
-#endif
-
-
-/* dumpinfo *******************************************************************/
-
-struct dumpinfo_t {
- dumpblock_t *block; /* the current top-most block */
- int32_t allocated; /* allocated bytes in this area */
- int32_t used; /* used bytes in this dump area */
-#if defined(ENABLE_MEMCHECK)
- dump_allocation_t *allocations; /* list of allocations in this area */
-#endif
-};
-
-
-/* convenience macros *********************************************************/
-
-#define DMARKER dumpmarker = dumpmemory_marker()
-#define DRELEASE dumpmemory_release(dumpmarker)
-
-#define DNEW(type) ((type *) dumpmemory_get(sizeof(type)))
-#define DMNEW(type,num) ((type *) dumpmemory_get(sizeof(type) * (num)))
-#define DMREALLOC(ptr,type,num1,num2) ((type*) dumpmemory_realloc((ptr), sizeof(type) * (num1), \
- sizeof(type) * (num2)))
-
-/* function prototypes ********************************************************/
-
-void *dumpmemory_get(size_t size);
-void *dumpmemory_realloc(void *src, int32_t len1, int32_t len2);
-int32_t dumpmemory_marker(void);
-void dumpmemory_release(int32_t size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _DUMPMEMORY_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/mm/dumpmemory.hpp - dump memory management
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ 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 _DUMPMEMORY_HPP
+#define _DUMPMEMORY_HPP
+
+#include "config.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+
+#include <cstddef>
+#include <list>
+#include <vector>
+#include <stdio.h> // REMOVEME
+
+
+// Forward declaration.
+class DumpMemoryArea;
+class DumpMemoryBlock;
+#if defined(ENABLE_MEMCHECK)
+class DumpMemoryAllocation;
+#endif
+
+
+/**
+ * Thread-local dump memory structure.
+ */
+class DumpMemory {
+private:
+ size_t _size; ///< Size of the dump areas in this dump memory.
+ size_t _used; ///< Used memory in this dump memory.
+ std::list<DumpMemoryArea*> _areas; ///< Pointer to the current dump area.
+
+public:
+ DumpMemory();
+ ~DumpMemory();
+
+ static inline DumpMemory* get_current();
+ static inline void* allocate(size_t size);
+
+ inline void add_size(size_t size) { _size += size; }
+
+ inline size_t get_size() const { return _size; }
+ inline size_t get_used() const { return _used; }
+
+ inline DumpMemoryArea* get_current_area() const;
+
+ static void* reallocate(void* src, size_t len1, size_t len2);
+
+ void add_area(DumpMemoryArea* dma);
+ void remove_area(DumpMemoryArea* dma);
+};
+
+
+/**
+ * Dump memory area.
+ */
+class DumpMemoryArea {
+private:
+ size_t _size; ///< Size of the current memory block.
+ size_t _used; ///< Used memory in the current memory block.
+ std::vector<DumpMemoryBlock*> _blocks; ///< List of memory blocks in this area.
+#if defined(ENABLE_MEMCHECK)
+ std::vector<DumpMemoryAllocation*> _allocs; ///< List of allocations in this area.
+#endif
+
+public:
+ DumpMemoryArea(size_t size = 0);
+ ~DumpMemoryArea();
+
+ inline size_t get_size() const { return _size; }
+ inline size_t get_used() const { return _used; }
+
+ // Inline functions.
+ inline void* allocate(size_t size);
+ inline DumpMemoryBlock* get_current_block() const;
+
+ DumpMemoryBlock* allocate_new_block(size_t size);
+
+#if defined(ENABLE_MEMCHECK)
+private:
+ void check_canaries();
+#endif
+};
+
+
+/**
+ * Dump memory block.
+ */
+class DumpMemoryBlock {
+private:
+ static const size_t DEFAULT_SIZE = 2 << 13; // 2 * 8192 bytes
+
+ size_t _size; ///< Size of the current memory block.
+ size_t _used; ///< Used memory in the current memory block.
+ void* _block; ///< List of memory blocks in this area.
+
+public:
+ DumpMemoryBlock(size_t size = 0);
+ ~DumpMemoryBlock();
+
+ inline size_t get_size() const { return _size; }
+ inline size_t get_used() const { return _used; }
+ inline size_t get_free() const { return _size - _used; }
+
+ // Inline functions.
+ inline void* allocate(size_t size);
+};
+
+
+/**
+ * Allocator for the dump memory.
+ */
+template<class T> class DumpMemoryAllocator {
+public:
+ // Type definitions.
+ typedef T value_type;
+ typedef T* pointer;
+ typedef const T* const_pointer;
+ typedef T& reference;
+ typedef const T& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ // Rebind allocator to type U.
+ template <class U> struct rebind {
+ typedef DumpMemoryAllocator<U> other;
+ };
+
+ // Constructors and destructor, nothing to do because the
+ // allocator has no state.
+ DumpMemoryAllocator() throw() {}
+ DumpMemoryAllocator(const DumpMemoryAllocator&) throw() {}
+ template <class U> DumpMemoryAllocator(const DumpMemoryAllocator<U>&) throw() {}
+
+ ~DumpMemoryAllocator() throw() {}
+
+ pointer allocate(size_type n, void* = 0) {
+// printf("allocate: n=%d * %d\n", n, sizeof(T));
+ return static_cast<pointer>(DumpMemory::allocate(n * sizeof(T)));
+ }
+
+ // Initialize elements of allocated storage p with value value.
+ void construct(pointer p, const T& value) {
+// printf("construct: p=%p, value=%p\n", (void*) p, (void*) value);
+ // Initialize memory with placement new.
+ new ((void*) p) T(value);
+ }
+
+ // Destroy elements of initialized storage p.
+ void destroy(pointer p) {
+// printf("destroy: p=%p\n", (void*) p);
+ // Destroy objects by calling their destructor.
+ p->~T();
+ }
+
+ void deallocate(pointer p, size_type n) {
+// printf("deallocate: p=%p, n=%d\n", (void*) p, n);
+ // We don't need to deallocate on dump memory.
+ }
+};
+
+
+/**
+ * Dump memory allocation, used for for ENABLE_MEMCHECK.
+ */
+#if defined(ENABLE_MEMCHECK)
+class DumpMemoryAllocation {
+private:
+ size_t _size;
+ void* _mem;
+
+public:
+ DumpMemoryAllocation() : _size(0), _mem(NULL) {}
+ DumpMemoryAllocation(size_t size, void* mem) : _size(size), _mem(mem) {}
+ ~DumpMemoryAllocation() {};
+
+ inline size_t get_size() const { return _size; }
+ inline void* get_mem() const { return _mem; }
+};
+#endif
+
+
+// Includes.
+#include "mm/memory.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+
+// Inline functions.
+
+inline DumpMemory* DumpMemory::get_current()
+{
+ // Get the DumpMemory object of the current thread.
+ threadobject* t = thread_get_current();
+ DumpMemory* dm = t->_dumpmemory;
+ return dm;
+}
+
+inline DumpMemoryArea* DumpMemory::get_current_area() const
+{
+ return _areas.back();
+}
+
+inline void* DumpMemory::allocate(size_t size)
+{
+ DumpMemory* dm = get_current();
+ DumpMemoryArea* dma = dm->get_current_area();
+
+ size_t alignedsize = size;
+
+#if defined(ENABLE_MEMCHECK)
+ alignedsize += 2 * MEMORY_CANARY_SIZE;
+#endif
+
+ // Align the allocation size.
+ alignedsize = MEMORY_ALIGN(alignedsize, ALIGNSIZE);
+
+ void* p = dma->allocate(alignedsize);
+
+ // Increase the used count of the dump memory.
+ dm->_used += alignedsize;
+
+ return p;
+}
+
+inline DumpMemoryBlock* DumpMemoryArea::get_current_block() const
+{
+ return _blocks.empty() ? NULL : _blocks.back();
+}
+
+inline void* DumpMemoryArea::allocate(size_t size)
+{
+ DumpMemoryBlock* dmb = get_current_block();
+
+ // Check if we have a memory block or have enough memory in the
+ // current memory block.
+ if (dmb == NULL || size > dmb->get_free()) {
+ // No, allocate a new one.
+ dmb = allocate_new_block(size);
+
+ // Increase the size of the memory area. We use get_size()
+ // here because the default size is very likely to be bigger
+ // than size.
+ _size += dmb->get_size();
+ }
+
+ void* p = dmb->allocate(size);
+
+#if defined(ENABLE_MEMCHECK)
+ uint8_t *pm;
+ size_t origsize = size - 2 * MEMORY_CANARY_SIZE;
+
+ // Make p point after the bottom canary.
+
+ p = ((uint8_t *) p) + MEMORY_CANARY_SIZE;
+
+ // Add the allocation to our list of allocations
+
+ DumpMemoryAllocation* dma = new DumpMemoryAllocation(origsize, p);
+
+ _allocs.push_back(dma);
+
+ // Write the canaries.
+
+ pm = ((uint8_t *) p) - MEMORY_CANARY_SIZE;
+
+ for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
+ pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
+
+ pm = ((uint8_t *) p) + dma->get_size();
+
+ for (int i = 0; i < MEMORY_CANARY_SIZE; ++i)
+ pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
+
+ // Clear the memory.
+
+ (void) os::memset(p, MEMORY_CLEAR_BYTE, dma->get_size());
+#endif /* defined(ENABLE_MEMCHECK) */
+
+ // Increase the used size of the memory area.
+ _used += size;
+
+ return p;
+}
+
+/**
+ * Allocate memory in the current dump memory area.
+ *
+ * This function is a fast allocator suitable for scratch memory that
+ * can be collectively freed when the current activity (eg. compiling)
+ * is done.
+ *
+ * You cannot selectively free dump memory. Before you start
+ * allocating it, you remember the current size returned by
+ * `dumpmemory_marker`. Later, when you no longer need the memory,
+ * call `dumpmemory_release` with the remembered size and all dump
+ * memory allocated since the call to `dumpmemory_marker` will be
+ * freed.
+ *
+ * @parm size Size of block to allocate in bytes. May be zero, in which case NULL is returned
+ *
+ * @return Pointer to allocated memory, or NULL iff size was zero.
+ */
+void* DumpMemoryBlock::allocate(size_t size)
+{
+ if (size == 0)
+ return NULL;
+
+ // Sanity check.
+ assert(size <= (_size - _used));
+
+ // Calculate the memory address of the newly allocated memory.
+ void* p = (void*) (((uint8_t*) _block) + _used);
+
+ // Increase used memory block size by the allocated memory size.
+ _used += size;
+
+ return p;
+}
+
+#else
+
+// Legacy C interface.
+
+void* DumpMemory_allocate(size_t size);
+void* DumpMemory_reallocate(void* src, size_t len1, size_t len2);
+
+#define DNEW(type) ((type*) DumpMemory_allocate(sizeof(type)))
+#define DMNEW(type,num) ((type*) DumpMemory_allocate(sizeof(type) * (num)))
+#define DMREALLOC(ptr,type,num1,num2) ((type*) DumpMemory_reallocate((ptr), sizeof(type) * (num1), sizeof(type) * (num2)))
+
+#endif
+
+#endif // _DUMPMEMORY_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 "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/finalizer.h"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/rt-timing.h"
#include "vm/string.hpp"
if (in_gc_out_of_memory) {
/* this is all we can do... */
- vm_abort("gc_out_of_memory: out of memory");
+ os::abort("gc_out_of_memory: out of memory");
}
in_gc_out_of_memory = true;
* Emacs will automagically detect them.
* ---------------------------------------------------------------------
* Local variables:
- * mode: c
+ * mode: c++
* indent-tabs-mode: t
* c-basic-offset: 4
* tab-width: 4
#include "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/vm.hpp"
#include "config.h"
+#include <assert.h>
#include <stdint.h>
+
#ifdef __cplusplus
-extern "C" {
+
+class GC {
+public:
+};
+
+
+/**
+ * Critical section for the GC.
+ */
+class GCCriticalSection {
+public:
+ GCCriticalSection() { enter(); }
+ ~GCCriticalSection() { leave(); }
+
+ inline static void enter ();
+ inline static void leave ();
+ inline static bool inside();
+};
+
+
+// Includes.
+#if defined(ENABLE_GC_CACAO)
+# include "threads/thread.hpp"
#endif
-#include "vm/global.h"
-#include "vm/method.h"
+
+/**
+ * Enters a LLNI critical section which prevents the GC from moving
+ * objects around on the collected heap.
+ *
+ * There are no race conditions possible while entering such a critical
+ * section, because each thread only modifies its own thread local flag
+ * and the GC reads the flags while the world is stopped.
+ */
+void GCCriticalSection::enter()
+{
+#if defined(ENABLE_GC_CACAO)
+ threadobject* t = thread_get_current();
+
+ // Sanity check.
+ assert(t->gc_critical == false);
+
+ t->gc_critical = true;
+#endif
+}
+
+/**
+ * Leaves a LLNI critical section and allows the GC to move objects
+ * around on the collected heap again.
+ */
+void GCCriticalSection::leave()
+{
+#if defined(ENABLE_GC_CACAO)
+ threadobject* t = thread_get_current();
+
+ // Sanity check.
+ assert(t->gc_critical == true);
+
+ t->gc_critical = false;
+#endif
+}
+
+
+/**
+ * Checks if the calling thread is inside a GC critical section.
+ *
+ * @return true if inside, false otherwise.
+ */
+bool GCCriticalSection::inside()
+{
+#if defined(ENABLE_GC_CACAO)
+ threadobject* t = thread_get_current();
+ return t->gc_critical;
+#else
+ return true;
+#endif
+}
+
+#endif
/* reference types ************************************************************/
};
+// Includes.
+#include "vm/global.h"
+#include "vm/method.h"
+
+
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void gc_init(size_t heapmaxsize, size_t heapstartsize);
void* heap_alloc_uncollectable(size_t size);
/* inlined functions **********************************************************/
-static inline int32_t heap_hashcode(java_object_t *obj)
+static inline int32_t heap_hashcode(java_object_t* obj)
{
#if defined(ENABLE_GC_CACAO)
return heap_get_hashcode(obj);
}
#ifdef __cplusplus
-}
+} // extern "C"
#endif
-#endif /* _GC_HPP */
+#endif // _GC_HPP
/*
* Emacs will automagically detect them.
* ---------------------------------------------------------------------
* Local variables:
- * mode: c
+ * 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 "native/native.h"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
#include "config.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <string.h>
+#include <stdint.h>
-#include "vm/types.h"
-#include "mm/codememory.h"
-#include "mm/dumpmemory.h"
+// Align the size of memory allocations to this size.
+#define ALIGNSIZE 8
+#define MEMORY_ALIGN(pos,size) ((((pos) + (size) - 1) / (size)) * (size))
-/* constants for ENABLE_MEMCHECK **********************************************/
+// Constants for ENABLE_MEMCHECK.
#if defined(ENABLE_MEMCHECK)
#define MEMORY_CANARY_SIZE 16
#define MEMORY_CANARY_FIRST_BYTE 0xca
#define MEMORY_CLEAR_BYTE 0xa5
-#endif /* defined(ENABLE_MEMCHECK) */
-
+#endif
-/* internal includes **********************************************************/
+// Includes.
+#include "mm/codememory.h"
+#include "mm/dumpmemory.hpp"
#include "mm/gc.hpp"
*/
-#define MEMORY_ALIGN(pos,size) ((((pos) + (size) - 1) / (size)) * (size))
#define PADDING(pos,size) (MEMORY_ALIGN((pos),(size)) - (pos))
#define OFFSET(s,el) ((int32_t) ((ptrint) &(((s*) 0)->el)))
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool memory_init(void);
void memory_mprotect(void *addr, size_t len, int prot);
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 "config.h"
+
#include <stddef.h>
#include <stdint.h>
unsigned overflows;
} tlh_t;
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void tlh_init(tlh_t *tlh);
void tlh_destroy(tlh_t *tlh);
void *tlh_alloc(tlh_t *tlh, size_t size);
+#ifdef __cplusplus
+}
+#endif
+
#endif
/*
if ENABLE_JNI
JNI_SOURCES = \
jni.cpp \
- jni.h \
- localref.c \
- localref.h
+ jni.hpp \
+ localref.cpp \
+ localref.hpp
endif
libnative_la_SOURCES = \
$(JNI_SOURCES) \
llni.c \
llni.h \
- native.c \
- native.h
+ native.cpp \
+ native.hpp
libnative_la_LIBADD = \
vm/libnativevm.la \
#include "mm/gc.hpp"
#include "mm/memory.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JVMTI)
# include "native/jvmti/cacaodbg.h"
#endif
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#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/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.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/jit.hpp"
#include "vm/jit/stacktrace.hpp"
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;
+ java_lang_Object o(method);
- if (o == NULL)
+ if (o.is_null())
return NULL;
- // FIXME We can't access the object here directly.
- if (o->vftbl->clazz == class_java_lang_reflect_Constructor) {
+ if (o.get_Class() == 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);
+ assert(o.get_Class() == class_java_lang_reflect_Method);
java_lang_reflect_Method rm(method);
m = rm.get_method();
*******************************************************************************/
-jint _Jv_JNI_RegisterNatives(JNIEnv *env, jclass clazz,
- const JNINativeMethod *methods, jint nMethods)
+jint jni_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods)
{
- classinfo *c;
+ TRACEJNICALLS(("jni_RegisterNatives(env=%p, clazz=%p, methods=%p, nMethods=%d)", env, clazz, methods, nMethods));
- STATISTICS(jniinvokation());
-
- c = LLNI_classinfo_unwrap(clazz);
+ classinfo* 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);
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(c->name, methods, nMethods);
return 0;
}
{
STATISTICS(jniinvokation());
- *javavm = vm->get_javavm();
+ *javavm = VM::get_current()->get_javavm();
return 0;
}
argument.
*******************************************************************************/
-
+
jobject jni_NewGlobalRef(JNIEnv* env, jobject obj)
{
hashtable_global_ref_entry *gre;
o = (java_handle_t *) obj;
- LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+ hashtable_global_ref->mutex->lock();
LLNI_CRITICAL_START;
hashtable_global_ref->entries++;
}
- LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+ hashtable_global_ref->mutex->unlock();
#if defined(ENABLE_HANDLES)
return gre;
o = (java_handle_t *) globalRef;
- LOCK_MONITOR_ENTER(hashtable_global_ref->header);
+ hashtable_global_ref->mutex->lock();
LLNI_CRITICAL_START;
LLNI_CRITICAL_END;
- LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+ hashtable_global_ref->mutex->unlock();
return;
}
LLNI_CRITICAL_END;
- LOCK_MONITOR_EXIT(hashtable_global_ref->header);
+ hashtable_global_ref->mutex->unlock();
}
TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(javavm=%p)", javavm));
- if (vm->is_created() == false)
+ if (VM::get_current()->is_created() == false)
return JNI_ERR;
status = vm_destroy(javavm);
result = thread_current_is_attached();
if (result == true) {
- *p_env = vm->get_jnienv();
+ *p_env = VM::get_current()->get_jnienv();
return JNI_OK;
}
return JNI_ERR;
#endif
- *p_env = vm->get_jnienv();
+ *p_env = VM::get_current()->get_jnienv();
return JNI_OK;
}
TRACEJNICALLS(("jni_AttachCurrentThread(javavm=%p, p_env=%p, thr_args=%p)", javavm, p_env, thr_args));
- if (vm->is_created() == false)
+ if (VM::get_current()->is_created() == false)
return JNI_ERR;
result = jni_attach_current_thread(p_env, thr_args, false);
{
TRACEJNICALLS(("jni_GetEnv(javavm=%p, env=%p, version=%d)", javavm, env, version));
- if (vm->is_created() == false) {
+ if (VM::get_current()->is_created() == false) {
*env = NULL;
return JNI_EDETACHED;
}
/* Check the JNI version. */
if (jni_version_check(version) == true) {
- *env = vm->get_jnienv();
+ *env = VM::get_current()->get_jnienv();
return JNI_OK;
}
TRACEJNICALLS(("jni_AttachCurrentThreadAsDaemon(javavm=%p, penv=%p, args=%p)", javavm, penv, args));
- if (vm->is_created() == false)
+ if (VM::get_current()->is_created() == false)
return JNI_ERR;
result = jni_attach_current_thread(penv, args, true);
_Jv_JNI_SetFloatArrayRegion,
_Jv_JNI_SetDoubleArrayRegion,
- _Jv_JNI_RegisterNatives,
+ jni_RegisterNatives,
_Jv_JNI_UnregisterNatives,
_Jv_JNI_MonitorEnter,
// We currently only support 1 VM running.
- vmBuf[0] = vm->get_javavm();
+ vmBuf[0] = VM::get_current()->get_javavm();
*nVMs = 1;
return JNI_OK;
+++ /dev/null
-/* src/native/jni.h - JNI types and data structures
-
- 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.
-
-*/
-
-
-/* jni.h ***********************************************************************
-
- ATTENTION: We include this file before we actually define our own
- jni.h. We do this because otherwise we can get into unresolvable
- circular header dependencies.
-
- This is OK as GNU Classpath defines:
-
- #define __CLASSPATH_JNI_MD_H__
- #define _CLASSPATH_JNI_H
-
- and OpenJDK defines:
-
- #define _JAVASOFT_JNI_MD_H_
- #define _JAVASOFT_JNI_H_
-
- CLASSPATH_JNI_MD_H and CLASSPATH_JNI_H are defined in config.h.
-
-*******************************************************************************/
-
-#include "config.h"
-
-/* We include both headers with the absolute path so we can be sure
- that the preprocessor does not take another header. Furthermore we
- include jni_md.h before jni.h as the latter includes the former. */
-
-#include INCLUDE_JNI_MD_H
-#include INCLUDE_JNI_H
-
-#ifndef _JNI_H
-#define _JNI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-#include "vm/method.h"
-
-
-#if 0
-/* _Jv_JNIEnv *****************************************************************/
-
-#ifndef __cplusplus
-
-// FIXME The __cplusplus define is just a quick workaround and needs
-// to be fixed properly.
-
-typedef struct _Jv_JNIEnv _Jv_JNIEnv;
-
-struct _Jv_JNIEnv {
- const struct JNINativeInterface_ *env; /* This MUST be the first entry */
-};
-
-#endif
-
-
-/* _Jv_JavaVM *****************************************************************/
-
-#ifndef __cplusplus
-
-// FIXME The __cplusplus define is just a quick workaround and needs
-// to be fixed properly.
-
-typedef struct _Jv_JavaVM _Jv_JavaVM;
-
-struct _Jv_JavaVM {
- const struct JNIInvokeInterface_ *functions;/*This MUST be the first entry*/
-
- /* JVM instance-specific variables */
-
- s8 starttime; /* VM startup time */
-
- s4 Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose;
- s4 Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose;
- s4 java_lang_management_ThreadMXBean_PeakThreadCount;
- s4 java_lang_management_ThreadMXBean_ThreadCount;
- s8 java_lang_management_ThreadMXBean_TotalStartedThreadCount;
-};
-
-#endif
-#endif
-
-
-/* CACAO related stuff ********************************************************/
-
-extern const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface;
-extern struct JNINativeInterface_ _Jv_JNINativeInterface;
-
-
-/* hashtable_global_ref_entry *************************************************/
-
-typedef struct hashtable_global_ref_entry hashtable_global_ref_entry;
-
-struct hashtable_global_ref_entry {
- java_object_t *o; /* object pointer of global ref */
- s4 refs; /* references of the current pointer */
- hashtable_global_ref_entry *hashlink; /* link for external chaining */
-};
-
-
-/* function prototypes ********************************************************/
-
-bool jni_init(void);
-bool jni_version_check(int version);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _JNI_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/native/jni.hpp - JNI types and data structures
+
+ 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.
+
+*/
+
+
+/* jni.hpp *********************************************************************
+
+ ATTENTION: We include this file before we actually define our own
+ jni.h. We do this because otherwise we can get into unresolvable
+ circular header dependencies.
+
+ GNU Classpath's headers define:
+
+ #define __CLASSPATH_JNI_MD_H__
+ #define _CLASSPATH_JNI_H
+
+ and jni.h uses:
+
+ _CLASSPATH_VM_JNI_TYPES_DEFINED
+
+ OpenJDK's headers define:
+
+ #define _JAVASOFT_JNI_MD_H_
+ #define _JAVASOFT_JNI_H_
+
+ and jni.h uses:
+
+ JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H
+
+ CLASSPATH_JNI_MD_H and CLASSPATH_JNI_H are defined in config.h.
+
+ We include both headers (jni.h and jni_md.h) with the absolute path
+ so we can be sure that the preprocessor does not pick up another
+ header from the search path. Furthermore we include jni_md.h
+ before jni.h as the latter includes the former.
+
+*******************************************************************************/
+
+
+#ifndef _JNI_HPP
+#define _JNI_HPP
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+// Define these to override the typedefs in jni.h
+#define _CLASSPATH_VM_JNI_TYPES_DEFINED 1 // GNU Classpath
+#define JNI_TYPES_ALREADY_DEFINED_IN_JNI_MD_H 1 // OpenJDK
+
+// First include jni_md.h so we have the Java primitive types.
+#include INCLUDE_JNI_MD_H
+
+
+// Include the C++ wrapper classes.
+//#include "vm/javaobjects.hpp"
+#include "vm/global.h"
+
+// Typedef the JNI types.
+typedef java_handle_t* jobject;
+typedef java_handle_t* jclass;
+typedef java_handle_t* jstring;
+typedef java_handle_t* jthrowable;
+typedef java_handle_t* jweak; // FIXME
+typedef java_handle_array_t* jarray;
+typedef java_handle_objectarray_t* jobjectArray;
+typedef java_handle_booleanarray_t* jbooleanArray;
+typedef java_handle_bytearray_t* jbyteArray;
+typedef java_handle_chararray_t* jcharArray;
+typedef java_handle_shortarray_t* jshortArray;
+typedef java_handle_intarray_t* jintArray;
+typedef java_handle_longarray_t* jlongArray;
+typedef java_handle_floatarray_t* jfloatArray;
+typedef java_handle_doublearray_t* jdoubleArray;
+
+
+// We need some additional stuff for the various JNI headers.
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH) || defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+// These typedefs and defines are copied from GNU Classpath's jni.h
+#define JNI_TRUE true
+#define JNI_FALSE false
+
+typedef struct _Jv_JNIEnv JNIEnv;
+typedef struct _Jv_JavaVM JavaVM;
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+// These typedefs are copied from OpenJDK's jni.h
+typedef unsigned char jboolean;
+typedef unsigned short jchar;
+typedef short jshort;
+typedef float jfloat;
+typedef double jdouble;
+
+typedef jint jsize;
+
+typedef union jvalue {
+ jboolean z;
+ jbyte b;
+ jchar c;
+ jshort s;
+ jint i;
+ jlong j;
+ jfloat f;
+ jdouble d;
+ jobject l;
+} jvalue;
+
+struct _jfieldID;
+typedef struct _jfieldID *jfieldID;
+
+struct _jmethodID;
+typedef struct _jmethodID *jmethodID;
+
+/* Return values from jobjectRefType */
+typedef enum _jobjectType {
+ JNIInvalidRefType = 0,
+ JNILocalRefType = 1,
+ JNIGlobalRefType = 2,
+ JNIWeakGlobalRefType = 3
+} jobjectRefType;
+
+#endif
+
+
+// Now include jni.h to complete the JNI header.
+#include INCLUDE_JNI_H
+
+
+// Includes.
+#include "vm/global.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* CACAO related stuff ********************************************************/
+
+extern const struct JNIInvokeInterface_ _Jv_JNIInvokeInterface;
+extern struct JNINativeInterface_ _Jv_JNINativeInterface;
+
+
+/* hashtable_global_ref_entry *************************************************/
+
+typedef struct hashtable_global_ref_entry hashtable_global_ref_entry;
+
+struct hashtable_global_ref_entry {
+ java_object_t *o; /* object pointer of global ref */
+ int32_t refs; /* references of the current pointer */
+ hashtable_global_ref_entry *hashlink; /* link for external chaining */
+};
+
+
+/* function prototypes ********************************************************/
+
+bool jni_init(void);
+bool jni_version_check(int version);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _JNI_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/jvmti/cacaodbg.h"
#include "native/jvmti/dbg.h"
#include "vm/vm.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/exceptions.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/jit/asmpart.h"
#include "vm/string.hpp"
#include "toolbox/logging.h"
#include <unistd.h>
#include <sched.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#include "native/jvmti/cacaodbg.h"
#include "native/jvmti/jvmti.h"
#include "vm/jit/stacktrace.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/builtin.h"
+#include "vm/loader.hpp"
+#include "vm/jit/builtin.hpp"
#include "vm/jit/asmpart.h"
#include "vm/class.h"
#include "vm/classcache.h"
#include "mm/memory.h"
#include "threads/mutex.h"
#include "threads/thread.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "vm/exceptions.hpp"
#include "native/include/java_io_PrintStream.h"
#include "native/include/java_io_InputStream.h"
#include "native/include/java_lang_VMObject.h"
#include "native/include/java_lang_VMSystem.h"
#include "native/include/java_lang_VMClass.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
#include "boehm-gc/include/gc.h"
#if defined(ENABLE_THREADS)
/* src/native/jvmti.c - implementation of the Java Virtual Machine Tool
Interface 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
-
- Author: Martin Platter
-
- Changes:
+*/
-
-*/
#ifndef _JVMTI_H
#define _JVMTI_H
-#include "native/jni.h"
+#include "config.h"
+
+#include "native/jni.hpp"
#define JVMTI_VERSION_INTERFACE_JNI 0x00000000
#ifndef _LLNI_H
#define _LLNI_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "config.h"
/* forward defines ************************************************************/
#endif
-#include "native/localref.h"
+#include "native/localref.hpp"
#include "threads/thread.hpp"
# define LLNI_CRITICAL_END_THREAD(t)
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void llni_critical_start();
void llni_critical_end();
void llni_critical_start_thread(threadobject *t);
+++ /dev/null
-/* src/native/localref.c - Management of local reference tables
-
- 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 "mm/memory.h"
-
-#include "native/localref.h"
-
-#include "threads/thread.hpp"
-
-#include "toolbox/logging.h"
-
-#include "vm/options.h"
-#include "vm/vm.hpp"
-
-#include "vm/jit/argument.h"
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-# define DEBUGLOCALREF(message, index) \
- do { \
- if (opt_DebugLocalReferences) { \
- localref_table *dlrt = LOCALREFTABLE; \
- log_start(); \
- log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used); \
- if (index >= 0) \
- log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
- log_print("]"); \
- log_finish(); \
- } \
- } while (0)
-#else
-# define DEBUGLOCALREF(message, index)
-#endif
-
-
-/* global variables ***********************************************************/
-
-#if !defined(ENABLE_THREADS)
-localref_table *_no_threads_localref_table;
-#endif
-
-
-/* some forward declarations **************************************************/
-
-#if !defined(NDEBUG)
-static bool localref_check_uncleared();
-#endif
-
-
-/* localref_table_init *********************************************************
-
- Initializes the local references table of the current thread.
-
-*******************************************************************************/
-
-bool localref_table_init(void)
-{
- localref_table *lrt;
-
- TRACESUBSYSTEMINITIALIZATION("localref_table_init");
-
- assert(LOCALREFTABLE == NULL);
-
-#if !defined(ENABLE_GC_BOEHM)
- /* this is freed by localref_table_destroy */
- lrt = NEW(localref_table);
-#else
- /* this does not need to be freed again */
- lrt = GCNEW(localref_table);
-#endif
-
- if (lrt == NULL)
- return false;
-
- localref_table_add(lrt);
-
- DEBUGLOCALREF("table init", -1);
-
- return true;
-}
-
-
-/* localref_table_destroy ******************************************************
-
- Destroys the complete local references table of the current thread.
-
-*******************************************************************************/
-
-bool localref_table_destroy(void)
-{
- localref_table *lrt;
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(lrt->prev == NULL);
-
- DEBUGLOCALREF("table destroy", -1);
-
-#if !defined(ENABLE_GC_BOEHM)
- FREE(lrt, localref_table);
-#endif
-
- LOCALREFTABLE = NULL;
-
- return true;
-}
-
-
-/* localref_table_add **********************************************************
-
- Adds a new local references table to the current thread.
-
-*******************************************************************************/
-
-void localref_table_add(localref_table *lrt)
-{
- /* initialize the local reference table */
-
- lrt->capacity = LOCALREFTABLE_CAPACITY;
- lrt->used = 0;
- lrt->localframes = 1;
- lrt->prev = LOCALREFTABLE;
-
- /* clear the references array (memset is faster the a for-loop) */
-
- MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
-
- /* add given local references table to this thread */
-
- LOCALREFTABLE = lrt;
-
- /*DEBUGLOCALREF("table add", -1);*/
-}
-
-
-/* localref_table_remove *******************************************************
-
- Removes the topmost local references table from the current thread.
-
-*******************************************************************************/
-
-void localref_table_remove()
-{
- localref_table *lrt;
-
-#if !defined(NDEBUG)
- /* check for uncleared local references */
-
- localref_check_uncleared();
-#endif
-
- /* get current local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(lrt->localframes == 1);
-
- /*DEBUGLOCALREF("table remove", -1);*/
-
- lrt = lrt->prev;
-
- LOCALREFTABLE = lrt;
-}
-
-
-/* localref_frame_push *********************************************************
-
- Creates a new local reference frame, in which at least a given
- number of local references can be created.
-
-*******************************************************************************/
-
-bool localref_frame_push(int32_t capacity)
-{
- localref_table *lrt;
- localref_table *nlrt;
- int32_t additionalrefs;
-
- /* get current local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(capacity > 0);
-
- /* Allocate new local reference table on Java heap. Calculate the
- additional memory we have to allocate. */
-
- if (capacity > LOCALREFTABLE_CAPACITY)
- additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
- else
- additionalrefs = 0;
-
-#if !defined(ENABLE_GC_BOEHM)
- nlrt = (localref_table *)
- MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
-#else
- nlrt = (localref_table *)
- GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
-#endif
-
- if (nlrt == NULL)
- return false;
-
- /* Set up the new local reference table and add it to the local
- frames chain. */
-
- nlrt->capacity = capacity;
- nlrt->used = 0;
- nlrt->localframes = lrt->localframes + 1;
- nlrt->prev = lrt;
-
- /* store new local reference table in thread */
-
- LOCALREFTABLE = nlrt;
-
- DEBUGLOCALREF("frame push", -1);
-
- return true;
-}
-
-
-/* localref_frame_pop_all ******************************************************
-
- Pops off all the local reference frames of the current table.
-
-*******************************************************************************/
-
-void localref_frame_pop_all(void)
-{
- localref_table *lrt;
- localref_table *plrt;
- int32_t localframes;
-#if !defined(ENABLE_GC_BOEHM)
- int32_t additionalrefs;
-#endif
-
- /* get current local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
-
- localframes = lrt->localframes;
-
- /* Don't delete the top local frame, as this one is allocated in
- the native stub on the stack and is freed automagically on
- return. */
-
- if (localframes == 1)
- return;
-
- /* release all current local frames */
-
- for (; localframes > 1; localframes--) {
- /* get previous frame */
-
- plrt = lrt->prev;
-
- DEBUGLOCALREF("frame pop", -1);
-
- /* clear all reference entries */
-
- MSET(lrt->refs, 0, void*, lrt->capacity);
-
- lrt->prev = NULL;
-
-#if !defined(ENABLE_GC_BOEHM)
- /* for the exact GC local reference tables are not on the heap,
- so we need to free them explicitly here. */
-
- if (lrt->capacity > LOCALREFTABLE_CAPACITY)
- additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
- else
- additionalrefs = 0;
-
- MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
-#endif
-
- /* set new local references table */
-
- lrt = plrt;
- }
-
- /* store new local reference table in thread */
-
- LOCALREFTABLE = lrt;
-}
-
-
-/* localref_add ****************************************************************
-
- Adds a new entry into the local reference table and returns the
- new local reference.
-
-*******************************************************************************/
-
-java_handle_t *localref_add(java_object_t *o)
-{
- localref_table *lrt;
- java_handle_t *h;
- int32_t i;
-
- /* get current local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(o != NULL);
- /* XXX: assert that we are in a GC critical section! */
-
- /* Check if we have space for the requested reference? No,
- allocate a new frame. This is actually not what the spec says,
- but for compatibility reasons... */
-
- if (lrt->used == lrt->capacity) {
- if (!localref_frame_push(64))
- assert(0);
-
- /* get the new local reference table */
-
- lrt = LOCALREFTABLE;
- }
-
- /* insert the reference into the local reference table */
-
- for (i = 0; i < lrt->capacity; i++) {
- if (lrt->refs[i] == NULL) {
- lrt->refs[i] = o;
- lrt->used++;
-
-#if defined(ENABLE_HANDLES)
- h = (java_handle_t *) &(lrt->refs[i]);
-#else
- h = (java_handle_t *) o;
-#endif
-
- /*DEBUGLOCALREF("entry add", i);*/
-
- return h;
- }
- }
-
- /* this should not happen */
-
- log_println("localref_add: WARNING: unable to add localref for %p", o);
-
- return NULL;
-}
-
-
-/* localref_del ****************************************************************
-
- Deletes an entry from the local reference table.
-
-*******************************************************************************/
-
-void localref_del(java_handle_t *localref)
-{
- localref_table *lrt;
- java_handle_t *h;
- int32_t localframes;
- int32_t i;
-
- /* get local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(localref != NULL);
-
- localframes = lrt->localframes;
-
- /* go through all local frames of the current table */
- /* XXX: this is propably not what the spec wants! */
-
- for (; localframes > 0; localframes--) {
-
- /* and try to remove the reference */
-
- for (i = 0; i < lrt->capacity; i++) {
-#if defined(ENABLE_HANDLES)
- h = (java_handle_t *) &(lrt->refs[i]);
-#else
- h = (java_handle_t *) lrt->refs[i];
-#endif
-
- if (h == localref) {
- DEBUGLOCALREF("entry delete", i);
-
- lrt->refs[i] = NULL;
- lrt->used--;
-
- return;
- }
- }
-
- lrt = lrt->prev;
- }
-
- /* this should not happen */
-
- log_println("localref_del: WARNING: unable to find localref %p", localref);
-}
-
-
-/* localref_native_enter *******************************************************
-
- Insert arguments to a native method into the local reference table.
- This is done by the native stub through codegen_start_native_call.
-
-*******************************************************************************/
-
-void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
-{
- localref_table *lrt;
- methoddesc *md;
- imm_union arg;
- java_handle_t *h;
- int i;
-
- /* get local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(m != NULL);
-
- md = m->parseddesc;
-
- /* walk through all parameters to the method */
-
- for (i = 0; i < md->paramcount; ++i) {
- /* load TYPE_ADR parameters ... */
-
- if (md->paramtypes[i].type == TYPE_ADR) {
- arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
-
- if (arg.a == NULL)
- continue;
-
- /* ... and insert them into the table */
-
- h = localref_add((java_object_t *) arg.a);
-
-#if defined(ENABLE_HANDLES)
- /* update the modified parameter if necesarry */
-
- arg.a = (void *) h;
- argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
-#endif
- }
- }
-}
-
-
-/* localref_native_exit ********************************************************
-
- Undo the wrapping of the return value of a native method. This is
- done by the native stub through codegen_finish_native_call.
-
- NOTE: This function is only useful if handles are enabled.
-
-*******************************************************************************/
-
-#if defined(ENABLE_HANDLES)
-void localref_native_exit(methodinfo *m, uint64_t *return_regs)
-{
- localref_table *lrt;
- methoddesc *md;
- imm_union ret;
- java_handle_t *h;
-
- /* get local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(m != NULL);
-
- md = m->parseddesc;
-
- /* load TYPE_ADR return values ... */
-
- if (md->returntype.type == TYPE_ADR) {
- ret = argument_jitreturn_load(md, return_regs);
-
- if (ret.a == NULL)
- return;
-
- h = (java_handle_t *) ret.a;
-
- /* update the modified return valie */
-
- ret.a = (void *) h->heap_object;
- argument_jitreturn_store(md, return_regs, ret);
-
-#if !defined(NDEBUG) && 0
- /* removing the entry from the local reference table is not really
- necesarry, but gives us warnings if the entry does not exist. */
-
- localref_del(h);
-#endif
- }
-}
-#endif /* defined(ENABLE_HANDLES) */
-
-
-/* localref_dump ***************************************************************
-
- Dumps all local reference tables, including all frames.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-# define LOCALREF_DUMP_REFS_PER_LINE 4
-void localref_dump()
-{
- localref_table *lrt;
- int i, j;
-
- /* get current local reference table from thread */
-
- lrt = LOCALREFTABLE;
-
- log_println("--------- Local Reference Tables Dump ---------");
-
- while (lrt != NULL) {
- log_println("Frame #%d, Used=%d, Capacity=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, (void *) lrt);
-
- if (lrt->used != 0) {
-
- log_start();
-
- j = 0;
- for (i = 0; i < lrt->capacity; i++) {
- if (lrt->refs[i] != NULL) {
- if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
- log_finish();
- log_start();
- }
- j++;
- log_print("\t0x%016lx ", (intptr_t) lrt->refs[i]);
- }
- }
-
- log_finish();
- }
-
- lrt = lrt->prev;
- }
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* localref_check_uncleared ****************************************************
-
- Checks the topmost local reference table for uncleared references.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-static bool localref_check_uncleared()
-{
- localref_table *lrt;
- int32_t localframes;
- int32_t lrt_uncleared;
- int32_t lrt_used;
- int i;
-
- /* get current local reference table from thread */
-
- lrt = LOCALREFTABLE;
- assert(lrt != NULL);
- assert(lrt->localframes > 0);
-
- localframes = lrt->localframes;
- lrt_uncleared = 0;
- lrt_used = 0;
-
- for (; localframes > 0; localframes--) {
- lrt_used += lrt->used;
-
- for (i = 0; i < lrt->capacity; i++) {
- if (lrt->refs[i] != NULL)
- lrt_uncleared++;
- }
-
- lrt = lrt->prev;
- }
-
- if (lrt_uncleared != lrt_used) {
- localref_dump();
- vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
- }
-
- if (lrt_uncleared <= 1)
- return true;
- else {
- /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
- return false;
- }
-}
-#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/localref.cpp - Management of local reference tables
+
+ 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 "mm/memory.h"
+
+#include "native/localref.hpp"
+
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/argument.hpp"
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define DEBUGLOCALREF(message, index) \
+ do { \
+ if (opt_DebugLocalReferences) { \
+ localref_table *dlrt = LOCALREFTABLE; \
+ log_start(); \
+ log_print("[local reference %-12s: lrt=%016p frame=%d capacity=%d used=%d", message, dlrt, dlrt->localframes, dlrt->capacity, dlrt->used); \
+ if (index >= 0) \
+ log_print(" localref=%p object=%p", &(dlrt->refs[index]), dlrt->refs[index]); \
+ log_print("]"); \
+ log_finish(); \
+ } \
+ } while (0)
+#else
+# define DEBUGLOCALREF(message, index)
+#endif
+
+
+/* global variables ***********************************************************/
+
+#if !defined(ENABLE_THREADS)
+localref_table *_no_threads_localref_table;
+#endif
+
+
+/* some forward declarations **************************************************/
+
+#if !defined(NDEBUG)
+static bool localref_check_uncleared();
+#endif
+
+
+/* localref_table_init *********************************************************
+
+ Initializes the local references table of the current thread.
+
+*******************************************************************************/
+
+bool localref_table_init(void)
+{
+ localref_table *lrt;
+
+ TRACESUBSYSTEMINITIALIZATION("localref_table_init");
+
+ assert(LOCALREFTABLE == NULL);
+
+#if !defined(ENABLE_GC_BOEHM)
+ /* this is freed by localref_table_destroy */
+ lrt = (localref_table*) NEW(localref_table);
+#else
+ /* this does not need to be freed again */
+ lrt = (localref_table*) GCNEW(localref_table);
+#endif
+
+ if (lrt == NULL)
+ return false;
+
+ localref_table_add(lrt);
+
+ DEBUGLOCALREF("table init", -1);
+
+ return true;
+}
+
+
+/* localref_table_destroy ******************************************************
+
+ Destroys the complete local references table of the current thread.
+
+*******************************************************************************/
+
+bool localref_table_destroy(void)
+{
+ localref_table *lrt;
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(lrt->prev == NULL);
+
+ DEBUGLOCALREF("table destroy", -1);
+
+#if !defined(ENABLE_GC_BOEHM)
+ FREE(lrt, localref_table);
+#endif
+
+ LOCALREFTABLE = NULL;
+
+ return true;
+}
+
+
+/* localref_table_add **********************************************************
+
+ Adds a new local references table to the current thread.
+
+*******************************************************************************/
+
+void localref_table_add(localref_table *lrt)
+{
+ /* initialize the local reference table */
+
+ lrt->capacity = LOCALREFTABLE_CAPACITY;
+ lrt->used = 0;
+ lrt->localframes = 1;
+ lrt->prev = LOCALREFTABLE;
+
+ /* clear the references array (memset is faster the a for-loop) */
+
+ MSET(lrt->refs, 0, void*, LOCALREFTABLE_CAPACITY);
+
+ /* add given local references table to this thread */
+
+ LOCALREFTABLE = lrt;
+
+ /*DEBUGLOCALREF("table add", -1);*/
+}
+
+
+/* localref_table_remove *******************************************************
+
+ Removes the topmost local references table from the current thread.
+
+*******************************************************************************/
+
+void localref_table_remove()
+{
+ localref_table *lrt;
+
+#if !defined(NDEBUG)
+ /* check for uncleared local references */
+
+ localref_check_uncleared();
+#endif
+
+ /* get current local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(lrt->localframes == 1);
+
+ /*DEBUGLOCALREF("table remove", -1);*/
+
+ lrt = lrt->prev;
+
+ LOCALREFTABLE = lrt;
+}
+
+
+/* localref_frame_push *********************************************************
+
+ Creates a new local reference frame, in which at least a given
+ number of local references can be created.
+
+*******************************************************************************/
+
+bool localref_frame_push(int32_t capacity)
+{
+ localref_table *lrt;
+ localref_table *nlrt;
+ int32_t additionalrefs;
+
+ /* get current local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(capacity > 0);
+
+ /* Allocate new local reference table on Java heap. Calculate the
+ additional memory we have to allocate. */
+
+ if (capacity > LOCALREFTABLE_CAPACITY)
+ additionalrefs = capacity - LOCALREFTABLE_CAPACITY;
+ else
+ additionalrefs = 0;
+
+#if !defined(ENABLE_GC_BOEHM)
+ nlrt = (localref_table *)
+ MNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#else
+ nlrt = (localref_table *)
+ GCMNEW(u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#endif
+
+ if (nlrt == NULL)
+ return false;
+
+ /* Set up the new local reference table and add it to the local
+ frames chain. */
+
+ nlrt->capacity = capacity;
+ nlrt->used = 0;
+ nlrt->localframes = lrt->localframes + 1;
+ nlrt->prev = lrt;
+
+ /* store new local reference table in thread */
+
+ LOCALREFTABLE = nlrt;
+
+ DEBUGLOCALREF("frame push", -1);
+
+ return true;
+}
+
+
+/* localref_frame_pop_all ******************************************************
+
+ Pops off all the local reference frames of the current table.
+
+*******************************************************************************/
+
+void localref_frame_pop_all(void)
+{
+ localref_table *lrt;
+ localref_table *plrt;
+ int32_t localframes;
+#if !defined(ENABLE_GC_BOEHM)
+ int32_t additionalrefs;
+#endif
+
+ /* get current local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+
+ localframes = lrt->localframes;
+
+ /* Don't delete the top local frame, as this one is allocated in
+ the native stub on the stack and is freed automagically on
+ return. */
+
+ if (localframes == 1)
+ return;
+
+ /* release all current local frames */
+
+ for (; localframes > 1; localframes--) {
+ /* get previous frame */
+
+ plrt = lrt->prev;
+
+ DEBUGLOCALREF("frame pop", -1);
+
+ /* clear all reference entries */
+
+ MSET(lrt->refs, 0, void*, lrt->capacity);
+
+ lrt->prev = NULL;
+
+#if !defined(ENABLE_GC_BOEHM)
+ /* for the exact GC local reference tables are not on the heap,
+ so we need to free them explicitly here. */
+
+ if (lrt->capacity > LOCALREFTABLE_CAPACITY)
+ additionalrefs = lrt->capacity - LOCALREFTABLE_CAPACITY;
+ else
+ additionalrefs = 0;
+
+ MFREE(lrt, u1, sizeof(localref_table) + additionalrefs * SIZEOF_VOID_P);
+#endif
+
+ /* set new local references table */
+
+ lrt = plrt;
+ }
+
+ /* store new local reference table in thread */
+
+ LOCALREFTABLE = lrt;
+}
+
+
+/* localref_add ****************************************************************
+
+ Adds a new entry into the local reference table and returns the
+ new local reference.
+
+*******************************************************************************/
+
+java_handle_t *localref_add(java_object_t *o)
+{
+ localref_table *lrt;
+ java_handle_t *h;
+ int32_t i;
+
+ /* get current local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(o != NULL);
+ /* XXX: assert that we are in a GC critical section! */
+
+ /* Check if we have space for the requested reference? No,
+ allocate a new frame. This is actually not what the spec says,
+ but for compatibility reasons... */
+
+ if (lrt->used == lrt->capacity) {
+ if (!localref_frame_push(64))
+ assert(0);
+
+ /* get the new local reference table */
+
+ lrt = LOCALREFTABLE;
+ }
+
+ /* insert the reference into the local reference table */
+
+ for (i = 0; i < lrt->capacity; i++) {
+ if (lrt->refs[i] == NULL) {
+ lrt->refs[i] = o;
+ lrt->used++;
+
+#if defined(ENABLE_HANDLES)
+ h = (java_handle_t *) &(lrt->refs[i]);
+#else
+ h = (java_handle_t *) o;
+#endif
+
+ /*DEBUGLOCALREF("entry add", i);*/
+
+ return h;
+ }
+ }
+
+ /* this should not happen */
+
+ log_println("localref_add: WARNING: unable to add localref for %p", o);
+
+ return NULL;
+}
+
+
+/* localref_del ****************************************************************
+
+ Deletes an entry from the local reference table.
+
+*******************************************************************************/
+
+void localref_del(java_handle_t *localref)
+{
+ localref_table *lrt;
+ java_handle_t *h;
+ int32_t localframes;
+ int32_t i;
+
+ /* get local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(localref != NULL);
+
+ localframes = lrt->localframes;
+
+ /* go through all local frames of the current table */
+ /* XXX: this is propably not what the spec wants! */
+
+ for (; localframes > 0; localframes--) {
+
+ /* and try to remove the reference */
+
+ for (i = 0; i < lrt->capacity; i++) {
+#if defined(ENABLE_HANDLES)
+ h = (java_handle_t *) &(lrt->refs[i]);
+#else
+ h = (java_handle_t *) lrt->refs[i];
+#endif
+
+ if (h == localref) {
+ DEBUGLOCALREF("entry delete", i);
+
+ lrt->refs[i] = NULL;
+ lrt->used--;
+
+ return;
+ }
+ }
+
+ lrt = lrt->prev;
+ }
+
+ /* this should not happen */
+
+ log_println("localref_del: WARNING: unable to find localref %p", localref);
+}
+
+
+/* localref_native_enter *******************************************************
+
+ Insert arguments to a native method into the local reference table.
+ This is done by the native stub through codegen_start_native_call.
+
+*******************************************************************************/
+
+void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack)
+{
+ localref_table *lrt;
+ methoddesc *md;
+ imm_union arg;
+ java_handle_t *h;
+ int i;
+
+ /* get local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(m != NULL);
+
+ md = m->parseddesc;
+
+ /* walk through all parameters to the method */
+
+ for (i = 0; i < md->paramcount; ++i) {
+ /* load TYPE_ADR parameters ... */
+
+ if (md->paramtypes[i].type == TYPE_ADR) {
+ arg = argument_jitarray_load(md, i, argument_regs, argument_stack);
+
+ if (arg.a == NULL)
+ continue;
+
+ /* ... and insert them into the table */
+
+ h = localref_add((java_object_t *) arg.a);
+
+#if defined(ENABLE_HANDLES)
+ /* update the modified parameter if necesarry */
+
+ arg.a = (void *) h;
+ argument_jitarray_store(md, i, argument_regs, argument_stack, arg);
+#endif
+ }
+ }
+}
+
+
+/* localref_native_exit ********************************************************
+
+ Undo the wrapping of the return value of a native method. This is
+ done by the native stub through codegen_finish_native_call.
+
+ NOTE: This function is only useful if handles are enabled.
+
+*******************************************************************************/
+
+#if defined(ENABLE_HANDLES)
+void localref_native_exit(methodinfo *m, uint64_t *return_regs)
+{
+ localref_table *lrt;
+ methoddesc *md;
+ imm_union ret;
+ java_handle_t *h;
+
+ /* get local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(m != NULL);
+
+ md = m->parseddesc;
+
+ /* load TYPE_ADR return values ... */
+
+ if (md->returntype.type == TYPE_ADR) {
+ ret = argument_jitreturn_load(md, return_regs);
+
+ if (ret.a == NULL)
+ return;
+
+ h = (java_handle_t *) ret.a;
+
+ /* update the modified return valie */
+
+ ret.a = (void *) h->heap_object;
+ argument_jitreturn_store(md, return_regs, ret);
+
+#if !defined(NDEBUG) && 0
+ /* removing the entry from the local reference table is not really
+ necesarry, but gives us warnings if the entry does not exist. */
+
+ localref_del(h);
+#endif
+ }
+}
+#endif /* defined(ENABLE_HANDLES) */
+
+
+/* localref_dump ***************************************************************
+
+ Dumps all local reference tables, including all frames.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+# define LOCALREF_DUMP_REFS_PER_LINE 4
+void localref_dump()
+{
+ localref_table *lrt;
+ int i, j;
+
+ /* get current local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+
+ log_println("--------- Local Reference Tables Dump ---------");
+
+ while (lrt != NULL) {
+ log_println("Frame #%d, Used=%d, Capacity=%d, Addr=%p:", lrt->localframes, lrt->used, lrt->capacity, (void *) lrt);
+
+ if (lrt->used != 0) {
+
+ log_start();
+
+ j = 0;
+ for (i = 0; i < lrt->capacity; i++) {
+ if (lrt->refs[i] != NULL) {
+ if (j != 0 && j % LOCALREF_DUMP_REFS_PER_LINE == 0) {
+ log_finish();
+ log_start();
+ }
+ j++;
+ log_print("\t0x%016lx ", (intptr_t) lrt->refs[i]);
+ }
+ }
+
+ log_finish();
+ }
+
+ lrt = lrt->prev;
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* localref_check_uncleared ****************************************************
+
+ Checks the topmost local reference table for uncleared references.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static bool localref_check_uncleared()
+{
+ localref_table *lrt;
+ int32_t localframes;
+ int32_t lrt_uncleared;
+ int32_t lrt_used;
+ int i;
+
+ /* get current local reference table from thread */
+
+ lrt = LOCALREFTABLE;
+ assert(lrt != NULL);
+ assert(lrt->localframes > 0);
+
+ localframes = lrt->localframes;
+ lrt_uncleared = 0;
+ lrt_used = 0;
+
+ for (; localframes > 0; localframes--) {
+ lrt_used += lrt->used;
+
+ for (i = 0; i < lrt->capacity; i++) {
+ if (lrt->refs[i] != NULL)
+ lrt_uncleared++;
+ }
+
+ lrt = lrt->prev;
+ }
+
+ if (lrt_uncleared != lrt_used) {
+ localref_dump();
+ vm_abort("localref_check_uncleared: (uncleared=%d) != (used=%d)", lrt_uncleared, lrt_used);
+ }
+
+ if (lrt_uncleared <= 1)
+ return true;
+ else {
+ /*log_println("localref_check_uncleared: %d uncleared local references", lrt_uncleared);*/
+ return false;
+ }
+}
+#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/localref.h - Management of local reference tables
-
- 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 _LOCALREF_H
-#define _LOCALREF_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct localref_table localref_table;
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-#include "vm/method.h"
-
-
-/* localref_table **************************************************************
-
- ATTENTION: keep this structure a multiple of 8-bytes!!! This is
- essential for the native stub on 64-bit architectures.
-
-*******************************************************************************/
-
-#define LOCALREFTABLE_CAPACITY 16
-
-struct localref_table {
- s4 capacity; /* table size */
- s4 used; /* currently used references */
- s4 localframes; /* number of current frames */
- s4 PADDING; /* 8-byte padding */
- localref_table *prev; /* link to prev table (LocalFrame) */
- java_object_t *refs[LOCALREFTABLE_CAPACITY]; /* references */
-};
-
-
-#if defined(ENABLE_THREADS)
-#define LOCALREFTABLE (THREADOBJECT->_localref_table)
-#else
-extern localref_table *_no_threads_localref_table;
-
-#define LOCALREFTABLE (_no_threads_localref_table)
-#endif
-
-
-/* function prototypes ********************************************************/
-
-bool localref_table_init(void);
-bool localref_table_destroy(void);
-void localref_table_add(localref_table *lrt);
-void localref_table_remove();
-
-bool localref_frame_push(int32_t capacity);
-void localref_frame_pop_all(void);
-
-java_handle_t *localref_add(java_object_t *o);
-void localref_del(java_handle_t *localref);
-
-void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack);
-void localref_native_exit(methodinfo *m, uint64_t *return_regs);
-
-#if !defined(NDEBUG)
-void localref_dump(void);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LOCALREF_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/native/localref.hpp - Management of local reference tables
+
+ 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 _LOCALREF_HPP
+#define _LOCALREF_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct localref_table localref_table;
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/method.h"
+
+
+/* localref_table **************************************************************
+
+ ATTENTION: keep this structure a multiple of 8-bytes!!! This is
+ essential for the native stub on 64-bit architectures.
+
+*******************************************************************************/
+
+#define LOCALREFTABLE_CAPACITY 16
+
+struct localref_table {
+ s4 capacity; /* table size */
+ s4 used; /* currently used references */
+ s4 localframes; /* number of current frames */
+ s4 PADDING; /* 8-byte padding */
+ localref_table *prev; /* link to prev table (LocalFrame) */
+ java_object_t *refs[LOCALREFTABLE_CAPACITY]; /* references */
+};
+
+
+#if defined(ENABLE_THREADS)
+#define LOCALREFTABLE (THREADOBJECT->_localref_table)
+#else
+extern localref_table *_no_threads_localref_table;
+
+#define LOCALREFTABLE (_no_threads_localref_table)
+#endif
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool localref_table_init(void);
+bool localref_table_destroy(void);
+void localref_table_add(localref_table *lrt);
+void localref_table_remove();
+
+bool localref_frame_push(int32_t capacity);
+void localref_frame_pop_all(void);
+
+java_handle_t *localref_add(java_object_t *o);
+void localref_del(java_handle_t *localref);
+
+void localref_native_enter(methodinfo *m, uint64_t *argument_regs, uint64_t *argument_stack);
+void localref_native_exit(methodinfo *m, uint64_t *return_regs);
+
+#if !defined(NDEBUG)
+void localref_dump(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LOCALREF_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/native.c - native library support
-
- 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 <stdint.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/vm/nativevm.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/avl.h"
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
-
-#include "vm/builtin.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/string.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-
-/* global variables ***********************************************************/
-
-static avl_tree_t *tree_native_methods;
-
-#if defined(ENABLE_DL)
-static hashtable *hashtable_library;
-#endif
-
-
-/* prototypes *****************************************************************/
-
-static s4 native_tree_native_methods_comparator(const void *treenode, const void *node);
-
-
-/* native_init *****************************************************************
-
- Initializes the native subsystem.
-
-*******************************************************************************/
-
-bool native_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("native_init");
-
-#if defined(ENABLE_DL)
- /* initialize library hashtable, 10 entries should be enough */
-
- hashtable_library = NEW(hashtable);
-
- hashtable_create(hashtable_library, 10);
-#endif
-
- /* initialize the native methods table */
-
- tree_native_methods = avl_create(&native_tree_native_methods_comparator);
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* native_tree_native_methods_comparator ***************************************
-
- Comparison function for AVL tree of native methods.
-
- IN:
- treenode....node in the tree
- node........node to compare with tree-node
-
- RETURN VALUE:
- -1, 0, +1
-
-*******************************************************************************/
-
-static s4 native_tree_native_methods_comparator(const void *treenode, const void *node)
-{
- const native_methods_node_t *treenmn;
- const native_methods_node_t *nmn;
-
- treenmn = treenode;
- nmn = node;
-
- /* these are for walking the tree */
-
- if (treenmn->classname < nmn->classname)
- return -1;
- else if (treenmn->classname > nmn->classname)
- return 1;
-
- if (treenmn->name < nmn->name)
- return -1;
- else if (treenmn->name > nmn->name)
- return 1;
-
- if (treenmn->descriptor < nmn->descriptor)
- return -1;
- else if (treenmn->descriptor > nmn->descriptor)
- return 1;
-
- /* all pointers are equal, we have found the entry */
-
- return 0;
-}
-
-
-/* native_make_overloaded_function *********************************************
-
- XXX
-
-*******************************************************************************/
-
-static utf *native_make_overloaded_function(utf *name, utf *descriptor)
-{
- char *newname;
- s4 namelen;
- char *utf_ptr;
- u2 c;
- s4 i;
- utf *u;
- int32_t dumpmarker;
-
- /* mark memory */
-
- DMARKER;
-
- utf_ptr = descriptor->text;
- namelen = strlen(name->text) + strlen("__") + strlen("0");
-
- /* calculate additional length */
-
- while ((c = utf_nextu2(&utf_ptr)) != ')') {
- switch (c) {
- case 'Z':
- case 'B':
- case 'C':
- case 'S':
- case 'I':
- case 'J':
- case 'F':
- case 'D':
- namelen++;
- break;
- case '[':
- namelen += 2;
- break;
- case 'L':
- namelen++;
- while (utf_nextu2(&utf_ptr) != ';')
- namelen++;
- namelen += 2;
- break;
- case '(':
- break;
- default:
- assert(0);
- }
- }
-
- /* reallocate memory */
-
- i = strlen(name->text);
-
- newname = DMNEW(char, namelen);
- MCOPY(newname, name->text, char, i);
-
- utf_ptr = descriptor->text;
-
- newname[i++] = '_';
- newname[i++] = '_';
-
- while ((c = utf_nextu2(&utf_ptr)) != ')') {
- switch (c) {
- case 'Z':
- case 'B':
- case 'C':
- case 'S':
- case 'J':
- case 'I':
- case 'F':
- case 'D':
- newname[i++] = c;
- break;
- case '[':
- newname[i++] = '_';
- newname[i++] = '3';
- break;
- case 'L':
- newname[i++] = 'L';
- while ((c = utf_nextu2(&utf_ptr)) != ';')
- if (((c >= 'a') && (c <= 'z')) ||
- ((c >= 'A') && (c <= 'Z')) ||
- ((c >= '0') && (c <= '9')))
- newname[i++] = c;
- else
- newname[i++] = '_';
- newname[i++] = '_';
- newname[i++] = '2';
- break;
- case '(':
- break;
- default:
- assert(0);
- }
- }
-
- /* close string */
-
- newname[i] = '\0';
-
- /* make a utf-string */
-
- u = utf_new_char(newname);
-
- /* release memory */
-
- DRELEASE;
-
- return u;
-}
-
-
-/* native_insert_char **********************************************************
-
- Inserts the passed UTF character into the native method name. If
- necessary it is escaped properly.
-
-*******************************************************************************/
-
-static s4 native_insert_char(char *name, u4 pos, u2 c)
-{
- s4 val;
- s4 i;
-
- switch (c) {
- case '/':
- case '.':
- /* replace '/' or '.' with '_' */
- name[pos] = '_';
- break;
-
- case '_':
- /* escape sequence for '_' is '_1' */
- name[pos] = '_';
- name[++pos] = '1';
- break;
-
- case ';':
- /* escape sequence for ';' is '_2' */
- name[pos] = '_';
- name[++pos] = '2';
- break;
-
- case '[':
- /* escape sequence for '[' is '_1' */
- name[pos] = '_';
- name[++pos] = '3';
- break;
-
- default:
- if (isalnum(c))
- name[pos] = c;
- else {
- /* unicode character */
- name[pos] = '_';
- name[++pos] = '0';
-
- for (i = 0; i < 4; ++i) {
- val = c & 0x0f;
- name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
- c >>= 4;
- }
-
- pos += 4;
- }
- break;
- }
-
- /* return the new buffer index */
-
- return pos;
-}
-
-
-/* native_method_symbol ********************************************************
-
- Generate a method-symbol string out of the class name and the
- method name.
-
-*******************************************************************************/
-
-static utf *native_method_symbol(utf *classname, utf *methodname)
-{
- char *name;
- s4 namelen;
- char *utf_ptr;
- char *utf_endptr;
- u2 c;
- u4 pos;
- utf *u;
- int32_t dumpmarker;
-
- /* mark memory */
-
- DMARKER;
-
- /* Calculate length of native function name. We multiply the
- class and method name length by 6 as this is the maxium
- escape-sequence that can be generated (unicode). */
-
- namelen =
- strlen("Java_") +
- utf_get_number_of_u2s(classname) * 6 +
- strlen("_") +
- utf_get_number_of_u2s(methodname) * 6 +
- strlen("0");
-
- /* allocate memory */
-
- name = DMNEW(char, namelen);
-
- /* generate name of native functions */
-
- strcpy(name, "Java_");
- pos = strlen("Java_");
-
- utf_ptr = classname->text;
- utf_endptr = UTF_END(classname);
-
- for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
- c = *utf_ptr;
- pos = native_insert_char(name, pos, c);
- }
-
- /* seperator between class and method */
-
- name[pos++] = '_';
-
- utf_ptr = methodname->text;
- utf_endptr = UTF_END(methodname);
-
- for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
- c = *utf_ptr;
- pos = native_insert_char(name, pos, c);
- }
-
- /* close string */
-
- name[pos] = '\0';
-
- /* check for an buffer overflow */
-
- assert(pos <= namelen);
-
- /* make a utf-string */
-
- u = utf_new_char(name);
-
- /* release memory */
-
- DRELEASE;
-
- return u;
-}
-
-
-/* native_method_register ******************************************************
-
- Register a native method in the native method table.
-
-*******************************************************************************/
-
-void native_method_register(utf *classname, const JNINativeMethod *methods,
- int32_t count)
-{
- native_methods_node_t *nmn;
- utf *name;
- utf *descriptor;
- int32_t i;
-
- /* insert all methods passed */
-
- for (i = 0; i < count; i++) {
- if (opt_verbosejni) {
- printf("[Registering JNI native method ");
- utf_display_printable_ascii_classname(classname);
- printf(".%s]\n", methods[i].name);
- }
-
- /* generate the utf8 names */
-
- name = utf_new_char(methods[i].name);
- descriptor = utf_new_char(methods[i].signature);
-
- /* allocate a new tree node */
-
- nmn = NEW(native_methods_node_t);
-
- nmn->classname = classname;
- nmn->name = name;
- nmn->descriptor = descriptor;
- nmn->function = (functionptr) (ptrint) methods[i].fnPtr;
-
- /* insert the method into the tree */
-
- avl_insert(tree_native_methods, nmn);
- }
-}
-
-
-/* native_method_find **********************************************************
-
- Find a native method in the native method table.
-
-*******************************************************************************/
-
-static functionptr native_method_find(methodinfo *m)
-{
- native_methods_node_t tmpnmn;
- native_methods_node_t *nmn;
-
- /* fill the temporary structure used for searching the tree */
-
- tmpnmn.classname = m->clazz->name;
- tmpnmn.name = m->name;
- tmpnmn.descriptor = m->descriptor;
-
- /* find the entry in the AVL-tree */
-
- nmn = avl_find(tree_native_methods, &tmpnmn);
-
- if (nmn == NULL)
- return NULL;
-
- return nmn->function;
-}
-
-
-/* native_method_resolve *******************************************************
-
- Resolves a native method, maybe from a dynamic library.
-
- IN:
- m ... methodinfo of the native Java method to resolve
-
- RESULT:
- pointer to the resolved method (symbol)
-
-*******************************************************************************/
-
-functionptr native_method_resolve(methodinfo *m)
-{
- utf *name;
- utf *newname;
- functionptr f;
-#if defined(ENABLE_DL)
- classloader_t *cl;
- hashtable_library_loader_entry *le;
- hashtable_library_name_entry *ne;
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
-#endif
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- methodinfo *method_findNative;
- java_handle_t *s;
-#endif
-
- /* verbose output */
-
- if (opt_verbosejni) {
- printf("[Dynamic-linking native method ");
- utf_display_printable_ascii_classname(m->clazz->name);
- printf(".");
- utf_display_printable_ascii(m->name);
- printf(" ... ");
- }
-
- /* generate method symbol string */
-
- name = native_method_symbol(m->clazz->name, m->name);
-
- /* generate overloaded function (having the types in it's name) */
-
- newname = native_make_overloaded_function(name, m->descriptor);
-
- /* check the library hash entries of the classloader of the
- methods's class */
-
- f = NULL;
-
-#if defined(ENABLE_DL)
- /* Get the classloader. */
-
- cl = class_get_classloader(m->clazz);
-
- /* normally addresses are aligned to 4, 8 or 16 bytes */
-
- key = ((u4) (ptrint) cl) >> 4; /* align to 16-byte */
- slot = key & (hashtable_library->size - 1);
- le = hashtable_library->ptr[slot];
-
- /* iterate through loaders in this hash slot */
-
- while ((le != NULL) && (f == NULL)) {
- /* iterate through names in this loader */
-
- ne = le->namelink;
-
- while ((ne != NULL) && (f == NULL)) {
- f = (functionptr) (ptrint) os_dlsym(ne->handle, name->text);
-
- if (f == NULL)
- f = (functionptr) (ptrint) os_dlsym(ne->handle, newname->text);
-
- ne = ne->hashlink;
- }
-
- le = le->hashlink;
- }
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- if (f == NULL) {
- /* We can resolve the function directly from
- java.lang.ClassLoader as it's a static function. */
- /* XXX should be done in native_init */
-
- method_findNative =
- class_resolveclassmethod(class_java_lang_ClassLoader,
- utf_findNative,
- utf_java_lang_ClassLoader_java_lang_String__J,
- class_java_lang_ClassLoader,
- true);
-
- if (method_findNative == NULL)
- return NULL;
-
- /* try the normal name */
-
- s = javastring_new(name);
-
- f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
- NULL, cl, s);
-
- /* if not found, try the mangled name */
-
- if (f == NULL) {
- s = javastring_new(newname);
-
- f = (functionptr) (intptr_t) vm_call_method_long(method_findNative,
- NULL, cl, s);
- }
- }
-# endif
-
- if (f != NULL)
- if (opt_verbosejni)
- printf("JNI ]\n");
-#endif
-
- /* If not found, try to find the native function symbol in the
- main program. */
-
- if (f == NULL) {
- f = native_method_find(m);
-
- if (f != NULL)
- if (opt_verbosejni)
- printf("internal ]\n");
- }
-
-#if defined(ENABLE_JVMTI)
- /* fire Native Method Bind event */
- if (jvmti) jvmti_NativeMethodBind(m, f, &f);
-#endif
-
- /* no symbol found? throw exception */
-
- if (f == NULL) {
- if (opt_verbosejni)
- printf("failed ]\n");
-
- exceptions_throw_unsatisfiedlinkerror(m->name);
- }
-
- return f;
-}
-
-
-/* native_library_open *********************************************************
-
- Open a native library with the given utf8 name.
-
- IN:
- filename ... filename of the library to open
-
- RETURN:
- handle of the opened library
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-void* native_library_open(utf *filename)
-{
- void* handle;
-
- if (opt_verbosejni) {
- printf("[Loading native library ");
- utf_display_printable_ascii(filename);
- printf(" ... ");
- }
-
- /* try to open the library */
-
- handle = os_dlopen(filename->text, RTLD_LAZY);
-
- if (handle == NULL) {
- if (opt_verbosejni)
- printf("failed ]\n");
-
- if (opt_verbose) {
- log_start();
- log_print("native_library_open: os_dlopen failed: ");
- log_print(dlerror());
- log_finish();
- }
-
- return NULL;
- }
-
- if (opt_verbosejni)
- printf("OK ]\n");
-
- return handle;
-}
-#endif
-
-
-/* native_library_close ********************************************************
-
- Close the native library of the given handle.
-
- IN:
- handle ... handle of the open library
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-void native_library_close(void* handle)
-{
- int result;
-
- if (opt_verbosejni) {
- printf("[Unloading native library ");
-/* utf_display_printable_ascii(filename); */
- printf(" ... ");
- }
-
- /* Close the library. */
-
- result = os_dlclose(handle);
-
- if (result != 0) {
- if (opt_verbose) {
- log_start();
- log_print("native_library_close: os_dlclose failed: ");
- log_print(dlerror());
- log_finish();
- }
- }
-}
-#endif
-
-
-/* native_library_add **********************************************************
-
- Adds an entry to the native library hashtable.
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-void native_library_add(utf *filename, classloader_t *loader, void* handle)
-{
- hashtable_library_loader_entry *le;
- hashtable_library_name_entry *ne; /* library name */
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
-
- LOCK_MONITOR_ENTER(hashtable_library->header);
-
- /* normally addresses are aligned to 4, 8 or 16 bytes */
-
- key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
- slot = key & (hashtable_library->size - 1);
- le = hashtable_library->ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (le) {
- if (le->loader == loader)
- break;
-
- le = le->hashlink; /* next element in external chain */
- }
-
- /* no loader found? create a new entry */
-
- if (le == NULL) {
- le = NEW(hashtable_library_loader_entry);
-
- le->loader = loader;
- le->namelink = NULL;
-
- /* insert entry into hashtable */
-
- le->hashlink =
- (hashtable_library_loader_entry *) hashtable_library->ptr[slot];
- hashtable_library->ptr[slot] = le;
-
- /* update number of hashtable-entries */
-
- hashtable_library->entries++;
- }
-
-
- /* search for library name */
-
- ne = le->namelink;
-
- while (ne) {
- if (ne->name == filename) {
- LOCK_MONITOR_EXIT(hashtable_library->header);
-
- return;
- }
-
- ne = ne->hashlink; /* next element in external chain */
- }
-
- /* not found? add the library name to the classloader */
-
- ne = NEW(hashtable_library_name_entry);
-
- ne->name = filename;
- ne->handle = handle;
-
- /* insert entry into external chain */
-
- ne->hashlink = le->namelink;
- le->namelink = ne;
-
- LOCK_MONITOR_EXIT(hashtable_library->header);
-}
-#endif
-
-
-/* native_library_find *********************************************************
-
- Find an entry in the native library hashtable.
-
-*******************************************************************************/
-
-#if defined(ENABLE_DL)
-hashtable_library_name_entry *native_library_find(utf *filename,
- classloader_t *loader)
-{
- hashtable_library_loader_entry *le;
- hashtable_library_name_entry *ne; /* library name */
- u4 key; /* hashkey */
- u4 slot; /* slot in hashtable */
-
- /* normally addresses are aligned to 4, 8 or 16 bytes */
-
- key = ((u4) (ptrint) loader) >> 4; /* align to 16-byte boundaries */
- slot = key & (hashtable_library->size - 1);
- le = hashtable_library->ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (le) {
- if (le->loader == loader)
- break;
-
- le = le->hashlink; /* next element in external chain */
- }
-
- /* no loader found? return NULL */
-
- if (le == NULL)
- return NULL;
-
- /* search for library name */
-
- ne = le->namelink;
-
- while (ne) {
- if (ne->name == filename)
- return ne;
-
- ne = ne->hashlink; /* next element in external chain */
- }
-
- /* return entry, if no entry was found, ne is NULL */
-
- return ne;
-}
-#endif
-
-
-/* native_library_load *********************************************************
-
- Load a native library and initialize it, if possible.
-
- IN:
- name ... name of the library
- cl ..... classloader which loads this library
-
- RETURN:
- 1 ... library loaded successfully
- 0 ... error
-
-*******************************************************************************/
-
-int native_library_load(JNIEnv *env, utf *name, classloader_t *cl)
-{
-#if defined(ENABLE_DL)
- void* handle;
-# if defined(ENABLE_JNI)
- void* onload;
- int32_t version;
-# endif
-
- if (name == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- /* Is the library already loaded? */
-
- if (native_library_find(name, cl) != NULL)
- return 1;
-
- /* Open the library. */
-
- handle = native_library_open(name);
-
- if (handle == NULL)
- return 0;
-
-# if defined(ENABLE_JNI)
- /* Resolve JNI_OnLoad function. */
-
- onload = os_dlsym(handle, "JNI_OnLoad");
-
- if (onload != NULL) {
- JNIEXPORT int32_t (JNICALL *JNI_OnLoad) (JavaVM *, void *);
- JavaVM *vm;
-
- JNI_OnLoad = (JNIEXPORT int32_t (JNICALL *)(JavaVM *, void *)) (ptrint) onload;
-
- (*env)->GetJavaVM(env, &vm);
-
- version = JNI_OnLoad(vm, NULL);
-
- /* If the version is not 1.2 and not 1.4 the library cannot be
- loaded. */
-
- if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
- os_dlclose(handle);
- return 0;
- }
- }
-# endif
-
- /* Insert the library name into the library hash. */
-
- native_library_add(name, cl, handle);
-
- return 1;
-#else
- vm_abort("native_library_load: not available");
-
- /* Keep compiler happy. */
-
- return 0;
-#endif
-}
-
-
-/* native_new_and_init *********************************************************
-
- Creates a new object on the heap and calls the initializer.
- Returns the object pointer or NULL if memory is exhausted.
-
-*******************************************************************************/
-
-java_handle_t *native_new_and_init(classinfo *c)
-{
- methodinfo *m;
- java_handle_t *o;
-
- if (c == NULL)
- vm_abort("native_new_and_init: c == NULL");
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* try to find the initializer */
-
- m = class_findmethod(c, utf_init, utf_void__void);
-
- /* ATTENTION: returning the object here is ok, since the class may
- not have an initializer */
-
- if (m == NULL)
- return o;
-
- /* call initializer */
-
- (void) vm_call_method(m, o);
-
- return o;
-}
-
-
-java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
-{
- methodinfo *m;
- java_handle_t *o;
-
- if (c == NULL)
- vm_abort("native_new_and_init_string: c == NULL");
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* find initializer */
-
- m = class_findmethod(c, utf_init, utf_java_lang_String__void);
-
- /* initializer not found */
-
- if (m == NULL)
- return NULL;
-
- /* call initializer */
-
- (void) vm_call_method(m, o, s);
-
- return 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/native.cpp - native library support
+
+ 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 <stdint.h>
+
+#include <algorithm>
+#include <functional>
+#include <map>
+
+#include "mm/memory.h"
+
+#include "native/jni.hpp"
+#include "native/native.hpp"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/resolve.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/jit.hpp"
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
+
+/* native_make_overloaded_function *********************************************
+
+ XXX
+
+*******************************************************************************/
+
+static utf *native_make_overloaded_function(utf *name, utf *descriptor)
+{
+ char *newname;
+ s4 namelen;
+ char *utf_ptr;
+ u2 c;
+ s4 i;
+ utf *u;
+
+ utf_ptr = descriptor->text;
+ namelen = strlen(name->text) + strlen("__") + strlen("0");
+
+ /* calculate additional length */
+
+ while ((c = utf_nextu2(&utf_ptr)) != ')') {
+ switch (c) {
+ case 'Z':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'I':
+ case 'J':
+ case 'F':
+ case 'D':
+ namelen++;
+ break;
+ case '[':
+ namelen += 2;
+ break;
+ case 'L':
+ namelen++;
+ while (utf_nextu2(&utf_ptr) != ';')
+ namelen++;
+ namelen += 2;
+ break;
+ case '(':
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ /* reallocate memory */
+
+ i = strlen(name->text);
+
+ newname = MNEW(char, namelen);
+ MCOPY(newname, name->text, char, i);
+
+ utf_ptr = descriptor->text;
+
+ newname[i++] = '_';
+ newname[i++] = '_';
+
+ while ((c = utf_nextu2(&utf_ptr)) != ')') {
+ switch (c) {
+ case 'Z':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'J':
+ case 'I':
+ case 'F':
+ case 'D':
+ newname[i++] = c;
+ break;
+ case '[':
+ newname[i++] = '_';
+ newname[i++] = '3';
+ break;
+ case 'L':
+ newname[i++] = 'L';
+ while ((c = utf_nextu2(&utf_ptr)) != ';')
+ if (((c >= 'a') && (c <= 'z')) ||
+ ((c >= 'A') && (c <= 'Z')) ||
+ ((c >= '0') && (c <= '9')))
+ newname[i++] = c;
+ else
+ newname[i++] = '_';
+ newname[i++] = '_';
+ newname[i++] = '2';
+ break;
+ case '(':
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ /* close string */
+
+ newname[i] = '\0';
+
+ /* make a utf-string */
+
+ u = utf_new_char(newname);
+
+ /* release memory */
+
+ MFREE(newname, char, namelen);
+
+ return u;
+}
+
+
+/* native_insert_char **********************************************************
+
+ Inserts the passed UTF character into the native method name. If
+ necessary it is escaped properly.
+
+*******************************************************************************/
+
+static s4 native_insert_char(char *name, u4 pos, u2 c)
+{
+ s4 val;
+ s4 i;
+
+ switch (c) {
+ case '/':
+ case '.':
+ /* replace '/' or '.' with '_' */
+ name[pos] = '_';
+ break;
+
+ case '_':
+ /* escape sequence for '_' is '_1' */
+ name[pos] = '_';
+ name[++pos] = '1';
+ break;
+
+ case ';':
+ /* escape sequence for ';' is '_2' */
+ name[pos] = '_';
+ name[++pos] = '2';
+ break;
+
+ case '[':
+ /* escape sequence for '[' is '_1' */
+ name[pos] = '_';
+ name[++pos] = '3';
+ break;
+
+ default:
+ if (isalnum(c))
+ name[pos] = c;
+ else {
+ /* unicode character */
+ name[pos] = '_';
+ name[++pos] = '0';
+
+ for (i = 0; i < 4; ++i) {
+ val = c & 0x0f;
+ name[pos + 4 - i] = (val > 10) ? ('a' + val - 10) : ('0' + val);
+ c >>= 4;
+ }
+
+ pos += 4;
+ }
+ break;
+ }
+
+ /* return the new buffer index */
+
+ return pos;
+}
+
+
+/* native_method_symbol ********************************************************
+
+ Generate a method-symbol string out of the class name and the
+ method name.
+
+*******************************************************************************/
+
+static utf *native_method_symbol(utf *classname, utf *methodname)
+{
+ char *name;
+ s4 namelen;
+ char *utf_ptr;
+ char *utf_endptr;
+ u2 c;
+ u4 pos;
+ utf *u;
+
+ /* Calculate length of native function name. We multiply the
+ class and method name length by 6 as this is the maxium
+ escape-sequence that can be generated (unicode). */
+
+ namelen =
+ strlen("Java_") +
+ utf_get_number_of_u2s(classname) * 6 +
+ strlen("_") +
+ utf_get_number_of_u2s(methodname) * 6 +
+ strlen("0");
+
+ /* allocate memory */
+
+ name = MNEW(char, namelen);
+
+ /* generate name of native functions */
+
+ strcpy(name, "Java_");
+ pos = strlen("Java_");
+
+ utf_ptr = classname->text;
+ utf_endptr = UTF_END(classname);
+
+ for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+ c = *utf_ptr;
+ pos = native_insert_char(name, pos, c);
+ }
+
+ /* seperator between class and method */
+
+ name[pos++] = '_';
+
+ utf_ptr = methodname->text;
+ utf_endptr = UTF_END(methodname);
+
+ for (; utf_ptr < utf_endptr; utf_ptr++, pos++) {
+ c = *utf_ptr;
+ pos = native_insert_char(name, pos, c);
+ }
+
+ /* close string */
+
+ name[pos] = '\0';
+
+ /* check for an buffer overflow */
+
+ assert((int32_t) pos <= namelen);
+
+ /* make a utf-string */
+
+ u = utf_new_char(name);
+
+ /* release memory */
+
+ MFREE(name, char, namelen);
+
+ return u;
+}
+
+
+bool operator< (const NativeMethod& first, const NativeMethod& second)
+{
+ if (first._classname < second._classname)
+ return true;
+ else if (first._classname > second._classname)
+ return false;
+
+ if (first._name < second._name)
+ return true;
+ else if (first._name > second._name)
+ return false;
+
+ if (first._descriptor < second._descriptor)
+ return true;
+ else if (first._descriptor > second._descriptor)
+ return false;
+
+ // All pointers are equal, we have found the entry.
+ return false;
+}
+
+
+/**
+ * Register native methods with the VM. This is done by inserting
+ * them into the native method table.
+ *
+ * @param classname
+ * @param methods Native methods array.
+ * @param count Number of methods in the array.
+ */
+void NativeMethods::register_methods(utf* classname, const JNINativeMethod* methods, size_t count)
+{
+ // Insert all methods passed */
+ for (size_t i = 0; i < count; i++) {
+ if (opt_verbosejni) {
+ printf("[Registering JNI native method ");
+ utf_display_printable_ascii_classname(classname);
+ printf(".%s]\n", methods[i].name);
+ }
+
+ // Generate the UTF8 names.
+ utf* name = utf_new_char(methods[i].name);
+ utf* signature = utf_new_char(methods[i].signature);
+
+ NativeMethod nm(classname, name, signature, methods[i].fnPtr);
+
+ // Insert the method into the table.
+ _methods.insert(nm);
+ }
+}
+
+
+/**
+ * Resolves a native method, maybe from a dynamic library.
+ *
+ * @param m Method structure of the native Java method to resolve.
+ *
+ * @return Pointer to the resolved method (symbol).
+ */
+void* NativeMethods::resolve_method(methodinfo* m)
+{
+ // Verbose output.
+ if (opt_verbosejni) {
+ printf("[Dynamic-linking native method ");
+ utf_display_printable_ascii_classname(m->clazz->name);
+ printf(".");
+ utf_display_printable_ascii(m->name);
+ printf(" ... ");
+ }
+
+ /* generate method symbol string */
+
+ utf* name = native_method_symbol(m->clazz->name, m->name);
+
+ /* generate overloaded function (having the types in it's name) */
+
+ utf* newname = native_make_overloaded_function(name, m->descriptor);
+
+ // Try to find the symbol.
+ void* symbol = NULL;
+
+#if defined(ENABLE_DL)
+ // Get the classloader.
+ classloader_t* classloader = class_get_classloader(m->clazz);
+
+ // Resolve the native method name from the native libraries.
+ NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
+ symbol = libraries.resolve_symbol(name, classloader);
+
+ if (symbol == NULL)
+ symbol = libraries.resolve_symbol(newname, classloader);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ if (symbol == NULL) {
+ /* We can resolve the function directly from
+ java.lang.ClassLoader as it's a static function. */
+ /* XXX should be done in native_init */
+
+ methodinfo* method_findNative =
+ class_resolveclassmethod(class_java_lang_ClassLoader,
+ utf_findNative,
+ utf_java_lang_ClassLoader_java_lang_String__J,
+ class_java_lang_ClassLoader,
+ true);
+
+ if (method_findNative == NULL)
+ return NULL;
+
+ // Try the normal name.
+ java_handle_t* s = javastring_new(name);
+ symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
+
+ // If not found, try the mangled name.
+ if (symbol == NULL) {
+ s = javastring_new(newname);
+ symbol = (void*) vm_call_method_long(method_findNative, NULL, classloader, s);
+ }
+ }
+# endif
+
+ if (symbol != NULL)
+ if (opt_verbosejni)
+ printf("JNI ]\n");
+#endif
+
+ // If not found already, try to find the native method symbol in
+ // the native methods registered with the VM.
+ if (symbol == NULL) {
+ symbol = find_registered_method(m);
+
+ if (symbol != NULL)
+ if (opt_verbosejni)
+ printf("internal ]\n");
+ }
+
+#if defined(ENABLE_JVMTI)
+ /* fire Native Method Bind event */
+ if (jvmti) jvmti_NativeMethodBind(m, f, &f);
+#endif
+
+ // Symbol not found? Throw an exception.
+ if (symbol == NULL) {
+ if (opt_verbosejni)
+ printf("failed ]\n");
+
+ exceptions_throw_unsatisfiedlinkerror(m->name);
+ }
+
+ return symbol;
+}
+
+
+/**
+ * Try to find the given method in the native methods registered with
+ * the VM.
+ *
+ * @param m Method structure.
+ *
+ * @return Pointer to function if found, NULL otherwise.
+ */
+void* NativeMethods::find_registered_method(methodinfo* m)
+{
+ NativeMethod nm(m);
+ std::set<NativeMethod>::iterator it = _methods.find(nm);
+
+ if (it == _methods.end())
+ return NULL;
+
+ return (*it).get_function();
+}
+
+
+/**
+ * Open this native library.
+ *
+ * @return File handle on success, NULL otherwise.
+ */
+#if defined(ENABLE_DL)
+void* NativeLibrary::open()
+{
+ if (opt_verbosejni) {
+ printf("[Loading native library ");
+ utf_display_printable_ascii(_filename);
+ printf(" ... ");
+ }
+
+ // Sanity check.
+ assert(_filename != NULL);
+
+ // Try to open the library.
+ _handle = os::dlopen(_filename->text, RTLD_LAZY);
+
+ if (_handle == NULL) {
+ if (opt_verbosejni)
+ printf("failed ]\n");
+
+ if (opt_verbose) {
+ log_start();
+ log_print("NativeLibrary::open: os::dlopen failed: ");
+ log_print(os::dlerror());
+ log_finish();
+ }
+
+ return NULL;
+ }
+
+ if (opt_verbosejni)
+ printf("OK ]\n");
+
+ return _handle;
+}
+#endif
+
+
+/**
+ * Close this native library.
+ */
+#if defined(ENABLE_DL)
+void NativeLibrary::close()
+{
+ if (opt_verbosejni) {
+ printf("[Unloading native library ");
+/* utf_display_printable_ascii(filename); */
+ printf(" ... ");
+ }
+
+ // Sanity check.
+ assert(_handle != NULL);
+
+ // Close the library.
+ int result = os::dlclose(_handle);
+
+ if (result != 0) {
+ if (opt_verbosejni)
+ printf("failed ]\n");
+
+ if (opt_verbose) {
+ log_start();
+ log_print("NativeLibrary::close: os::dlclose failed: ");
+ log_print(os::dlerror());
+ log_finish();
+ }
+ }
+
+ if (opt_verbosejni)
+ printf("OK ]\n");
+}
+#endif
+
+
+/**
+ * Load this native library and initialize it, if possible.
+ *
+ * @param env JNI environment.
+ *
+ * @return true if library loaded successfully, false otherwise.
+ */
+bool NativeLibrary::load(JNIEnv* env)
+{
+#if defined(ENABLE_DL)
+ if (_filename == NULL) {
+ exceptions_throw_nullpointerexception();
+ return false;
+ }
+
+ // Is the library already loaded?
+ if (is_loaded())
+ return true;
+
+ // Open the library.
+ open();
+
+ if (_handle == NULL)
+ return false;
+
+# if defined(ENABLE_JNI)
+ // Resolve JNI_OnLoad function.
+ void* onload = os::dlsym(_handle, "JNI_OnLoad");
+
+ if (onload != NULL) {
+ JNIEXPORT jint (JNICALL *JNI_OnLoad) (JavaVM*, void*);
+ JavaVM *vm;
+
+ JNI_OnLoad = (JNIEXPORT jint (JNICALL *)(JavaVM*, void*)) (uintptr_t) onload;
+
+ env->GetJavaVM(&vm);
+
+ jint version = JNI_OnLoad(vm, NULL);
+
+ // If the version is not 1.2 and not 1.4 the library cannot be
+ // loaded.
+ if ((version != JNI_VERSION_1_2) && (version != JNI_VERSION_1_4)) {
+ os::dlclose(_handle);
+ return false;
+ }
+ }
+# endif
+
+ // Insert the library name into the native library table.
+ NativeLibraries& nativelibraries = VM::get_current()->get_nativelibraries();
+ nativelibraries.add(*this);
+
+ return true;
+#else
+ os::abort("NativeLibrary::load: Not available in this configuration.");
+
+ // Keep the compiler happy.
+ return false;
+#endif
+}
+
+
+/**
+ * Checks if this native library is loaded.
+ *
+ * @return true if loaded, false otherwise.
+ */
+#if defined(ENABLE_DL)
+bool NativeLibrary::is_loaded()
+{
+ NativeLibraries& libraries = VM::get_current()->get_nativelibraries();
+ return libraries.is_loaded(*this);
+}
+#endif
+
+
+/**
+ * Resolve the given symbol in this native library.
+ *
+ * @param symbolname Symbol name.
+ *
+ * @return Pointer to symbol if found, NULL otherwise.
+ */
+void* NativeLibrary::resolve_symbol(utf* symbolname) const
+{
+ return os::dlsym(_handle, symbolname->text);
+}
+
+
+/**
+ * Add the given native library to the native libraries table.
+ *
+ * @param library Native library to insert.
+ */
+#if defined(ENABLE_DL)
+void NativeLibraries::add(NativeLibrary& library)
+{
+ // Make the container thread-safe.
+ _mutex.lock();
+
+ // XXX Check for double entries.
+ // Insert the native library.
+ _libraries.insert(std::make_pair(library.get_classloader(), library));
+
+ _mutex.unlock();
+}
+#endif
+
+
+/**
+ * Checks if the given native library is loaded.
+ *
+ * @param library Native library.
+ *
+ * @return true if loaded, false otherwise.
+ */
+bool NativeLibraries::is_loaded(NativeLibrary& library)
+{
+ std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(library.get_classloader());
+
+ // No entry for the classloader was found (the range has length
+ // zero).
+ if (its.first == its.second)
+ return false;
+
+ MAP::const_iterator it = find_if(its.first, its.second, std::bind2nd(comparator(), library.get_filename()));
+
+ // No matching entry in the range found.
+ if (it == its.second)
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Try to find a symbol with the given name in all loaded native
+ * libraries defined by classloader.
+ *
+ * @param symbolname Name of the symbol to find.
+ * @param classloader Defining classloader.
+ *
+ * @return Pointer to symbol if found, NULL otherwise.
+ */
+void* NativeLibraries::resolve_symbol(utf* symbolname, classloader_t* classloader)
+{
+ std::pair<MAP::const_iterator, MAP::const_iterator> its = _libraries.equal_range(classloader);
+
+ // No entry for the classloader was found (the range has length
+ // zero).
+ if (its.first == its.second)
+ return NULL;
+
+ for (MAP::const_iterator it = its.first; it != its.second; it++) {
+ const NativeLibrary& library = (*it).second;
+ void* symbol = library.resolve_symbol(symbolname);
+
+ if (symbol != NULL)
+ return symbol;
+ }
+
+ return NULL;
+}
+
+
+/* native_new_and_init *********************************************************
+
+ Creates a new object on the heap and calls the initializer.
+ Returns the object pointer or NULL if memory is exhausted.
+
+*******************************************************************************/
+
+java_handle_t *native_new_and_init(classinfo *c)
+{
+ methodinfo *m;
+ java_handle_t *o;
+
+ if (c == NULL)
+ vm_abort("native_new_and_init: c == NULL");
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return NULL;
+
+ /* try to find the initializer */
+
+ m = class_findmethod(c, utf_init, utf_void__void);
+
+ /* ATTENTION: returning the object here is ok, since the class may
+ not have an initializer */
+
+ if (m == NULL)
+ return o;
+
+ /* call initializer */
+
+ (void) vm_call_method(m, o);
+
+ return o;
+}
+
+
+java_handle_t *native_new_and_init_string(classinfo *c, java_handle_t *s)
+{
+ methodinfo *m;
+ java_handle_t *o;
+
+ if (c == NULL)
+ vm_abort("native_new_and_init_string: c == NULL");
+
+ /* create object */
+
+ o = builtin_new(c);
+
+ if (o == NULL)
+ return NULL;
+
+ /* find initializer */
+
+ m = class_findmethod(c, utf_init, utf_java_lang_String__void);
+
+ /* initializer not found */
+
+ if (m == NULL)
+ return NULL;
+
+ /* call initializer */
+
+ (void) vm_call_method(m, o, s);
+
+ return 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/native.h - native library support
-
- 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 _NATIVE_H
-#define _NATIVE_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "native/jni.h"
-
-#include "vm/class.h"
-#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/method.h"
-#include "vm/os.hpp"
-#include "vm/utf8.h"
-
-
-/* defines ********************************************************************/
-
-#define NATIVE_METHODS_COUNT sizeof(methods) / sizeof(JNINativeMethod)
-
-
-#define NATIVE_LIBRARY_PREFIX "lib"
-
-#if defined(__DARWIN__)
-# define NATIVE_LIBRARY_SUFFIX ".dylib"
-#else
-# define NATIVE_LIBRARY_SUFFIX ".so"
-#endif
-
-
-/* native_methods_node_t ******************************************************/
-
-typedef struct native_methods_node_t native_methods_node_t;
-
-struct native_methods_node_t {
- utf *classname; /* class name */
- utf *name; /* method name */
- utf *descriptor; /* descriptor name */
- functionptr function; /* pointer to the implementation */
-};
-
-
-/* hashtable_library_loader_entry *********************************************/
-
-#if defined(ENABLE_DL)
-typedef struct hashtable_library_loader_entry hashtable_library_loader_entry;
-typedef struct hashtable_library_name_entry hashtable_library_name_entry;
-
-struct hashtable_library_loader_entry {
- classloader_t *loader; /* class loader */
- hashtable_library_name_entry *namelink;/* libs loaded by this loader */
- hashtable_library_loader_entry *hashlink;/* link for external chaining */
-};
-#endif
-
-
-/* hashtable_library_name_entry ***********************************************/
-
-#if defined(ENABLE_DL)
-struct hashtable_library_name_entry {
- utf *name; /* library name */
- void* handle; /* libtool library handle */
- hashtable_library_name_entry *hashlink; /* link for external chaining */
-};
-#endif
-
-
-/* function prototypes ********************************************************/
-
-bool native_init(void);
-
-void native_method_register(utf *classname, const JNINativeMethod *methods, int32_t count);
-functionptr native_method_resolve(methodinfo *m);
-
-#if defined(ENABLE_DL)
-void* native_library_open(utf *filename);
-void native_library_close(void* handle);
-void native_library_add(utf *filename, classloader_t *loader, void *handle);
-hashtable_library_name_entry *native_library_find(utf *filename, classloader_t *loader);
-int native_library_load(JNIEnv *env, utf *name, classloader_t *cl);
-#endif
-
-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 */
-
-
-/*
- * These 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/native.hpp - native library support
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ 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 _NATIVE_HPP
+#define _NATIVE_HPP
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <map>
+#include <set>
+#endif
+
+#include "native/jni.hpp"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.hpp"
+#include "vm/method.h"
+#include "vm/os.hpp"
+#include "vm/utf8.h"
+
+
+/* defines ********************************************************************/
+
+#define NATIVE_METHODS_COUNT sizeof(methods) / sizeof(JNINativeMethod)
+
+
+#define NATIVE_LIBRARY_PREFIX "lib"
+
+#if defined(__DARWIN__)
+# define NATIVE_LIBRARY_SUFFIX ".dylib"
+#else
+# define NATIVE_LIBRARY_SUFFIX ".so"
+#endif
+
+
+#ifdef __cplusplus
+
+#if defined(ENABLE_DL)
+/**
+ * Represents a native library.
+ */
+class NativeLibrary {
+private:
+ utf* _filename; ///< Name of the native library.
+ classloader_t* _classloader; ///< Defining classloader.
+ void* _handle; ///< Filesystem handle.
+
+public:
+ NativeLibrary(utf* filename, classloader_t* classloader = 0, void* handle = 0) : _filename(filename), _classloader(classloader), _handle(handle) {}
+ NativeLibrary(void* handle) : _filename(0), _classloader(0), _handle(handle) {}
+
+ inline classloader_t* get_classloader() const { return _classloader; }
+ inline utf* get_filename () const { return _filename; }
+ inline void* get_handle () const { return _handle; }
+
+ void* open();
+ void close();
+ bool load(JNIEnv* env);
+ bool is_loaded();
+ void* resolve_symbol(utf* symbolname) const;
+};
+
+
+/**
+ * Table containing all loaded native libraries.
+ */
+class NativeLibraries {
+private:
+ Mutex _mutex; ///< Mutex to make the container thread-safe.
+ typedef std::multimap<classloader_t*, NativeLibrary> MAP;
+ MAP _libraries;
+
+private:
+ // Comparator class.
+ class comparator : public std::binary_function<std::pair<classloader_t*, NativeLibrary>, utf*, bool> {
+ public:
+ bool operator() (std::pair<classloader_t*, NativeLibrary> args, const utf* filename) const
+ {
+ return (args.second.get_filename() == filename);
+ }
+ };
+
+public:
+ void add(NativeLibrary& library);
+ bool is_loaded(NativeLibrary& library);
+ void* resolve_symbol(utf* symbolname, classloader_t* classloader);
+};
+#endif
+
+
+/**
+ * Represents a native method.
+ */
+class NativeMethod {
+private:
+ utf* _classname; ///< Class name.
+ utf* _name; ///< Method name.
+ utf* _descriptor; ///< Method signature.
+ void* _function; ///< Pointer to the native function.
+
+ friend bool operator< (const NativeMethod& first, const NativeMethod& second);
+
+public:
+ NativeMethod(utf* classname, utf* name, utf* signature, void* function) : _classname(classname), _name(name), _descriptor(signature), _function(function) {}
+ NativeMethod(methodinfo* m) : _classname(m->clazz->name), _name(m->name), _descriptor(m->descriptor), _function(0) {}
+
+ inline void* get_function() const { return _function; }
+};
+
+
+/**
+ * Table containing all native methods registered with the VM.
+ */
+class NativeMethods {
+private:
+ Mutex _mutex;
+ std::set<NativeMethod> _methods;
+
+private:
+ // Comparator class.
+ class comparator : public std::binary_function<std::pair<classloader_t*, NativeLibrary>, utf*, bool> {
+ public:
+ bool operator() (std::pair<classloader_t*, NativeLibrary> args, const utf* filename) const
+ {
+ return (args.second.get_filename() == filename);
+ }
+ };
+
+public:
+ void register_methods(utf* classname, const JNINativeMethod* methods, size_t count);
+ void* resolve_method(methodinfo* m);
+ void* find_registered_method(methodinfo* m);
+};
+
+#endif
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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
+} // extern "C"
+#endif
+
+#endif // _NATIVE_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:
+ */
if ENABLE_JAVASE
REFLECTION_SOURCES = \
- reflection.c \
- reflection.h
+ reflection.cpp \
+ reflection.hpp
SUN_MISC_UNSAFE_SOURCES = \
sun_misc_Unsafe.cpp
libnativevm.la
libnativevm_la_SOURCES = \
- nativevm.c \
- nativevm.h \
+ nativevm.cpp \
+ nativevm.hpp \
$(REFLECTION_SOURCES) \
$(SUN_MISC_UNSAFE_SOURCES)
#include "mm/memory.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/com_sun_cldc_io_ResourceInputStream.h"
#endif
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/javaobjects.hpp"
#include "vm/string.hpp"
*/
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;
/* 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)) {
-
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+ list_classpath_entry* lce = *it;
+
#if defined(ENABLE_ZLIB)
if (lce->type == CLASSPATH_ARCHIVE) {
/* enter a monitor on zip/jar archives */
- LOCK_MONITOR_ENTER(lce);
+ lce->mutex->lock();
/* try to get the file in current archive */
descriptor = zip_read_resource(lce, uname);
/* leave the monitor */
- LOCK_MONITOR_EXIT(lce);
+ lce->mutex->unlock();
if (descriptor != NULL) { /* file exists */
break;
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_com_sun_cldc_io_ResourceInputStream_init(void)
{
- utf *u;
+ utf* u = utf_new_char("com/sun/cldc/io/ResourceInputStream");
- u = utf_new_char("com/sun/cldc/io/ResourceInputStream");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/memory.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/com_sun_cldc_io_j2me_socket_Protocol.h"
*******************************************************************************/
-// 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");
+ utf* u = utf_new_char("com/sun/cldc/io/j2me/socket/Protocol");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "vm/types.h"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/com_sun_cldchi_io_ConsoleOutputStream.h"
#endif
+#include "vm/vm.hpp"
+
// Native functions are exported as C functions.
extern "C" {
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init(void)
{
- utf *u;
-
- u = utf_new_char("com/sun/cldchi/io/ConsoleOutputStream");
+ utf* u = utf_new_char("com/sun/cldchi/io/ConsoleOutputStream");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/com_sun_cldchi_jvm_JVM.h"
#include "vm/exceptions.hpp"
#include "vm/string.hpp"
+#include "vm/vm.hpp"
// Native functions are exported as C functions.
return;
}
- /* REMOVEME When we use Java-strings internally. */
+ // REMOVEME When we use Java-strings internally.
+ utf* name = javastring_toutf((java_handle_t*) libName, false);
- utf* name = javastring_toutf((java_handle_t *) libName, false);
+ NativeLibrary nl(name);
+ bool result = nl.load(env);
- int result = native_library_load(env, name, NULL);
-
- /* Check for error and throw an exception in case. */
-
- if (result == 0) {
+ // Check for error and throw an exception in case.
+ if (result == false) {
exceptions_throw_unsatisfiedlinkerror(name);
}
}
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_com_sun_cldchi_jvm_JVM_init(void)
{
- utf *u;
+ utf* u = utf_new_char("com/sun/cldchi/jvm/JVM");
- u = utf_new_char("com/sun/cldchi/jvm/JVM");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Class.h"
{ (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");
+ utf* u = utf_new_char("java/lang/Class");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Double.h"
#endif
-#include "vm/builtin.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/builtin.hpp"
// Native functions are exported as C functions.
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_Double_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/Double");
+ utf* u = utf_new_char("java/lang/Double");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Float.h"
#endif
-#include "vm/builtin.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/builtin.hpp"
// Native functions are exported as C functions.
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_Float_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/Float");
+ utf* u = utf_new_char("java/lang/Float");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "fdlibm/fdlibm.h"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Math.h"
#endif
+#include "vm/vm.hpp"
+
// Native functions are exported as C functions.
extern "C" {
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_Math_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/Math");
+ utf* u = utf_new_char("java/lang/Math");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
#include <stdlib.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Object.h"
#endif
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
// Native functions are exported as C functions.
*/
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);
+ java_lang_Object o(obj);
- return (jclass) LLNI_classinfo_wrap(c);
+ return (jclass) LLNI_classinfo_wrap(o.get_Class());
}
*/
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
+ java_lang_Object o(_this);
+
+ return o.get_hashcode();
}
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_Object_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/Object");
+ utf* u = utf_new_char("java/lang/Object");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/gc.hpp"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Runtime.h"
*******************************************************************************/
-// 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);
-}
+ utf* u = utf_new_char("java/lang/Runtime");
+
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdlib.h>
#include <string.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_String.h"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_String_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/String");
+ utf* u = utf_new_char("java/lang/String");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_System.h"
#endif
-#include "vm/builtin.h"
-#include "vm/properties.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/properties.hpp"
#include "vm/string.hpp"
+#include "vm/vm.hpp"
// Native functions are exported as C functions.
/* get the property from the internal table */
- value = properties_get(key);
+ value = VM::get_current()->get_properties().get(key);
/* release the memory allocated in javastring_tochar */
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_System_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/System");
+ utf* u = utf_new_char("java/lang/System");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Thread.h"
#include "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/javaobjects.hpp"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_Thread_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/Thread");
+ utf* u = utf_new_char("java/lang/Thread");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <assert.h>
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_lang_Throwable.h"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_Throwable_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/Throwable");
+ utf* u = utf_new_char("java/lang/Throwable");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
java_lang_VMSystem.cpp \
java_lang_VMThread.cpp \
java_lang_VMThrowable.cpp \
- java_lang_management_VMManagementFactory.c \
+ java_lang_management_VMManagementFactory.cpp \
java_lang_reflect_VMConstructor.cpp \
java_lang_reflect_VMField.cpp \
java_lang_reflect_VMMethod.cpp \
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/gnu_classpath_VMStackWalker.h"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_gnu_classpath_VMStackWalker_init(void)
{
- utf *u;
-
- u = utf_new_char("gnu/classpath/VMStackWalker");
+ utf* u = utf_new_char("gnu/classpath/VMStackWalker");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/gnu_classpath_VMSystemProperties.h"
#endif
#include "vm/exceptions.hpp"
-#include "vm/properties.h"
+#include "vm/properties.hpp"
#include "vm/vm.hpp"
return;
}
- /* fill the java.util.Properties object */
-
- properties_system_add_all(p);
+ // Fill the java.util.Properties object.
+ VM::get_current()->get_properties().fill(p);
}
/* XXX when we do it that way, we can't set these properties on
commandline */
- java_home = properties_get("java.home");
+ java_home = VM::get_current()->get_properties().get("java.home");
- properties_system_add(p, "gnu.classpath.home", java_home);
+ Properties::put(p, "gnu.classpath.home", java_home);
len =
strlen("file://") +
strcat(path, java_home);
strcat(path, "/lib");
- properties_system_add(p, "gnu.classpath.home.url", path);
+ Properties::put(p, "gnu.classpath.home.url", path);
MFREE(path, char, len);
#endif
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_gnu_classpath_VMSystemProperties_init(void)
{
- utf *u;
+ utf* u = utf_new_char("gnu/classpath/VMSystemProperties");
- u = utf_new_char("gnu/classpath/VMSystemProperties");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/include/java_lang_Object.h"
#include "native/include/gnu_classpath_jdwp_VMFrame.h"
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/include/gnu_classpath_jdwp_VMMethod.h"
#include <string.h>
#include "toolbox/logging.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/include/java_lang_Thread.h"
#include "native/include/java_nio_ByteBuffer.h"
#include "native/include/java_lang_Class.h"
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/gnu_java_lang_VMCPStringBuilder.h"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
#include "vm/javaobjects.hpp"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_gnu_java_lang_VMCPStringBuilder_init(void)
{
- utf *u;
+ utf* u = utf_new_char("gnu/java/lang/VMCPStringBuilder");
- u = utf_new_char("gnu/java/lang/VMCPStringBuilder");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/gc.hpp"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/gnu_java_lang_management_VMClassLoadingMXBeanImpl.h"
/* 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++!");
+ return 0;
}
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init(void)
{
- utf *u;
+ utf* u = utf_new_char("gnu/java/lang/management/VMClassLoadingMXBeanImpl");
- u = utf_new_char("gnu/java/lang/management/VMClassLoadingMXBeanImpl");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/gc.hpp"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/gnu_java_lang_management_VMMemoryMXBeanImpl.h"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/global.h"
-#include "vm/loader.h" /* XXX only for load_class_bootstrap */
+#include "vm/loader.hpp" /* XXX only for load_class_bootstrap */
#include "vm/options.h"
#include "vm/vm.hpp"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init(void)
{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/management/VMMemoryMXBeanImpl");
+ utf* u = utf_new_char("gnu/java/lang/management/VMMemoryMXBeanImpl");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/gnu_java_lang_management_VMRuntimeMXBeanImpl.h"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/utf8.h"
*/
JNIEXPORT int64_t JNICALL Java_gnu_java_lang_management_VMRuntimeMXBeanImpl_getStartTime(JNIEnv *env, jclass clazz)
{
- return vm->get_starttime();
+ return VM::get_current()->get_starttime();
}
} // extern "C"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init(void)
{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/management/VMRuntimeMXBeanImpl");
+ utf* u = utf_new_char("gnu/java/lang/management/VMRuntimeMXBeanImpl");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/gc.hpp"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/gnu_java_lang_management_VMThreadMXBeanImpl.h"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init(void)
{
- utf *u;
-
- u = utf_new_char("gnu/java/lang/management/VMThreadMXBeanImpl");
+ utf* u = utf_new_char("gnu/java/lang/management/VMThreadMXBeanImpl");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_VMClass.h"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_VMClass_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/VMClass");
+ utf* u = utf_new_char("java/lang/VMClass");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/memory.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_VMClassLoader.h"
#endif
#include "toolbox/logging.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
#if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
+#include "vm/assertion.hpp"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/initialize.h"
#include "vm/javaobjects.hpp"
#include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#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"
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 */
/* 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)) {
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+ list_classpath_entry* lce = *it;
+
/* clear path pointer */
path = NULL;
#if defined(ENABLE_ASSERTION)
java_handle_t *js;
methodinfo *m;
- assertion_name_t *item;
#endif
/* new HashMap() */
return NULL;
}
- item = (assertion_name_t *)list_first(list_assertion_names);
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
- while (item != NULL) {
- if (item->package == false) {
- item = (assertion_name_t *)list_next(list_assertion_names, item);
+ if (item->package == false)
continue;
- }
if (strcmp(item->name, "") == 0) {
/* unnamed package wanted */
else {
vm_call_method(m, hm, js, jfalse);
}
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
}
#endif
#if defined(ENABLE_ASSERTION)
java_handle_t *js;
methodinfo *m;
- assertion_name_t *item;
#endif
/* new HashMap() */
return NULL;
}
- item = (assertion_name_t *)list_first(list_assertion_names);
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
- while (item != NULL) {
- if (item->package == true) {
- item = (assertion_name_t *)list_next(list_assertion_names, item);
+ if (item->package == true)
continue;
- }
js = javastring_new_from_ascii(item->name);
if (js == NULL) {
else {
vm_call_method(m, hm, js, jfalse);
}
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
}
#endif
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_VMClassLoader_init(void)
{
- utf *u;
+ utf* u = utf_new_char("java/lang/VMClassLoader");
- u = utf_new_char("java/lang/VMClassLoader");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_VMObject.h"
#endif
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/utf8.h"
* Method: getClass
* Signature: (Ljava/lang/Object;)Ljava/lang/Class;
*/
-JNIEXPORT jclass JNICALL Java_java_lang_VMObject_getClass(JNIEnv *env, jclass clazz, jobject obj)
+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);
+ java_lang_Object o(obj);
- return (jclass) LLNI_classinfo_wrap(c);
+ return (jclass) LLNI_classinfo_wrap(o.get_Class());
}
* Method: clone
* Signature: (Ljava/lang/Cloneable;)Ljava/lang/Object;
*/
-JNIEXPORT jobject JNICALL Java_java_lang_VMObject_clone(JNIEnv *env, jclass clazz, jobject _this)
+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;
+ return builtin_clone(NULL, _this);
}
* Method: notify
* Signature: (Ljava/lang/Object;)V
*/
-JNIEXPORT void JNICALL Java_java_lang_VMObject_notify(JNIEnv *env, jclass clazz, jobject _this)
+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);
+ lock_notify_object(_this);
#endif
}
* Method: notifyAll
* Signature: (Ljava/lang/Object;)V
*/
-JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(JNIEnv *env, jclass clazz, jobject _this)
+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);
+ lock_notify_all_object(_this);
#endif
}
* 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)
+JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnv* env, jclass clazz, jobject o, jlong ms, jint ns)
{
#if defined(ENABLE_JVMTI)
/* Monitor Wait */
#endif
#if defined(ENABLE_THREADS)
- lock_wait_for_object((java_handle_t *) o, ms, ns);
+ lock_wait_for_object(o, ms, ns);
#endif
#if defined(ENABLE_JVMTI)
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_VMObject_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/VMObject");
+ utf* u = utf_new_char("java/lang/VMObject");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
# include <mach/mach.h>
#endif
-#include "mm/dumpmemory.h"
+#include "mm/memory.h"
#include "mm/gc.hpp"
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_VMRuntime.h"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/os.hpp"
#include "vm/string.hpp"
*/
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);
+ classloader_t* cl = loader_hashtable_classloader_add((java_handle_t *) loader);
/* REMOVEME When we use Java-strings internally. */
return 0;
}
- name = javastring_toutf((java_handle_t *) libname, false);
+ utf* name = javastring_toutf((java_handle_t *) libname, false);
- return native_library_load(env, name, cl);
+ NativeLibrary library(name, cl);
+ return library.load(env);
}
char *buffer;
int32_t buffer_len;
java_handle_t *o;
- int32_t dumpmarker;
if (libname == NULL) {
exceptions_throw_nullpointerexception();
strlen(NATIVE_LIBRARY_SUFFIX) +
strlen("0");
- DMARKER;
-
- buffer = DMNEW(char, buffer_len);
+ buffer = MNEW(char, buffer_len);
/* generate library name */
/* release memory */
- DRELEASE;
+ MFREE(buffer, char, buffer_len);
return (jstring) o;
}
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_VMRuntime_init(void)
{
- utf *u;
+ utf* u = utf_new_char("java/lang/VMRuntime");
- u = utf_new_char("java/lang/VMRuntime");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
#include <stdlib.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_VMString.h"
#endif
#include "vm/string.hpp"
+#include "vm/vm.hpp"
// Native functions are exported as C functions.
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_VMString_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/VMString");
+ utf* u = utf_new_char("java/lang/VMString");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/gc.hpp"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vminclude/java_lang_VMSystem.h"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/javaobjects.hpp"
// Native functions are exported as C functions.
* Method: identityHashCode
* Signature: (Ljava/lang/Object;)I
*/
-JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, jobject o)
+JNIEXPORT jint JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, jobject obj)
{
- int32_t hashcode;
+ java_lang_Object o(obj);
- // 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;
+ return o.get_hashcode();
}
} // extern "C"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_VMSystem_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/VMSystem");
+ utf* u = utf_new_char("java/lang/VMSystem");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_VMThread.h"
#endif
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "threads/thread.hpp"
#include "vm/exceptions.hpp"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_VMThread_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/VMThread");
+ utf* u = utf_new_char("java/lang/VMThread");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "vm/types.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_VMThrowable.h"
#endif
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
#include "vm/javaobjects.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/string.hpp"
-#include "vm/jit/code.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/stacktrace.hpp"
linenumber = -1;
}
else {
- /* FIXME The linenumbertable_linenumber_for_pc could
- change the methodinfo pointer when hitting an inlined
- method. */
+ /* FIXME linenumbertable->find could change the methodinfo
+ pointer when hitting an inlined method. */
- linenumber = linenumbertable_linenumber_for_pc(&m, code, ste->pc);
+ linenumber = code->linenumbertable->find(&m, ste->pc);
linenumber = (linenumber == 0) ? -1 : linenumber;
}
*******************************************************************************/
-extern "C" {
void _Jv_java_lang_VMThrowable_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/VMThrowable");
+ utf* u = utf_new_char("java/lang/VMThrowable");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
+++ /dev/null
-/* src/native/vm/gnuclasspath/java_lang_management_VMManagementFactory.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 "vm/types.h"
-
-#include "native/jni.h"
-#include "native/native.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 "vm/globals.hpp"
-
-
-/*
- * Class: java/lang/management/VMManagementFactory
- * Method: getMemoryPoolNames
- * Signature: ()[Ljava/lang/String;
- */
-JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryPoolNames(JNIEnv *env, jclass clazz)
-{
- java_handle_objectarray_t *oa;
-
- log_println("Java_java_lang_management_VMManagementFactory_getMemoryPoolNames: IMPLEMENT ME!");
-
- oa = builtin_anewarray(0, class_java_lang_String);
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/management/VMManagementFactory
- * Method: getMemoryManagerNames
- * Signature: ()[Ljava/lang/String;
- */
-JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryManagerNames(JNIEnv *env, jclass clazz)
-{
- java_handle_objectarray_t *oa;
-
- log_println("Java_java_lang_management_VMManagementFactory_getMemoryManagerNames: IMPLEMENT ME!");
-
- oa = builtin_anewarray(0, class_java_lang_String);
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/management/VMManagementFactory
- * Method: getGarbageCollectorNames
- * Signature: ()[Ljava/lang/String;
- */
-JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames(JNIEnv *env, jclass clazz)
-{
- java_handle_objectarray_t *oa;
-
- log_println("Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames: IMPLEMENT ME!");
-
- oa = builtin_anewarray(0, class_java_lang_String);
-
- return 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
- * 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_management_VMManagementFactory.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 "vm/types.h"
+
+#include "native/jni.hpp"
+#include "native/native.hpp"
+
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_management_VMManagementFactory.h"
+#endif
+
+#include "toolbox/logging.h"
+
+#include "vm/globals.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/builtin.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class: java/lang/management/VMManagementFactory
+ * Method: getMemoryPoolNames
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryPoolNames(JNIEnv *env, jclass clazz)
+{
+ java_handle_objectarray_t *oa;
+
+ log_println("Java_java_lang_management_VMManagementFactory_getMemoryPoolNames: IMPLEMENT ME!");
+
+ oa = builtin_anewarray(0, class_java_lang_String);
+
+ return oa;
+}
+
+
+/*
+ * Class: java/lang/management/VMManagementFactory
+ * Method: getMemoryManagerNames
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getMemoryManagerNames(JNIEnv *env, jclass clazz)
+{
+ java_handle_objectarray_t *oa;
+
+ log_println("Java_java_lang_management_VMManagementFactory_getMemoryManagerNames: IMPLEMENT ME!");
+
+ oa = builtin_anewarray(0, class_java_lang_String);
+
+ return oa;
+}
+
+
+/*
+ * Class: java/lang/management/VMManagementFactory
+ * Method: getGarbageCollectorNames
+ * Signature: ()[Ljava/lang/String;
+ */
+JNIEXPORT jobjectArray JNICALL Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames(JNIEnv *env, jclass clazz)
+{
+ java_handle_objectarray_t *oa;
+
+ log_println("Java_java_lang_management_VMManagementFactory_getGarbageCollectorNames: IMPLEMENT ME!");
+
+ oa = builtin_anewarray(0, class_java_lang_String);
+
+ return oa;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { (char*) "getMemoryPoolNames", (char*) "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryPoolNames },
+ { (char*) "getMemoryManagerNames", (char*) "()[Ljava/lang/String;", (void*) (uintptr_t) &Java_java_lang_management_VMManagementFactory_getMemoryManagerNames },
+ { (char*) "getGarbageCollectorNames", (char*) "()[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 = utf_new_char("java/lang/management/VMManagementFactory");
+
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(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:
+ */
#include <assert.h>
#include <stdlib.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_reflect_VMConstructor.h"
if (declaredAnnotations == NULL) {
java_handle_bytearray_t* annotations = rvmc.get_annotations();
classinfo* declaringClass = rvmc.get_clazz();
-
- classinfo *referer;
- LLNI_class_get(_this, referer);
+ classinfo* referer = rvmc.get_Class();
declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
java_handle_bytearray_t* parameterAnnotations = rvmc.get_parameterAnnotations();
methodinfo* m = rvmc.get_method();
-
- classinfo* referer;
- LLNI_class_get((java_lang_reflect_VMConstructor*) _this, referer);
+ classinfo* referer = rvmc.get_Class();
java_handle_objectarray_t* oa = Reflection::get_parameterannotations(parameterAnnotations, m, referer);
*******************************************************************************/
-extern "C" {
void _Jv_java_lang_reflect_VMConstructor_init(void)
{
- utf *u;
+ utf* u = utf_new_char("java/lang/reflect/VMConstructor");
- u = utf_new_char("java/lang/reflect/VMConstructor");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <assert.h>
#include <stdint.h>
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_reflect_VMField.h"
#endif
#include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/initialize.h"
#include "vm/javaobjects.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/string.hpp"
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return NULL;
imm_union value;
case PRIMITIVETYPE_CHAR:
case PRIMITIVETYPE_SHORT:
case PRIMITIVETYPE_INT:
- value.i = _field_get_int(f, ho);
+ value.i = _field_get_int(f, o);
break;
case PRIMITIVETYPE_LONG:
- value.l = _field_get_long(f, ho);
+ value.l = _field_get_long(f, o);
break;
case PRIMITIVETYPE_FLOAT:
- value.f = _field_get_float(f, ho);
+ value.f = _field_get_float(f, o);
break;
case PRIMITIVETYPE_DOUBLE:
- value.d = _field_get_double(f, ho);
+ value.d = _field_get_double(f, o);
break;
case TYPE_ADR:
- return (jobject) _field_get_handle(f, ho);
+ return (jobject) _field_get_handle(f, o);
}
- /* Now box the primitive types. */
-
+ // Now box the primitive types.
java_handle_t* object = Primitive::box(f->parseddesc->primitivetype, value);
- return (jobject) object;
+ return object;
}
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // Check the field type and return the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_BOOLEAN:
- return (int32_t) _field_get_int(f, ho);
+ return (jint) _field_get_int(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // Check the field type and return the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_BYTE:
- return (int32_t) _field_get_int(f, ho);
+ return (jint) _field_get_int(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // Check the field type and return the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_CHAR:
- return (int32_t) _field_get_int(f, ho);
+ return (jint) _field_get_int(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // 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);
+ return (jint) _field_get_int(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // 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);
+ return (jint) _field_get_int(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // 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);
+ return (jlong) _field_get_int(f, o);
case PRIMITIVETYPE_LONG:
- return (int64_t) _field_get_long(f, ho);
+ return (jlong) _field_get_long(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // 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);
+ return (jfloat) _field_get_int(f, o);
case PRIMITIVETYPE_LONG:
- return (float) _field_get_long(f, ho);
+ return (jfloat) _field_get_long(f, o);
case PRIMITIVETYPE_FLOAT:
- return (float) _field_get_float(f, ho);
+ return (jfloat) _field_get_float(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return 0;
- /* check the field type and return the value */
-
+ // 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);
+ return (jdouble) _field_get_int(f, o);
case PRIMITIVETYPE_LONG:
- return (jdouble) _field_get_long(f, ho);
+ return (jdouble) _field_get_long(f, o);
case PRIMITIVETYPE_FLOAT:
- return (jdouble) _field_get_float(f, ho);
+ return (jdouble) _field_get_float(f, o);
case PRIMITIVETYPE_DOUBLE:
- return (jdouble) _field_get_double(f, ho);
+ return (jdouble) _field_get_double(f, o);
default:
exceptions_throw_illegalargumentexception();
return 0;
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, df, o))
return;
- /* get the source classinfo from the object */
-
- if (hvalue == NULL)
+ // Get the source classinfo from the object.
+ if (value == NULL)
sc = NULL;
else
- LLNI_class_get(hvalue, sc);
+ 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
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_BOOLEAN:
- val = java_lang_Boolean(hvalue).get_value();
+ val = java_lang_Boolean(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_int(df, ho, val);
+ _field_set_int(df, o, val);
return;
}
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_BYTE:
- val = java_lang_Byte(hvalue).get_value();
+ val = java_lang_Byte(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_int(df, ho, val);
+ _field_set_int(df, o, val);
return;
}
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_CHAR:
- val = java_lang_Character(hvalue).get_value();
+ val = java_lang_Character(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_int(df, ho, val);
+ _field_set_int(df, o, val);
return;
}
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_BYTE:
- val = java_lang_Byte(hvalue).get_value();
+ val = java_lang_Byte(value).get_value();
break;
case PRIMITIVETYPE_SHORT:
- val = java_lang_Short(hvalue).get_value();
+ val = java_lang_Short(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_int(df, ho, val);
+ _field_set_int(df, o, val);
return;
}
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_BYTE:
- val = java_lang_Byte(hvalue).get_value();
+ val = java_lang_Byte(value).get_value();
break;
case PRIMITIVETYPE_CHAR:
- val = java_lang_Character(hvalue).get_value();
+ val = java_lang_Character(value).get_value();
break;
case PRIMITIVETYPE_SHORT:
- val = java_lang_Short(hvalue).get_value();
+ val = java_lang_Short(value).get_value();
break;
case PRIMITIVETYPE_INT:
- val = java_lang_Integer(hvalue).get_value();
+ val = java_lang_Integer(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_int(df, ho, val);
+ _field_set_int(df, o, val);
return;
}
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_BYTE:
- val = java_lang_Byte(hvalue).get_value();
+ val = java_lang_Byte(value).get_value();
break;
case PRIMITIVETYPE_CHAR:
- val = java_lang_Character(hvalue).get_value();
+ val = java_lang_Character(value).get_value();
break;
case PRIMITIVETYPE_SHORT:
- val = java_lang_Short(hvalue).get_value();
+ val = java_lang_Short(value).get_value();
break;
case PRIMITIVETYPE_INT:
- val = java_lang_Integer(hvalue).get_value();
+ val = java_lang_Integer(value).get_value();
break;
case PRIMITIVETYPE_LONG:
- val = java_lang_Long(hvalue).get_value();
+ val = java_lang_Long(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_long(df, ho, val);
+ _field_set_long(df, o, val);
return;
}
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_BYTE:
- val = java_lang_Byte(hvalue).get_value();
+ val = java_lang_Byte(value).get_value();
break;
case PRIMITIVETYPE_CHAR:
- val = java_lang_Character(hvalue).get_value();
+ val = java_lang_Character(value).get_value();
break;
case PRIMITIVETYPE_SHORT:
- val = java_lang_Short(hvalue).get_value();
+ val = java_lang_Short(value).get_value();
break;
case PRIMITIVETYPE_INT:
- val = java_lang_Integer(hvalue).get_value();
+ val = java_lang_Integer(value).get_value();
break;
case PRIMITIVETYPE_LONG:
- val = java_lang_Long(hvalue).get_value();
+ val = java_lang_Long(value).get_value();
break;
case PRIMITIVETYPE_FLOAT:
- val = java_lang_Float(hvalue).get_value();
+ val = java_lang_Float(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_float(df, ho, val);
+ _field_set_float(df, o, val);
return;
}
switch (sf->parseddesc->primitivetype) {
case PRIMITIVETYPE_BYTE:
- val = java_lang_Byte(hvalue).get_value();
+ val = java_lang_Byte(value).get_value();
break;
case PRIMITIVETYPE_CHAR:
- val = java_lang_Character(hvalue).get_value();
+ val = java_lang_Character(value).get_value();
break;
case PRIMITIVETYPE_SHORT:
- val = java_lang_Short(hvalue).get_value();
+ val = java_lang_Short(value).get_value();
break;
case PRIMITIVETYPE_INT:
- val = java_lang_Integer(hvalue).get_value();
+ val = java_lang_Integer(value).get_value();
break;
case PRIMITIVETYPE_LONG:
- val = java_lang_Long(hvalue).get_value();
+ val = java_lang_Long(value).get_value();
break;
case PRIMITIVETYPE_FLOAT:
- val = java_lang_Float(hvalue).get_value();
+ val = java_lang_Float(value).get_value();
break;
case PRIMITIVETYPE_DOUBLE:
- val = java_lang_Double(hvalue).get_value();
+ val = java_lang_Double(value).get_value();
break;
default:
exceptions_throw_illegalargumentexception();
return;
}
- _field_set_double(df, ho, val);
+ _field_set_double(df, o, val);
return;
}
/* if (!builtin_instanceof((java_handle_t *) value, df->class)) */
/* break; */
- _field_set_handle(df, ho, hvalue);
+ _field_set_handle(df, o, value);
return;
}
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // Check the field type and set the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_BOOLEAN:
- _field_set_int(f, ho, value);
+ _field_set_int(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // 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);
+ _field_set_int(f, o, value);
break;
case PRIMITIVETYPE_LONG:
- _field_set_long(f, ho, value);
+ _field_set_long(f, o, value);
break;
case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, ho, value);
+ _field_set_float(f, o, value);
break;
case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, ho, value);
+ _field_set_double(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // Check the field type and set the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_CHAR:
case PRIMITIVETYPE_INT:
- _field_set_int(f, ho, value);
+ _field_set_int(f, o, value);
break;
case PRIMITIVETYPE_LONG:
- _field_set_long(f, ho, value);
+ _field_set_long(f, o, value);
break;
case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, ho, value);
+ _field_set_float(f, o, value);
break;
case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, ho, value);
+ _field_set_double(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // Check the field type and set the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_SHORT:
case PRIMITIVETYPE_INT:
- _field_set_int(f, ho, value);
+ _field_set_int(f, o, value);
break;
case PRIMITIVETYPE_LONG:
- _field_set_long(f, ho, value);
+ _field_set_long(f, o, value);
break;
case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, ho, value);
+ _field_set_float(f, o, value);
break;
case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, ho, value);
+ _field_set_double(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // Check the field type and set the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_INT:
- _field_set_int(f, ho, value);
+ _field_set_int(f, o, value);
break;
case PRIMITIVETYPE_LONG:
- _field_set_long(f, ho, value);
+ _field_set_long(f, o, value);
break;
case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, ho, value);
+ _field_set_float(f, o, value);
break;
case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, ho, value);
+ _field_set_double(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // Check the field type and set the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_LONG:
- _field_set_long(f, ho, value);
+ _field_set_long(f, o, value);
break;
case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, ho, value);
+ _field_set_float(f, o, value);
break;
case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, ho, value);
+ _field_set_double(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // Check the field type and set the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, ho, value);
+ _field_set_float(f, o, value);
break;
case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, ho, value);
+ _field_set_double(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
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))
+ // Check if the field can be accessed.
+ if (!_field_access_check(rvmf, f, o))
return;
- /* check the field type and set the value */
-
+ // Check the field type and set the value.
switch (f->parseddesc->primitivetype) {
case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, ho, value);
+ _field_set_double(f, o, value);
break;
default:
exceptions_throw_illegalargumentexception();
/* in error case o is NULL */
- return (jstring) o;
+ return o;
}
if (declaredAnnotations == NULL) {
java_handle_bytearray_t* annotations = rvmf.get_annotations();
classinfo* declaringClass = rvmf.get_clazz();
-
- classinfo* referer;
- LLNI_class_get(_this, referer);
+ classinfo* referer = rvmf.get_Class();
declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_reflect_VMField_init(void)
{
- utf *u;
-
- u = utf_new_char("java/lang/reflect/VMField");
+ utf* u = utf_new_char("java/lang/reflect/VMField");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "vm/vm.hpp"
#endif
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_lang_reflect_VMMethod.h"
#include "native/vm/reflection.hpp"
#include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
return NULL;
}
- classinfo *referer;
- LLNI_class_get((java_lang_reflect_VMMethod *) _this, referer);
+ classinfo *referer = rvmm.get_Class();
m_parseAnnotationDefault = class_resolveclassmethod(
class_sun_reflect_annotation_AnnotationParser,
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);
+ classinfo* referer = rvmm.get_Class();
declaredAnnotations = Reflection::get_declaredannotations(annotations, declaringClass, referer);
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);
+ classinfo* referer = rvmm.get_Class();
java_handle_objectarray_t* oa = Reflection::get_parameterannotations(parameterAnnotations, m, referer);
return (jobjectArray) oa;
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_lang_reflect_VMMethod_init(void)
{
- utf *u;
+ utf* u = utf_new_char("java/lang/reflect/VMMethod");
- u = utf_new_char("java/lang/reflect/VMMethod");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdlib.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
// FIXME
//#include "native/include/java_lang_reflect_VMProxy.h"
*******************************************************************************/
+#if 0
void _Jv_java_lang_reflect_VMProxy_init(void)
{
-#if 0
utf *u;
u = utf_new_char("java/lang/reflect/VMProxy");
native_method_register(u, methods, NATIVE_METHODS_COUNT);
-#endif
}
+#endif
#if 0
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/vm/include/java_security_VMAccessController.h"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_security_VMAccessController_init(void)
{
- utf *u;
-
- u = utf_new_char("java/security/VMAccessController");
+ utf* u = utf_new_char("java/security/VMAccessController");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/jni.hpp"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/java_util_concurrent_atomic_AtomicLong.h"
#endif
#include "vm/utf8.h"
+#include "vm/vm.hpp"
// Native functions are exported as C functions.
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_java_util_concurrent_atomic_AtomicLong_init(void)
{
- utf *u;
-
- u = utf_new_char("java/util/concurrent/atomic/AtomicLong");
+ utf* u = utf_new_char("java/util/concurrent/atomic/AtomicLong");
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
#include "mm/memory.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
// FIXME
//#include "native/include/sun_reflect_ConstantPool.h"
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_sun_reflect_ConstantPool_init(void)
{
- native_method_register(utf_new_char("sun/reflect/ConstantPool"), methods, NATIVE_METHODS_COUNT);
-}
+ utf* u = utf_new_char("sun/reflect/ConstantPool");
+
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
}
+++ /dev/null
-/* src/native/vm/nativevm.c - register the native 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 <stdint.h>
-
-#include "native/vm/nativevm.h"
-
-#include "vm/class.h"
-#include "vm/initialize.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/native.h"
-
-# include "native/vm/openjdk/hpi.h"
-
-# include "vm/globals.hpp"
-# include "vm/properties.h"
-# include "vm/utf8.h"
-# include "vm/vm.hpp"
-#endif
-
-
-/* nativevm_preinit ************************************************************
-
- Pre-initialize the implementation specific native stuff.
-
-*******************************************************************************/
-
-void nativevm_preinit(void)
-{
- /* Register native methods of all classes implemented. */
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
-
- _Jv_gnu_classpath_VMStackWalker_init();
- _Jv_gnu_classpath_VMSystemProperties_init();
- _Jv_gnu_java_lang_VMCPStringBuilder_init();
- _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
- _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
- _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
- _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
- _Jv_java_lang_VMClass_init();
- _Jv_java_lang_VMClassLoader_init();
- _Jv_java_lang_VMObject_init();
- _Jv_java_lang_VMRuntime_init();
- _Jv_java_lang_VMSystem_init();
- _Jv_java_lang_VMString_init();
- _Jv_java_lang_VMThread_init();
- _Jv_java_lang_VMThrowable_init();
- _Jv_java_lang_management_VMManagementFactory_init();
- _Jv_java_lang_reflect_VMConstructor_init();
- _Jv_java_lang_reflect_VMField_init();
- _Jv_java_lang_reflect_VMMethod_init();
- _Jv_java_lang_reflect_VMProxy_init();
- _Jv_java_security_VMAccessController_init();
- _Jv_java_util_concurrent_atomic_AtomicLong_init();
- _Jv_sun_misc_Unsafe_init();
-
-#if defined(ENABLE_ANNOTATIONS)
- _Jv_sun_reflect_ConstantPool_init();
-#endif
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- const char* boot_library_path;
- int len;
- char* p;
- utf* u;
- void* handle;
-
- TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
-
- /* Load libjava.so */
-
- boot_library_path = properties_get("sun.boot.library.path");
-
- len =
- os_strlen(boot_library_path) +
- os_strlen("/libjava.so") +
- os_strlen("0");
-
- p = MNEW(char, len);
-
- os_strcpy(p, boot_library_path);
- os_strcat(p, "/libjava.so");
-
- u = utf_new_char(p);
-
- handle = native_library_open(u);
-
- if (handle == NULL)
- vm_abort("nativevm_init: failed to open libjava.so at: %s", p);
-
- MFREE(p, char, len);
-
- native_library_add(u, NULL, handle);
-
- /* Initialize the HPI. */
-
- hpi_initialize();
-
- _Jv_sun_misc_Unsafe_init();
-
-# else
-# error unknown classpath configuration
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
-
- _Jv_com_sun_cldc_io_ResourceInputStream_init();
- _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
- _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
- _Jv_com_sun_cldchi_jvm_JVM_init();
- _Jv_java_lang_Class_init();
- _Jv_java_lang_Double_init();
- _Jv_java_lang_Float_init();
- _Jv_java_lang_Math_init();
- _Jv_java_lang_Object_init();
- _Jv_java_lang_Runtime_init();
- _Jv_java_lang_String_init();
- _Jv_java_lang_System_init();
- _Jv_java_lang_Thread_init();
- _Jv_java_lang_Throwable_init();
-
-#else
-# error unknown Java configuration
-#endif
-}
-
-
-/* nativevm_init ***************************************************************
-
- Initialize the implementation specific native stuff.
-
-*******************************************************************************/
-
-void nativevm_init(void)
-{
-#if defined(ENABLE_JAVASE)
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- TRACESUBSYSTEMINITIALIZATION("nativevm_init");
-
- /* nothing to do */
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- methodinfo *m;
-
- TRACESUBSYSTEMINITIALIZATION("nativevm_init");
-
- m = class_resolveclassmethod(class_java_lang_System,
- utf_new_char("initializeSystemClass"),
- utf_void__void,
- class_java_lang_Object,
- false);
-
- if (m == NULL)
- vm_abort("nativevm_init: Error resolving java.lang.System.initializeSystemClass()");
-
- (void) vm_call_method(m, NULL);
-
-# else
-# error unknown classpath configuration
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- TRACESUBSYSTEMINITIALIZATION("nativevm_init");
-
- /* nothing to do */
-
-#else
-# error unknown Java configuration
-#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/nativevm.cpp - Register native 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 <stdint.h>
+
+#include "native/vm/nativevm.hpp"
+
+#include "vm/class.h"
+#include "vm/initialize.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/native.hpp"
+
+# include "native/vm/openjdk/hpi.hpp"
+
+# include "vm/globals.hpp"
+# include "vm/properties.hpp"
+# include "vm/utf8.h"
+# include "vm/vm.hpp"
+#endif
+
+
+/* nativevm_preinit ************************************************************
+
+ Pre-initialize the implementation specific native stuff.
+
+*******************************************************************************/
+
+void nativevm_preinit(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
+
+ /* Register native methods of all classes implemented. */
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ _Jv_gnu_classpath_VMStackWalker_init();
+ _Jv_gnu_classpath_VMSystemProperties_init();
+ _Jv_gnu_java_lang_VMCPStringBuilder_init();
+ _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
+ _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
+ _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
+ _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
+ _Jv_java_lang_VMClass_init();
+ _Jv_java_lang_VMClassLoader_init();
+ _Jv_java_lang_VMObject_init();
+ _Jv_java_lang_VMRuntime_init();
+ _Jv_java_lang_VMSystem_init();
+ _Jv_java_lang_VMString_init();
+ _Jv_java_lang_VMThread_init();
+ _Jv_java_lang_VMThrowable_init();
+ _Jv_java_lang_management_VMManagementFactory_init();
+ _Jv_java_lang_reflect_VMConstructor_init();
+ _Jv_java_lang_reflect_VMField_init();
+ _Jv_java_lang_reflect_VMMethod_init();
+ //_Jv_java_lang_reflect_VMProxy_init();
+ _Jv_java_security_VMAccessController_init();
+ _Jv_java_util_concurrent_atomic_AtomicLong_init();
+ _Jv_sun_misc_Unsafe_init();
+
+#if defined(ENABLE_ANNOTATIONS)
+ _Jv_sun_reflect_ConstantPool_init();
+#endif
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ // Load libjava.so
+ VM* vm = VM::get_current();
+ Properties& properties = vm->get_properties();
+ const char* boot_library_path = properties.get("sun.boot.library.path");
+
+ size_t len =
+ os::strlen(boot_library_path) +
+ os::strlen("/libjava.so") +
+ os::strlen("0");
+
+ char* p = MNEW(char, len);
+
+ os::strcpy(p, boot_library_path);
+ os::strcat(p, "/libjava.so");
+
+ utf* u = utf_new_char(p);
+
+ NativeLibrary nl(u);
+ void* handle = nl.open();
+
+ if (handle == NULL)
+ os::abort("nativevm_init: failed to open libjava.so at: %s", p);
+
+ MFREE(p, char, len);
+
+ NativeLibraries& nls = vm->get_nativelibraries();
+ nls.add(nl);
+
+ // Initialize the HPI.
+ HPI& hpi = vm->get_hpi();
+ hpi.initialize();
+
+ _Jv_sun_misc_Unsafe_init();
+
+# else
+# error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ _Jv_com_sun_cldc_io_ResourceInputStream_init();
+ _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
+ _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
+ _Jv_com_sun_cldchi_jvm_JVM_init();
+ _Jv_java_lang_Class_init();
+ _Jv_java_lang_Double_init();
+ _Jv_java_lang_Float_init();
+ _Jv_java_lang_Math_init();
+ _Jv_java_lang_Object_init();
+ _Jv_java_lang_Runtime_init();
+ _Jv_java_lang_String_init();
+ _Jv_java_lang_System_init();
+ _Jv_java_lang_Thread_init();
+ _Jv_java_lang_Throwable_init();
+
+#else
+# error unknown Java configuration
+#endif
+}
+
+
+/* nativevm_init ***************************************************************
+
+ Initialize the implementation specific native stuff.
+
+*******************************************************************************/
+
+void nativevm_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("nativevm_init");
+
+#if defined(ENABLE_JAVASE)
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ // Nothing to do.
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ methodinfo* m = class_resolveclassmethod(class_java_lang_System,
+ utf_new_char("initializeSystemClass"),
+ utf_void__void,
+ class_java_lang_Object,
+ false);
+
+ if (m == NULL)
+ os::abort("nativevm_init: Error resolving java.lang.System.initializeSystemClass()");
+
+ (void) vm_call_method(m, NULL);
+
+# else
+# error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ // Nothing to do.
+
+#else
+# error unknown Java configuration
+#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/nativevm.h - register the native 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 _NATIVEVM_H
-#define _NATIVEVM_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-void nativevm_preinit(void);
-void nativevm_init(void);
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-void _Jv_gnu_classpath_VMStackWalker_init();
-void _Jv_gnu_classpath_VMSystemProperties_init();
-void _Jv_gnu_java_lang_VMCPStringBuilder_init();
-void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
-void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
-void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
-void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
-void _Jv_java_lang_VMClass_init();
-void _Jv_java_lang_VMClassLoader_init();
-void _Jv_java_lang_VMObject_init();
-void _Jv_java_lang_VMRuntime_init();
-void _Jv_java_lang_VMString_init();
-void _Jv_java_lang_VMSystem_init();
-void _Jv_java_lang_VMThread_init();
-void _Jv_java_lang_VMThrowable_init();
-void _Jv_java_lang_management_VMManagementFactory_init();
-void _Jv_java_lang_reflect_VMConstructor_init();
-void _Jv_java_lang_reflect_VMField_init();
-void _Jv_java_lang_reflect_VMMethod_init();
-void _Jv_java_lang_reflect_VMProxy_init();
-void _Jv_java_security_VMAccessController_init();
-void _Jv_java_util_concurrent_atomic_AtomicLong_init();
-void _Jv_sun_misc_Unsafe_init();
-
-#if defined(ENABLE_ANNOTATIONS)
-void _Jv_sun_reflect_ConstantPool_init();
-#endif
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-void _Jv_sun_misc_Unsafe_init();
-
-# else
-# error unknown classpath configuration
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
-void _Jv_com_sun_cldc_io_ResourceInputStream_init();
-void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
-void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
-void _Jv_com_sun_cldchi_jvm_JVM_init();
-void _Jv_java_lang_Class_init();
-void _Jv_java_lang_Double_init();
-void _Jv_java_lang_Float_init();
-void _Jv_java_lang_Math_init();
-void _Jv_java_lang_Object_init();
-void _Jv_java_lang_Runtime_init();
-void _Jv_java_lang_String_init();
-void _Jv_java_lang_System_init();
-void _Jv_java_lang_Thread_init();
-void _Jv_java_lang_Throwable_init();
-
-#else
-# 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
- * 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/nativevm.hpp - Register native 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.
+
+*/
+
+
+#ifndef _NATIVEVM_HPP
+#define _NATIVEVM_HPP
+
+#include "config.h"
+
+/* function prototypes ********************************************************/
+
+void nativevm_preinit(void);
+void nativevm_init(void);
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+void _Jv_gnu_classpath_VMStackWalker_init();
+void _Jv_gnu_classpath_VMSystemProperties_init();
+void _Jv_gnu_java_lang_VMCPStringBuilder_init();
+void _Jv_gnu_java_lang_management_VMClassLoadingMXBeanImpl_init();
+void _Jv_gnu_java_lang_management_VMMemoryMXBeanImpl_init();
+void _Jv_gnu_java_lang_management_VMRuntimeMXBeanImpl_init();
+void _Jv_gnu_java_lang_management_VMThreadMXBeanImpl_init();
+void _Jv_java_lang_VMClass_init();
+void _Jv_java_lang_VMClassLoader_init();
+void _Jv_java_lang_VMObject_init();
+void _Jv_java_lang_VMRuntime_init();
+void _Jv_java_lang_VMString_init();
+void _Jv_java_lang_VMSystem_init();
+void _Jv_java_lang_VMThread_init();
+void _Jv_java_lang_VMThrowable_init();
+void _Jv_java_lang_management_VMManagementFactory_init();
+void _Jv_java_lang_reflect_VMConstructor_init();
+void _Jv_java_lang_reflect_VMField_init();
+void _Jv_java_lang_reflect_VMMethod_init();
+void _Jv_java_lang_reflect_VMProxy_init();
+void _Jv_java_security_VMAccessController_init();
+void _Jv_java_util_concurrent_atomic_AtomicLong_init();
+void _Jv_sun_misc_Unsafe_init();
+
+#if defined(ENABLE_ANNOTATIONS)
+void _Jv_sun_reflect_ConstantPool_init();
+#endif
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+void _Jv_sun_misc_Unsafe_init();
+
+# else
+# error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+void _Jv_com_sun_cldc_io_ResourceInputStream_init();
+void _Jv_com_sun_cldc_io_j2me_socket_Protocol_init();
+void _Jv_com_sun_cldchi_io_ConsoleOutputStream_init();
+void _Jv_com_sun_cldchi_jvm_JVM_init();
+void _Jv_java_lang_Class_init();
+void _Jv_java_lang_Double_init();
+void _Jv_java_lang_Float_init();
+void _Jv_java_lang_Math_init();
+void _Jv_java_lang_Object_init();
+void _Jv_java_lang_Runtime_init();
+void _Jv_java_lang_String_init();
+void _Jv_java_lang_System_init();
+void _Jv_java_lang_Thread_init();
+void _Jv_java_lang_Throwable_init();
+
+#else
+# error unknown Java configuration
+#endif
+
+#endif // _NATIVEVM_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:
+ */
libnativevmcore.la
libnativevmcore_la_SOURCES = \
- hpi.c \
- hpi.h \
- jvm.cpp
+ hpi.cpp \
+ hpi.hpp \
+ jvm.cpp \
+ management.cpp \
+ management.hpp
## Local variables:
+++ /dev/null
-/* src/native/vm/openjdk/hpi.c - HotSpot HPI interface 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"
-
-/* We include hpi_md.h before hpi.h as the latter includes the
- former. */
-
-#include INCLUDE_HPI_MD_H
-#include INCLUDE_HPI_H
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/vm/openjdk/hpi.h"
-
-#include "vm/options.h"
-#include "vm/os.hpp"
-#include "vm/properties.h"
-#include "vm/utf8.h"
-#include "vm/vm.hpp"
-
-
-/* VM callback functions ******************************************************/
-
-static vm_calls_t callbacks = {
- /* TODO What should we use here? */
-/* jio_fprintf, */
-/* unimplemented_panic, */
-/* unimplemented_monitorRegister, */
- NULL,
- NULL,
- NULL,
-
- NULL, /* unused */
- NULL, /* unused */
- NULL /* unused */
-};
-
-
-/* HPI interfaces *************************************************************/
-
-GetInterfaceFunc hpi_get_interface = NULL;
-HPI_FileInterface *hpi_file = NULL;
-HPI_SocketInterface *hpi_socket = NULL;
-HPI_LibraryInterface *hpi_library = NULL;
-HPI_SystemInterface *hpi_system = NULL;
-
-
-/* hpi_initialize **************************************************************
-
- Initialize the Host Porting Interface (HPI).
-
-*******************************************************************************/
-
-void hpi_initialize(void)
-{
- const char* boot_library_path;
- int len;
- char* p;
- utf* u;
- void* handle;
- void* dll_initialize;
- int result;
-
- jint (JNICALL * DLL_Initialize)(GetInterfaceFunc *, void *);
-
- TRACESUBSYSTEMINITIALIZATION("hpi_init");
-
- /* Load libhpi.so */
-
- boot_library_path = properties_get("sun.boot.library.path");
-
- len =
- os_strlen(boot_library_path) +
- os_strlen("/native_threads/libhpi.so") +
- os_strlen("0");
-
- p = MNEW(char, len);
-
- os_strcpy(p, boot_library_path);
- os_strcat(p, "/native_threads/libhpi.so");
-
- u = utf_new_char(p);
-
- if (opt_TraceHPI)
- log_println("hpi_init: Loading HPI %s ", p);
-
- MFREE(p, char, len);
-
- handle = native_library_open(u);
-
- if (handle == NULL)
- if (opt_TraceHPI)
- vm_abort("hpi_init: HPI open failed");
-
- /* Resolve the DLL_Initialize function from the library. */
-
- 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", os_dlerror());
-
- if (DLL_Initialize == NULL ||
- (*DLL_Initialize)(&hpi_get_interface, &callbacks) < 0) {
-
- if (opt_TraceHPI)
- vm_abort("hpi_init: HPI DLL_Initialize failed");
- }
-
- native_library_add(u, NULL, handle);
-
- if (opt_TraceHPI)
- log_println("hpi_init: HPI loaded successfully");
-
- /* Resolve the interfaces. */
- /* NOTE: The intptr_t-case is only to prevent the a compiler
- warning with -O2: warning: dereferencing type-punned pointer
- will break strict-aliasing rules */
-
- result = (*hpi_get_interface)((void **) (intptr_t) &hpi_file, "File", 1);
-
- if (result != 0)
- vm_abort("hpi_init: Can't find HPI_FileInterface");
-
- result = (*hpi_get_interface)((void **) (intptr_t) &hpi_library, "Library", 1);
-
- if (result != 0)
- vm_abort("hpi_init: Can't find HPI_LibraryInterface");
-
- result = (*hpi_get_interface)((void **) (intptr_t) &hpi_system, "System", 1);
-
- if (result != 0)
- vm_abort("hpi_init: Can't find HPI_SystemInterface");
-}
-
-
-/* hpi_initialize_socket_library ***********************************************
-
- Initialize the library Host Porting Interface (HPI).
-
-*******************************************************************************/
-
-int hpi_initialize_socket_library(void)
-{
- int result;
-
- /* Resolve the socket library interface. */
-
- result = (*hpi_get_interface)((void **) (intptr_t) &hpi_socket, "Socket", 1);
-
- if (result != 0) {
- if (opt_TraceHPI)
- log_println("hpi_initialize_socket_library: Can't find HPI_SocketInterface");
-
- 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/vm/openjdk/hpi.cpp - HotSpot HPI interface 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 this one early.
+#include "native/vm/openjdk/hpi.hpp"
+
+#include "mm/memory.h"
+
+#include "native/native.hpp"
+
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/properties.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/* VM callback functions ******************************************************/
+
+static vm_calls_t callbacks = {
+ /* TODO What should we use here? */
+/* jio_fprintf, */
+/* unimplemented_panic, */
+/* unimplemented_monitorRegister, */
+ NULL,
+ NULL,
+ NULL,
+
+ NULL, /* unused */
+ NULL, /* unused */
+ NULL /* unused */
+};
+
+
+/**
+ * Initialize the Host Porting Interface (HPI).
+ */
+HPI::HPI()
+{
+}
+
+void HPI::initialize() // REMOVEME
+{
+ TRACESUBSYSTEMINITIALIZATION("hpi_init");
+
+ // Load libhpi.so
+ VM* vm = VM::get_current();
+ Properties& properties = vm->get_properties();
+ const char* boot_library_path = properties.get("sun.boot.library.path");
+
+ size_t len =
+ os::strlen(boot_library_path) +
+ os::strlen("/native_threads/libhpi.so") +
+ os::strlen("0");
+
+ char* p = MNEW(char, len);
+
+ os::strcpy(p, boot_library_path);
+ os::strcat(p, "/native_threads/libhpi.so");
+
+ utf* u = utf_new_char(p);
+
+ if (opt_TraceHPI)
+ log_println("HPI::initialize: Loading HPI %s ", p);
+
+ MFREE(p, char, len);
+
+ NativeLibrary nl(u);
+ void* handle = nl.open();
+
+ if (handle == NULL)
+ if (opt_TraceHPI)
+ os::abort("HPI::initialize: HPI open failed");
+
+ // Resolve the DLL_Initialize function from the library.
+ void* dll_initialize = os::dlsym(handle, "DLL_Initialize");
+
+ jint (JNICALL *DLL_Initialize)(GetInterfaceFunc*, void*);
+ DLL_Initialize = (jint (JNICALL *)(GetInterfaceFunc*, void*)) (uintptr_t) dll_initialize;
+
+ if (opt_TraceHPI && DLL_Initialize == NULL)
+ log_println("hpi_init: HPI dlsym of DLL_Initialize failed: %s", os::dlerror());
+
+ if (DLL_Initialize == NULL || (*DLL_Initialize)(&_get_interface, &callbacks) < 0) {
+ if (opt_TraceHPI)
+ vm_abort("hpi_init: HPI DLL_Initialize failed");
+ }
+
+ NativeLibraries& nls = vm->get_nativelibraries();
+ nls.add(nl);
+
+ if (opt_TraceHPI)
+ log_println("HPI::initialize: HPI loaded successfully");
+
+ // Resolve the interfaces.
+ /* NOTE: The intptr_t-case is only to prevent the a compiler
+ warning with -O2: warning: dereferencing type-punned pointer
+ will break strict-aliasing rules */
+
+ int result;
+
+ result = (*_get_interface)((void**) (uintptr_t) &_file, "File", 1);
+
+ if (result != 0)
+ os::abort("hpi_init: Can't find HPI_FileInterface");
+
+ result = (*_get_interface)((void**) (uintptr_t) &_library, "Library", 1);
+
+ if (result != 0)
+ os::abort("hpi_init: Can't find HPI_LibraryInterface");
+
+ result = (*_get_interface)((void**) (uintptr_t) &_system, "System", 1);
+
+ if (result != 0)
+ os::abort("hpi_init: Can't find HPI_SystemInterface");
+}
+
+
+/**
+ * Initialize the Host Porting Interface (HPI) socket library.
+ */
+int HPI::initialize_socket_library()
+{
+ // Resolve the socket library interface.
+ int result = (*_get_interface)((void**) (uintptr_t) &_socket, "Socket", 1);
+
+ if (result != 0) {
+ if (opt_TraceHPI)
+ log_println("HPI::initialize_socket_library: Can't find HPI_SocketInterface");
+
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+
+// Legacy C interface.
+extern "C" {
+ void HPI_initialize() { VM::get_current()->get_hpi().initialize(); }
+}
+
+
+/*
+ * These 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/openjdk/hpi.h - HotSpot HPI interface 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 _HPI_H
-#define _HPI_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-
-/* HPI headers *****************************************************************
-
- We include hpi_md.h before hpi.h as the latter includes the former.
-
- These includes define:
-
- #define _JAVASOFT_HPI_MD_H_
- #define _JAVASOFT_HPI_H_
-
-*******************************************************************************/
-
-#include INCLUDE_HPI_MD_H
-#include INCLUDE_HPI_H
-
-
-/* HPI interfaces *************************************************************/
-
-extern HPI_FileInterface *hpi_file;
-extern HPI_SocketInterface *hpi_socket;
-extern HPI_LibraryInterface *hpi_library;
-extern HPI_SystemInterface *hpi_system;
-
-
-/* functions ******************************************************************/
-
-void hpi_initialize(void);
-int hpi_initialize_socket_library(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _HPI_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/openjdk/hpi.hpp - HotSpot HPI interface 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 _HPI_HPP
+#define _HPI_HPP
+
+#include "config.h"
+
+/* HPI headers *****************************************************************
+
+ We include hpi_md.h before hpi.h as the latter includes the former.
+
+ These includes define:
+
+ #define _JAVASOFT_HPI_MD_H_
+ #define _JAVASOFT_HPI_H_
+
+*******************************************************************************/
+
+// Include our JNI header before the HPI headers, because the HPI
+// headers include jni.h and we want to override the typedefs in
+// jni.h.
+#include "native/jni.hpp"
+
+#include INCLUDE_HPI_MD_H
+#include INCLUDE_HPI_H
+
+
+#ifdef __cplusplus
+
+/**
+ * Host Porting Interface (HPI).
+ */
+class HPI {
+private:
+ GetInterfaceFunc _get_interface;
+ HPI_FileInterface* _file;
+ HPI_SocketInterface* _socket;
+ HPI_LibraryInterface* _library;
+ HPI_SystemInterface* _system;
+
+public:
+ HPI();
+
+ inline HPI_FileInterface& get_file () const { return *_file; }
+ inline HPI_SocketInterface& get_socket () const { return *_socket; }
+ inline HPI_LibraryInterface& get_library() const { return *_library; }
+ inline HPI_SystemInterface& get_system () const { return *_system; }
+
+ void initialize(); // REMOVEME
+ int initialize_socket_library();
+};
+
+#else
+
+void HPI_initialize();
+
+#endif
+
+#endif // _HPI_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 <sys/stat.h>
#include <sys/types.h>
-#include "vm/types.h"
+// Include our JNI header before the JVM headers, because the JVM
+// headers include jni.h and we want to override the typedefs in
+// jni.h.
+#include "native/jni.hpp"
+
+// We include jvm_md.h before jvm.h as the latter includes the former.
+#include INCLUDE_JVM_MD_H
+#include INCLUDE_JVM_H
#include "mm/memory.h"
-#include "native/jni.h"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#include "native/vm/reflection.hpp"
-#include "native/vm/openjdk/hpi.h"
+#include "native/vm/openjdk/hpi.hpp"
+#include "native/vm/openjdk/management.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "toolbox/list.h"
+#include "toolbox/list.hpp"
-#include "vm/array.h"
+#include "vm/array.hpp"
#if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
+#include "vm/assertion.hpp"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/os.hpp"
#include "vm/package.hpp"
#include "vm/primitive.hpp"
-#include "vm/properties.h"
+#include "vm/properties.hpp"
#include "vm/resolve.h"
#include "vm/signallocal.h"
#include "vm/string.hpp"
#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" {
-D option, as requested. */
jio_snprintf(buf, sizeof(buf), PRINTF_FORMAT_INT64_T, opt_MaxDirectMemorySize);
- properties_add("sun.nio.MaxDirectMemorySize", buf);
-
- /* Add all properties. */
+ VM::get_current()->get_properties().put("sun.nio.MaxDirectMemorySize", buf);
- properties_system_add_all(h);
+ // Fill the java.util.Properties object.
+ VM::get_current()->get_properties().fill(h);
return properties;
}
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);
+ // FIXME linenumbertable->find could change the methodinfo
+ // pointer when hitting an inlined method.
+ linenumber = code->linenumbertable->find(&m, ste->pc);
linenumber = (linenumber == 0) ? -1 : linenumber;
}
{
TRACEJVMCALLS(("JVM_IHashCode(env=%p, jobject=%p)", env, handle));
- return (jint) ((ptrint) handle);
+ java_lang_Object o(handle);
+
+ return o.get_hashcode();
}
/* JVM_GetLastErrorString */
-jint JVM_GetLastErrorString(char *buf, int len)
+jint JVM_GetLastErrorString(char* buf, int len)
{
TRACEJVMCALLS(("JVM_GetLastErrorString(buf=%p, len=%d", buf, len));
- return hpi_system->GetLastErrorString(buf, len);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.get_system().GetLastErrorString(buf, len);
}
/* JVM_NativePath */
-char *JVM_NativePath(char *path)
+char *JVM_NativePath(char* path)
{
TRACEJVMCALLS(("JVM_NativePath(path=%s)", path));
- return hpi_file->NativePath(path);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.get_file().NativePath(path);
}
jboolean JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls)
{
#if defined(ENABLE_ASSERTION)
- assertion_name_t *item;
classinfo *c;
jboolean status;
utf *name;
}
if (list_assertion_names != NULL) {
- item = (assertion_name_t *)list_first(list_assertion_names);
- while (item != NULL) {
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin();
+ it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
+
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);
}
}
java_booleanarray_t *classEnabled;
java_booleanarray_t *packageEnabled;
#if defined(ENABLE_ASSERTION)
- assertion_name_t *item;
java_handle_t *js;
s4 i, j;
#endif
i = 0;
j = 0;
- item = (assertion_name_t *)list_first(list_assertion_names);
- while (item != NULL) {
+ for (List<assertion_name_t*>::iterator it = list_assertion_names->begin(); it != list_assertion_names->end(); it++) {
+ assertion_name_t* item = *it;
+
js = javastring_new_from_ascii(item->name);
if (js == NULL) {
return NULL;
packageEnabled->data[j] = (jboolean) item->enabled;
j += 1;
}
-
- item = (assertion_name_t *)list_next(list_assertion_names, item);
}
}
#endif
*/
#define JVM_EEXIST -100
-jint JVM_Open(const char *fname, jint flags, jint mode)
+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);
+ HPI& hpi = VM::get_current()->get_hpi();
+ result = hpi.get_file().Open(fname, flags, mode);
if (result >= 0) {
return result;
{
TRACEJVMCALLS(("JVM_Close(fd=%d)", fd));
- return hpi_file->Close(fd);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.get_file().Close(fd);
}
/* JVM_Read */
-jint JVM_Read(jint fd, char *buf, jint nbytes)
+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);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return (jint) hpi.get_file().Read(fd, buf, nbytes);
}
/* JVM_Write */
-jint JVM_Write(jint fd, char *buf, jint nbytes)
+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);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return (jint) hpi.get_file().Write(fd, buf, nbytes);
}
/* JVM_Available */
-jint JVM_Available(jint fd, jlong *pbytes)
+jint JVM_Available(jint fd, jlong* pbytes)
{
TRACEJVMCALLS(("JVM_Available(fd=%d, pbytes=%p)", fd, pbytes));
- return hpi_file->Available(fd, pbytes);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.get_file().Available(fd, pbytes);
}
{
TRACEJVMCALLS(("JVM_Lseek(fd=%d, offset=%ld, whence=%d)", fd, offset, whence));
- return hpi_file->Seek(fd, (off_t) offset, whence);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.get_file().Seek(fd, (off_t) offset, whence);
}
{
TRACEJVMCALLS(("JVM_SetLength(fd=%d, length=%ld)", length));
- return hpi_file->SetLength(fd, length);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.get_file().SetLength(fd, length);
}
{
TRACEJVMCALLS(("JVM_Sync(fd=%d)", fd));
- return hpi_file->Sync(fd);
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.get_file().Sync(fd);
}
{
TRACEJVMCALLS(("JVM_InitializeSocketLibrary()"));
- return hpi_initialize_socket_library();
+ HPI& hpi = VM::get_current()->get_hpi();
+ return hpi.initialize_socket_library();
}
/* JVM_LoadLibrary */
-void *JVM_LoadLibrary(const char *name)
+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);
+ utf* u = utf_new_char(name);
+ NativeLibrary nl(u);
+ void* handle = nl.open();
+
TRACEJVMCALLSEXIT(("->%p", handle));
return handle;
{
TRACEJVMCALLS(("JVM_UnloadLibrary(handle=%p)", handle));
- native_library_close(handle);
+ NativeLibrary nl(handle);
+ nl.close();
}
/* JVM_FindLibraryEntry */
-void *JVM_FindLibraryEntry(void *handle, const char *name)
+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);
+ HPI& hpi = VM::get_current()->get_hpi();
+ symbol = hpi.get_library().FindLibraryEntry(handle, name);
TRACEJVMCALLSEXIT(("->%p", symbol));
JNIEXPORT void* JNICALL JVM_RawMonitorCreate(void)
{
- java_object_t *o;
-
TRACEJVMCALLS(("JVM_RawMonitorCreate()"));
- o = NEW(java_object_t);
-
- lock_init_object_lock(o);
+ Mutex* m = new Mutex();
- return o;
+ return m;
}
/* JVM_RawMonitorDestroy */
-JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon)
+JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void* mon)
{
TRACEJVMCALLS(("JVM_RawMonitorDestroy(mon=%p)", mon));
- FREE(mon, java_object_t);
+ delete ((Mutex*) mon);
}
/* JVM_RawMonitorEnter */
-JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon)
+JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void* mon)
{
TRACEJVMCALLS(("JVM_RawMonitorEnter(mon=%p)", mon));
- (void) lock_monitor_enter((java_object_t *) mon);
+ ((Mutex*) mon)->lock();
return 0;
}
/* JVM_RawMonitorExit */
-JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon)
+JNIEXPORT void JNICALL JVM_RawMonitorExit(void* mon)
{
TRACEJVMCALLS(("JVM_RawMonitorExit(mon=%p)", mon));
- (void) lock_monitor_exit((java_object_t *) mon);
+ ((Mutex*) mon)->unlock();
}
{
TRACEJVMCALLS(("JVM_GetManagement(version=%d)", version));
- /* TODO We current don't support the management interface. */
-
- return NULL;
+ return Management::get_jmm_interface(version);
}
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/
--- /dev/null
+ /* src/native/vm/openjdk/management.cpp - HotSpot management interface functions
+
+ 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 our JNI header before the JMM header, because the JMM
+// header include jni.h and we want to override the typedefs in jni.h.
+#include "native/jni.hpp"
+
+#include INCLUDE_JMM_H
+
+#include "native/vm/openjdk/management.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/os.hpp"
+#include "vm/vm.hpp"
+
+
+/**
+ * Initialize the Management subsystem.
+ */
+Management::Management()
+{
+ // Initialize optional support
+ _optional_support.isLowMemoryDetectionSupported = 1;
+ _optional_support.isCompilationTimeMonitoringSupported = 1;
+ _optional_support.isThreadContentionMonitoringSupported = 1;
+
+// if (os::is_thread_cpu_time_supported()) {
+ if (false) {
+ _optional_support.isCurrentThreadCpuTimeSupported = 1;
+ _optional_support.isOtherThreadCpuTimeSupported = 1;
+ }
+ else {
+ _optional_support.isCurrentThreadCpuTimeSupported = 0;
+ _optional_support.isOtherThreadCpuTimeSupported = 0;
+ }
+
+ _optional_support.isBootClassPathSupported = 1;
+ _optional_support.isObjectMonitorUsageSupported = 1;
+ _optional_support.isSynchronizerUsageSupported = 1;
+}
+
+
+/**
+ * Return a pointer to the optional support structure.
+ *
+ * @param Pointer to optional support structure.
+ */
+const jmmOptionalSupport& Management::get_optional_support() const
+{
+ return _optional_support;
+}
+
+
+// Interface functions are exported as C functions.
+extern "C" {
+
+// Returns a version string and sets major and minor version if the
+// input parameters are non-null.
+jint jmm_GetVersion(JNIEnv* env)
+{
+ return JMM_VERSION;
+}
+
+
+// Gets the list of VM monitoring and management optional supports
+// Returns 0 if succeeded; otherwise returns non-zero.
+jint jmm_GetOptionalSupport(JNIEnv* env, jmmOptionalSupport* support)
+{
+ if (support == NULL) {
+ return -1;
+ }
+
+ Management& mm = VM::get_current()->get_management();
+
+ // memcpy the structure.
+ os::memcpy(support, &mm.get_optional_support(), sizeof(jmmOptionalSupport));
+
+ return 0;
+}
+
+
+jobject jmm_GetInputArguments(JNIEnv* env)
+{
+ log_println("jmm_GetInputArguments: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobjectArray jmm_GetInputArgumentArray(JNIEnv* env)
+{
+ log_println("jmm_GetInputArgumentArray: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobjectArray jmm_GetMemoryPools(JNIEnv* env, jobject obj)
+{
+ log_println("jmm_GetMemoryPools: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobjectArray jmm_GetMemoryManagers(JNIEnv* env, jobject obj)
+{
+ log_println("jmm_GetMemoryManagers: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobject jmm_GetMemoryPoolUsage(JNIEnv* env, jobject obj)
+{
+ log_println("jmm_GetMemoryPoolUsage: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobject jmm_GetPeakMemoryPoolUsage(JNIEnv* env, jobject obj)
+{
+ log_println("jmm_GetPeakMemoryPoolUsage: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobject jmm_GetPoolCollectionUsage(JNIEnv* env, jobject obj)
+{
+ log_println("jmm_GetPoolCollectionUsage: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+void jmm_SetPoolSensor(JNIEnv* env, jobject obj, jmmThresholdType type, jobject sensorObj)
+{
+ log_println("jmm_SetPoolSensor: IMPLEMENT ME!");
+}
+
+
+jlong jmm_SetPoolThreshold(JNIEnv* env, jobject obj, jmmThresholdType type, jlong threshold)
+{
+ log_println("jmm_SetPoolThreshold: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jobject jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)
+{
+ log_println("jmm_GetMemoryUsage: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jboolean jmm_GetBoolAttribute(JNIEnv* env, jmmBoolAttribute att)
+{
+ log_println("jmm_GetBoolAttribute: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jboolean jmm_SetBoolAttribute(JNIEnv* env, jmmBoolAttribute att, jboolean flag)
+{
+ log_println("jmm_SetBoolAttribute: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jlong jmm_GetLongAttribute(JNIEnv* env, jobject obj, jmmLongAttribute att)
+{
+ log_println("jmm_GetLongAttribute: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jint jmm_GetLongAttributes(JNIEnv* env, jobject obj, jmmLongAttribute* atts, jint count, jlong* result)
+{
+ log_println("jmm_GetLongAttributes: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jint jmm_GetThreadInfo(JNIEnv* env, jlongArray ids, jint maxDepth, jobjectArray infoArray)
+{
+ log_println("jmm_GetThreadInfo: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jobjectArray jmm_DumpThreads(JNIEnv* env, jlongArray thread_ids, jboolean locked_monitors, jboolean locked_synchronizers)
+{
+ log_println("jmm_DumpThreads: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobjectArray jmm_GetLoadedClasses(JNIEnv* env)
+{
+ log_println("jmm_GetLoadedClasses: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jboolean jmm_ResetStatistic(JNIEnv* env, jvalue obj, jmmStatisticType type)
+{
+ log_println("jmm_ResetStatistic: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jlong jmm_GetThreadCpuTime(JNIEnv* env, jlong thread_id)
+{
+ log_println("jmm_GetThreadCpuTime: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jlong jmm_GetThreadCpuTimeWithKind(JNIEnv* env, jlong thread_id, jboolean user_sys_cpu_time)
+{
+ log_println("jmm_GetThreadCpuTimeWithKind: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jobjectArray jmm_GetVMGlobalNames(JNIEnv* env)
+{
+ log_println("jmm_GetVMGlobalNames: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jint jmm_GetVMGlobals(JNIEnv* env, jobjectArray names, jmmVMGlobal* globals, jint count)
+{
+ log_println("jmm_GetVMGlobals: IMPLEMENT ME!");
+ return 0;
+}
+
+
+void jmm_SetVMGlobal(JNIEnv* env, jstring flag_name, jvalue new_value)
+{
+ log_println("jmm_SetVMGlobal: IMPLEMENT ME!");
+}
+
+
+jint jmm_GetInternalThreadTimes(JNIEnv* env, jobjectArray names, jlongArray times)
+{
+ log_println("jmm_GetInternalThreadTimes: IMPLEMENT ME!");
+ return 0;
+}
+
+
+jobjectArray jmm_FindDeadlockedThreads(JNIEnv* env, jboolean object_monitors_only)
+{
+ log_println("jmm_FindDeadlockedThreads: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jobjectArray jmm_FindMonitorDeadlockedThreads(JNIEnv* env)
+{
+ log_println("jmm_FindMonitorDeadlockedThreads: IMPLEMENT ME!");
+ return NULL;
+}
+
+
+jint jmm_GetGCExtAttributeInfo(JNIEnv* env, jobject mgr, jmmExtAttributeInfo* info, jint count)
+{
+ log_println("jmm_GetGCExtAttributeInfo: IMPLEMENT ME!");
+ return 0;
+}
+
+
+void jmm_GetLastGCStat(JNIEnv* env, jobject obj, jmmGCStat* gc_stat)
+{
+ log_println("jmm_GetLastGCStat: IMPLEMENT ME!");
+}
+
+
+jint jmm_DumpHeap0(JNIEnv* env, jstring outputfile, jboolean live)
+{
+ log_println("jmm_DumpHeap0: IMPLEMENT ME!");
+ return 0;
+}
+
+} // extern "C"
+
+
+const struct jmmInterface_1_ jmm_interface = {
+ NULL,
+ NULL,
+ jmm_GetVersion,
+ jmm_GetOptionalSupport,
+ jmm_GetInputArguments,
+ jmm_GetThreadInfo,
+ jmm_GetInputArgumentArray,
+ jmm_GetMemoryPools,
+ jmm_GetMemoryManagers,
+ jmm_GetMemoryPoolUsage,
+ jmm_GetPeakMemoryPoolUsage,
+ NULL,
+ jmm_GetMemoryUsage,
+ jmm_GetLongAttribute,
+ jmm_GetBoolAttribute,
+ jmm_SetBoolAttribute,
+ jmm_GetLongAttributes,
+ jmm_FindMonitorDeadlockedThreads,
+ jmm_GetThreadCpuTime,
+ jmm_GetVMGlobalNames,
+ jmm_GetVMGlobals,
+ jmm_GetInternalThreadTimes,
+ jmm_ResetStatistic,
+ jmm_SetPoolSensor,
+ jmm_SetPoolThreshold,
+ jmm_GetPoolCollectionUsage,
+ jmm_GetGCExtAttributeInfo,
+ jmm_GetLastGCStat,
+ jmm_GetThreadCpuTimeWithKind,
+ NULL,
+ jmm_DumpHeap0,
+ jmm_FindDeadlockedThreads,
+ jmm_SetVMGlobal,
+ NULL,
+ jmm_DumpThreads
+};
+
+
+/**
+ * Return the requested management interface.
+ *
+ * @param version Requested management interface version.
+ *
+ * @return Pointer to management interface structure.
+ */
+void* Management::get_jmm_interface(int version)
+{
+ if (version == JMM_VERSION_1_0) {
+ return (void*) &jmm_interface;
+ }
+
+ 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/native/vm/openjdk/management.hpp - HotSpot management interface functions
+
+ 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 _MANAGEMENT_HPP
+#define _MANAGEMENT_HPP
+
+#include <stdint.h>
+
+// Include our JNI header before the JMM header, because the JMM
+// header include jni.h and we want to override the typedefs in jni.h.
+#include "native/jni.hpp"
+
+#include INCLUDE_JMM_H
+
+
+#ifdef __cplusplus
+
+/**
+ * Management support.
+ */
+class Management {
+private:
+ jmmOptionalSupport _optional_support;
+
+public:
+ Management();
+
+ static void* get_jmm_interface(int version);
+
+ const jmmOptionalSupport& get_optional_support() const;
+};
+
+#else
+
+typedef struct Management Management;
+
+#endif
+
+#endif // _MANAGEMENT_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 "native/jni.h"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_ANNOTATIONS) && defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
# include "vm/vm.hpp"
#include "native/vm/reflection.hpp"
#include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include <stdint.h>
-#include "native/jni.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/method.h"
#include "mm/memory.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#if defined(ENABLE_JNI_HEADERS)
# include "native/include/sun_misc_Unsafe.h"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/initialize.h"
#include "vm/javaobjects.hpp"
*/
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;
+ return FieldAccess::get<int32_t>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, x);
}
*/
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;
+ return FieldAccess::get<jobject>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, x);
}
*/
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;
+ return FieldAccess::get<int32_t>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, (int32_t) x);
}
*/
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;
+ return FieldAccess::get<int32_t>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, (int32_t) x);
}
*/
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;
+ return FieldAccess::get<int32_t>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, (int32_t) x);
}
*/
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;
+ return FieldAccess::get<int32_t>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, (int32_t) x);
}
*/
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;
+ return FieldAccess::get<int64_t>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, x);
}
*/
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;
+ return FieldAccess::get<float>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, x);
}
*/
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;
+ return FieldAccess::get<double>(o, offset);
}
*/
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;
+ FieldAccess::set(o, offset, x);
}
*/
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;
+ return FieldAccess::get_volatile<jobject>(o, offset);
}
*/
JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject x)
{
- volatile void **p;
+ FieldAccess::set_volatile(o, offset, x);
+}
- 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: getByteVolatile
+ * Signature: (Ljava/lang/Object;J)B
+ */
+JNIEXPORT jbyte JNICALL Java_sun_misc_Unsafe_getByteVolatile(JNIEnv* env, jobject _this, jobject o, jlong offset)
+{
+ return FieldAccess::get_volatile<int32_t>(o, offset);
+}
/*
*/
JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
{
- UNSAFE_GET_VOLATILE(int32_t);
+ return FieldAccess::get_volatile<int32_t>(o, offset);
}
*/
JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putIntVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
{
- UNSAFE_PUT_VOLATILE(int32_t);
+ FieldAccess::set_volatile(o, offset, x);
}
*/
JNIEXPORT jlong JNICALL Java_sun_misc_Unsafe_getLongVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
{
- UNSAFE_GET_VOLATILE(int64_t);
+ return FieldAccess::get_volatile<int64_t>(o, offset);
}
*/
JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLongVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
{
- UNSAFE_PUT_VOLATILE(int64_t);
+ FieldAccess::set_volatile(o, offset, x);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getFloatVolatile
+ * Signature: (Ljava/lang/Object;J)F
+ */
+JNIEXPORT jfloat JNICALL Java_sun_misc_Unsafe_getFloatVolatile(JNIEnv* env, jobject _this, jobject o, jlong offset)
+{
+ return FieldAccess::get_volatile<float>(o, offset);
}
* Method: getDoubleVolatile
* Signature: (Ljava/lang/Object;J)D
*/
-JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDoubleVolatile(JNIEnv *env, jobject __this, jobject o, jlong offset)
+JNIEXPORT jdouble JNICALL Java_sun_misc_Unsafe_getDoubleVolatile(JNIEnv *env, jobject _this, jobject o, jlong offset)
{
- UNSAFE_GET_VOLATILE(double);
+ return FieldAccess::get_volatile<double>(o, offset);
}
*/
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;
+ FieldAccess::set_volatile(o, offset, x);
}
*/
JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedInt(JNIEnv *env, jobject _this, jobject o, jlong offset, jint x)
{
- UNSAFE_PUT_VOLATILE(int32_t);
+ FieldAccess::set_volatile(o, offset, x);
}
*/
JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedLong(JNIEnv *env, jobject _this, jobject o, jlong offset, jlong x)
{
- UNSAFE_PUT_VOLATILE(int64_t);
+ FieldAccess::set_volatile(o, offset, x);
}
{ (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*) "getByteVolatile", (char*) "(Ljava/lang/Object;J)B", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getByteVolatile },
{ (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*) "getFloatVolatile", (char*) "(Ljava/lang/Object;J)F", (void*) (uintptr_t) &Java_sun_misc_Unsafe_getFloatVolatile },
{ (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 },
*******************************************************************************/
-// FIXME
-extern "C" {
void _Jv_sun_misc_Unsafe_init(void)
{
- utf *u;
+ utf* u = utf_new_char("sun/misc/Unsafe");
- u = utf_new_char("sun/misc/Unsafe");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ nm.register_methods(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
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/
atomic.cpp \
atomic.hpp \
condition.hpp \
- lock-common.h \
+ lock.cpp \
+ lock.hpp \
+ lockword.cpp \
+ lockword.hpp \
removeme.cpp \
mutex.hpp \
- threadlist.c \
- threadlist.h \
+ threadlist.cpp \
+ threadlist.hpp \
thread.cpp \
thread.hpp
else
+++ /dev/null
-/* src/threads/lock-common.h - common stuff of lock implementation
-
- 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 _LOCK_COMMON_H
-#define _LOCK_COMMON_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/posix/lock.h"
-#else
-# include "threads/none/lock.h"
-#endif
-
-
-/* only define the following stuff with thread enabled ************************/
-
-#if defined(ENABLE_THREADS)
-
-/* functions ******************************************************************/
-
-void lock_init(void);
-
-void lock_init_object_lock(java_object_t *);
-
-ptrint lock_pre_compute_thinlock(s4 index);
-
-bool lock_monitor_enter(java_handle_t *);
-bool lock_monitor_exit(java_handle_t *);
-
-#define LOCK_monitor_enter (functionptr) lock_monitor_enter
-#define LOCK_monitor_exit (functionptr) lock_monitor_exit
-
-bool lock_is_held_by_current_thread(java_handle_t *o);
-
-void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos);
-void lock_notify_object(java_handle_t *o);
-void lock_notify_all_object(java_handle_t *o);
-
-#endif /* ENABLE_THREADS */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LOCK_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:
- * vim:noexpandtab:sw=4:ts=4:
- */
--- /dev/null
+/* src/threads/lock.cpp - lock implementation
+
+ 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 <stdlib.h>
+#include <sys/time.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/atomic.hpp"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
+#include "threads/threadlist.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+#include "vm/exceptions.hpp"
+#include "vm/finalizer.h"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
+#if defined(ENABLE_GC_BOEHM)
+# include "mm/boehm-gc/include/gc.h"
+#endif
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define DEBUGLOCKS(format) \
+ do { \
+ if (opt_DebugLocks) { \
+ log_println format; \
+ } \
+ } while (0)
+#else
+# define DEBUGLOCKS(format)
+#endif
+
+
+/******************************************************************************/
+/* MACROS */
+/******************************************************************************/
+
+/* number of lock records in the first pool allocated for a thread */
+#define LOCK_INITIAL_LOCK_RECORDS 8
+
+#define LOCK_INITIAL_HASHTABLE_SIZE 1613 /* a prime in the middle between 1024 and 2048 */
+
+
+/******************************************************************************/
+/* MACROS FOR THIN/FAT LOCKS */
+/******************************************************************************/
+
+/* We use a variant of the tasuki locks described in the paper
+ *
+ * Tamiya Onodera, Kiyokuni Kawachiya
+ * A Study of Locking Objects with Bimodal Fields
+ * Proceedings of the ACM OOPSLA '99, pp. 223-237
+ * 1999
+ *
+ * The underlying thin locks are a variant of the thin locks described in
+ *
+ * Bacon, Konuru, Murthy, Serrano
+ * Thin Locks: Featherweight Synchronization for Java
+ * Proceedings of the ACM Conference on Programming Language Design and
+ * Implementation (Montreal, Canada), SIGPLAN Notices volume 33, number 6,
+ * June 1998
+ *
+ * In thin lock mode the lockword looks like this:
+ *
+ * ,----------------------,-----------,---,
+ * | thread ID | count | 0 |
+ * `----------------------'-----------'---'
+ *
+ * thread ID......the 'index' of the owning thread, or 0
+ * count..........number of times the lock has been entered minus 1
+ * 0..............the shape bit is 0 in thin lock mode
+ *
+ * In fat lock mode it is basically a lock_record_t *:
+ *
+ * ,----------------------------------,---,
+ * | lock_record_t * (without LSB) | 1 |
+ * `----------------------------------'---'
+ *
+ * 1..............the shape bit is 1 in fat lock mode
+ */
+
+/* global variables ***********************************************************/
+
+/* hashtable mapping objects to lock records */
+static lock_hashtable_t lock_hashtable;
+
+
+/******************************************************************************/
+/* PROTOTYPES */
+/******************************************************************************/
+
+static void lock_hashtable_init(void);
+
+static inline Lockword* lock_lockword_get(java_handle_t* o);
+static void lock_record_enter(threadobject *t, lock_record_t *lr);
+static void lock_record_exit(threadobject *t, lock_record_t *lr);
+static bool lock_record_wait(threadobject *t, lock_record_t *lr, s8 millis, s4 nanos);
+static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one);
+
+
+/*============================================================================*/
+/* INITIALIZATION OF DATA STRUCTURES */
+/*============================================================================*/
+
+
+/* lock_init *******************************************************************
+
+ Initialize global data for locking.
+
+*******************************************************************************/
+
+void lock_init(void)
+{
+ /* initialize lock hashtable */
+
+ lock_hashtable_init();
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_init_lock();
+#endif
+}
+
+
+/* lock_record_new *************************************************************
+
+ Allocate a lock record.
+
+*******************************************************************************/
+
+static lock_record_t *lock_record_new(void)
+{
+ lock_record_t *lr;
+
+ /* allocate the data structure on the C heap */
+
+ lr = NEW(lock_record_t);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lock_record += sizeof(lock_record_t);
+#endif
+
+ /* initialize the members */
+
+ lr->object = NULL;
+ lr->owner = NULL;
+ lr->count = 0;
+ lr->waiters = new List<threadobject*>();
+
+#if defined(ENABLE_GC_CACAO)
+ /* register the lock object as weak reference with the GC */
+
+ gc_weakreference_register(&(lr->object), GC_REFTYPE_LOCKRECORD);
+#endif
+
+ // Initialize the mutex.
+ lr->mutex = new Mutex();
+
+ DEBUGLOCKS(("[lock_record_new : lr=%p]", (void *) lr));
+
+ return lr;
+}
+
+
+/* lock_record_free ************************************************************
+
+ Free a lock record.
+
+ IN:
+ lr....lock record to free
+
+*******************************************************************************/
+
+static void lock_record_free(lock_record_t *lr)
+{
+ DEBUGLOCKS(("[lock_record_free : lr=%p]", (void *) lr));
+
+ // Destroy the mutex.
+ delete lr->mutex;
+
+#if defined(ENABLE_GC_CACAO)
+ /* unregister the lock object reference with the GC */
+
+ gc_weakreference_unregister(&(lr->object));
+#endif
+
+ // Free the waiters list.
+ delete lr->waiters;
+
+ /* Free the data structure. */
+
+ FREE(lr, lock_record_t);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lock_record -= sizeof(lock_record_t);
+#endif
+}
+
+
+/*============================================================================*/
+/* HASHTABLE MAPPING OBJECTS TO LOCK RECORDS */
+/*============================================================================*/
+
+/* lock_hashtable_init *********************************************************
+
+ Initialize the global hashtable mapping objects to lock records.
+
+*******************************************************************************/
+
+static void lock_hashtable_init(void)
+{
+ lock_hashtable.mutex = new Mutex();
+
+ lock_hashtable.size = LOCK_INITIAL_HASHTABLE_SIZE;
+ lock_hashtable.entries = 0;
+ lock_hashtable.ptr = MNEW(lock_record_t *, lock_hashtable.size);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lock_hashtable += sizeof(lock_record_t *) * lock_hashtable.size;
+#endif
+
+ MZERO(lock_hashtable.ptr, lock_record_t *, lock_hashtable.size);
+}
+
+
+/* lock_hashtable_grow *********************************************************
+
+ Grow the lock record hashtable to about twice its current size and
+ rehash the entries.
+
+*******************************************************************************/
+
+/* must be called with hashtable mutex locked */
+static void lock_hashtable_grow(void)
+{
+ u4 oldsize;
+ u4 newsize;
+ lock_record_t **oldtable;
+ lock_record_t **newtable;
+ lock_record_t *lr;
+ lock_record_t *next;
+ u4 i;
+ u4 h;
+ u4 newslot;
+
+ /* allocate a new table */
+
+ oldsize = lock_hashtable.size;
+ newsize = oldsize*2 + 1; /* XXX should use prime numbers */
+
+ DEBUGLOCKS(("growing lock hashtable to size %d", newsize));
+
+ oldtable = lock_hashtable.ptr;
+ newtable = MNEW(lock_record_t *, newsize);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lock_hashtable += sizeof(lock_record_t *) * newsize;
+#endif
+
+ MZERO(newtable, lock_record_t *, newsize);
+
+ /* rehash the entries */
+
+ for (i = 0; i < oldsize; i++) {
+ lr = oldtable[i];
+ while (lr) {
+ next = lr->hashlink;
+
+ h = heap_hashcode(lr->object);
+ newslot = h % newsize;
+
+ lr->hashlink = newtable[newslot];
+ newtable[newslot] = lr;
+
+ lr = next;
+ }
+ }
+
+ /* replace the old table */
+
+ lock_hashtable.ptr = newtable;
+ lock_hashtable.size = newsize;
+
+ MFREE(oldtable, lock_record_t *, oldsize);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lock_hashtable -= sizeof(lock_record_t *) * oldsize;
+#endif
+}
+
+
+/* lock_hashtable_cleanup ******************************************************
+
+ Removes (and frees) lock records which have a cleared object reference
+ from the hashtable. The locked object was reclaimed by the GC.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void lock_hashtable_cleanup(void)
+{
+ threadobject *t;
+ lock_record_t *lr;
+ lock_record_t *prev;
+ lock_record_t *next;
+ int i;
+
+ t = THREADOBJECT;
+
+ /* lock the hashtable */
+
+ Mutex_lock(lock_hashtable.mutex);
+
+ /* search the hashtable for cleared references */
+
+ for (i = 0; i < lock_hashtable.size; i++) {
+ lr = lock_hashtable.ptr[i];
+ prev = NULL;
+
+ while (lr) {
+ next = lr->hashlink;
+
+ /* remove lock records with cleared references */
+
+ if (lr->object == NULL) {
+
+ /* unlink the lock record from the hashtable */
+
+ if (prev == NULL)
+ lock_hashtable.ptr[i] = next;
+ else
+ prev->hashlink = next;
+
+ /* free the lock record */
+
+ lock_record_free(lr);
+
+ } else {
+ prev = lr;
+ }
+
+ lr = next;
+ }
+ }
+
+ /* unlock the hashtable */
+
+ Mutex_unlock(lock_hashtable.mutex);
+}
+#endif
+
+
+/* lock_hashtable_get **********************************************************
+
+ Find the lock record for the given object. If it does not exists,
+ yet, create it and enter it in the hashtable.
+
+ IN:
+ o....the object to look up
+
+ RETURN VALUE:
+ the lock record to use for this object
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_BOEHM)
+static void lock_record_finalizer(void *object, void *p);
+#endif
+
+static lock_record_t *lock_hashtable_get(java_handle_t* o)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
+
+ u4 slot;
+ lock_record_t *lr;
+
+ Lockword* lockword = lock_lockword_get(o);
+
+ if (lockword->is_fat_lock())
+ return lockword->get_fat_lock();
+
+ // Lock the hashtable.
+ lock_hashtable.mutex->lock();
+
+ /* lookup the lock record in the hashtable */
+
+ slot = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
+ lr = lock_hashtable.ptr[slot];
+
+ for (; lr != NULL; lr = lr->hashlink) {
+ if (lr->object == LLNI_DIRECT(o))
+ break;
+ }
+
+ if (lr == NULL) {
+ /* not found, we must create a new one */
+
+ lr = lock_record_new();
+
+ lr->object = LLNI_DIRECT(o);
+
+#if defined(ENABLE_GC_BOEHM)
+ /* register new finalizer to clean up the lock record */
+
+ GC_REGISTER_FINALIZER(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
+#endif
+
+ /* enter it in the hashtable */
+
+ lr->hashlink = lock_hashtable.ptr[slot];
+ lock_hashtable.ptr[slot] = lr;
+ lock_hashtable.entries++;
+
+ /* check whether the hash should grow */
+
+ if (lock_hashtable.entries * 3 > lock_hashtable.size * 4) {
+ lock_hashtable_grow();
+ }
+ }
+
+ // Unlock the hashtable.
+ lock_hashtable.mutex->unlock();
+
+ /* return the new lock record */
+
+ return lr;
+}
+
+
+/* lock_hashtable_remove *******************************************************
+
+ Remove the lock record for the given object from the hashtable
+ and free it afterwards.
+
+ IN:
+ t....the current thread
+ o....the object to look up
+
+*******************************************************************************/
+
+static void lock_hashtable_remove(threadobject *t, java_handle_t *o)
+{
+ lock_record_t *lr;
+ u4 slot;
+ lock_record_t *tmplr;
+
+ // Lock the hashtable.
+ lock_hashtable.mutex->lock();
+
+ /* get lock record */
+
+ Lockword* lockword = lock_lockword_get(o);
+
+ // Sanity check.
+ assert(lockword->is_fat_lock());
+
+ lr = lockword->get_fat_lock();
+
+ /* remove the lock-record from the hashtable */
+
+ slot = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
+ tmplr = lock_hashtable.ptr[slot];
+
+ if (tmplr == lr) {
+ /* special handling if it's the first in the chain */
+
+ lock_hashtable.ptr[slot] = lr->hashlink;
+ }
+ else {
+ for (; tmplr != NULL; tmplr = tmplr->hashlink) {
+ if (tmplr->hashlink == lr) {
+ tmplr->hashlink = lr->hashlink;
+ break;
+ }
+ }
+
+ assert(tmplr != NULL);
+ }
+
+ /* decrease entry count */
+
+ lock_hashtable.entries--;
+
+ // Unlock the hashtable.
+ lock_hashtable.mutex->unlock();
+
+ /* free the lock record */
+
+ lock_record_free(lr);
+}
+
+
+/* lock_record_finalizer *******************************************************
+
+ XXX Remove me for exact GC.
+
+*******************************************************************************/
+
+static void lock_record_finalizer(void *object, void *p)
+{
+ java_handle_t *o;
+ classinfo *c;
+
+ o = (java_handle_t *) object;
+
+#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_class_get(o, c);
+
+#if !defined(NDEBUG)
+ if (opt_DebugFinalizer) {
+ log_start();
+ log_print("[finalizer lockrecord: o=%p p=%p class=", object, p);
+ class_print(c);
+ log_print("]");
+ log_finish();
+ }
+#endif
+
+ /* check for a finalizer function */
+
+ if (c->finalizer != NULL)
+ finalizer_run(object, p);
+
+ /* remove the lock-record entry from the hashtable and free it */
+
+ lock_hashtable_remove(THREADOBJECT, o);
+}
+
+
+/*============================================================================*/
+/* LOCKING ALGORITHM */
+/*============================================================================*/
+
+
+/* lock_lockword_get ***********************************************************
+
+ Get the lockword for the given object.
+
+ IN:
+ o............the object
+
+*******************************************************************************/
+
+static inline Lockword* lock_lockword_get(java_handle_t* o)
+{
+#if defined(ENABLE_GC_CACAO)
+ // Sanity check.
+ assert(GCCriticalSection::inside() == true);
+#endif
+
+ return &(LLNI_DIRECT(o)->lockword);
+}
+
+
+/* lock_record_enter ***********************************************************
+
+ Enter the lock represented by the given lock record.
+
+ IN:
+ t.................the current thread
+ lr................the lock record
+
+*******************************************************************************/
+
+static inline void lock_record_enter(threadobject *t, lock_record_t *lr)
+{
+ lr->mutex->lock();
+ lr->owner = t;
+}
+
+
+/* lock_record_exit ************************************************************
+
+ Release the lock represented by the given lock record.
+
+ IN:
+ t.................the current thread
+ lr................the lock record
+
+ PRE-CONDITION:
+ The current thread must own the lock represented by this lock record.
+ This is NOT checked by this function!
+
+*******************************************************************************/
+
+static inline void lock_record_exit(threadobject *t, lock_record_t *lr)
+{
+ lr->owner = NULL;
+ lr->mutex->unlock();
+}
+
+
+/* lock_inflate ****************************************************************
+
+ Inflate the lock of the given object. This may only be called by the
+ owner of the monitor of the object.
+
+ IN:
+ o............the object of which to inflate the lock
+ lr...........the lock record to install. The current thread must
+ own the lock of this lock record!
+
+ PRE-CONDITION:
+ The current thread must be the owner of this object's monitor AND
+ of the lock record's lock!
+
+*******************************************************************************/
+
+static void lock_inflate(java_handle_t *o, lock_record_t *lr)
+{
+ Lockword* lockword = lock_lockword_get(o);
+ lockword->inflate(lr);
+}
+
+
+static void sable_flc_waiting(Lockword *lockword, threadobject *t, java_handle_t *o)
+{
+ int32_t index;
+ threadobject *t_other;
+ int old_flc;
+
+ index = lockword->get_thin_lock_thread_index();
+ t_other = ThreadList::get_thread_by_index(index);
+
+ // The lockword could have changed during our way here. If the
+ // thread index is zero, the lock got unlocked and we simply
+ // return.
+ if (t_other == NULL)
+/* failure, TODO: add statistics */
+ return;
+
+ t_other->flc_lock->lock();
+ old_flc = t_other->flc_bit;
+ t_other->flc_bit = true;
+
+ DEBUGLOCKS(("thread %d set flc bit for lock-holding thread %d", t->index, t_other->index));
+
+ // Set FLC bit first, then read the lockword again.
+ Atomic::memory_barrier();
+
+ lockword = lock_lockword_get(o);
+
+ /* Lockword is still the way it was seen before */
+ if (lockword->is_thin_lock() && (lockword->get_thin_lock_thread_index() == index))
+ {
+ threadobject *f;
+ /* Add tuple (t, o) to the other thread's FLC list */
+ t->flc_object = o;
+ t->flc_next = t_other->flc_list;
+ t_other->flc_list = t;
+ if (t->flc_next == 0)
+ t_other->flc_tail = t;
+ f = t_other->flc_tail;
+
+ for (;;)
+ {
+ threadobject *current;
+
+ // Wait until another thread sees the flc bit and notifies
+ // us of unlocking.
+ t->flc_cond->wait(t_other->flc_lock);
+
+ if (t_other->flc_tail != f)
+ break;
+ /* Traverse FLC list looking if we're still there */
+ current = t_other->flc_list;
+ while (current && current != t)
+ current = current->flc_next;
+ if (!current)
+ /* not in list anymore, can stop waiting */
+ break;
+
+ /* We are still in the list -- the other thread cannot have seen
+ the FLC bit yet */
+ assert(t_other->flc_bit);
+ }
+
+ t->flc_object = NULL; /* for garbage collector? */
+ t->flc_next = NULL;
+ }
+ else
+ t_other->flc_bit = old_flc;
+
+ t_other->flc_lock->unlock();
+}
+
+static void notify_flc_waiters(threadobject *t, java_handle_t *o)
+{
+ threadobject *current;
+
+ t->flc_lock->lock();
+
+ current = t->flc_list;
+ while (current)
+ {
+ if (current->flc_object != o)
+ {
+ /* The object has to be inflated so the other threads can properly
+ block on it. */
+
+ // Only if not already inflated.
+ Lockword* lockword = lock_lockword_get(current->flc_object);
+ if (lockword->is_thin_lock()) {
+ lock_record_t *lr = lock_hashtable_get(current->flc_object);
+ lock_record_enter(t, lr);
+
+ DEBUGLOCKS(("thread %d inflating lock of %p to lr %p",
+ t->index, (void*) current->flc_object, (void*) lr));
+
+ lock_inflate(current->flc_object, lr);
+ }
+ }
+
+ // Wake the waiting threads.
+ current->flc_cond->broadcast();
+
+ current = current->flc_next;
+ }
+
+ t->flc_list = NULL;
+ t->flc_bit = false;
+
+ t->flc_lock->unlock();
+}
+
+/* lock_monitor_enter **********************************************************
+
+ Acquire the monitor of the given object. If the current thread already
+ owns the monitor, the lock counter is simply increased.
+
+ This function blocks until it can acquire the monitor.
+
+ IN:
+ t............the current thread
+ o............the object of which to enter the monitor
+
+ RETURN VALUE:
+ true.........the lock has been successfully acquired
+ false........an exception has been thrown
+
+*******************************************************************************/
+
+bool lock_monitor_enter(java_handle_t *o)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
+
+ if (o == NULL) {
+ exceptions_throw_nullpointerexception();
+ return false;
+ }
+
+ threadobject* t = thread_get_current();
+
+ uintptr_t thinlock = t->thinlock;
+
+retry:
+ // Most common case: try to thin-lock an unlocked object.
+ Lockword* lockword = lock_lockword_get(o);
+ bool result = lockword->lock(thinlock);
+
+ if (result == true) {
+ // Success, we locked it.
+ // NOTE: The Java Memory Model requires an instruction barrier
+ // here (because of the CAS above).
+ Atomic::instruction_barrier();
+ return true;
+ }
+
+ // Next common case: recursive lock with small recursion count.
+ // NOTE: We don't have to worry about stale values here, as any
+ // stale value will indicate another thread holding the lock (or
+ // an inflated lock).
+ if (lockword->get_thin_lock_without_count() == thinlock) {
+ // We own this monitor. Check the current recursion count.
+ if (lockword->is_max_thin_lock_count() == false) {
+ // The recursion count is low enough.
+ lockword->increase_thin_lock_count();
+
+ // Success, we locked it.
+ return true;
+ }
+ else {
+ // Recursion count overflow.
+ lock_record_t* lr = lock_hashtable_get(o);
+ lock_record_enter(t, lr);
+ lock_inflate(o, lr);
+ lr->count++;
+
+ notify_flc_waiters(t, o);
+
+ return true;
+ }
+ }
+
+ // The lock is either contented or fat.
+ if (lockword->is_fat_lock()) {
+ lock_record_t* lr = lockword->get_fat_lock();
+
+ // Check for recursive entering.
+ if (lr->owner == t) {
+ lr->count++;
+ return true;
+ }
+
+ // Acquire the mutex of the lock record.
+ lock_record_enter(t, lr);
+
+ // Sanity check.
+ assert(lr->count == 0);
+ return true;
+ }
+
+ /****** inflation path ******/
+
+#if defined(ENABLE_JVMTI)
+ /* Monitor Contended Enter */
+ jvmti_MonitorContendedEntering(false, o);
+#endif
+
+ sable_flc_waiting(lockword, t, o);
+
+#if defined(ENABLE_JVMTI)
+ /* Monitor Contended Entered */
+ jvmti_MonitorContendedEntering(true, o);
+#endif
+ goto retry;
+}
+
+
+/* lock_monitor_exit ***********************************************************
+
+ Decrement the counter of a (currently owned) monitor. If the counter
+ reaches zero, release the monitor.
+
+ If the current thread is not the owner of the monitor, an
+ IllegalMonitorState exception is thrown.
+
+ IN:
+ t............the current thread
+ o............the object of which to exit the monitor
+
+ RETURN VALUE:
+ true.........everything ok,
+ false........an exception has been thrown
+
+*******************************************************************************/
+
+bool lock_monitor_exit(java_handle_t* o)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
+
+ if (o == NULL) {
+ exceptions_throw_nullpointerexception();
+ return false;
+ }
+
+ threadobject* t = thread_get_current();
+
+ uintptr_t thinlock = t->thinlock;
+
+ // We don't have to worry about stale values here, as any stale
+ // value will indicate that we don't own the lock.
+ Lockword* lockword = lock_lockword_get(o);
+
+ // Most common case: we release a thin lock that we hold once.
+ if (lockword->get_thin_lock() == thinlock) {
+ // Memory barrier for Java Memory Model.
+ Atomic::write_memory_barrier();
+ lockword->unlock();
+ // Memory barrier for thin locking.
+ Atomic::memory_barrier();
+
+ /* check if there has been a flat lock contention on this object */
+
+ if (t->flc_bit) {
+ DEBUGLOCKS(("thread %d saw flc bit", t->index));
+
+ /* there has been a contention on this thin lock */
+ notify_flc_waiters(t, o);
+ }
+
+ return true;
+ }
+
+ // Next common case: we release a recursive lock, count > 0.
+ if (lockword->get_thin_lock_without_count() == thinlock) {
+ lockword->decrease_thin_lock_count();
+ return true;
+ }
+
+ // Either the lock is fat, or we don't hold it at all.
+ if (lockword->is_fat_lock()) {
+ lock_record_t* lr = lockword->get_fat_lock();
+
+ // Check if we own this monitor.
+ // NOTE: We don't have to worry about stale values here, as
+ // any stale value will be != t and thus fail this check.
+ if (lr->owner != t) {
+ exceptions_throw_illegalmonitorstateexception();
+ return false;
+ }
+
+ /* { the current thread `t` owns the lock record `lr` on object `o` } */
+
+ if (lr->count != 0) {
+ // We had locked this one recursively. Just decrement, it
+ // will still be locked.
+ lr->count--;
+ return true;
+ }
+
+ // Unlock this lock record.
+ lock_record_exit(t, lr);
+ return true;
+ }
+
+ // Legal thin lock cases have been handled above, so this is an
+ // error.
+ exceptions_throw_illegalmonitorstateexception();
+
+ return false;
+}
+
+
+/* lock_record_add_waiter ******************************************************
+
+ Add a thread to the list of waiting threads of a lock record.
+
+ IN:
+ lr...........the lock record
+ thread.......the thread to add
+
+*******************************************************************************/
+
+static void lock_record_add_waiter(lock_record_t *lr, threadobject* t)
+{
+ // Add the thread as last entry to waiters list.
+ lr->waiters->push_back(t);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lock_waiter += sizeof(threadobject*);
+#endif
+}
+
+
+/* lock_record_remove_waiter ***************************************************
+
+ Remove a thread from the list of waiting threads of a lock record.
+
+ IN:
+ lr...........the lock record
+ t............the current thread
+
+ PRE-CONDITION:
+ The current thread must be the owner of the lock record.
+
+*******************************************************************************/
+
+static void lock_record_remove_waiter(lock_record_t *lr, threadobject* t)
+{
+ // Remove the thread from the waiters.
+ lr->waiters->remove(t);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lock_waiter -= sizeof(threadobject*);
+#endif
+}
+
+
+/* lock_record_wait ************************************************************
+
+ Wait on a lock record for a given (maximum) amount of time.
+
+ IN:
+ t............the current thread
+ lr...........the lock record
+ millis.......milliseconds of timeout
+ nanos........nanoseconds of timeout
+
+ RETURN VALUE:
+ true.........we have been interrupted,
+ false........everything ok
+
+ PRE-CONDITION:
+ The current thread must be the owner of the lock record.
+ This is NOT checked by this function!
+
+*******************************************************************************/
+
+static bool lock_record_wait(threadobject *thread, lock_record_t *lr, s8 millis, s4 nanos)
+{
+ s4 lockcount;
+ bool wasinterrupted = false;
+
+ DEBUGLOCKS(("[lock_record_wait : lr=%p, t=%p, millis=%lld, nanos=%d]",
+ lr, thread, millis, nanos));
+
+ /* { the thread t owns the fat lock record lr on the object o } */
+
+ /* register us as waiter for this object */
+
+ lock_record_add_waiter(lr, thread);
+
+ /* remember the old lock count */
+
+ lockcount = lr->count;
+
+ /* unlock this record */
+
+ lr->count = 0;
+ lock_record_exit(thread, lr);
+
+ /* wait until notified/interrupted/timed out */
+
+ threads_wait_with_timeout_relative(thread, millis, nanos);
+
+ /* re-enter the monitor */
+
+ lock_record_enter(thread, lr);
+
+ /* remove us from the list of waiting threads */
+
+ lock_record_remove_waiter(lr, thread);
+
+ /* restore the old lock count */
+
+ lr->count = lockcount;
+
+ /* We can only be signaled OR interrupted, not both. If both flags
+ are set, reset only signaled and leave the thread in
+ interrupted state. Otherwise, clear both. */
+
+ if (!thread->signaled) {
+ wasinterrupted = thread->interrupted;
+ thread->interrupted = false;
+ }
+
+ thread->signaled = false;
+
+ /* return if we have been interrupted */
+
+ return wasinterrupted;
+}
+
+
+/* lock_monitor_wait ***********************************************************
+
+ Wait on an object for a given (maximum) amount of time.
+
+ IN:
+ t............the current thread
+ o............the object
+ millis.......milliseconds of timeout
+ nanos........nanoseconds of timeout
+
+ PRE-CONDITION:
+ The current thread must be the owner of the object's monitor.
+
+*******************************************************************************/
+
+static void lock_monitor_wait(threadobject *t, java_handle_t *o, s8 millis, s4 nanos)
+{
+ lock_record_t *lr;
+
+ Lockword* lockword = lock_lockword_get(o);
+
+ // Check if we own this monitor.
+ // NOTE: We don't have to worry about stale values here, as any
+ // stale value will fail this check.
+ if (lockword->is_fat_lock()) {
+ lr = lockword->get_fat_lock();
+
+ if (lr->owner != t) {
+ exceptions_throw_illegalmonitorstateexception();
+ return;
+ }
+ }
+ else {
+ // It's a thin lock.
+ if (lockword->get_thin_lock_without_count() != t->thinlock) {
+ exceptions_throw_illegalmonitorstateexception();
+ return;
+ }
+
+ // Get the lock-record.
+ lr = lock_hashtable_get(o);
+ lock_record_enter(t, lr);
+
+ // Inflate this lock.
+ lockword->inflate(lr);
+
+ notify_flc_waiters(t, o);
+ }
+
+ /* { the thread t owns the fat lock record lr on the object o } */
+
+ if (lock_record_wait(t, lr, millis, nanos))
+ exceptions_throw_interruptedexception();
+}
+
+
+/* lock_record_notify **********************************************************
+
+ Notify one thread or all threads waiting on the given lock record.
+
+ IN:
+ t............the current thread
+ lr...........the lock record
+ one..........if true, only notify one thread
+
+ PRE-CONDITION:
+ The current thread must be the owner of the lock record.
+ This is NOT checked by this function!
+
+*******************************************************************************/
+
+static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one)
+{
+#if defined(ENABLE_GC_CACAO)
+ // Sanity check.
+ assert(GCCriticalSection::inside() == false);
+#endif
+
+ // { The thread t owns the fat lock record lr on the object o }
+
+ for (List<threadobject*>::iterator it = lr->waiters->begin(); it != lr->waiters->end(); it++) {
+ threadobject* waiter = *it;
+
+ // We must skip threads which have already been notified. They
+ // will remove themselves from the list.
+ if (waiter->signaled)
+ continue;
+
+ // Enter the wait-mutex.
+ waiter->waitmutex->lock();
+
+ DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, one=%d]", lr, t, waiter, one));
+
+ // Signal the waiter.
+ waiter->waitcond->signal();
+
+ // Mark the thread as signaled.
+ waiter->signaled = true;
+
+ // Leave the wait-mutex.
+ waiter->waitmutex->unlock();
+
+ // If we should only wake one thread, we are done.
+ if (one)
+ break;
+ }
+}
+
+
+/* lock_monitor_notify *********************************************************
+
+ Notify one thread or all threads waiting on the given object.
+
+ IN:
+ t............the current thread
+ o............the object
+ one..........if true, only notify one thread
+
+ PRE-CONDITION:
+ The current thread must be the owner of the object's monitor.
+
+*******************************************************************************/
+
+static void lock_monitor_notify(threadobject *t, java_handle_t *o, bool one)
+{
+ lock_record_t* lr = NULL;
+
+ {
+ // This scope is inside a critical section.
+ GCCriticalSection cs;
+
+ Lockword* lockword = lock_lockword_get(o);
+
+ // Check if we own this monitor.
+ // NOTE: We don't have to worry about stale values here, as any
+ // stale value will fail this check.
+
+ if (lockword->is_fat_lock()) {
+ lr = lockword->get_fat_lock();
+
+ if (lr->owner != t) {
+ exceptions_throw_illegalmonitorstateexception();
+ return;
+ }
+ }
+ else {
+ // It's a thin lock.
+ if (lockword->get_thin_lock_without_count() != t->thinlock) {
+ exceptions_throw_illegalmonitorstateexception();
+ return;
+ }
+
+ // No thread can wait on a thin lock, so there's nothing to do.
+ return;
+ }
+ }
+
+ // { The thread t owns the fat lock record lr on the object o }
+ lock_record_notify(t, lr, one);
+}
+
+
+
+/*============================================================================*/
+/* INQUIRY FUNCIONS */
+/*============================================================================*/
+
+
+/* lock_is_held_by_current_thread **********************************************
+
+ Return true if the current thread owns the monitor of the given object.
+
+ IN:
+ o............the object
+
+ RETURN VALUE:
+ true, if the current thread holds the lock of this object.
+
+*******************************************************************************/
+
+bool lock_is_held_by_current_thread(java_handle_t *o)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
+
+ // Check if we own this monitor.
+ // NOTE: We don't have to worry about stale values here, as any
+ // stale value will fail this check.
+ threadobject* t = thread_get_current();
+ Lockword* lockword = lock_lockword_get(o);
+
+ if (lockword->is_fat_lock()) {
+ // It's a fat lock.
+ lock_record_t* lr = lockword->get_fat_lock();
+ return (lr->owner == t);
+ }
+ else {
+ // It's a thin lock.
+ return (lockword->get_thin_lock_without_count() == t->thinlock);
+ }
+}
+
+
+
+/*============================================================================*/
+/* WRAPPERS FOR OPERATIONS ON THE CURRENT THREAD */
+/*============================================================================*/
+
+
+/* lock_wait_for_object ********************************************************
+
+ Wait for the given object.
+
+ IN:
+ o............the object
+ millis.......milliseconds to wait
+ nanos........nanoseconds to wait
+
+*******************************************************************************/
+
+void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos)
+{
+ threadobject *thread;
+
+ thread = THREADOBJECT;
+
+ lock_monitor_wait(thread, o, millis, nanos);
+}
+
+
+/* lock_notify_object **********************************************************
+
+ Notify one thread waiting on the given object.
+
+ IN:
+ o............the object
+
+*******************************************************************************/
+
+void lock_notify_object(java_handle_t *o)
+{
+ threadobject *thread;
+
+ thread = THREADOBJECT;
+
+ lock_monitor_notify(thread, o, true);
+}
+
+
+/* lock_notify_all_object ******************************************************
+
+ Notify all threads waiting on the given object.
+
+ IN:
+ o............the object
+
+*******************************************************************************/
+
+void lock_notify_all_object(java_handle_t *o)
+{
+ threadobject *thread;
+
+ thread = THREADOBJECT;
+
+ lock_monitor_notify(thread, o, false);
+}
+
+
+/*
+ * These 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/lock.hpp - lock implementation
+
+ 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 _LOCK_HPP
+#define _LOCK_HPP
+
+#include <stdint.h>
+
+#include "native/llni.h"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/list.hpp"
+
+#include "vm/global.h"
+
+
+/* typedefs *******************************************************************/
+
+typedef struct lock_record_t lock_record_t;
+typedef struct lock_hashtable_t lock_hashtable_t;
+
+
+/* lock_record_t ***************************************************************
+
+ Lock record struct representing an inflated ("fat") lock.
+
+*******************************************************************************/
+
+struct lock_record_t {
+ java_object_t *object; /* object for which this lock is */
+ struct threadobject *owner; /* current owner of this monitor */
+ s4 count; /* recursive lock count */
+ Mutex* mutex; /* mutex for synchronizing */
+#ifdef __cplusplus
+ List<threadobject*>* waiters; /* list of threads waiting */
+#else
+ List* waiters;
+#endif
+ lock_record_t *hashlink; /* next record in hash chain */
+};
+
+
+/* lock_hashtable_t ************************************************************
+
+ The global hashtable mapping objects to lock records.
+
+*******************************************************************************/
+
+struct lock_hashtable_t {
+ 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. */
+};
+
+
+/* functions ******************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void lock_init(void);
+
+bool lock_monitor_enter(java_handle_t *);
+bool lock_monitor_exit(java_handle_t *);
+
+#define LOCK_monitor_enter (functionptr) lock_monitor_enter
+#define LOCK_monitor_exit (functionptr) lock_monitor_exit
+
+bool lock_is_held_by_current_thread(java_handle_t *o);
+
+void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos);
+void lock_notify_object(java_handle_t *o);
+void lock_notify_all_object(java_handle_t *o);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* defines ********************************************************************/
+
+/* only define the following stuff with thread enabled ************************/
+
+#if defined(ENABLE_THREADS)
+
+#define LOCK_MONITOR_ENTER(o) lock_monitor_enter((java_handle_t *) LLNI_QUICKWRAP(o))
+#define LOCK_MONITOR_EXIT(o) lock_monitor_exit((java_handle_t *) LLNI_QUICKWRAP(o))
+
+#endif
+
+#endif // _LOCK_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/lockword.cpp - lockword 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 <assert.h>
+#include <stdint.h>
+
+#include "threads/lock.hpp"
+
+
+/**
+ * Inflate the lock of the given object. This may only be called by
+ * the owner of the monitor of the object.
+ *
+ * PRE-CONDITION: The current thread must be the owner of this
+ * object's monitor AND of the lock record's lock!
+ *
+ * @param lr The lock-record to install. The current thread must own
+ * the lock of this lock record!
+ */
+void Lockword::inflate(lock_record_t* lr)
+{
+ if (is_fat_lock()) {
+ // Sanity check.
+ assert(get_fat_lock() == lr);
+ return;
+ }
+
+ // Sanity check.
+ assert(get_thin_lock_without_count() == thread_get_current()->thinlock);
+
+ // Copy the count from the thinlock.
+ lr->count = get_thin_lock_count();
+
+// DEBUGLOCKS(("[lock_inflate : lr=%p, t=%p, o=%p, o->lockword=%lx, count=%d]",
+// lr, thread_get_current(), o, get_thin_lock(), lr->count));
+
+ // Install the lock-record in the lockword.
+ set(lr);
+}
+
+
+extern "C" {
+ void Lockword_init(Lockword* lockword) { lockword->init(); }
+}
+
+/*
+ * These 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/lockword.hpp - lockword 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 _LOCKWORD_HPP
+#define _LOCKWORD_HPP
+
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+
+/**
+ * Lockword.
+ */
+class Lockword {
+private:
+ static const int THIN_LOCK_WORD_SIZE = SIZEOF_VOID_P * 8; // Pointer size multiplied by 8-bit.
+ static const int THIN_LOCK_SHAPE_BIT = 0x01;
+
+ static const uintptr_t THIN_UNLOCKED = 0;
+
+ static const int THIN_LOCK_COUNT_SHIFT = 1;
+ static const int THIN_LOCK_COUNT_SIZE = 8;
+ static const int THIN_LOCK_COUNT_INCR = (1 << THIN_LOCK_COUNT_SHIFT);
+ static const int THIN_LOCK_COUNT_MAX = ((1 << THIN_LOCK_COUNT_SIZE) - 1);
+
+ static const int THIN_LOCK_COUNT_MASK = (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT);
+
+ static const int THIN_LOCK_TID_SHIFT = (THIN_LOCK_COUNT_SIZE + THIN_LOCK_COUNT_SHIFT);
+ static const int THIN_LOCK_TID_SIZE = (THIN_LOCK_WORD_SIZE - THIN_LOCK_TID_SHIFT);
+
+private:
+ // The actual lockword.
+ uintptr_t _lockword;
+
+private:
+ Lockword(uintptr_t lockword) : _lockword(lockword) {}
+
+public:
+ Lockword() : _lockword(THIN_UNLOCKED) {}
+
+ void init() { _lockword = THIN_UNLOCKED; } // REMOVEME
+
+ static inline uintptr_t pre_compute_thinlock(int32_t index);
+
+ inline bool is_thin_lock () const;
+ inline bool is_fat_lock () const;
+
+ inline bool is_unlocked() const;
+ inline bool lock (uintptr_t thinlock);
+ inline void unlock ();
+
+ inline uintptr_t get_thin_lock () const;
+ inline uintptr_t get_thin_lock_without_count() const;
+ inline int32_t get_thin_lock_count () const;
+ inline int32_t get_thin_lock_thread_index () const;
+ inline struct lock_record_t* get_fat_lock () const;
+
+ inline void set(uintptr_t lockword);
+ inline void set(struct lock_record_t* lr);
+
+ inline bool is_max_thin_lock_count () const;
+ inline void increase_thin_lock_count();
+ inline void decrease_thin_lock_count();
+
+ void inflate(struct lock_record_t* lr);
+};
+
+
+// Includes.
+#include <assert.h>
+
+#include "threads/atomic.hpp"
+
+
+/**
+ * Pre-compute the thin lock value for a thread index.
+ *
+ * @param index The thead index (>= 1).
+ *
+ * @return The thin lock value for this thread index.
+ */
+uintptr_t Lockword::pre_compute_thinlock(int32_t index)
+{
+ return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
+}
+
+
+bool Lockword::is_thin_lock() const
+{
+ return ((_lockword & THIN_LOCK_SHAPE_BIT) == 0);
+}
+
+
+bool Lockword::is_fat_lock() const
+{
+ return ((_lockword & THIN_LOCK_SHAPE_BIT) != 0);
+}
+
+
+/**
+ * Check if the lockword is an unlocked thin-lock.
+ *
+ * @return true if unlocked, false otherwise.
+ */
+bool Lockword::is_unlocked() const
+{
+ return (_lockword == THIN_UNLOCKED);
+}
+
+
+/**
+ * Try to lock the lockword with the given thin-lock value.
+ *
+ * @param thinlock Thin-lock value to store in the Lockword.
+ *
+ * @return true if lock was successful, false otherwise.
+ */
+bool Lockword::lock(uintptr_t thinlock)
+{
+ // Atomically exchange the lockword value.
+ uintptr_t oldlockword = Atomic::compare_and_swap(&_lockword, THIN_UNLOCKED, thinlock);
+
+ return Lockword(oldlockword).is_unlocked();
+}
+
+
+/**
+ * Set the lockword to THIN_UNLOCKED.
+ */
+void Lockword::unlock()
+{
+ _lockword = THIN_UNLOCKED;
+}
+
+
+uintptr_t Lockword::get_thin_lock() const
+{
+ return _lockword;
+}
+
+
+uintptr_t Lockword::get_thin_lock_without_count() const
+{
+ return (_lockword & ~THIN_LOCK_COUNT_MASK);
+}
+
+
+int32_t Lockword::get_thin_lock_count() const
+{
+ return (int32_t) (_lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
+}
+
+
+int32_t Lockword::get_thin_lock_thread_index() const
+{
+ return (int32_t) (_lockword >> THIN_LOCK_TID_SHIFT);
+}
+
+
+struct lock_record_t* Lockword::get_fat_lock() const
+{
+ return (struct lock_record_t*) (_lockword & ~THIN_LOCK_SHAPE_BIT);
+}
+
+
+void Lockword::set(uintptr_t lockword)
+{
+ _lockword = lockword;
+}
+
+
+void Lockword::set(struct lock_record_t* lr)
+{
+ _lockword = ((uintptr_t) lr) | THIN_LOCK_SHAPE_BIT;
+}
+
+
+bool Lockword::is_max_thin_lock_count() const
+{
+ return (get_thin_lock_count() >= THIN_LOCK_COUNT_MAX);
+}
+
+
+void Lockword::increase_thin_lock_count()
+{
+ // Sanity check.
+ assert(get_thin_lock_count() < THIN_LOCK_COUNT_MAX);
+
+ _lockword += (1 << THIN_LOCK_COUNT_SHIFT);
+}
+
+
+void Lockword::decrease_thin_lock_count()
+{
+ // Sanity check.
+ assert(get_thin_lock_count() > 0);
+
+ _lockword -= (1 << THIN_LOCK_COUNT_SHIFT);
+}
+
+#else
+
+// This structure must have the same layout as the C++ class above.
+typedef struct Lockword {
+ uintptr_t _lockword;
+} Lockword;
+
+void Lockword_init(Lockword* lockword);
+
+#endif
+
+#endif // _LOCKWORD_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:
+ */
/* define some stuff to no-ops *************************************************/
-#define LOCK_INIT_OBJECT_LOCK(o)
-
#define LOCK_MONITOR_ENTER(o)
#define LOCK_MONITOR_EXIT(o)
#include "vm/types.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/globals.hpp"
#include "vm/jit/stacktrace.hpp"
libthreadsposix_la_SOURCES = \
condition-posix.hpp \
- lock.c \
- lock.h \
mutex-posix.hpp \
thread-posix.cpp \
thread-posix.hpp
#include <pthread.h>
#include <time.h>
-#include "vm/vm.hpp"
#ifdef __cplusplus
void signal();
void timedwait(Mutex* mutex, const struct timespec* abstime);
void wait(Mutex* mutex);
+ void wait(Mutex& mutex);
};
+// Includes.
+#include "vm/vm.hpp"
+
+
+// Includes.
+#include "vm/os.hpp"
+
+
/**
* Initialize a POSIX condition variable.
*/
inline Condition::Condition()
{
- int result;
+ int result = pthread_cond_init(&_cond, NULL);
- result = pthread_cond_init(&_cond, NULL);
-
- if (result != 0)
- vm_abort_errnum(result, "Condition::Condition(): pthread_cond_init failed");
+ if (result != 0) {
+ os::abort_errnum(result, "Condition::Condition(): pthread_cond_init failed");
+ }
}
*/
inline Condition::~Condition()
{
- int result;
+ // Restart all threads waiting on this condition.
+ broadcast();
- result = pthread_cond_destroy(&_cond);
+ int result = pthread_cond_destroy(&_cond);
- if (result != 0)
- vm_abort_errnum(result, "Condition::~Condition(): pthread_cond_destroy failed");
+ if (result != 0) {
+ os::abort_errnum(result, "Condition::~Condition(): pthread_cond_destroy failed");
+ }
}
*/
inline void Condition::broadcast()
{
- int result;
-
- result = pthread_cond_broadcast(&_cond);
+ int result = pthread_cond_broadcast(&_cond);
- if (result != 0)
- vm_abort_errnum(result, "Condition::broadcast(): pthread_cond_broadcast failed");
+ if (result != 0) {
+ os::abort_errnum(result, "Condition::broadcast(): pthread_cond_broadcast failed");
+ }
}
*/
inline void Condition::signal()
{
- int result;
+ int result = pthread_cond_signal(&_cond);
- result = pthread_cond_signal(&_cond);
-
- if (result != 0)
- vm_abort_errnum(result, "Condition::signal(): pthread_cond_signal failed");
+ if (result != 0) {
+ os::abort_errnum(result, "Condition::signal(): pthread_cond_signal failed");
+ }
}
*/
inline void Condition::wait(Mutex* mutex)
{
- int result;
+ wait(*mutex);
+}
- result = pthread_cond_wait(&_cond, &(mutex->_mutex));
- if (result != 0)
- vm_abort_errnum(result, "Condition::wait(): pthread_cond_wait failed");
+/**
+ * Waits for the condition variable.
+ */
+inline void Condition::wait(Mutex& mutex)
+{
+ int result = pthread_cond_wait(&_cond, &(mutex._mutex));
+
+ if (result != 0) {
+ os::abort_errnum(result, "Condition::wait(): pthread_cond_wait failed");
+ }
}
#else
+++ /dev/null
-/* src/threads/posix/lock.c - lock implementation
-
- 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 <stdlib.h>
-#include <sys/time.h>
-#include <pthread.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
-#include "threads/thread.hpp"
-
-#include "threads/posix/lock.h"
-
-#include "toolbox/list.h"
-
-#include "vm/exceptions.hpp"
-#include "vm/finalizer.h"
-#include "vm/global.h"
-#include "vm/options.h"
-#include "vm/string.hpp"
-#include "vm/vm.hpp"
-
-#if defined(ENABLE_STATISTICS)
-# include "vm/statistics.h"
-#endif
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-/* arch.h must be here because it defines USE_FAKE_ATOMIC_INSTRUCTIONS */
-
-#include "arch.h"
-
-/* includes for atomic instructions: */
-
-#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
-#include "threads/posix/generic-primitives.h"
-#else
-#include "threads/atomic.hpp"
-#endif
-
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-#if defined(ENABLE_GC_BOEHM)
-# include "mm/boehm-gc/include/gc.h"
-#endif
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-# define DEBUGLOCKS(format) \
- do { \
- if (opt_DebugLocks) { \
- log_println format; \
- } \
- } while (0)
-#else
-# define DEBUGLOCKS(format)
-#endif
-
-
-/******************************************************************************/
-/* MACROS */
-/******************************************************************************/
-
-/* number of lock records in the first pool allocated for a thread */
-#define LOCK_INITIAL_LOCK_RECORDS 8
-
-#define LOCK_INITIAL_HASHTABLE_SIZE 1613 /* a prime in the middle between 1024 and 2048 */
-
-
-/******************************************************************************/
-/* MACROS FOR THIN/FAT LOCKS */
-/******************************************************************************/
-
-/* We use a variant of the tasuki locks described in the paper
- *
- * Tamiya Onodera, Kiyokuni Kawachiya
- * A Study of Locking Objects with Bimodal Fields
- * Proceedings of the ACM OOPSLA '99, pp. 223-237
- * 1999
- *
- * The underlying thin locks are a variant of the thin locks described in
- *
- * Bacon, Konuru, Murthy, Serrano
- * Thin Locks: Featherweight Synchronization for Java
- * Proceedings of the ACM Conference on Programming Language Design and
- * Implementation (Montreal, Canada), SIGPLAN Notices volume 33, number 6,
- * June 1998
- *
- * In thin lock mode the lockword looks like this:
- *
- * ,----------------------,-----------,---,
- * | thread ID | count | 0 |
- * `----------------------'-----------'---'
- *
- * thread ID......the 'index' of the owning thread, or 0
- * count..........number of times the lock has been entered minus 1
- * 0..............the shape bit is 0 in thin lock mode
- *
- * In fat lock mode it is basically a lock_record_t *:
- *
- * ,----------------------------------,---,
- * | lock_record_t * (without LSB) | 1 |
- * `----------------------------------'---'
- *
- * 1..............the shape bit is 1 in fat lock mode
- */
-
-#if SIZEOF_VOID_P == 8
-#define THIN_LOCK_WORD_SIZE 64
-#else
-#define THIN_LOCK_WORD_SIZE 32
-#endif
-
-#define THIN_LOCK_SHAPE_BIT 0x01
-
-#define THIN_UNLOCKED 0
-
-#define THIN_LOCK_COUNT_SHIFT 1
-#define THIN_LOCK_COUNT_SIZE 8
-#define THIN_LOCK_COUNT_INCR (1 << THIN_LOCK_COUNT_SHIFT)
-#define THIN_LOCK_COUNT_MAX ((1 << THIN_LOCK_COUNT_SIZE) - 1)
-#define THIN_LOCK_COUNT_MASK (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT)
-
-#define THIN_LOCK_TID_SHIFT (THIN_LOCK_COUNT_SIZE + THIN_LOCK_COUNT_SHIFT)
-#define THIN_LOCK_TID_SIZE (THIN_LOCK_WORD_SIZE - THIN_LOCK_TID_SHIFT)
-
-#define IS_THIN_LOCK(lockword) (!((lockword) & THIN_LOCK_SHAPE_BIT))
-#define IS_FAT_LOCK(lockword) ((lockword) & THIN_LOCK_SHAPE_BIT)
-
-#define GET_FAT_LOCK(lockword) ((lock_record_t *) ((lockword) & ~THIN_LOCK_SHAPE_BIT))
-#define MAKE_FAT_LOCK(ptr) ((uintptr_t) (ptr) | THIN_LOCK_SHAPE_BIT)
-
-#define LOCK_WORD_WITHOUT_COUNT(lockword) ((lockword) & ~THIN_LOCK_COUNT_MASK)
-#define GET_THREAD_INDEX(lockword) ((unsigned) lockword >> THIN_LOCK_TID_SHIFT)
-
-
-/* global variables ***********************************************************/
-
-/* hashtable mapping objects to lock records */
-static lock_hashtable_t lock_hashtable;
-
-
-/******************************************************************************/
-/* PROTOTYPES */
-/******************************************************************************/
-
-static void lock_hashtable_init(void);
-
-static inline uintptr_t lock_lockword_get(threadobject *t, java_handle_t *o);
-static inline void lock_lockword_set(threadobject *t, java_handle_t *o, uintptr_t lockword);
-static void lock_record_enter(threadobject *t, lock_record_t *lr);
-static void lock_record_exit(threadobject *t, lock_record_t *lr);
-static bool lock_record_wait(threadobject *t, lock_record_t *lr, s8 millis, s4 nanos);
-static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one);
-
-
-/*============================================================================*/
-/* INITIALIZATION OF DATA STRUCTURES */
-/*============================================================================*/
-
-
-/* lock_init *******************************************************************
-
- Initialize global data for locking.
-
-*******************************************************************************/
-
-void lock_init(void)
-{
- /* initialize lock hashtable */
-
- lock_hashtable_init();
-
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_init_lock();
-#endif
-}
-
-
-/* lock_pre_compute_thinlock ***************************************************
-
- Pre-compute the thin lock value for a thread index.
-
- IN:
- index........the thead index (>= 1)
-
- RETURN VALUE:
- the thin lock value for this thread index
-
-*******************************************************************************/
-
-ptrint lock_pre_compute_thinlock(s4 index)
-{
- return (index << THIN_LOCK_TID_SHIFT) | THIN_UNLOCKED;
-}
-
-
-/* lock_record_new *************************************************************
-
- Allocate a lock record.
-
-*******************************************************************************/
-
-static lock_record_t *lock_record_new(void)
-{
- lock_record_t *lr;
-
- /* allocate the data structure on the C heap */
-
- lr = NEW(lock_record_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lock_record += sizeof(lock_record_t);
-#endif
-
- /* initialize the members */
-
- lr->object = NULL;
- lr->owner = NULL;
- lr->count = 0;
- lr->waiters = list_create(OFFSET(lock_waiter_t, linkage));
-
-#if defined(ENABLE_GC_CACAO)
- /* register the lock object as weak reference with the GC */
-
- gc_weakreference_register(&(lr->object), GC_REFTYPE_LOCKRECORD);
-#endif
-
- /* initialize the mutex */
-
- lr->mutex = Mutex_new();
-
- DEBUGLOCKS(("[lock_record_new : lr=%p]", (void *) lr));
-
- return lr;
-}
-
-
-/* lock_record_free ************************************************************
-
- Free a lock record.
-
- IN:
- lr....lock record to free
-
-*******************************************************************************/
-
-static void lock_record_free(lock_record_t *lr)
-{
- DEBUGLOCKS(("[lock_record_free : lr=%p]", (void *) lr));
-
- /* Destroy the mutex. */
-
- Mutex_delete(lr->mutex);
-
-#if defined(ENABLE_GC_CACAO)
- /* unregister the lock object reference with the GC */
-
- gc_weakreference_unregister(&(lr->object));
-#endif
-
- /* Free the waiters list. */
-
- list_free(lr->waiters);
-
- /* Free the data structure. */
-
- FREE(lr, lock_record_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lock_record -= sizeof(lock_record_t);
-#endif
-}
-
-
-/*============================================================================*/
-/* HASHTABLE MAPPING OBJECTS TO LOCK RECORDS */
-/*============================================================================*/
-
-/* lock_hashtable_init *********************************************************
-
- Initialize the global hashtable mapping objects to lock records.
-
-*******************************************************************************/
-
-static void lock_hashtable_init(void)
-{
- lock_hashtable.mutex = Mutex_new();
-
- lock_hashtable.size = LOCK_INITIAL_HASHTABLE_SIZE;
- lock_hashtable.entries = 0;
- lock_hashtable.ptr = MNEW(lock_record_t *, lock_hashtable.size);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lock_hashtable += sizeof(lock_record_t *) * lock_hashtable.size;
-#endif
-
- MZERO(lock_hashtable.ptr, lock_record_t *, lock_hashtable.size);
-}
-
-
-/* lock_hashtable_grow *********************************************************
-
- Grow the lock record hashtable to about twice its current size and
- rehash the entries.
-
-*******************************************************************************/
-
-/* must be called with hashtable mutex locked */
-static void lock_hashtable_grow(void)
-{
- u4 oldsize;
- u4 newsize;
- lock_record_t **oldtable;
- lock_record_t **newtable;
- lock_record_t *lr;
- lock_record_t *next;
- u4 i;
- u4 h;
- u4 newslot;
-
- /* allocate a new table */
-
- oldsize = lock_hashtable.size;
- newsize = oldsize*2 + 1; /* XXX should use prime numbers */
-
- DEBUGLOCKS(("growing lock hashtable to size %d", newsize));
-
- oldtable = lock_hashtable.ptr;
- newtable = MNEW(lock_record_t *, newsize);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lock_hashtable += sizeof(lock_record_t *) * newsize;
-#endif
-
- MZERO(newtable, lock_record_t *, newsize);
-
- /* rehash the entries */
-
- for (i = 0; i < oldsize; i++) {
- lr = oldtable[i];
- while (lr) {
- next = lr->hashlink;
-
- h = heap_hashcode(lr->object);
- newslot = h % newsize;
-
- lr->hashlink = newtable[newslot];
- newtable[newslot] = lr;
-
- lr = next;
- }
- }
-
- /* replace the old table */
-
- lock_hashtable.ptr = newtable;
- lock_hashtable.size = newsize;
-
- MFREE(oldtable, lock_record_t *, oldsize);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lock_hashtable -= sizeof(lock_record_t *) * oldsize;
-#endif
-}
-
-
-/* lock_hashtable_cleanup ******************************************************
-
- Removes (and frees) lock records which have a cleared object reference
- from the hashtable. The locked object was reclaimed by the GC.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void lock_hashtable_cleanup(void)
-{
- threadobject *t;
- lock_record_t *lr;
- lock_record_t *prev;
- lock_record_t *next;
- int i;
-
- t = THREADOBJECT;
-
- /* lock the hashtable */
-
- Mutex_lock(lock_hashtable.mutex);
-
- /* search the hashtable for cleared references */
-
- for (i = 0; i < lock_hashtable.size; i++) {
- lr = lock_hashtable.ptr[i];
- prev = NULL;
-
- while (lr) {
- next = lr->hashlink;
-
- /* remove lock records with cleared references */
-
- if (lr->object == NULL) {
-
- /* unlink the lock record from the hashtable */
-
- if (prev == NULL)
- lock_hashtable.ptr[i] = next;
- else
- prev->hashlink = next;
-
- /* free the lock record */
-
- lock_record_free(lr);
-
- } else {
- prev = lr;
- }
-
- lr = next;
- }
- }
-
- /* unlock the hashtable */
-
- Mutex_unlock(lock_hashtable.mutex);
-}
-#endif
-
-
-/* lock_hashtable_get **********************************************************
-
- Find the lock record for the given object. If it does not exists,
- yet, create it and enter it in the hashtable.
-
- IN:
- t....the current thread
- o....the object to look up
-
- RETURN VALUE:
- the lock record to use for this object
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_BOEHM)
-static void lock_record_finalizer(void *object, void *p);
-#endif
-
-static lock_record_t *lock_hashtable_get(threadobject *t, java_handle_t *o)
-{
- uintptr_t lockword;
- u4 slot;
- lock_record_t *lr;
-
- lockword = lock_lockword_get(t, o);
-
- if (IS_FAT_LOCK(lockword))
- return GET_FAT_LOCK(lockword);
-
- /* lock the hashtable */
-
- Mutex_lock(lock_hashtable.mutex);
-
- /* lookup the lock record in the hashtable */
-
- LLNI_CRITICAL_START_THREAD(t);
- slot = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
- lr = lock_hashtable.ptr[slot];
-
- for (; lr != NULL; lr = lr->hashlink) {
- if (lr->object == LLNI_DIRECT(o))
- break;
- }
- LLNI_CRITICAL_END_THREAD(t);
-
- if (lr == NULL) {
- /* not found, we must create a new one */
-
- lr = lock_record_new();
-
- LLNI_CRITICAL_START_THREAD(t);
- lr->object = LLNI_DIRECT(o);
- LLNI_CRITICAL_END_THREAD(t);
-
-#if defined(ENABLE_GC_BOEHM)
- /* register new finalizer to clean up the lock record */
-
- GC_REGISTER_FINALIZER(LLNI_DIRECT(o), lock_record_finalizer, 0, 0, 0);
-#endif
-
- /* enter it in the hashtable */
-
- lr->hashlink = lock_hashtable.ptr[slot];
- lock_hashtable.ptr[slot] = lr;
- lock_hashtable.entries++;
-
- /* check whether the hash should grow */
-
- if (lock_hashtable.entries * 3 > lock_hashtable.size * 4) {
- lock_hashtable_grow();
- }
- }
-
- /* unlock the hashtable */
-
- Mutex_unlock(lock_hashtable.mutex);
-
- /* return the new lock record */
-
- return lr;
-}
-
-
-/* lock_hashtable_remove *******************************************************
-
- Remove the lock record for the given object from the hashtable
- and free it afterwards.
-
- IN:
- t....the current thread
- o....the object to look up
-
-*******************************************************************************/
-
-static void lock_hashtable_remove(threadobject *t, java_handle_t *o)
-{
- uintptr_t lockword;
- lock_record_t *lr;
- u4 slot;
- lock_record_t *tmplr;
-
- /* lock the hashtable */
-
- Mutex_lock(lock_hashtable.mutex);
-
- /* get lock record */
-
- lockword = lock_lockword_get(t, o);
-
- assert(IS_FAT_LOCK(lockword));
-
- lr = GET_FAT_LOCK(lockword);
-
- /* remove the lock-record from the hashtable */
-
- LLNI_CRITICAL_START_THREAD(t);
- slot = heap_hashcode(LLNI_DIRECT(o)) % lock_hashtable.size;
- tmplr = lock_hashtable.ptr[slot];
- LLNI_CRITICAL_END_THREAD(t);
-
- if (tmplr == lr) {
- /* special handling if it's the first in the chain */
-
- lock_hashtable.ptr[slot] = lr->hashlink;
- }
- else {
- for (; tmplr != NULL; tmplr = tmplr->hashlink) {
- if (tmplr->hashlink == lr) {
- tmplr->hashlink = lr->hashlink;
- break;
- }
- }
-
- assert(tmplr != NULL);
- }
-
- /* decrease entry count */
-
- lock_hashtable.entries--;
-
- /* unlock the hashtable */
-
- Mutex_unlock(lock_hashtable.mutex);
-
- /* free the lock record */
-
- lock_record_free(lr);
-}
-
-
-/* lock_record_finalizer *******************************************************
-
- XXX Remove me for exact GC.
-
-*******************************************************************************/
-
-static void lock_record_finalizer(void *object, void *p)
-{
- java_handle_t *o;
- classinfo *c;
-
- o = (java_handle_t *) object;
-
-#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_class_get(o, c);
-
-#if !defined(NDEBUG)
- if (opt_DebugFinalizer) {
- log_start();
- log_print("[finalizer lockrecord: o=%p p=%p class=", object, p);
- class_print(c);
- log_print("]");
- log_finish();
- }
-#endif
-
- /* check for a finalizer function */
-
- if (c->finalizer != NULL)
- finalizer_run(object, p);
-
- /* remove the lock-record entry from the hashtable and free it */
-
- lock_hashtable_remove(THREADOBJECT, o);
-}
-
-
-/*============================================================================*/
-/* OBJECT LOCK INITIALIZATION */
-/*============================================================================*/
-
-
-/* lock_init_object_lock *******************************************************
-
- Initialize the monitor pointer of the given object. The monitor gets
- initialized to an unlocked state.
-
-*******************************************************************************/
-
-void lock_init_object_lock(java_object_t *o)
-{
- assert(o);
-
- o->lockword = THIN_UNLOCKED;
-}
-
-
-/*============================================================================*/
-/* LOCKING ALGORITHM */
-/*============================================================================*/
-
-
-/* lock_lockword_get ***********************************************************
-
- Get the lockword for the given object.
-
- IN:
- t............the current thread
- o............the object
-
-*******************************************************************************/
-
-static inline uintptr_t lock_lockword_get(threadobject *t, java_handle_t *o)
-{
- uintptr_t lockword;
-
- LLNI_CRITICAL_START_THREAD(t);
- lockword = LLNI_DIRECT(o)->lockword;
- LLNI_CRITICAL_END_THREAD(t);
-
- return lockword;
-}
-
-
-/* lock_lockword_set ***********************************************************
-
- Set the lockword for the given object.
-
- IN:
- t............the current thread
- o............the object
- lockword.....the new lockword value
-
-*******************************************************************************/
-
-static inline void lock_lockword_set(threadobject *t, java_handle_t *o, uintptr_t lockword)
-{
- LLNI_CRITICAL_START_THREAD(t);
- LLNI_DIRECT(o)->lockword = lockword;
- LLNI_CRITICAL_END_THREAD(t);
-}
-
-
-/* lock_record_enter ***********************************************************
-
- Enter the lock represented by the given lock record.
-
- IN:
- t.................the current thread
- lr................the lock record
-
-*******************************************************************************/
-
-static inline void lock_record_enter(threadobject *t, lock_record_t *lr)
-{
- Mutex_lock(lr->mutex);
- lr->owner = t;
-}
-
-
-/* lock_record_exit ************************************************************
-
- Release the lock represented by the given lock record.
-
- IN:
- t.................the current thread
- lr................the lock record
-
- PRE-CONDITION:
- The current thread must own the lock represented by this lock record.
- This is NOT checked by this function!
-
-*******************************************************************************/
-
-static inline void lock_record_exit(threadobject *t, lock_record_t *lr)
-{
- lr->owner = NULL;
- Mutex_unlock(lr->mutex);
-}
-
-
-/* lock_inflate ****************************************************************
-
- Inflate the lock of the given object. This may only be called by the
- owner of the monitor of the object.
-
- IN:
- t............the current thread
- o............the object of which to inflate the lock
- lr...........the lock record to install. The current thread must
- own the lock of this lock record!
-
- PRE-CONDITION:
- The current thread must be the owner of this object's monitor AND
- of the lock record's lock!
-
-*******************************************************************************/
-
-static void lock_inflate(threadobject *t, java_handle_t *o, lock_record_t *lr)
-{
- uintptr_t lockword;
-
- /* get the current lock count */
-
- lockword = lock_lockword_get(t, o);
-
- if (IS_FAT_LOCK(lockword)) {
- assert(GET_FAT_LOCK(lockword) == lr);
- return;
- }
- else {
- assert(LOCK_WORD_WITHOUT_COUNT(lockword) == t->thinlock);
-
- /* copy the count from the thin lock */
-
- lr->count = (lockword & THIN_LOCK_COUNT_MASK) >> THIN_LOCK_COUNT_SHIFT;
- }
-
- DEBUGLOCKS(("[lock_inflate : lr=%p, t=%p, o=%p, o->lockword=%lx, count=%d]",
- lr, t, o, lockword, lr->count));
-
- /* install it */
-
- lock_lockword_set(t, o, MAKE_FAT_LOCK(lr));
-}
-
-
-/* TODO Move this function into threadlist.[ch]. */
-
-static threadobject *threads_lookup_thread_id(int index)
-{
- threadobject *t;
-
- threadlist_lock();
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- if (t->state == THREAD_STATE_NEW)
- continue;
- if (t->index == index)
- break;
- }
-
- threadlist_unlock();
- return t;
-}
-
-static void sable_flc_waiting(ptrint lockword, threadobject *t, java_handle_t *o)
-{
- int index;
- threadobject *t_other;
- int old_flc;
-
- index = GET_THREAD_INDEX(lockword);
- t_other = threads_lookup_thread_id(index);
- if (!t_other)
-/* failure, TODO: add statistics */
- return;
-
- Mutex_lock(t_other->flc_lock);
- old_flc = t_other->flc_bit;
- t_other->flc_bit = true;
-
- DEBUGLOCKS(("thread %d set flc bit for lock-holding thread %d",
- t->index, t_other->index));
-
- /* Set FLC bit first, then read the lockword again */
- Atomic_memory_barrier();
-
- lockword = lock_lockword_get(t, o);
-
- /* Lockword is still the way it was seen before */
- if (IS_THIN_LOCK(lockword) && (GET_THREAD_INDEX(lockword) == index))
- {
- /* Add tuple (t, o) to the other thread's FLC list */
- t->flc_object = o;
- t->flc_next = t_other->flc_list;
- t_other->flc_list = t;
-
- for (;;)
- {
- threadobject *current;
-
- /* Wait until another thread sees the flc bit and notifies
- us of unlocking. */
- Condition_wait(t->flc_cond, t_other->flc_lock);
-
- /* Traverse FLC list looking if we're still there */
- current = t_other->flc_list;
- while (current && current != t)
- current = current->flc_next;
- if (!current)
- /* not in list anymore, can stop waiting */
- break;
-
- /* We are still in the list -- the other thread cannot have seen
- the FLC bit yet */
- assert(t_other->flc_bit);
- }
-
- t->flc_object = NULL; /* for garbage collector? */
- t->flc_next = NULL;
- }
- else
- t_other->flc_bit = old_flc;
-
- Mutex_unlock(t_other->flc_lock);
-}
-
-static void notify_flc_waiters(threadobject *t, java_handle_t *o)
-{
- threadobject *current;
-
- Mutex_lock(t->flc_lock);
-
- current = t->flc_list;
- while (current)
- {
- if (current->flc_object != o)
- {
- /* The object has to be inflated so the other threads can properly
- block on it. */
-
- /* Only if not already inflated */
- ptrint lockword = lock_lockword_get(t, current->flc_object);
- if (IS_THIN_LOCK(lockword)) {
- lock_record_t *lr = lock_hashtable_get(t, current->flc_object);
- lock_record_enter(t, lr);
-
- DEBUGLOCKS(("thread %d inflating lock of %p to lr %p",
- t->index, (void*) current->flc_object, (void*) lr));
-
- lock_inflate(t, current->flc_object, lr);
- }
- }
- /* Wake the waiting thread */
- Condition_broadcast(current->flc_cond);
-
- current = current->flc_next;
- }
-
- t->flc_list = NULL;
- t->flc_bit = false;
- Mutex_unlock(t->flc_lock);
-}
-
-/* lock_monitor_enter **********************************************************
-
- Acquire the monitor of the given object. If the current thread already
- owns the monitor, the lock counter is simply increased.
-
- This function blocks until it can acquire the monitor.
-
- IN:
- t............the current thread
- o............the object of which to enter the monitor
-
- RETURN VALUE:
- true.........the lock has been successfully acquired
- false........an exception has been thrown
-
-*******************************************************************************/
-
-bool lock_monitor_enter(java_handle_t *o)
-{
- threadobject *t;
- /* CAUTION: This code assumes that ptrint is unsigned! */
- ptrint lockword;
- ptrint thinlock;
- lock_record_t *lr;
-
- if (o == NULL) {
- exceptions_throw_nullpointerexception();
- return false;
- }
-
- t = THREADOBJECT;
-
- thinlock = t->thinlock;
-
-retry:
- /* most common case: try to thin-lock an unlocked object */
-
- LLNI_CRITICAL_START_THREAD(t);
- 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 */
- Atomic_instruction_barrier();
- return true;
- }
-
- /* next common case: recursive lock with small recursion count */
- /* We don't have to worry about stale values here, as any stale value */
- /* will indicate another thread holding the lock (or an inflated lock) */
-
- if (LOCK_WORD_WITHOUT_COUNT(lockword) == thinlock) {
- /* we own this monitor */
- /* check the current recursion count */
-
- if ((lockword ^ thinlock) < (THIN_LOCK_COUNT_MAX << THIN_LOCK_COUNT_SHIFT))
- {
- /* the recursion count is low enough */
-
- lock_lockword_set(t, o, lockword + THIN_LOCK_COUNT_INCR);
-
- /* success. we locked it */
- return true;
- }
- else {
- /* recursion count overflow */
-
- lr = lock_hashtable_get(t, o);
- lock_record_enter(t, lr);
- lock_inflate(t, o, lr);
- lr->count++;
-
- notify_flc_waiters(t, o);
-
- return true;
- }
- }
-
- /* the lock is either contented or fat */
-
- if (IS_FAT_LOCK(lockword)) {
-
- lr = GET_FAT_LOCK(lockword);
-
- /* check for recursive entering */
- if (lr->owner == t) {
- lr->count++;
- return true;
- }
-
- /* acquire the mutex of the lock record */
-
- lock_record_enter(t, lr);
-
- assert(lr->count == 0);
-
- return true;
- }
-
- /****** inflation path ******/
-
-#if defined(ENABLE_JVMTI)
- /* Monitor Contended Enter */
- jvmti_MonitorContendedEntering(false, o);
-#endif
-
- sable_flc_waiting(lockword, t, o);
-
-#if defined(ENABLE_JVMTI)
- /* Monitor Contended Entered */
- jvmti_MonitorContendedEntering(true, o);
-#endif
- goto retry;
-}
-
-
-/* lock_monitor_exit ***********************************************************
-
- Decrement the counter of a (currently owned) monitor. If the counter
- reaches zero, release the monitor.
-
- If the current thread is not the owner of the monitor, an
- IllegalMonitorState exception is thrown.
-
- IN:
- t............the current thread
- o............the object of which to exit the monitor
-
- RETURN VALUE:
- true.........everything ok,
- false........an exception has been thrown
-
-*******************************************************************************/
-
-bool lock_monitor_exit(java_handle_t *o)
-{
- threadobject *t;
- uintptr_t lockword;
- ptrint thinlock;
-
- if (o == NULL) {
- exceptions_throw_nullpointerexception();
- return false;
- }
-
- t = THREADOBJECT;
-
- thinlock = t->thinlock;
-
- /* We don't have to worry about stale values here, as any stale value */
- /* will indicate that we don't own the lock. */
-
- lockword = lock_lockword_get(t, o);
-
- /* most common case: we release a thin lock that we hold once */
-
- if (lockword == thinlock) {
- /* memory barrier for Java Memory Model */
- Atomic_write_memory_barrier();
- lock_lockword_set(t, o, THIN_UNLOCKED);
- /* Memory barrier for thin locking. */
- Atomic_memory_barrier();
-
- /* check if there has been a flat lock contention on this object */
-
- if (t->flc_bit) {
- DEBUGLOCKS(("thread %d saw flc bit", t->index));
-
- /* there has been a contention on this thin lock */
- notify_flc_waiters(t, o);
- }
-
- return true;
- }
-
- /* next common case: we release a recursive lock, count > 0 */
-
- if (LOCK_WORD_WITHOUT_COUNT(lockword) == thinlock) {
- lock_lockword_set(t, o, lockword - THIN_LOCK_COUNT_INCR);
- return true;
- }
-
- /* either the lock is fat, or we don't hold it at all */
-
- if (IS_FAT_LOCK(lockword)) {
-
- lock_record_t *lr;
-
- lr = GET_FAT_LOCK(lockword);
-
- /* check if we own this monitor */
- /* We don't have to worry about stale values here, as any stale value */
- /* will be != t and thus fail this check. */
-
- if (lr->owner != t) {
- exceptions_throw_illegalmonitorstateexception();
- return false;
- }
-
- /* { the current thread `t` owns the lock record `lr` on object `o` } */
-
- if (lr->count != 0) {
- /* we had locked this one recursively. just decrement, it will */
- /* still be locked. */
- lr->count--;
- return true;
- }
-
- /* unlock this lock record */
-
- lr->owner = NULL;
- Mutex_unlock(lr->mutex);
-
- return true;
- }
-
- /* legal thin lock cases have been handled above, so this is an error */
-
- exceptions_throw_illegalmonitorstateexception();
-
- return false;
-}
-
-
-/* lock_record_add_waiter ******************************************************
-
- Add a thread to the list of waiting threads of a lock record.
-
- IN:
- lr...........the lock record
- thread.......the thread to add
-
-*******************************************************************************/
-
-static void lock_record_add_waiter(lock_record_t *lr, threadobject *thread)
-{
- lock_waiter_t *w;
-
- /* Allocate a waiter data structure. */
-
- w = NEW(lock_waiter_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lock_waiter += sizeof(lock_waiter_t);
-#endif
-
- /* Store the thread in the waiter structure. */
-
- w->thread = thread;
-
- /* Add the waiter as last entry to waiters list. */
-
- list_add_last(lr->waiters, w);
-}
-
-
-/* lock_record_remove_waiter ***************************************************
-
- Remove a thread from the list of waiting threads of a lock record.
-
- IN:
- lr...........the lock record
- t............the current thread
-
- PRE-CONDITION:
- The current thread must be the owner of the lock record.
-
-*******************************************************************************/
-
-static void lock_record_remove_waiter(lock_record_t *lr, threadobject *thread)
-{
- list_t *l;
- lock_waiter_t *w;
-
- /* Get the waiters list. */
-
- l = lr->waiters;
-
- for (w = list_first(l); w != NULL; w = list_next(l, w)) {
- if (w->thread == thread) {
- /* Remove the waiter entry from the list. */
-
- list_remove(l, w);
-
- /* Free the waiter data structure. */
-
- FREE(w, lock_waiter_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lock_waiter -= sizeof(lock_waiter_t);
-#endif
-
- return;
- }
- }
-
- /* This should never happen. */
-
- vm_abort("lock_record_remove_waiter: thread not found in list of waiters\n");
-}
-
-
-/* lock_record_wait ************************************************************
-
- Wait on a lock record for a given (maximum) amount of time.
-
- IN:
- t............the current thread
- lr...........the lock record
- millis.......milliseconds of timeout
- nanos........nanoseconds of timeout
-
- RETURN VALUE:
- true.........we have been interrupted,
- false........everything ok
-
- PRE-CONDITION:
- The current thread must be the owner of the lock record.
- This is NOT checked by this function!
-
-*******************************************************************************/
-
-static bool lock_record_wait(threadobject *thread, lock_record_t *lr, s8 millis, s4 nanos)
-{
- s4 lockcount;
- bool wasinterrupted = false;
-
- DEBUGLOCKS(("[lock_record_wait : lr=%p, t=%p, millis=%lld, nanos=%d]",
- lr, thread, millis, nanos));
-
- /* { the thread t owns the fat lock record lr on the object o } */
-
- /* register us as waiter for this object */
-
- lock_record_add_waiter(lr, thread);
-
- /* remember the old lock count */
-
- lockcount = lr->count;
-
- /* unlock this record */
-
- lr->count = 0;
- lock_record_exit(thread, lr);
-
- /* wait until notified/interrupted/timed out */
-
- threads_wait_with_timeout_relative(thread, millis, nanos);
-
- /* re-enter the monitor */
-
- lock_record_enter(thread, lr);
-
- /* remove us from the list of waiting threads */
-
- lock_record_remove_waiter(lr, thread);
-
- /* restore the old lock count */
-
- lr->count = lockcount;
-
- /* We can only be signaled OR interrupted, not both. If both flags
- are set, reset only signaled and leave the thread in
- interrupted state. Otherwise, clear both. */
-
- if (!thread->signaled) {
- wasinterrupted = thread->interrupted;
- thread->interrupted = false;
- }
-
- thread->signaled = false;
-
- /* return if we have been interrupted */
-
- return wasinterrupted;
-}
-
-
-/* lock_monitor_wait ***********************************************************
-
- Wait on an object for a given (maximum) amount of time.
-
- IN:
- t............the current thread
- o............the object
- millis.......milliseconds of timeout
- nanos........nanoseconds of timeout
-
- PRE-CONDITION:
- The current thread must be the owner of the object's monitor.
-
-*******************************************************************************/
-
-static void lock_monitor_wait(threadobject *t, java_handle_t *o, s8 millis, s4 nanos)
-{
- uintptr_t lockword;
- lock_record_t *lr;
-
- lockword = lock_lockword_get(t, o);
-
- /* check if we own this monitor */
- /* We don't have to worry about stale values here, as any stale value */
- /* will fail this check. */
-
- if (IS_FAT_LOCK(lockword)) {
-
- lr = GET_FAT_LOCK(lockword);
-
- if (lr->owner != t) {
- exceptions_throw_illegalmonitorstateexception();
- return;
- }
- }
- else {
- /* it's a thin lock */
-
- if (LOCK_WORD_WITHOUT_COUNT(lockword) != t->thinlock) {
- exceptions_throw_illegalmonitorstateexception();
- return;
- }
-
- /* inflate this lock */
-
- lr = lock_hashtable_get(t, o);
- lock_record_enter(t, lr);
- lock_inflate(t, o, lr);
-
- notify_flc_waiters(t, o);
- }
-
- /* { the thread t owns the fat lock record lr on the object o } */
-
- if (lock_record_wait(t, lr, millis, nanos))
- exceptions_throw_interruptedexception();
-}
-
-
-/* lock_record_notify **********************************************************
-
- Notify one thread or all threads waiting on the given lock record.
-
- IN:
- t............the current thread
- lr...........the lock record
- one..........if true, only notify one thread
-
- PRE-CONDITION:
- The current thread must be the owner of the lock record.
- This is NOT checked by this function!
-
-*******************************************************************************/
-
-static void lock_record_notify(threadobject *t, lock_record_t *lr, bool one)
-{
- list_t *l;
- lock_waiter_t *w;
- threadobject *waitingthread;
-
- /* { the thread t owns the fat lock record lr on the object o } */
-
- /* Get the waiters list. */
-
- l = lr->waiters;
-
- for (w = list_first(l); w != NULL; w = list_next(l, w)) {
- /* signal the waiting thread */
-
- waitingthread = w->thread;
-
- /* We must skip threads which have already been notified. They will
- remove themselves from the list. */
-
- if (waitingthread->signaled)
- continue;
-
- /* Enter the wait-mutex. */
-
- Mutex_lock(waitingthread->waitmutex);
-
- DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, one=%d]",
- lr, t, waitingthread, one));
-
- Condition_signal(waitingthread->waitcond);
-
- /* Mark the thread as signaled. */
-
- waitingthread->signaled = true;
-
- /* Leave the wait-mutex. */
-
- Mutex_unlock(waitingthread->waitmutex);
-
- /* if we should only wake one, we are done */
-
- if (one)
- break;
- }
-}
-
-
-/* lock_monitor_notify *********************************************************
-
- Notify one thread or all threads waiting on the given object.
-
- IN:
- t............the current thread
- o............the object
- one..........if true, only notify one thread
-
- PRE-CONDITION:
- The current thread must be the owner of the object's monitor.
-
-*******************************************************************************/
-
-static void lock_monitor_notify(threadobject *t, java_handle_t *o, bool one)
-{
- uintptr_t lockword;
- lock_record_t *lr;
-
- lockword = lock_lockword_get(t, o);
-
- /* check if we own this monitor */
- /* We don't have to worry about stale values here, as any stale value */
- /* will fail this check. */
-
- if (IS_FAT_LOCK(lockword)) {
-
- lr = GET_FAT_LOCK(lockword);
-
- if (lr->owner != t) {
- exceptions_throw_illegalmonitorstateexception();
- return;
- }
- }
- else {
- /* it's a thin lock */
-
- if (LOCK_WORD_WITHOUT_COUNT(lockword) != t->thinlock) {
- exceptions_throw_illegalmonitorstateexception();
- return;
- }
-
- /* no thread can wait on a thin lock, so there's nothing to do. */
- return;
- }
-
- /* { the thread t owns the fat lock record lr on the object o } */
-
- lock_record_notify(t, lr, one);
-}
-
-
-
-/*============================================================================*/
-/* INQUIRY FUNCIONS */
-/*============================================================================*/
-
-
-/* lock_is_held_by_current_thread **********************************************
-
- Return true if the current thread owns the monitor of the given object.
-
- IN:
- o............the object
-
- RETURN VALUE:
- true, if the current thread holds the lock of this object.
-
-*******************************************************************************/
-
-bool lock_is_held_by_current_thread(java_handle_t *o)
-{
- threadobject *t;
- uintptr_t lockword;
- lock_record_t *lr;
-
- t = THREADOBJECT;
-
- /* check if we own this monitor */
- /* We don't have to worry about stale values here, as any stale value */
- /* will fail this check. */
-
- lockword = lock_lockword_get(t, o);
-
- if (IS_FAT_LOCK(lockword)) {
- /* it's a fat lock */
-
- lr = GET_FAT_LOCK(lockword);
-
- return (lr->owner == t);
- }
- else {
- /* it's a thin lock */
-
- return (LOCK_WORD_WITHOUT_COUNT(lockword) == t->thinlock);
- }
-}
-
-
-
-/*============================================================================*/
-/* WRAPPERS FOR OPERATIONS ON THE CURRENT THREAD */
-/*============================================================================*/
-
-
-/* lock_wait_for_object ********************************************************
-
- Wait for the given object.
-
- IN:
- o............the object
- millis.......milliseconds to wait
- nanos........nanoseconds to wait
-
-*******************************************************************************/
-
-void lock_wait_for_object(java_handle_t *o, s8 millis, s4 nanos)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- lock_monitor_wait(thread, o, millis, nanos);
-}
-
-
-/* lock_notify_object **********************************************************
-
- Notify one thread waiting on the given object.
-
- IN:
- o............the object
-
-*******************************************************************************/
-
-void lock_notify_object(java_handle_t *o)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- lock_monitor_notify(thread, o, true);
-}
-
-
-/* lock_notify_all_object ******************************************************
-
- Notify all threads waiting on the given object.
-
- IN:
- o............the object
-
-*******************************************************************************/
-
-void lock_notify_all_object(java_handle_t *o)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- lock_monitor_notify(thread, o, false);
-}
-
-
-/*
- * These 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/lock.h - lock implementation
-
- 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 _LOCK_H
-#define _LOCK_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <pthread.h>
-
-#include "vm/types.h"
-
-#include "native/llni.h"
-
-#include "threads/mutex.hpp"
-
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-
-
-
-/* typedefs *******************************************************************/
-
-typedef struct lock_record_t lock_record_t;
-typedef struct lock_waiter_t lock_waiter_t;
-typedef struct lock_hashtable_t lock_hashtable_t;
-
-
-/* lock_waiter_t ***************************************************************
-
- List node for storing a waiting thread.
-
-*******************************************************************************/
-
-struct lock_waiter_t {
- struct threadobject *thread; /* the waiting thread */
- listnode_t linkage;
-};
-
-
-/* lock_record_t ***************************************************************
-
- Lock record struct representing an inflated ("fat") lock.
-
-*******************************************************************************/
-
-struct lock_record_t {
- java_object_t *object; /* object for which this lock is */
- struct threadobject *owner; /* current owner of this monitor */
- s4 count; /* recursive lock count */
- Mutex* mutex; /* mutex for synchronizing */
- list_t *waiters; /* list of threads waiting */
- lock_record_t *hashlink; /* next record in hash chain */
-};
-
-
-/* lock_hashtable_t ************************************************************
-
- The global hashtable mapping objects to lock records.
-
-*******************************************************************************/
-
-struct lock_hashtable_t {
- 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. */
-};
-
-
-/* defines ********************************************************************/
-
-#define LOCK_INIT_OBJECT_LOCK(o) lock_init_object_lock((java_object_t *) (o))
-
-#define LOCK_MONITOR_ENTER(o) lock_monitor_enter((java_handle_t *) LLNI_QUICKWRAP(o))
-#define LOCK_MONITOR_EXIT(o) lock_monitor_exit((java_handle_t *) LLNI_QUICKWRAP(o))
-
-#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 */
-
-
-/*
- * These 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:
- */
Copyright (C) 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include <pthread.h>
-#include "vm/vm.hpp"
#ifdef __cplusplus
class Mutex {
private:
// POSIX mutex structure.
- pthread_mutex_t _mutex;
+ pthread_mutex_t _mutex;
+ pthread_mutexattr_t _attr;
// Condition class needs to access _mutex for wait() and
// timedwait().
friend class Condition;
public:
- Mutex();
- ~Mutex();
+ inline Mutex();
+ inline ~Mutex();
- void lock();
- void unlock();
+ inline void lock();
+ inline void unlock();
};
+#else
+
+// Forward typedefs
+typedef struct Mutex Mutex;
+
+#endif
-/* static mutex initializer ***************************************************/
-#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+// Includes.
+#include "vm/os.hpp"
+#ifdef __cplusplus
+
/**
* Initializes the given mutex object and checks for errors.
*/
inline Mutex::Mutex()
{
- int result;
+ int result = pthread_mutexattr_init(&_attr);
+
+ if (result != 0) {
+ os::abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_init failed");
+ }
- result = pthread_mutex_init(&_mutex, NULL);
+ result = pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
- if (result != 0)
- vm_abort_errnum(result, "Mutex::Mutex(): pthread_mutex_init failed");
+ if (result != 0) {
+ os::abort_errnum(result, "Mutex::Mutex(): pthread_mutexattr_settype failed");
+ }
+
+ result = pthread_mutex_init(&_mutex, &_attr);
+
+ if (result != 0) {
+ os::abort_errnum(result, "Mutex::Mutex(): pthread_mutex_init failed");
+ }
}
*/
inline Mutex::~Mutex()
{
- int result;
+ int result = pthread_mutexattr_destroy(&_attr);
+
+ if (result != 0) {
+ os::abort_errnum(result, "Mutex::~Mutex(): pthread_mutexattr_destroy failed");
+ }
result = pthread_mutex_destroy(&_mutex);
- if (result != 0)
- vm_abort_errnum(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
+ if (result != 0) {
+ os::abort_errnum(result, "Mutex::~Mutex(): pthread_mutex_destroy failed");
+ }
}
*/
inline void Mutex::lock()
{
- int result;
+ int result = pthread_mutex_lock(&_mutex);
- result = pthread_mutex_lock(&_mutex);
-
- if (result != 0)
- vm_abort_errnum(result, "Mutex::lock(): pthread_mutex_lock failed");
+ if (result != 0) {
+ os::abort_errnum(result, "Mutex::lock(): pthread_mutex_lock failed");
+ }
}
*/
inline void Mutex::unlock()
{
- int result;
-
- result = pthread_mutex_unlock(&_mutex);
+ int result = pthread_mutex_unlock(&_mutex);
- if (result != 0)
- vm_abort_errnum(result, "Mutex::unlock: pthread_mutex_unlock failed");
+ if (result != 0) {
+ os::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;
+struct Mutex {
+ pthread_mutex_t _mutex;
+ pthread_mutexattr_t _attr;
+};
Mutex* Mutex_new();
void Mutex_delete(Mutex* mutex);
# include "mm/cacao-gc/gc.h"
#endif
-#include "native/jni.h"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
#include "threads/condition.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#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. */
#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
t->es = NULL;
#endif
- MZERO(&t->dumpinfo, dumpinfo_t, 1);
+ // Simply reuse the existing dump memory.
}
/* threads_impl_thread_reuse ***************************************************
compare against 1 because the current (main thread) is also a
non-daemon thread. */
- while (threadlist_get_non_daemons() > 1)
+ while (ThreadList::get_number_of_non_daemon_threads() > 1)
cond_join->wait(mutex_join);
/* leave join mutex */
#endif
-} // extern "C"
-
/*
* These are local overrides for various environment variables in Emacs.
#ifndef _THREAD_POSIX_HPP
#define _THREAD_POSIX_HPP
-/* forward typedefs ***********************************************************/
-
-typedef struct threadobject threadobject;
-
-
#include "config.h"
#include <pthread.h>
#include "vm/types.h"
-#include "mm/memory.h"
+
+// Includes required by Thread.
#if defined(ENABLE_TLH)
-#include "mm/tlh.h"
+# 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 ****************************************************************
#define SUSPEND_REASON_STOPWORLD 2 /* suspended from stop-thw-world */
+typedef struct threadobject threadobject;
+
struct threadobject {
java_object_t *object; /* link to java.lang.Thread object */
/* for the sable tasuki lock extension */
bool flc_bit;
struct threadobject *flc_list; /* FLC list head for this thread */
+ struct threadobject *flc_tail; /* tail pointer for FLC list */
struct threadobject *flc_next; /* next pointer for FLC list */
java_handle_t *flc_object;
Mutex* flc_lock; /* controlling access to these fields */
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 */
+ struct stackframeinfo_t *_stackframeinfo; /* current native stackframeinfo */
+ struct localref_table *_localref_table; /* JNI local references */
#if defined(ENABLE_INTRP)
Cell *_global_sp; /* stack pointer for interpreter */
executionstate_t *es;
#endif
- dumpinfo_t dumpinfo; /* dump memory info structure */
+ struct DumpMemory* _dumpmemory; ///< Dump memory structure.
#if defined(ENABLE_DEBUG_FILTER)
u2 filterverbosecallctr[2]; /* counters for verbose call filter */
#if defined(ENABLE_ESCAPE_REASON)
void *escape_reasons;
#endif
-
- listnode_t linkage; /* threads-list */
- listnode_t linkage_free; /* free-list */
};
+/* 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) */
+
+
/* native-world flags *********************************************************/
#if defined(ENABLE_GC_CACAO)
#endif
-/* inline functions ***********************************************************/
+// FIXME
+#ifdef __cplusplus
+extern "C" {
+#endif
+inline static threadobject* thread_get_current(void);
+#ifdef __cplusplus
+}
+#endif
+
-/* thread_get_current **********************************************************
+// Includes.
+#include "mm/memory.h"
- Return the threadobject of the current thread.
-
- RETURN:
- the current threadobject *
+#include "native/localref.hpp"
-*******************************************************************************/
+#include "threads/lock.hpp"
+
+#include "vm/global.h"
+#include "vm/vm.hpp"
+
+#if defined(ENABLE_GC_CACAO)
+# include "vm/jit/executionstate.h"
+# include "vm/jit/replace.hpp"
+#endif
-inline static threadobject *thread_get_current(void)
+#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
+
+/* inline functions ***********************************************************/
+
+/**
+ * Return the Thread object of the current thread.
+ *
+ * @return The current Thread object.
+ */
+inline static threadobject* thread_get_current(void)
{
threadobject *t;
}
-/* thread_set_current **********************************************************
-
- Set the current thread object.
-
- IN:
- t ... the thread object to set
-
-*******************************************************************************/
-
-inline static void thread_set_current(threadobject *t)
+/**
+ * Set the current Thread object.
+ *
+ * @param t The thread object to set.
+ */
+inline static void thread_set_current(threadobject* t)
{
#if defined(HAVE___THREAD)
thread_current = t;
}
-inline static stackframeinfo_t *threads_get_current_stackframeinfo(void)
+inline static struct stackframeinfo_t* threads_get_current_stackframeinfo(void)
{
return THREADOBJECT->_stackframeinfo;
}
-inline static void threads_set_current_stackframeinfo(stackframeinfo_t *sfi)
+inline static void threads_set_current_stackframeinfo(struct stackframeinfo_t* sfi)
{
THREADOBJECT->_stackframeinfo = sfi;
}
# include "mm/boehm-gc/include/gc.h"
#endif
-#include "native/jni.h"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/lock.hpp"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
#include "vm/jit/stacktrace.hpp"
-// FIXME
-extern "C" {
-
/* global variables ***********************************************************/
static methodinfo *thread_method_init;
/* Get the main-thread (NOTE: The main thread is always the first
thread in the list). */
- t = threadlist_first();
+ t = ThreadList::get_main_thread();
/* The thread name. */
/* Lock the thread lists */
- threadlist_lock();
+ ThreadList::lock();
- index = threadlist_get_free_index();
+ index = ThreadList::get_free_thread_index();
/* Allocate a thread data structure. */
/* First, try to get one from the free-list. */
- t = threadlist_free_first();
+ t = ThreadList::get_free_thread();
if (t != NULL) {
- /* Remove from free list. */
-
- threadlist_free_remove(t);
-
/* Equivalent of MZERO on the else path */
threads_impl_thread_clear(t);
MZERO(t, threadobject, 1);
+ // 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
+
#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->_exceptionptr), GC_REFTYPE_THREADOBJECT);
#endif
- /* Initialize the implementation-specific bits. */
-
- threads_impl_thread_init(t);
+ t->_dumpmemory = new DumpMemory();
}
/* Pre-compute the thinlock-word. */
assert(index != 0);
t->index = index;
- t->thinlock = lock_pre_compute_thinlock(t->index);
+ t->thinlock = Lockword::pre_compute_thinlock(t->index);
t->flags = 0;
t->state = THREAD_STATE_NEW;
/* Add the thread to the thread list. */
- threadlist_add(t);
+ ThreadList::add_to_active_thread_list(t);
/* Unlock the thread lists. */
- threadlist_unlock();
+ ThreadList::unlock();
return t;
}
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. */
+ /* Release the thread. */
- threadlist_unlock();
+ ThreadList::release_thread(t);
}
#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;
+ //java_chararray_t *name;
/* FIXME This prints to stdout. */
utf_display_printable_ascii(utf_null);
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
t->state = THREAD_STATE_RUNNABLE;
DEBUGTHREADS("is RUNNABLE", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
t->state = THREAD_STATE_WAITING;
DEBUGTHREADS("is WAITING", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
if (t->state != THREAD_STATE_TERMINATED) {
t->state = THREAD_STATE_TIMED_WAITING;
DEBUGTHREADS("is TIMED_WAITING", t);
}
- threadlist_unlock();
+ ThreadList::unlock();
}
{
/* Set the state inside a lock. */
- threadlist_lock();
+ ThreadList::lock();
t->state = THREAD_STATE_TERMINATED;
DEBUGTHREADS("is TERMINATED", t);
- threadlist_unlock();
+ ThreadList::unlock();
}
#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();
+ threadobject* t = ThreadList::get_thread_from_java_object(h);
#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- log_println("threads_get_thread: IMPLEMENT ME!");
+ log_println("thread_get_thread: IMPLEMENT ME!");
threadobject* t = NULL;
#else
}
-/* 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
#include "config.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "vm/types.h"
// Include early to get threadobject.
#include "vm/os.hpp"
-#include "native/jni.h"
#include "native/llni.h"
#include "threads/mutex.hpp"
#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* inline functions ***********************************************************/
/* thread_get_object ***********************************************************
bool threads_thread_is_alive(threadobject *t);
-void threads_dump(void);
-
/* implementation specific functions */
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_yield(void);
-#endif /* ENABLE_THREADS */
-
#ifdef __cplusplus
}
#endif
+#endif /* ENABLE_THREADS */
+
#endif // _THREAD_HPP
+++ /dev/null
-/* src/threads/threadlist.c - different thread-lists
-
- 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 "mm/memory.h"
-
-#include "threads/mutex.hpp"
-#include "threads/threadlist.h"
-#include "threads/thread.hpp"
-
-#include "toolbox/list.h"
-
-#include "vm/options.h"
-
-
-/* global variables ***********************************************************/
-
-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 */
-static list_t *list_thread_index_free;
-
-
-typedef struct thread_index_t {
- int32_t index;
- listnode_t linkage;
-} thread_index_t;
-
-
-/* threadlist_init *************************************************************
-
- Initialize thread-lists.
-
-*******************************************************************************/
-
-void threadlist_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("threadlist_init");
-
- /* Initialize the thread list mutex. */
-
- threadlist_mutex = Mutex_new();
-
- /* Initialize the thread lists. */
-
- list_thread = list_create(OFFSET(threadobject, linkage));
- list_thread_free = list_create(OFFSET(threadobject, linkage_free));
- list_thread_index_free = list_create(OFFSET(thread_index_t, linkage));
-}
-
-
-/* threadlist_lock *************************************************************
-
- Enter the thread list mutex.
-
- NOTE: We need this function as we can't use an internal lock for
- the threads lists because the thread's lock is initialized in
- threads_table_add (when we have the thread index), but we
- already need the lock at the entry of the function.
-
-*******************************************************************************/
-
-void threadlist_lock(void)
-{
- Mutex_lock(threadlist_mutex);
-}
-
-
-/* threadlist_unlock *********************************************************
-
- Leave the thread list mutex.
-
-*******************************************************************************/
-
-void threadlist_unlock(void)
-{
- Mutex_unlock(threadlist_mutex);
-}
-
-
-/* threadlist_add **************************************************************
-
- Add the given threadobject as last entry to the thread list.
-
- IN:
- t ... threadobject to be added
-
-*******************************************************************************/
-
-void threadlist_add(threadobject *t)
-{
- list_add_last(list_thread, t);
-}
-
-
-/* threadlist_remove ***********************************************************
-
- Remove the given threadobject from the thread list.
-
- IN:
- t ... threadobject to be removed
-
-*******************************************************************************/
-
-void threadlist_remove(threadobject *t)
-{
- list_remove(list_thread, t);
-}
-
-
-/* threadlist_first ************************************************************
-
- Return the first entry in the thread list.
-
- RETURN:
- threadobject of the first entry
-
-*******************************************************************************/
-
-threadobject *threadlist_first(void)
-{
- threadobject *t;
-
- t = list_first(list_thread);
-
- return t;
-}
-
-
-/* threadlist_next *************************************************************
-
- Return the next entry in the thread list.
-
- IN:
- t ... threadobject to get next thread of
-
- RETURN:
- threadobject of the next entry
-
-*******************************************************************************/
-
-threadobject *threadlist_next(threadobject *t)
-{
- threadobject *next;
-
- next = list_next(list_thread, t);
-
- return next;
-}
-
-
-/* threadlist_free_add *********************************************************
-
- Add the given threadobject as last entry to the free thread list.
-
- IN:
- t ... threadobject to be added
-
-*******************************************************************************/
-
-void threadlist_free_add(threadobject *t)
-{
- list_add_last(list_thread_free, t);
-}
-
-
-/* threadlist_free_remove ******************************************************
-
- Remove the given entry from the free thread list.
-
- IN:
- t ... threadobject to be removed
-
-*******************************************************************************/
-
-void threadlist_free_remove(threadobject *t)
-{
- list_remove(list_thread_free, t);
-}
-
-
-/* threadlist_free_first *******************************************************
-
- Return the first entry in the free thread list.
-
- RETURN:
- threadobject of the first free entry
-
-*******************************************************************************/
-
-threadobject *threadlist_free_first(void)
-{
- threadobject *t;
-
- t = list_first(list_thread_free);
-
- return t;
-}
-
-
-/* threadlist_get_non_daemons **************************************************
-
- Return the number of non-daemon threads.
-
- NOTE: This function does a linear-search over the threads list,
- because it's only used for joining the threads.
-
-*******************************************************************************/
-
-int threadlist_get_non_daemons(void)
-{
- threadobject *t;
- int nondaemons;
-
- /* Lock the thread lists. */
-
- threadlist_lock();
-
- nondaemons = 0;
-
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
- if (!thread_is_daemon(t))
- nondaemons++;
- }
-
- /* Unlock the thread lists. */
-
- threadlist_unlock();
-
- return nondaemons;
-}
-
-
-/* threadlist_index_first ******************************************************
-
- Return the first entry in the thread-index list.
-
- RETURN VALUE:
- thread-index structure
-
-*******************************************************************************/
-
-static inline thread_index_t *threadlist_index_first(void)
-{
- thread_index_t *ti;
-
- ti = list_first(list_thread_index_free);
-
- return ti;
-}
-
-
-/* threadlist_index_add ********************************************************
-
- Add the given thread-index to the thread-index free list.
-
- IN:
- i ... thread index
-
-*******************************************************************************/
-
-void threadlist_index_add(int index)
-{
- thread_index_t *ti;
-
- ti = NEW(thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_thread_index_t += sizeof(thread_index_t);
-#endif
-
- /* Set the index in the structure. */
-
- ti->index = index;
-
- list_add_last(list_thread_index_free, ti);
-}
-
-
-/* threadlist_index_remove *****************************************************
-
- Remove the given thread-index from the thread-index list and free
- the thread-index structure.
-
- IN:
- ti ... thread-index structure
-
-*******************************************************************************/
-
-static inline void threadlist_index_remove(thread_index_t *ti)
-{
- list_remove(list_thread_index_free, ti);
-
- FREE(ti, thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_thread_index_t -= sizeof(thread_index_t);
-#endif
-}
-
-
-/* threadlist_get_free_index ***************************************************
-
- Return a free thread index.
-
- RETURN VALUE:
- free thread index
-
-*******************************************************************************/
-
-int threadlist_get_free_index(void)
-{
- thread_index_t *ti;
- int index;
-
- /* Try to get a thread index from the free-list. */
-
- ti = threadlist_index_first();
-
- /* Is a free thread index available? */
-
- if (ti != NULL) {
- /* Yes, get the index and remove it from the free list. */
-
- index = ti->index;
-
- threadlist_index_remove(ti);
- }
- else {
- /* Get a new the thread index. */
-
- index = list_thread->size + 1;
- }
-
- return index;
-}
-
-
-/*
- * These 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/threadlist.cpp - thread list
+
+ 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 <algorithm>
+
+#include "threads/mutex.hpp"
+#include "threads/threadlist.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"
+
+#include "vm/jit/stacktrace.hpp"
+
+
+/* class variables */
+
+Mutex ThreadList::_mutex; // a mutex for all thread lists
+
+list<threadobject*> ThreadList::_active_thread_list; // list of active threads
+list<threadobject*> ThreadList::_free_thread_list; // list of free threads
+list<int32_t> ThreadList::_free_index_list; // list of free thread indexes
+
+int32_t ThreadList::_number_of_non_daemon_threads;
+
+
+/**
+ * Dumps info for all threads running in the VM. This function is
+ * called when SIGQUIT (<ctrl>-\) is sent to the VM.
+ */
+void ThreadList::dump_threads()
+{
+ // XXX we should stop the world here
+ // Lock the thread lists.
+ lock();
+
+ printf("Full thread dump CACAO "VERSION":\n");
+
+ // Iterate over all started threads.
+ for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+ threadobject* t = *it;
+
+ // 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.
+ unlock();
+}
+
+
+/**
+ * Return a free thread object.
+ *
+ * @return free thread object or NULL if none available
+ */
+threadobject* ThreadList::get_free_thread()
+{
+ threadobject* t = NULL;
+
+ // Do we have free threads in the free-list?
+ if (_free_thread_list.empty() == false) {
+ // Yes, get the index and remove it from the free list.
+ threadobject* t = _free_thread_list.front();
+ _free_thread_list.remove(t);
+ }
+
+ return t;
+}
+
+
+/**
+ * Return a free thread index.
+ *
+ * @return free thread index
+ */
+int32_t ThreadList::get_free_thread_index()
+{
+ int32_t index;
+
+ // Do we have free indexes in the free-list?
+ if (_free_index_list.empty() == false) {
+ // Yes, get the index and remove it from the free list.
+ index = _free_index_list.front();
+ _free_index_list.remove(index);
+ }
+ else {
+ // Get a new the thread index.
+ index = _active_thread_list.size() + 1;
+ }
+
+ return index;
+}
+
+
+/**
+ * Return the number of non-daemon threads.
+ *
+ * NOTE: This function does a linear-search over the threads list,
+ * because it is only used for joining the threads.
+ *
+ * @return number of non daemon threads
+ */
+int32_t ThreadList::get_number_of_non_daemon_threads(void)
+{
+ int nondaemons = 0;
+
+ lock();
+
+ for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+ threadobject* t = *it;
+
+ if (!thread_is_daemon(t))
+ nondaemons++;
+ }
+
+ unlock();
+
+ return nondaemons;
+}
+
+
+/**
+ * Return the thread object with the given index.
+ *
+ * @return thread object
+ */
+threadobject* ThreadList::get_thread_by_index(int32_t index)
+{
+ lock();
+
+ List<threadobject*>::iterator it = find_if(_active_thread_list.begin(), _active_thread_list.end(), std::bind2nd(comparator(), index));
+
+ // No thread found.
+ if (it == _active_thread_list.end()) {
+ unlock();
+ return NULL;
+ }
+
+ threadobject* t = *it;
+
+ // The thread found is in state new.
+ if (t->state == THREAD_STATE_NEW) {
+ unlock();
+ return NULL;
+ }
+
+ unlock();
+ return t;
+}
+
+
+/**
+ * Return the Java thread object from the given thread object.
+ *
+ * @return Java thread object
+ */
+threadobject* ThreadList::get_thread_from_java_object(java_handle_t* h)
+{
+ List<threadobject*>::iterator it;
+ threadobject* t;
+ bool equal;
+
+ lock();
+
+ for (it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+ t = *it;
+
+ LLNI_equals(t->object, h, equal);
+
+ if (equal == true) {
+ unlock();
+ return t;
+ }
+ }
+
+ unlock();
+
+ return NULL;
+}
+
+
+/**
+ * Release the thread.
+ *
+ * @return free thread index
+ */
+void ThreadList::release_thread(threadobject* t)
+{
+ lock();
+
+ // Move thread from active thread list to free thread list.
+ remove_from_active_thread_list(t);
+ add_to_free_thread_list(t);
+
+ // Add thread index to free index list.
+ add_to_free_index_list(t->index);
+
+ unlock();
+}
+
+
+/* C interface functions ******************************************************/
+
+extern "C" {
+ void ThreadList_lock() { ThreadList::lock(); }
+ void ThreadList_unlock() { ThreadList::unlock(); }
+ void ThreadList_dump_threads() { ThreadList::dump_threads(); }
+ void ThreadList_release_thread(threadobject* t) { ThreadList::release_thread(t); }
+ threadobject* ThreadList_get_free_thread() { return ThreadList::get_free_thread(); }
+ int32_t ThreadList_get_free_thread_index() { return ThreadList::get_free_thread_index(); }
+ void ThreadList_add_to_active_thread_list(threadobject* t) { ThreadList::add_to_active_thread_list(t); }
+ threadobject* ThreadList_get_thread_by_index(int32_t index) { return ThreadList::get_thread_by_index(index); }
+ threadobject* ThreadList_get_main_thread() { return ThreadList::get_main_thread(); }
+ threadobject* ThreadList_get_thread_from_java_object(java_handle_t* h) { return ThreadList::get_thread_from_java_object(h); }
+
+ int32_t ThreadList_get_number_of_non_daemon_threads() { return ThreadList::get_number_of_non_daemon_threads(); }
+}
+
+/*
+ * These 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/threadlist.h - different thread-lists
-
- 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 _THREADLIST_H
-#define _THREADLIST_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "threads/thread.hpp"
-
-
-/* function prototypes ********************************************************/
-
-void threadlist_init(void);
-
-void threadlist_add(threadobject *t);
-void threadlist_remove(threadobject *t);
-threadobject *threadlist_first(void);
-threadobject *threadlist_next(threadobject *t);
-
-void threadlist_free_add(threadobject *t);
-void threadlist_free_remove(threadobject *t);
-threadobject *threadlist_free_first(void);
-
-int threadlist_get_non_daemons(void);
-
-void threadlist_index_add(int index);
-int threadlist_get_free_index(void);
-
-/* implementation specific functions */
-
-void threadlist_impl_init(void);
-
-void threadlist_lock(void);
-void threadlist_unlock(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _THREADLIST_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/threadlist.hpp - different thread-lists
+
+ 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 _THREADLIST_HPP
+#define _THREADLIST_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+
+/* ThreadList *****************************************************************/
+
+#ifdef __cplusplus
+
+using std::list;
+
+class ThreadList {
+private:
+ static Mutex _mutex; // a mutex for all thread lists
+
+ static list<threadobject*> _active_thread_list; // list of active threads
+ static list<threadobject*> _free_thread_list; // list of free threads
+ static list<int32_t> _free_index_list; // list of free thread indexes
+
+ static int32_t _number_of_non_daemon_threads;
+
+ static inline void remove_from_active_thread_list(threadobject* t);
+ static inline void add_to_free_thread_list(threadobject* t);
+ static inline void add_to_free_index_list(int32_t index);
+
+private:
+ // Comparator class.
+ class comparator : public std::binary_function<threadobject*, int32_t, bool> {
+ public:
+ bool operator() (const threadobject* t, const int32_t index) const
+ {
+ return (t->index == index);
+ }
+ };
+
+public:
+ static inline void lock() { _mutex.lock(); }
+ static inline void unlock() { _mutex.unlock(); }
+
+ // TODO make private
+ static inline void add_to_active_thread_list(threadobject* t);
+
+ static void dump_threads();
+ static inline threadobject* get_main_thread();
+ static threadobject* get_free_thread();
+ static int32_t get_free_thread_index();
+ static int32_t get_number_of_non_daemon_threads();
+ static threadobject* get_thread_by_index(int32_t index);
+ static threadobject* get_thread_from_java_object(java_handle_t* h);
+ static void release_thread(threadobject* t);
+};
+
+
+inline void ThreadList::add_to_active_thread_list(threadobject* t)
+{
+ _active_thread_list.push_back(t);
+}
+
+inline void ThreadList::remove_from_active_thread_list(threadobject* t)
+{
+ _active_thread_list.remove(t);
+}
+
+inline void ThreadList::add_to_free_thread_list(threadobject* t)
+{
+ _free_thread_list.push_back(t);
+}
+
+inline void ThreadList::add_to_free_index_list(int32_t index)
+{
+ _free_index_list.push_back(index);
+}
+
+inline threadobject* ThreadList::get_main_thread()
+{
+ return _active_thread_list.front();
+}
+
+#else
+
+typedef struct ThreadList ThreadList;
+
+void ThreadList_lock();
+void ThreadList_unlock();
+void ThreadList_dump_threads();
+void ThreadList_release_thread(threadobject* t);
+threadobject* ThreadList_get_free_thread();
+int32_t ThreadList_get_free_thread_index();
+void ThreadList_add_to_active_thread_list(threadobject* t);
+threadobject* ThreadList_get_thread_by_index(int32_t index);
+threadobject* ThreadList_get_main_thread();
+threadobject* ThreadList_get_thread_from_java_object(java_handle_t* h);
+int32_t ThreadList_get_number_of_non_daemon_threads();
+
+#endif
+
+#endif // _THREADLIST_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/toolbox/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.
##
## 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
-##
-##
+
+
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 =
avl.h \
bitvector.c \
bitvector.h \
- chain.c \
- chain.h \
hashtable.c \
hashtable.h \
- list.c \
- list.h \
+ list.hpp \
logging.c \
logging.h \
set.h \
set.c \
- tree.c \
- tree.h \
util.c \
util.h \
worklist.c \
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
avl_tree_t *avl_create(avl_comparator *comparator);
bool avl_insert(avl_tree_t *tree, void *data);
void *avl_find(avl_tree_t *tree, void *data);
void avl_dump(avl_node_t* node, s4 indent);
#endif
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* _AVL_H */
/* src/toolbox/bitvector.c - bitvector implementation
- 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
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
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
+*/
-*/
+#include "config.h"
#include "mm/memory.h"
#include "toolbox/bitvector.h"
/* n = (((size+7)/8) + sizeof(int) - 1)/sizeof(int); */
n = BV_NUM_INTS(size);
- bv = DMNEW(int, n);
+ bv = DumpMemory_allocate(sizeof(int) * n);
for(i = 0; i < n; i++) bv[i] = 0;
+++ /dev/null
-/* src/toolbox/chain.c - management of doubly linked lists with external linking
-
- 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: Reinhard Grafl
-
- Changes: Christian Thalinger
-
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include "mm/memory.h"
-#include "toolbox/chain.h"
-
-
-chain *chain_new(void)
-{
- chain *c;
-
- c = NEW(chain);
- c->usedump = 0;
- c->first = NULL;
- c->last = NULL;
- c->active = NULL;
-
- return c;
-}
-
-
-chain *chain_dnew(void)
-{
- chain *c;
-
- c = DNEW(chain);
- c->usedump = 1;
- c->first = NULL;
- c->last = NULL;
- c->active = NULL;
-
- return c;
-}
-
-
-void chain_free(chain *c)
-{
- chainlink *l;
-
- assert(!c->usedump);
-
- l = c->first;
- while (l) {
- chainlink *nextl = l->next;
-
- FREE(l, chainlink);
- l = nextl;
- }
-
- FREE(c, chain);
-}
-
-
-void chain_addafter(chain *c, void *element)
-{
- chainlink *active;
- chainlink *newlink;
-
- active = c->active;
-
- if (c->usedump) {
- newlink = DNEW(chainlink);
-
- } else {
- newlink = NEW(chainlink);
- }
-
- newlink->element = element;
-
- if (active) {
- newlink->next = active->next;
- newlink->prev = active;
-
- active->next = newlink;
- if (newlink->next) {
- newlink->next->prev = newlink;
-
- } else {
- c->last = newlink;
- }
-
- } else {
- newlink->next = NULL;
- newlink->prev = NULL;
-
- c->active = newlink;
- c->first = newlink;
- c->last = newlink;
- }
-}
-
-
-void chain_addbefore(chain *c, void *element)
-{
- chainlink *active;
- chainlink *newlink;
-
- active = c->active;
-
- if (c->usedump) {
- newlink = DNEW(chainlink);
-
- } else {
- newlink = NEW(chainlink);
- }
-
- newlink->element = element;
-
- if (active) {
- newlink->next = active;
- newlink->prev = active->prev;
-
- active->prev = newlink;
- if (newlink->prev) {
- newlink->prev->next = newlink;
-
- } else {
- c->first = newlink;
- }
-
- } else {
- newlink->next = NULL;
- newlink->prev = NULL;
-
- c->active = newlink;
- c->first = newlink;
- c->last = newlink;
- }
-}
-
-
-void chain_addlast(chain *c, void *e)
-{
- chain_last(c);
- chain_addafter(c, e);
-}
-
-
-void chain_addfirst(chain *c, void *e)
-{
- chain_first(c);
- chain_addbefore(c, e);
-}
-
-
-void chain_remove(chain *c)
-{
- chainlink *active;
-
- active = c->active;
- assert(active);
-
- if (active->next) {
- active->next->prev = active->prev;
-
- } else {
- c->last = active->prev;
- }
-
- if (active->prev) {
- active->prev->next = active->next;
-
- } else {
- c->first = active->next;
- }
-
-
- if (active->prev) {
- c->active = active->prev;
-
- } else {
- c->active = active->next;
- }
-
- if (!c->usedump)
- FREE(active, chainlink);
-}
-
-
-void *chain_remove_go_prev(chain *c)
-{
- chain_remove(c);
- return chain_this(c);
-}
-
-
-
-void chain_removespecific(chain *c, void *e)
-{
- void *ce;
-
- ce = chain_first(c);
- while (ce) {
- if (e == ce) {
- chain_remove(c);
- return;
- }
-
- ce = chain_next(c);
- }
-}
-
-
-void *chain_next(chain *c)
-{
- chainlink *active;
-
- active = c->active;
-
- if (!active)
- return NULL;
-
- if (active->next) {
- c->active = active->next;
- return c->active->element;
- }
-
- return NULL;
-}
-
-
-void *chain_prev(chain *c)
-{
- chainlink *active;
-
- active = c->active;
-
- if (!active)
- return NULL;
-
- if (active->prev) {
- c->active = active->prev;
- return c->active->element;
- }
-
- return NULL;
-}
-
-
-void *chain_this(chain *c)
-{
- if (c->active)
- return c->active->element;
-
- return NULL;
-}
-
-
-void *chain_first(chain *c)
-{
- c->active = c->first;
-
- if (c -> active)
- return c->active->element;
-
- return NULL;
-}
-
-void *chain_last(chain *c)
-{
- c->active = c->last;
-
- if (c->active)
- return c->active->element;
-
- 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
-/* toolbox/chain.h - management of doubly linked lists with external linking
-
- 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: Reinhard Grafl
-
-
-*/
-
-
-#ifndef _CHAIN_H
-#define _CHAIN_H
-
-typedef struct chainlink { /* structure for list element */
- struct chainlink *next;
- struct chainlink *prev;
- void *element;
-} chainlink;
-
-typedef struct chain { /* structure for list */
- int usedump;
-
- chainlink *first;
- chainlink *last;
- chainlink *active;
-} chain;
-
-
-/* function prototypes */
-chain *chain_new(void);
-chain *chain_dnew(void);
-void chain_free(chain *c);
-
-void chain_addafter(chain *c, void *element);
-void chain_addbefore(chain *c, void *element);
-void chain_addlast(chain *c, void *element);
-void chain_addfirst(chain *c, void *element);
-
-void chain_remove(chain *c);
-void *chain_remove_go_prev(chain *c);
-void chain_removespecific(chain *c, void *element);
-
-void *chain_next(chain *c);
-void *chain_prev(chain *c);
-void *chain_this(chain *c);
-
-void *chain_first(chain *c);
-void *chain_last(chain *c);
-
-
-/*
---------------------------- interface description ------------------------
-
-Usage of these functions for list management is possible without additional
-preparation in the element structures, as opposed to the module 'list'.
-
-Consequently, the functions are a little slower and need more memory.
-
-A new list is created with
- chain_new
-or chain_dnew.
-The latter allocates all additional data structures on the dump memory (faster)
-for which no explicit freeing is necessary after the processing. Care needs to
-be taken to not accidentally free parts of these structures by calling
-'dump_release' too early.
-
-After usage, a list can be freed with
- chain_free.
-(use only if the list was created with 'chain_new')
-
-
-Adding elements is easy with:
- chain_addafter, chain_addlast, chain_addbefore, chain_addfirst
-
-Search the list with:
- chain_first, chain_last, chain_prev, chain_next, chain_this
-
-Delete elements from the list:
- chain_remove, chain_remove_go_prev, chain_removespecific
-
-
-ATTENTION: As mentioned earlier, there are no pointers to the list or to other
-nodes inside the list elements, so list elements cannot be used as pointers
-into the list. Therefore a 'cursor' is used to make one element current. Every
-insertion/deletion occurs at a position relative to this cursor.
-
-*/
-
-#endif /* _CHAIN_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:
- */
/* src/toolbox/hashtable.c - functions for internal hashtables
- 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/hashtable.h"
Initializes a hashtable structure and allocates memory. The
parameter size specifies the initial size of the hashtable.
-
+
*******************************************************************************/
void hashtable_create(hashtable *hash, u4 size)
/* initialize locking pointer */
#if defined(ENABLE_THREADS)
- /* We need to seperately allocate a java_object_t here, as we
- need to store the lock object in the new hashtable if it's
- resized. Otherwise we get an IllegalMonitorStateException. */
-
- hash->header = NEW(java_object_t);
+ /* We need to seperately allocate a mutex here, as we need to
+ store the lock object in the new hashtable if it's resized.
+ Otherwise we get an IllegalMonitorStateException. */
- LOCK_INIT_OBJECT_LOCK(hash->header);
+ hash->mutex = Mutex_new();
#endif
/* set initial hash values */
/* We need to store the old lock object in the new hashtable.
Otherwise we get an IllegalMonitorStateException. */
- FREE(newhash->header, java_object_t);
+ Mutex_delete(newhash->mutex);
- newhash->header = hash->header;
+ newhash->mutex = hash->mutex;
#endif
/* store the number of entries in the new hashtable */
#include "config.h"
#include "vm/types.h"
+#include "threads/mutex.hpp"
+
#include "vm/global.h"
#include "vm/utf8.h"
struct hashtable {
#if defined(ENABLE_THREADS)
- java_object_t *header; /* required for locking */
+ Mutex *mutex; /* required for locking */
#endif
u4 size; /* current size of the hashtable */
u4 entries; /* number of entries in the table */
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* create hashtable */
void hashtable_create(hashtable *hash, u4 size);
/* frees a hashtable */
void hashtable_free(hashtable *hash);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _HASHTABLE_H */
+++ /dev/null
-/* src/toolbox/list.c - double linked list
-
- 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 "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/list.h"
-
-
-/* list_create *****************************************************************
-
- Allocates a new list and initializes the lock object.
-
-*******************************************************************************/
-
-list_t *list_create(int nodeoffset)
-{
- list_t *l;
-
- l = NEW(list_t);
-
- LOCK_INIT_OBJECT_LOCK(l);
-
- l->first = NULL;
- l->last = NULL;
- l->nodeoffset = nodeoffset;
- l->size = 0;
-
- return l;
-}
-
-
-/* list_free *******************************************************************
-
- Free a list.
-
-*******************************************************************************/
-
-void list_free(list_t *l)
-{
- assert(l != NULL);
-
- FREE(l, list_t);
-}
-
-
-/* list_create_dump ************************************************************
-
- Allocates a new list on the dump memory.
-
- ATTENTION: This list does NOT initialize the locking object!!!
-
-*******************************************************************************/
-
-list_t *list_create_dump(int nodeoffset)
-{
- list_t *l;
-
- l = DNEW(list_t);
-
- l->first = NULL;
- l->last = NULL;
- l->nodeoffset = nodeoffset;
- l->size = 0;
-
- return l;
-}
-
-
-/* list_lock *******************************************************************
-
- Locks the list.
-
-*******************************************************************************/
-
-void list_lock(list_t *l)
-{
- LOCK_MONITOR_ENTER(l);
-}
-
-
-/* list_unlock *****************************************************************
-
- Unlocks the list.
-
-*******************************************************************************/
-
-void list_unlock(list_t *l)
-{
- LOCK_MONITOR_EXIT(l);
-}
-
-
-/* list_add_first **************************************************************
-
- Adds the element as first element.
-
-*******************************************************************************/
-
-void list_add_first(list_t *l, void *element)
-{
- listnode_t *ln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (l->first) {
- ln->prev = NULL;
- ln->next = l->first;
- l->first->prev = ln;
- l->first = ln;
- }
- else {
- ln->prev = NULL;
- ln->next = NULL;
- l->last = ln;
- l->first = ln;
- }
-
- /* Increase number of elements. */
-
- l->size++;
-}
-
-
-/* list_add_last ***************************************************************
-
- Adds the element as last element.
-
-*******************************************************************************/
-
-void list_add_last(list_t *l, void *element)
-{
- listnode_t *ln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (l->last) {
- ln->prev = l->last;
- ln->next = NULL;
- l->last->next = ln;
- l->last = ln;
- }
- else {
- ln->prev = NULL;
- ln->next = NULL;
- l->last = ln;
- l->first = ln;
- }
-
- /* Increase number of elements. */
-
- l->size++;
-}
-
-
-/* list_add_before *************************************************************
-
- Adds the element newelement to the list l before element.
-
- [ A ] <-> [ newn ] <-> [ n ] <-> [ B ]
-
-*******************************************************************************/
-
-void list_add_before(list_t *l, void *element, void *newelement)
-{
- listnode_t *ln;
- listnode_t *newln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
- newln = (listnode_t *) (((uint8_t *) newelement) + l->nodeoffset);
-
- /* Set the new links. */
-
- newln->prev = ln->prev;
- newln->next = ln;
-
- if (newln->prev)
- newln->prev->next = newln;
-
- ln->prev = newln;
-
- /* set list's first and last if necessary */
-
- if (l->first == ln)
- l->first = newln;
-
- if (l->last == ln)
- l->last = newln;
-
- /* Increase number of elements. */
-
- l->size++;
-}
-
-
-/* list_remove ***************************************************************
-
- Removes the element.
-
-*******************************************************************************/
-
-void list_remove(list_t *l, void *element)
-{
- listnode_t *ln;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (ln->next)
- ln->next->prev = ln->prev;
- else
- l->last = ln->prev;
-
- if (ln->prev)
- ln->prev->next = ln->next;
- else
- l->first = ln->next;
-
- ln->next = NULL;
- ln->prev = NULL;
-
- /* Decrease number of elements. */
-
- l->size--;
-}
-
-
-/* list_first ******************************************************************
-
- Returns the first element of the list.
-
-*******************************************************************************/
-
-void *list_first(list_t *l)
-{
- void *el;
-
- if (l->first == NULL)
- el = NULL;
- else
- el = ((uint8_t *) l->first) - l->nodeoffset;
-
- return el;
-}
-
-
-/* list_last *******************************************************************
-
- Returns the last element of the list.
-
-*******************************************************************************/
-
-void *list_last(list_t *l)
-{
- void *el;
-
- if (l->last == NULL)
- el = NULL;
- else
- el = ((uint8_t *) l->last) - l->nodeoffset;
-
- return el;
-}
-
-
-/* list_next *******************************************************************
-
- Returns the next element of element from the list.
-
-*******************************************************************************/
-
-void *list_next(list_t *l, void *element)
-{
- listnode_t *ln;
- void *el;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (ln->next == NULL)
- el = NULL;
- else
- el = ((uint8_t *) ln->next) - l->nodeoffset;
-
- return el;
-}
-
-
-/* list_prev *******************************************************************
-
- Returns the previous element of element from the list.
-
-*******************************************************************************/
-
-void *list_prev(list_t *l, void *element)
-{
- listnode_t *ln;
- void *el;
-
- ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
-
- if (ln->prev == NULL)
- el = NULL;
- else
- el = ((uint8_t *) ln->prev) - l->nodeoffset;
-
- return el;
-}
-
-
-/*
- * These 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/toolbox/list.h - synchronized linked list
-
- 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 _LIST_H
-#define _LIST_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "vm/global.h"
-
-
-/* ---------------------- interface description -----------------------------
-
-The list management with this module works like this:
-
- - to be used in a list, a structure must have an element of type
- 'listnode'.
-
- - there needs to be a structure of type 'list'.
-
- - the function list_init(l, nodeoffset) initializes the structure.
- nodeoffset is the offset of the 'listnode' from the start of the
- structure in bytes.
-
- - The remaining functions provide inserting, removing and searching.
-
-This small example aims to demonstrate correct usage:
-
-
-
- void bsp() {
- struct node {
- listnode linkage;
- int value;
- } a,b,c, *el;
-
- list l;
-
- a.value = 7;
- b.value = 9;
- c.value = 11;
-
- list_init (&l, OFFSET(struct node,linkage) );
- list_addlast (&l, a);
- list_addlast (&l, b);
- list_addlast (&l, c);
-
- e = list_first (&l);
- while (e) {
- printf ("Element: %d\n", e->value);
- e = list_next (&l,e);
- }
- }
-
-
- The output from this program should be:
- 7
- 9
- 11
-
-
-
-The reason for the usage of 'nodeoffset' is that this way, the same node can
-part of different lists (there must be one 'listnode' element for every
-distinct list).
-
-*/
-
-/* listnode_t *****************************************************************/
-
-typedef struct listnode_t listnode_t;
-
-struct listnode_t {
- listnode_t *next;
- listnode_t *prev;
-};
-
-
-/* list_t *********************************************************************/
-
-typedef struct list_t list_t;
-
-struct list_t {
-#if defined(ENABLE_THREADS)
- java_object_t lock; /* threads lock object */
-#endif
- listnode_t *first;
- listnode_t *last;
- int nodeoffset;
- int size; /* number of elements in the list */
-};
-
-
-/* function prototypes ********************************************************/
-
-list_t *list_create(int nodeoffset);
-list_t *list_create_dump(int nodeoffset);
-
-void list_free(list_t *l);
-
-void list_lock(list_t *l);
-void list_unlock(list_t *l);
-
-void list_add_first(list_t *l, void *element);
-void list_add_last(list_t *l, void *element);
-void list_add_before(list_t *l, void *element, void *newelement);
-
-void list_remove(list_t *l, void *element);
-
-void *list_first(list_t *l);
-void *list_last(list_t *l);
-
-void *list_next(list_t *l, void *element);
-void *list_prev(list_t *l, void *element);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LIST_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/toolbox/list.hpp - linked list
+
+ 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 _LIST_HPP
+#define _LIST_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <list>
+#endif
+
+#include "threads/mutex.hpp"
+
+
+#ifdef __cplusplus
+
+/**
+ * List implementation with a Mutex.
+ */
+template<class T> class List : protected std::list<T> {
+private:
+ Mutex _mutex;
+
+public:
+ virtual ~List() {}
+
+ void lock () { _mutex.lock(); }
+ void unlock() { _mutex.unlock(); }
+
+ // make iterator of std::list visible
+ using std::list<T>::iterator;
+ using std::list<T>::reverse_iterator;
+
+ // make functions of std::list visible
+ using std::list<T>::back;
+ using std::list<T>::begin;
+ using std::list<T>::clear;
+ using std::list<T>::empty;
+ using std::list<T>::end;
+ using std::list<T>::front;
+ using std::list<T>::push_back;
+ using std::list<T>::push_front;
+ using std::list<T>::rbegin;
+ using std::list<T>::remove;
+ using std::list<T>::rend;
+ using std::list<T>::size;
+};
+
+
+// Required by DumpList.
+#include "mm/dumpmemory.hpp"
+
+
+/**
+ * List implementation with dump memory.
+ */
+template<class T> class DumpList : protected std::list<T, DumpMemoryAllocator<T> > {
+public:
+ virtual ~DumpList() {}
+
+ // make iterator of std::list visible
+ using std::list<T, DumpMemoryAllocator<T> >::iterator;
+ using std::list<T, DumpMemoryAllocator<T> >::reverse_iterator;
+
+ // make functions of std::list visible
+ using std::list<T, DumpMemoryAllocator<T> >::back;
+ using std::list<T, DumpMemoryAllocator<T> >::begin;
+ using std::list<T, DumpMemoryAllocator<T> >::clear;
+ using std::list<T, DumpMemoryAllocator<T> >::empty;
+ using std::list<T, DumpMemoryAllocator<T> >::end;
+ using std::list<T, DumpMemoryAllocator<T> >::front;
+ using std::list<T, DumpMemoryAllocator<T> >::push_back;
+ using std::list<T, DumpMemoryAllocator<T> >::push_front;
+ using std::list<T, DumpMemoryAllocator<T> >::rbegin;
+ using std::list<T, DumpMemoryAllocator<T> >::remove;
+ using std::list<T, DumpMemoryAllocator<T> >::rend;
+ using std::list<T, DumpMemoryAllocator<T> >::size;
+
+ void* operator new(size_t size) {
+ return DumpMemory::allocate(size);
+ }
+
+ void operator delete(void* p) {}
+};
+
+#else
+
+typedef struct List List;
+typedef struct DumpList DumpList;
+
+#endif
+
+#endif // _LIST_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 "vm/utf8.h"
-/*500 is to small for eclipse traces, (builtin_trace_args, perhaps the
-buffer should be created there dynamically, if the text is longer,
-instead of setting the size for all invocations that big*/
-
-#define MAXLOGTEXT 16383
-
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void log_init(const char *fname);
void log_start(void);
#define log_text(s) log_println("%s", (s))
#define dolog log_println
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _LOGGING_H */
*******************************************************************************/
set *set_new(unsigned capacity) {
- set *s = DNEW(set);
+ set *s = DumpMemory_allocate(sizeof(set));
- s->elements = DMNEW(void *, capacity);
+ s->elements = DumpMemory_allocate(sizeof(void*) * capacity);
MZERO(s->elements, void *, capacity);
s->capacity = capacity;
s->size = 0;
+++ /dev/null
-/* toolbox/tree.h - binary tree management
-
- 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: Reinhard Grafl
-
-
-*/
-
-
-#include <stdio.h>
-#include <assert.h>
-
-#include "mm/memory.h"
-#include "toolbox/tree.h"
-
-
-tree *tree_new(treeelementcomperator comperator)
-{
- tree *t = NEW(tree);
-
- t->usedump = 0;
- t->comperator = comperator;
- t->top = NULL;
- t->active = NULL;
-
- return t;
-}
-
-
-tree *tree_dnew(treeelementcomperator comperator)
-{
- tree *t = DNEW(tree);
-
- t->usedump = 1;
- t->comperator = comperator;
- t->top = NULL;
- t->active = NULL;
-
- return t;
-}
-
-
-static void tree_nodefree(treenode *tn)
-{
- if (!tn)
- return;
-
- tree_nodefree(tn->left);
- tree_nodefree(tn->right);
- FREE(tn, treenode);
-}
-
-
-void tree_free(tree *t)
-{
- assert(!t->usedump);
-
- tree_nodefree(t->top);
- FREE(t, tree);
-}
-
-
-static treenode *tree_nodeadd(tree *t, treenode *par, treenode *n,
- void *element, void *key)
-{
- if (!n) {
- if (t->usedump) {
- n = DNEW(treenode);
-
- } else {
- n = NEW(treenode);
- }
-
- n->left = NULL;
- n->right = NULL;
- n->parent = par;
- n->element = element;
-
- } else {
- if (t->comperator(key, n->element) < 0) {
- n->left = tree_nodeadd(t, n, n->left, element, key);
-
- } else {
- n->right = tree_nodeadd(t, n, n->right, element, key);
- }
- }
-
- return n;
-}
-
-
-void tree_add(tree *t, void *element, void *key)
-{
- t->top = tree_nodeadd(t, NULL, t->top, element, key);
- t->active = t->top;
-}
-
-
-static treenode *tree_nodefind(tree *t, treenode *n, void *key)
-{
- int way;
-
- if (!n)
- return NULL;
-
- way = t->comperator(key, n->element);
- if (way == 0)
- return n;
-
- if (way < 0) {
- return tree_nodefind(t, n->left, key);
-
- } else {
- return tree_nodefind (t, n -> right, key);
- }
-}
-
-
-void *tree_find(tree *t, void *key)
-{
- treenode *tn = tree_nodefind(t, t->top, key);
-
- if (!tn)
- return NULL;
-
- t->active = tn;
-
- return tn->element;
-}
-
-
-
-void *tree_this(tree *t)
-{
- if (!t->active)
- return NULL;
-
- return t->active->element;
-}
-
-
-static treenode *leftmostnode(treenode *t)
-{
- while (t->left) {
- t = t->left;
- }
-
- return t;
-}
-
-
-void *tree_first(tree *t)
-{
- treenode *a = t->top;
-
- if (!a)
- return NULL;
-
- a = leftmostnode(a);
- t->active = a;
-
- return a->element;
-}
-
-
-void *tree_next (tree *t)
-{
- treenode *a = t->active;
- treenode *comefrom = NULL;
-
- while (a) {
- if (!a)
- return NULL;
-
- if (a->left && (a->left == comefrom)) {
- t -> active = a;
- return a->element;
- }
-
- if (a->right && (a->right != comefrom)) {
- a = leftmostnode(a->right);
- t -> active = a;
- return a->element;
- }
-
- comefrom = a;
- a = a->parent;
- }
-
- t->active = NULL;
-
- 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
-/* toolbox/tree.h - binary tree management
-
- 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: Reinhard Grafl
-
-
-*/
-
-
-#ifndef _TREE_H
-#define _TREE_H
-
-typedef int (*treeelementcomperator) (void *key, void * element);
-
-
-typedef struct treenode {
- struct treenode *left,*right;
- struct treenode *parent;
-
- void *element;
-} treenode;
-
-typedef struct {
- int usedump;
- treeelementcomperator comperator;
-
- treenode *top;
- treenode *active;
-} tree;
-
-
-/* function prototypes */
-
-tree *tree_new(treeelementcomperator comperator);
-tree *tree_dnew(treeelementcomperator comperator);
-void tree_free(tree *t);
-
-void tree_add(tree *t, void *element, void *key);
-void *tree_find(tree *t, void *key);
-
-void *tree_this(tree *t);
-void *tree_first(tree *t);
-void *tree_next(tree *t);
-
-#endif /* _TREE_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:
- */
#ifndef _UTIL_H
#define _UTIL_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "config.h"
#include <stdarg.h>
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
char *_Jv_getcwd(void);
int get_variable_message_length(const char *fmt, va_list ap);
if ENABLE_ASSERTION
ASSERTION_SOURCES = \
- assertion.c \
- assertion.h
+ assertion.cpp \
+ assertion.hpp
endif
if ENABLE_CYCLES_STATS
access.c \
access.h \
$(ANNOTATION_SOURCES) \
- array.c \
- array.h \
+ array.cpp \
+ array.hpp \
$(ASSERTION_SOURCES) \
- builtin.c \
- builtin.h \
- builtintable.inc \
class.c \
class.h \
classcache.c \
descriptor.h \
exceptions.cpp \
exceptions.hpp \
- field.c \
- field.h \
+ field.cpp \
+ field.hpp \
finalizer.c \
finalizer.h \
globals.cpp \
initialize.h \
javaobjects.cpp \
javaobjects.hpp \
- jit_interface.h \
linker.c \
linker.h \
- loader.c \
- loader.h \
+ loader.cpp \
+ loader.hpp \
method.c \
method.h \
options.c \
package.hpp \
primitive.cpp \
primitive.hpp \
- primitivecore.c \
- properties.c \
- properties.h \
+ properties.cpp \
+ properties.hpp \
references.h \
resolve.c \
resolve.h \
$(STATISTICS_SOURCES) \
string.cpp \
string.hpp \
- suck.c \
- suck.h \
+ suck.cpp \
+ suck.hpp \
utf8.c \
utf8.h \
+ vftbl.hpp \
vm.cpp \
vm.hpp \
$(ZLIB_SOURCES)
#include "native/llni.h"
#include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/globals.hpp"
#include "vm/method.h"
#endif
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "toolbox/logging.h"
#include "vm/annotation.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/primitive.hpp"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
#include "vm/types.h"
#if !defined(ENABLE_ANNOTATIONS)
#include "vm/types.h"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/method.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool annotation_load_class_attribute_runtimevisibleannotations(
classbuffer *cb);
bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
classbuffer *cb, methodinfo *m);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _ANNOTATION_H */
+++ /dev/null
-/* src/vm/array.c - Java array 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"
-
-#include <stdint.h>
-
-#include "native/llni.h"
-
-#include "vm/array.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/primitive.hpp"
-#include "vm/vm.hpp"
-
-
-/* array_element_get ***********************************************************
-
- Returns a boxed element of the given Java array.
-
-*******************************************************************************/
-
-java_handle_t *array_element_get(java_handle_t *a, int32_t index)
-{
- vftbl_t *v;
- int type;
- imm_union value;
- java_handle_t *o;
-
- if (a == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- v = LLNI_vftbl_direct(a);
-
- type = v->arraydesc->arraytype;
-
- value = array_element_primitive_get(a, index);
-
- o = Primitive_box(type, value);
-
- return o;
-}
-
-
-/* array_element_set ***********************************************************
-
- Sets a boxed element in the given Java array.
-
-*******************************************************************************/
-
-void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o)
-{
- imm_union value;
-
- value = Primitive_unbox(o);
-
- array_element_primitive_set(a, index, value);
-}
-
-
-/* array_element_primitive_get *************************************************
-
- Returns a primitive element of the given Java array.
-
-*******************************************************************************/
-
-imm_union array_element_primitive_get(java_handle_t *a, int32_t index)
-{
- vftbl_t *v;
- int type;
- imm_union value;
-
- if (a == NULL) {
- exceptions_throw_nullpointerexception();
- value.a = NULL;
- return value;
- }
-
- v = LLNI_vftbl_direct(a);
-
- type = v->arraydesc->arraytype;
-
- switch (type) {
- case ARRAYTYPE_BOOLEAN:
- value.i = array_booleanarray_element_get((java_handle_booleanarray_t *) a, index);
- break;
- case ARRAYTYPE_BYTE:
- value.i = array_bytearray_element_get((java_handle_bytearray_t *) a,
- index);
- break;
- case ARRAYTYPE_CHAR:
- value.i = array_chararray_element_get((java_handle_chararray_t *) a,
- index);
- break;
- case ARRAYTYPE_SHORT:
- value.i = array_shortarray_element_get((java_handle_shortarray_t *) a,
- index);
- break;
- case ARRAYTYPE_INT:
- value.i = array_intarray_element_get((java_handle_intarray_t *) a,
- index);
- break;
- case ARRAYTYPE_LONG:
- value.l = array_longarray_element_get((java_handle_longarray_t *) a,
- index);
- break;
- case ARRAYTYPE_FLOAT:
- value.f = array_floatarray_element_get((java_handle_floatarray_t *) a,
- index);
- break;
- case ARRAYTYPE_DOUBLE:
- value.d = array_doublearray_element_get((java_handle_doublearray_t *) a,
- index);
- break;
- case ARRAYTYPE_OBJECT:
- value.a = array_objectarray_element_get((java_handle_objectarray_t *) a,
- index);
- break;
- default:
- vm_abort("array_element_primitive_get: invalid array element type %d",
- type);
- }
-
- return value;
-}
-
-
-/* array_element_primitive_set *************************************************
-
- Sets a primitive element in the given Java array.
-
-*******************************************************************************/
-
-void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value)
-{
- vftbl_t *v;
- int type;
-
- if (a == NULL) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- v = LLNI_vftbl_direct(a);
-
- type = v->arraydesc->arraytype;
-
- switch (type) {
- case ARRAYTYPE_BOOLEAN:
- array_booleanarray_element_set((java_handle_booleanarray_t *) a,
- index, value.i);
- break;
- case ARRAYTYPE_BYTE:
- array_bytearray_element_set((java_handle_bytearray_t *) a,
- index, value.i);
- break;
- case ARRAYTYPE_CHAR:
- array_chararray_element_set((java_handle_chararray_t *) a,
- index, value.i);
- break;
- case ARRAYTYPE_SHORT:
- array_shortarray_element_set((java_handle_shortarray_t *) a,
- index, value.i);
- break;
- case ARRAYTYPE_INT:
- array_intarray_element_set((java_handle_intarray_t *) a,
- index, value.i);
- break;
- case ARRAYTYPE_LONG:
- array_longarray_element_set((java_handle_longarray_t *) a,
- index, value.l);
- break;
- case ARRAYTYPE_FLOAT:
- array_floatarray_element_set((java_handle_floatarray_t *) a,
- index, value.f);
- break;
- case ARRAYTYPE_DOUBLE:
- array_doublearray_element_set((java_handle_doublearray_t *) a,
- index, value.d);
- break;
- case ARRAYTYPE_OBJECT:
- array_objectarray_element_set((java_handle_objectarray_t *) a,
- index, value.a);
- break;
- default:
- vm_abort("array_element_primitive_set: invalid array element type %d",
- type);
- }
-}
-
-
-/* array_xxxarray_element_get **************************************************
-
- Returns a primitive element of the given Java array.
-
-*******************************************************************************/
-
-#define ARRAY_TYPEARRAY_ELEMENT_GET(name, type) \
-type array_##name##array_element_get(java_handle_##name##array_t *a, int32_t index) \
-{ \
- type value; \
- int32_t size; \
- \
- if (a == NULL) { \
- exceptions_throw_nullpointerexception(); \
- return (type) 0; \
- } \
- \
- size = LLNI_array_size(a); \
- \
- if ((index < 0) || (index >= size)) { \
- exceptions_throw_arrayindexoutofboundsexception(); \
- return (type) 0; \
- } \
- \
- value = LLNI_array_direct(a, index); \
- \
- return value; \
-}
-
-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) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- size = LLNI_array_size(a);
-
- if ((index < 0) || (index >= size)) {
- exceptions_throw_arrayindexoutofboundsexception();
- return NULL;
- }
-
- LLNI_CRITICAL_START;
- value = LLNI_WRAP(LLNI_array_direct(a, index));
- LLNI_CRITICAL_END;
-
- return value;
-}
-
-ARRAY_TYPEARRAY_ELEMENT_GET(boolean, uint8_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(byte, int8_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(char, uint16_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(short, int16_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(int, int32_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(long, int64_t)
-ARRAY_TYPEARRAY_ELEMENT_GET(float, float)
-ARRAY_TYPEARRAY_ELEMENT_GET(double, double)
-
-
-/* array_xxxarray_element_set **************************************************
-
- Sets a primitive element in the given Java array.
-
-*******************************************************************************/
-
-#define ARRAY_TYPEARRAY_ELEMENT_SET(name, type) \
-void array_##name##array_element_set(java_handle_##name##array_t *a, int32_t index, type value) \
-{ \
- int32_t size; \
- \
- if (a == NULL) { \
- exceptions_throw_nullpointerexception(); \
- return; \
- } \
- \
- size = LLNI_array_size(a); \
- \
- if ((index < 0) || (index >= size)) { \
- exceptions_throw_arrayindexoutofboundsexception(); \
- return; \
- } \
- \
- LLNI_array_direct(a, index) = value; \
-}
-
-void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value)
-{
- int32_t size;
-
- if (a == NULL) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- /* Sanity check. */
-
- assert(a->header.objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
-
- if (value != NULL) {
- if (builtin_canstore(a, value) == false) {
- exceptions_throw_illegalargumentexception();
- return;
- }
- }
-
- size = LLNI_array_size(a);
-
- if ((index < 0) || (index >= size)) {
- exceptions_throw_arrayindexoutofboundsexception();
- return;
- }
-
- LLNI_CRITICAL_START;
- LLNI_array_direct(a, index) = LLNI_UNWRAP(value);
- LLNI_CRITICAL_END;
-}
-
-ARRAY_TYPEARRAY_ELEMENT_SET(boolean, uint8_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(byte, int8_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(char, uint16_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(short, int16_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(int, int32_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(long, int64_t)
-ARRAY_TYPEARRAY_ELEMENT_SET(float, float)
-ARRAY_TYPEARRAY_ELEMENT_SET(double, double)
-
-
-/* array_length_get ***********************************************************
-
- Returns a the length of the given Java array.
-
- ARGUMENTS:
- a ... Java array
-
- RETURN VALUE:
- -1 ... exception thrown
- >= 0 ... length of the Java array
-
-*******************************************************************************/
-
-int32_t array_length_get(java_handle_t *a)
-{
- classinfo *c;
- int32_t size;
-
- if (a == NULL) {
- exceptions_throw_nullpointerexception();
- return -1;
- }
-
- LLNI_class_get(a, c);
-
- if (!class_is_array(c)) {
-/* exceptions_throw_illegalargumentexception("Argument is not an array"); */
- exceptions_throw_illegalargumentexception();
- return -1;
- }
-
- size = LLNI_array_size(a);
-
- return size;
-}
-
-
-/*
- * These 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/array.cpp - Java array 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"
+
+#include <stdint.h>
+
+#include "native/llni.h"
+
+#include "vm/array.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/primitive.hpp"
+#include "vm/vm.hpp"
+
+
+/* array_element_get ***********************************************************
+
+ Returns a boxed element of the given Java array.
+
+*******************************************************************************/
+
+java_handle_t *array_element_get(java_handle_t *a, int32_t index)
+{
+ vftbl_t *v;
+ int type;
+ imm_union value;
+ java_handle_t *o;
+
+ if (a == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ v = LLNI_vftbl_direct(a);
+
+ type = v->arraydesc->arraytype;
+
+ value = array_element_primitive_get(a, index);
+
+ o = Primitive::box(type, value);
+
+ return o;
+}
+
+
+/* array_element_set ***********************************************************
+
+ Sets a boxed element in the given Java array.
+
+*******************************************************************************/
+
+void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o)
+{
+ imm_union value;
+
+ value = Primitive::unbox(o);
+
+ array_element_primitive_set(a, index, value);
+}
+
+
+/* array_element_primitive_get *************************************************
+
+ Returns a primitive element of the given Java array.
+
+*******************************************************************************/
+
+imm_union array_element_primitive_get(java_handle_t *a, int32_t index)
+{
+ vftbl_t *v;
+ int type;
+ imm_union value;
+
+ if (a == NULL) {
+ exceptions_throw_nullpointerexception();
+ value.a = NULL;
+ return value;
+ }
+
+ v = LLNI_vftbl_direct(a);
+
+ type = v->arraydesc->arraytype;
+
+ switch (type) {
+ case ARRAYTYPE_BOOLEAN:
+ value.i = array_booleanarray_element_get((java_handle_booleanarray_t *) a, index);
+ break;
+ case ARRAYTYPE_BYTE:
+ value.i = array_bytearray_element_get((java_handle_bytearray_t *) a,
+ index);
+ break;
+ case ARRAYTYPE_CHAR:
+ value.i = array_chararray_element_get((java_handle_chararray_t *) a,
+ index);
+ break;
+ case ARRAYTYPE_SHORT:
+ value.i = array_shortarray_element_get((java_handle_shortarray_t *) a,
+ index);
+ break;
+ case ARRAYTYPE_INT:
+ value.i = array_intarray_element_get((java_handle_intarray_t *) a,
+ index);
+ break;
+ case ARRAYTYPE_LONG:
+ value.l = array_longarray_element_get((java_handle_longarray_t *) a,
+ index);
+ break;
+ case ARRAYTYPE_FLOAT:
+ value.f = array_floatarray_element_get((java_handle_floatarray_t *) a,
+ index);
+ break;
+ case ARRAYTYPE_DOUBLE:
+ value.d = array_doublearray_element_get((java_handle_doublearray_t *) a,
+ index);
+ break;
+ case ARRAYTYPE_OBJECT:
+ value.a = array_objectarray_element_get((java_handle_objectarray_t *) a,
+ index);
+ break;
+ default:
+ vm_abort("array_element_primitive_get: invalid array element type %d",
+ type);
+ }
+
+ return value;
+}
+
+
+/* array_element_primitive_set *************************************************
+
+ Sets a primitive element in the given Java array.
+
+*******************************************************************************/
+
+void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value)
+{
+ vftbl_t *v;
+ int type;
+
+ if (a == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ v = LLNI_vftbl_direct(a);
+
+ type = v->arraydesc->arraytype;
+
+ switch (type) {
+ case ARRAYTYPE_BOOLEAN:
+ array_booleanarray_element_set((java_handle_booleanarray_t *) a,
+ index, value.i);
+ break;
+ case ARRAYTYPE_BYTE:
+ array_bytearray_element_set((java_handle_bytearray_t *) a,
+ index, value.i);
+ break;
+ case ARRAYTYPE_CHAR:
+ array_chararray_element_set((java_handle_chararray_t *) a,
+ index, value.i);
+ break;
+ case ARRAYTYPE_SHORT:
+ array_shortarray_element_set((java_handle_shortarray_t *) a,
+ index, value.i);
+ break;
+ case ARRAYTYPE_INT:
+ array_intarray_element_set((java_handle_intarray_t *) a,
+ index, value.i);
+ break;
+ case ARRAYTYPE_LONG:
+ array_longarray_element_set((java_handle_longarray_t *) a,
+ index, value.l);
+ break;
+ case ARRAYTYPE_FLOAT:
+ array_floatarray_element_set((java_handle_floatarray_t *) a,
+ index, value.f);
+ break;
+ case ARRAYTYPE_DOUBLE:
+ array_doublearray_element_set((java_handle_doublearray_t *) a,
+ index, value.d);
+ break;
+ case ARRAYTYPE_OBJECT:
+ array_objectarray_element_set((java_handle_objectarray_t *) a,
+ index, static_cast<java_handle_t*>(value.a));
+ break;
+ default:
+ vm_abort("array_element_primitive_set: invalid array element type %d",
+ type);
+ }
+}
+
+
+/* array_xxxarray_element_get **************************************************
+
+ Returns a primitive element of the given Java array.
+
+*******************************************************************************/
+
+#define ARRAY_TYPEARRAY_ELEMENT_GET(name, type) \
+type array_##name##array_element_get(java_handle_##name##array_t *a, int32_t index) \
+{ \
+ type value; \
+ int32_t size; \
+ \
+ if (a == NULL) { \
+ exceptions_throw_nullpointerexception(); \
+ return (type) 0; \
+ } \
+ \
+ size = LLNI_array_size(a); \
+ \
+ if ((index < 0) || (index >= size)) { \
+ exceptions_throw_arrayindexoutofboundsexception(); \
+ return (type) 0; \
+ } \
+ \
+ value = LLNI_array_direct(a, index); \
+ \
+ return value; \
+}
+
+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) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ size = LLNI_array_size(a);
+
+ if ((index < 0) || (index >= size)) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return NULL;
+ }
+
+ LLNI_CRITICAL_START;
+ value = LLNI_WRAP(LLNI_array_direct(a, index));
+ LLNI_CRITICAL_END;
+
+ return value;
+}
+
+ARRAY_TYPEARRAY_ELEMENT_GET(boolean, uint8_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(byte, int8_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(char, uint16_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(short, int16_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(int, int32_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(long, int64_t)
+ARRAY_TYPEARRAY_ELEMENT_GET(float, float)
+ARRAY_TYPEARRAY_ELEMENT_GET(double, double)
+
+
+/* array_xxxarray_element_set **************************************************
+
+ Sets a primitive element in the given Java array.
+
+*******************************************************************************/
+
+#define ARRAY_TYPEARRAY_ELEMENT_SET(name, type) \
+void array_##name##array_element_set(java_handle_##name##array_t *a, int32_t index, type value) \
+{ \
+ int32_t size; \
+ \
+ if (a == NULL) { \
+ exceptions_throw_nullpointerexception(); \
+ return; \
+ } \
+ \
+ size = LLNI_array_size(a); \
+ \
+ if ((index < 0) || (index >= size)) { \
+ exceptions_throw_arrayindexoutofboundsexception(); \
+ return; \
+ } \
+ \
+ LLNI_array_direct(a, index) = value; \
+}
+
+void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value)
+{
+ int32_t size;
+
+ if (a == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ /* Sanity check. */
+
+ assert(a->header.objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
+
+ if (value != NULL) {
+ if (builtin_canstore(a, value) == false) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+ }
+
+ size = LLNI_array_size(a);
+
+ if ((index < 0) || (index >= size)) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return;
+ }
+
+ LLNI_CRITICAL_START;
+ LLNI_array_direct(a, index) = LLNI_UNWRAP(value);
+ LLNI_CRITICAL_END;
+}
+
+ARRAY_TYPEARRAY_ELEMENT_SET(boolean, uint8_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(byte, int8_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(char, uint16_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(short, int16_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(int, int32_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(long, int64_t)
+ARRAY_TYPEARRAY_ELEMENT_SET(float, float)
+ARRAY_TYPEARRAY_ELEMENT_SET(double, double)
+
+
+/* array_length_get ***********************************************************
+
+ Returns a the length of the given Java array.
+
+ ARGUMENTS:
+ a ... Java array
+
+ RETURN VALUE:
+ -1 ... exception thrown
+ >= 0 ... length of the Java array
+
+*******************************************************************************/
+
+int32_t array_length_get(java_handle_t *a)
+{
+ classinfo *c;
+ int32_t size;
+
+ if (a == NULL) {
+ exceptions_throw_nullpointerexception();
+ return -1;
+ }
+
+ LLNI_class_get(a, c);
+
+ if (!class_is_array(c)) {
+/* exceptions_throw_illegalargumentexception("Argument is not an array"); */
+ exceptions_throw_illegalargumentexception();
+ return -1;
+ }
+
+ size = LLNI_array_size(a);
+
+ return size;
+}
+
+
+/*
+ * These 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/array.h - Java array 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.
-
-*/
-
-
-#ifndef _VM_ARRAY_H
-#define _VM_ARRAY_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/global.h"
-#include "vm/primitive.hpp"
-
-
-/* array types ****************************************************************/
-
-/* CAUTION: Don't change the numerical values! These constants (with
- the exception of ARRAYTYPE_OBJECT) are used as indices in the
- primitive type table. */
-
-#define ARRAYTYPE_INT PRIMITIVETYPE_INT
-#define ARRAYTYPE_LONG PRIMITIVETYPE_LONG
-#define ARRAYTYPE_FLOAT PRIMITIVETYPE_FLOAT
-#define ARRAYTYPE_DOUBLE PRIMITIVETYPE_DOUBLE
-#define ARRAYTYPE_BYTE PRIMITIVETYPE_BYTE
-#define ARRAYTYPE_CHAR PRIMITIVETYPE_CHAR
-#define ARRAYTYPE_SHORT PRIMITIVETYPE_SHORT
-#define ARRAYTYPE_BOOLEAN PRIMITIVETYPE_BOOLEAN
-#define ARRAYTYPE_OBJECT PRIMITIVETYPE_VOID /* don't use as index! */
-
-
-/* function prototypes ********************************************************/
-
-java_handle_t *array_element_get(java_handle_t *a, int32_t index);
-void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o);
-
-imm_union array_element_primitive_get(java_handle_t *a, int32_t index);
-void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value);
-
-uint8_t array_booleanarray_element_get(java_handle_booleanarray_t *a, int32_t index);
-int8_t array_bytearray_element_get(java_handle_bytearray_t *a, int32_t index);
-uint16_t array_chararray_element_get(java_handle_chararray_t *a, int32_t index);
-int16_t array_shortarray_element_get(java_handle_shortarray_t *a, int32_t index);
-int32_t array_intarray_element_get(java_handle_intarray_t *a, int32_t index);
-int64_t array_longarray_element_get(java_handle_longarray_t *a, int32_t index);
-float array_floatarray_element_get(java_handle_floatarray_t *a, int32_t index);
-double array_doublearray_element_get(java_handle_doublearray_t *a, int32_t index);
-java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index);
-
-void array_booleanarray_element_set(java_handle_booleanarray_t *a, int32_t index, uint8_t value);
-void array_bytearray_element_set(java_handle_bytearray_t *a, int32_t index, int8_t value);
-void array_chararray_element_set(java_handle_chararray_t *a, int32_t index, uint16_t value);
-void array_shortarray_element_set(java_handle_shortarray_t *a, int32_t index, int16_t value);
-void array_intarray_element_set(java_handle_intarray_t *a, int32_t index, int32_t value);
-void array_longarray_element_set(java_handle_longarray_t *a, int32_t index, int64_t value);
-void array_floatarray_element_set(java_handle_floatarray_t *a, int32_t index, float value);
-void array_doublearray_element_set(java_handle_doublearray_t *a, int32_t index, double value);
-void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value);
-
-int32_t array_length_get(java_handle_t *a);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _VM_ARRAY_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/array.hpp - Java array 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.
+
+*/
+
+
+#ifndef _VM_ARRAY_HPP
+#define _VM_ARRAY_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/global.h"
+#include "vm/primitive.hpp"
+
+
+/* array types ****************************************************************/
+
+/* CAUTION: Don't change the numerical values! These constants (with
+ the exception of ARRAYTYPE_OBJECT) are used as indices in the
+ primitive type table. */
+
+#define ARRAYTYPE_INT PRIMITIVETYPE_INT
+#define ARRAYTYPE_LONG PRIMITIVETYPE_LONG
+#define ARRAYTYPE_FLOAT PRIMITIVETYPE_FLOAT
+#define ARRAYTYPE_DOUBLE PRIMITIVETYPE_DOUBLE
+#define ARRAYTYPE_BYTE PRIMITIVETYPE_BYTE
+#define ARRAYTYPE_CHAR PRIMITIVETYPE_CHAR
+#define ARRAYTYPE_SHORT PRIMITIVETYPE_SHORT
+#define ARRAYTYPE_BOOLEAN PRIMITIVETYPE_BOOLEAN
+#define ARRAYTYPE_OBJECT PRIMITIVETYPE_VOID /* don't use as index! */
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+java_handle_t *array_element_get(java_handle_t *a, int32_t index);
+void array_element_set(java_handle_t *a, int32_t index, java_handle_t *o);
+
+imm_union array_element_primitive_get(java_handle_t *a, int32_t index);
+void array_element_primitive_set(java_handle_t *a, int32_t index, imm_union value);
+
+uint8_t array_booleanarray_element_get(java_handle_booleanarray_t *a, int32_t index);
+int8_t array_bytearray_element_get(java_handle_bytearray_t *a, int32_t index);
+uint16_t array_chararray_element_get(java_handle_chararray_t *a, int32_t index);
+int16_t array_shortarray_element_get(java_handle_shortarray_t *a, int32_t index);
+int32_t array_intarray_element_get(java_handle_intarray_t *a, int32_t index);
+int64_t array_longarray_element_get(java_handle_longarray_t *a, int32_t index);
+float array_floatarray_element_get(java_handle_floatarray_t *a, int32_t index);
+double array_doublearray_element_get(java_handle_doublearray_t *a, int32_t index);
+java_handle_t *array_objectarray_element_get(java_handle_objectarray_t *a, int32_t index);
+
+void array_booleanarray_element_set(java_handle_booleanarray_t *a, int32_t index, uint8_t value);
+void array_bytearray_element_set(java_handle_bytearray_t *a, int32_t index, int8_t value);
+void array_chararray_element_set(java_handle_chararray_t *a, int32_t index, uint16_t value);
+void array_shortarray_element_set(java_handle_shortarray_t *a, int32_t index, int16_t value);
+void array_intarray_element_set(java_handle_intarray_t *a, int32_t index, int32_t value);
+void array_longarray_element_set(java_handle_longarray_t *a, int32_t index, int64_t value);
+void array_floatarray_element_set(java_handle_floatarray_t *a, int32_t index, float value);
+void array_doublearray_element_set(java_handle_doublearray_t *a, int32_t index, double value);
+void array_objectarray_element_set(java_handle_objectarray_t *a, int32_t index, java_handle_t *value);
+
+int32_t array_length_get(java_handle_t *a);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _VM_ARRAY_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/assertion.c - assertion options
-
- 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 "mm/memory.h"
-
-#include "toolbox/list.h"
-
-#include "vm/assertion.h"
-#include "vm/global.h"
-#include "vm/os.hpp"
-#include "vm/vm.hpp"
-
-
-/* -ea/-da options ************************************************************/
-
-list_t *list_assertion_names = (list_t *)NULL;
-int32_t assertion_class_count = 0;
-int32_t assertion_package_count = 0;
-bool assertion_user_enabled = false;
-bool assertion_system_enabled = false;
-
-
-/* assertion_ea_da *************************************************************
-
- Handle -ea:/-enableassertions: and -da:/-disableassertions: options.
-
-*******************************************************************************/
-
-void assertion_ea_da(const char *name, bool enabled)
-{
- bool package;
- size_t len;
- char *buf;
- assertion_name_t *item;
- int32_t i;
-
- if (name == NULL) {
- assertion_user_enabled = enabled;
- return;
- }
-
- package = false;
- len = os_strlen(name);
-
- if (name[len - 1] == '/') {
- return;
- }
-
- buf = os_strdup(name);
-
- if (buf == NULL) {
- vm_abort("assertion_ea_da: strdup failed: %s", strerror(errno));
- }
-
- if ((len > 2) && (strcmp(name + (len - 3), "...") == 0)) {
- package = true;
- assertion_package_count += 1;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- buf[len - 2] = '\0';
- buf[len - 3] = '/';
-#else
- buf[len - 3] = '\0';
-#endif
- }
- else {
- assertion_class_count += 1;
- }
-
- len = os_strlen(buf);
-
- for (i = 0; i < len; i++) {
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- if (buf[i] == '.') {
- buf[i] = '/';
- }
-#else
- if (buf[i] == '/') {
- buf[i] = '.';
- }
-#endif
- }
-
- item = NEW(assertion_name_t);
- item->name = buf;
- item->enabled = enabled;
- item->package = package;
-
- if (list_assertion_names == NULL) {
- list_assertion_names = list_create(OFFSET(assertion_name_t, linkage));
- }
-
- list_add_last(list_assertion_names, item);
-}
-
-
-/*
- * These 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/assertion.cpp - assertion options
+
+ 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 <cstddef>
+
+#include "mm/memory.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/assertion.hpp"
+#include "vm/global.h"
+#include "vm/os.hpp"
+
+
+/* -ea/-da options ************************************************************/
+
+List<assertion_name_t*>* list_assertion_names = NULL;
+int32_t assertion_class_count = 0;
+int32_t assertion_package_count = 0;
+bool assertion_user_enabled = false;
+bool assertion_system_enabled = false;
+
+
+/* assertion_ea_da *************************************************************
+
+ Handle -ea:/-enableassertions: and -da:/-disableassertions: options.
+
+*******************************************************************************/
+
+void assertion_ea_da(const char *name, bool enabled)
+{
+ bool package;
+ size_t len;
+ char *buf;
+ assertion_name_t *item;
+
+ if (name == NULL) {
+ assertion_user_enabled = enabled;
+ return;
+ }
+
+ package = false;
+ len = os::strlen(name);
+
+ if (name[len - 1] == '/') {
+ return;
+ }
+
+ buf = os::strdup(name);
+
+ if (buf == NULL) {
+ os::abort_errno("assertion_ea_da: strdup failed");
+ }
+
+ if ((len > 2) && (strcmp(name + (len - 3), "...") == 0)) {
+ package = true;
+ assertion_package_count += 1;
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ buf[len - 2] = '\0';
+ buf[len - 3] = '/';
+#else
+ buf[len - 3] = '\0';
+#endif
+ }
+ else {
+ assertion_class_count += 1;
+ }
+
+ len = os::strlen(buf);
+
+ for (size_t i = 0; i < len; i++) {
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ if (buf[i] == '.') {
+ buf[i] = '/';
+ }
+#else
+ if (buf[i] == '/') {
+ buf[i] = '.';
+ }
+#endif
+ }
+
+ item = NEW(assertion_name_t);
+ item->name = buf;
+ item->enabled = enabled;
+ item->package = package;
+
+ if (list_assertion_names == NULL) {
+ list_assertion_names = new List<assertion_name_t*>();
+ }
+
+ list_assertion_names->push_back(item);
+}
+
+
+/*
+ * These 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/assertion.h - assertion options
-
- 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.
-
-*/
-
-
-#ifndef _ASSERTION_H
-#define _ASSERTION_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/global.h"
-#include "toolbox/list.h"
-
-
-typedef struct assertion_name_t assertion_name_t;
-
-struct assertion_name_t {
- char *name;
- bool enabled;
- bool package;
- listnode_t linkage;
-};
-
-/* -ea/-esa/-da/-dsa options **************************************************/
-
-extern list_t *list_assertion_names;
-extern int32_t assertion_class_count;
-extern int32_t assertion_package_count;
-extern bool assertion_user_enabled;
-extern bool assertion_system_enabled;
-
-/* function prototypes ********************************************************/
-
-void assertion_ea_da(const char *name, bool enabled);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ASSERTION_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/assertion.hpp - assertion options
+
+ 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 _ASSERTION_HPP
+#define _ASSERTION_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "toolbox/list.hpp"
+
+
+typedef struct assertion_name_t assertion_name_t;
+
+struct assertion_name_t {
+ char *name;
+ bool enabled;
+ bool package;
+/* listnode_t linkage; */
+};
+
+/* -ea/-esa/-da/-dsa options **************************************************/
+
+#ifdef __cplusplus
+extern List<assertion_name_t*>* list_assertion_names;
+#else
+extern List* list_assertion_names;
+#endif
+
+extern int32_t assertion_class_count;
+extern int32_t assertion_package_count;
+extern bool assertion_user_enabled;
+extern bool assertion_system_enabled;
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void assertion_ea_da(const char *name, bool enabled);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _ASSERTION_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/builtin.c - functions for unsupported operations
-
- 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.
-
- Contains C functions for JavaVM Instructions that cannot be
- translated to machine language directly. Consequently, the
- generated machine code for these instructions contains function
- calls instead of machine instructions, using the C calling
- convention.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-
-#include "vm/types.h"
-
-#include "arch.h"
-#include "md-abi.h"
-
-#include "fdlibm/fdlibm.h"
-#if defined(__CYGWIN__) && defined(Bias)
-# undef Bias
-#endif
-
-#include "mm/gc.hpp"
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "threads/lock-common.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.hpp"
-#include "vm/global.h"
-#include "vm/globals.hpp"
-#include "vm/initialize.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.hpp"
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-
-/* include builtin tables *****************************************************/
-
-#include "vm/builtintable.inc"
-
-
-CYCLES_STATS_DECLARE(builtin_new ,100,5)
-CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
-
-
-/*============================================================================*/
-/* BUILTIN TABLE MANAGEMENT FUNCTIONS */
-/*============================================================================*/
-
-/* builtintable_init ***********************************************************
-
- Parse the descriptors of builtin functions and create the parsed
- descriptors.
-
-*******************************************************************************/
-
-static bool builtintable_init(void)
-{
- descriptor_pool *descpool;
- builtintable_entry *bte;
- methodinfo *m;
- int32_t dumpmarker;
-
- /* mark start of dump memory area */
-
- DMARKER;
-
- /* create a new descriptor pool */
-
- descpool = descriptor_pool_new(class_java_lang_Object);
-
- /* add some entries we need */
-
- if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
- return false;
-
- if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
- return false;
-
- /* first add all descriptors to the pool */
-
- for (bte = builtintable_internal; bte->fp != NULL; bte++) {
- bte->name = utf_new_char(bte->cname);
- bte->descriptor = utf_new_char(bte->cdescriptor);
-
- if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
- /* release dump area */
-
- DRELEASE;
-
- return false;
- }
- }
-
- for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
- bte->descriptor = utf_new_char(bte->cdescriptor);
-
- if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
- DRELEASE;
- return false;
- }
- }
-
- for (bte = builtintable_function; bte->fp != NULL; bte++) {
- bte->classname = utf_new_char(bte->cclassname);
- bte->name = utf_new_char(bte->cname);
- bte->descriptor = utf_new_char(bte->cdescriptor);
-
- if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
- DRELEASE;
- return false;
- }
- }
-
- /* create the class reference table */
-
- (void) descriptor_pool_create_classrefs(descpool, NULL);
-
- /* allocate space for the parsed descriptors */
-
- descriptor_pool_alloc_parsed_descriptors(descpool);
-
- /* Now parse all descriptors. NOTE: builtin-functions are treated
- like static methods (no `this' pointer). */
-
- for (bte = builtintable_internal; bte->fp != NULL; bte++) {
- bte->md =
- descriptor_pool_parse_method_descriptor(descpool,
- bte->descriptor,
- ACC_STATIC | ACC_METHOD_BUILTIN,
- NULL);
-
- /* generate a builtin stub if we need one */
-
- if (bte->flags & BUILTINTABLE_FLAG_STUB) {
- m = method_new_builtin(bte);
- codegen_generate_stub_builtin(m, bte);
- }
- }
-
- for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
- bte->md =
- descriptor_pool_parse_method_descriptor(descpool,
- bte->descriptor,
- ACC_STATIC | ACC_METHOD_BUILTIN,
- NULL);
-
- /* no stubs should be needed for this table */
-
- assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
- }
-
- for (bte = builtintable_function; bte->fp != NULL; bte++) {
- bte->md =
- descriptor_pool_parse_method_descriptor(descpool,
- bte->descriptor,
- ACC_STATIC | ACC_METHOD_BUILTIN,
- NULL);
-
- /* generate a builtin stub if we need one */
-
- if (bte->flags & BUILTINTABLE_FLAG_STUB) {
- m = method_new_builtin(bte);
- codegen_generate_stub_builtin(m, bte);
- }
- }
-
- /* release dump area */
-
- DRELEASE;
-
- return true;
-}
-
-
-/* builtintable_comparator *****************************************************
-
- qsort comparator for the automatic builtin table.
-
-*******************************************************************************/
-
-static int builtintable_comparator(const void *a, const void *b)
-{
- builtintable_entry *bte1;
- builtintable_entry *bte2;
-
- bte1 = (builtintable_entry *) a;
- bte2 = (builtintable_entry *) b;
-
- return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
-}
-
-
-/* builtintable_sort_automatic *************************************************
-
- Sorts the automatic builtin table.
-
-*******************************************************************************/
-
-static void builtintable_sort_automatic(void)
-{
- s4 entries;
-
- /* calculate table size statically (`- 1' comment see builtintable.inc) */
-
- entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
-
- qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
- builtintable_comparator);
-}
-
-
-/* builtin_init ****************************************************************
-
- Initialize the global table of builtin functions.
-
-*******************************************************************************/
-
-bool builtin_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("builtin_init");
-
- /* initialize the builtin tables */
-
- if (!builtintable_init())
- return false;
-
- /* sort builtin tables */
-
- builtintable_sort_automatic();
-
- return true;
-}
-
-
-/* builtintable_get_by_key *****************************************************
-
- Returns a key for the given builtintable_entry object which is suitable
- for retrieving the instance again by calling builtintable_get_by_key.
-
- The key can be regarded fixed between multiple runs of the JVM.
-
-*******************************************************************************/
-
-s4 builtintable_get_key(builtintable_entry *bte)
-{
- s4 entries;
-/*
- int i;
- entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
- for (i = 0; i < entries; i++)
- if (&builtintable_internal[i] == bte)
- return i + 1;
-
- entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
- for (i = 0; i < entries; i++)
- if (&builtintable_automatic[i] == bte)
- return -i;
-
- entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
- for (i = 0; i < entries; i++)
- if (&builtintable_function[i] == bte)
- return -1000 - i;
-*/
-
- entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
- if (&builtintable_internal[0] <= bte
- && &builtintable_internal[entries - 1] >= bte)
- {
- return (s4) (bte - &builtintable_internal[0]) + 1;
- }
-
- entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
- if (&builtintable_automatic[0] <= bte
- && &builtintable_automatic[entries - 1] >= bte)
- {
- return -(s4) (bte - &builtintable_automatic[0]);
- }
-
- entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
- if (&builtintable_function[0] <= bte
- && &builtintable_function[entries - 1] >= bte)
- {
- return -1000 - (s4) (bte - &builtintable_function[0]);
- }
-
- /* builtintable_entry is not in our tables. */
- assert (0);
-
- return 0;
-}
-
-/* builtintable_get_by_key *****************************************************
-
- Retrieves an entry in the internal and automatic builtin functions tables
- using a key that was retrived previously with builtintable_get_key()
-
-*******************************************************************************/
-
-builtintable_entry *builtintable_get_by_key(s4 key)
-{
- /* If key is positive it is the index into builtintable_internal. If it is
- * negative it is the index into builtintable_automatic. If it is <= -1000
- * it is the index into builtintable_function.
- */
- return (key > 0)
- ? &builtintable_internal[key - 1]
- : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
-}
-
-/* builtintable_get_internal ***************************************************
-
- Finds an entry in the builtintable for internal functions and
- returns the a pointer to the structure.
-
-*******************************************************************************/
-
-builtintable_entry *builtintable_get_internal(functionptr fp)
-{
- builtintable_entry *bte;
-
- for (bte = builtintable_internal; bte->fp != NULL; bte++) {
- if (bte->fp == fp)
- return bte;
- }
-
- return NULL;
-}
-
-
-/* builtintable_get_automatic **************************************************
-
- Finds an entry in the builtintable for functions which are replaced
- automatically and returns the a pointer to the structure.
-
-*******************************************************************************/
-
-builtintable_entry *builtintable_get_automatic(s4 opcode)
-{
- builtintable_entry *first;
- builtintable_entry *last;
- builtintable_entry *middle;
- s4 half;
- s4 entries;
-
- /* calculate table size statically (`- 1' comment see builtintable.inc) */
-
- entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
-
- first = builtintable_automatic;
- last = builtintable_automatic + entries;
-
- while (entries > 0) {
- half = entries / 2;
- middle = first + half;
-
- if (middle->opcode < opcode) {
- first = middle + 1;
- entries -= half + 1;
- }
- else
- entries = half;
- }
-
- return (first != last ? first : NULL);
-}
-
-
-/* builtintable_replace_function ***********************************************
-
- XXX
-
-*******************************************************************************/
-
-#if defined(ENABLE_JIT)
-bool builtintable_replace_function(void *iptr_)
-{
- constant_FMIref *mr;
- builtintable_entry *bte;
- instruction *iptr;
-
- iptr = (instruction *) iptr_; /* twisti will kill me ;) */
-
- /* get name and descriptor of the function */
-
- switch (iptr->opc) {
- case ICMD_INVOKESTATIC:
- /* The instruction MUST be resolved, otherwise we run into
- lazy loading troubles. Anyway, we should/can only replace
- very VM-close functions. */
-
- if (INSTRUCTION_IS_UNRESOLVED(iptr))
- return false;
-
- mr = iptr->sx.s23.s3.fmiref;
- break;
-
- default:
- return false;
- }
-
- /* search the function table */
-
- for (bte = builtintable_function; bte->fp != NULL; bte++) {
- if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
- (mr->name == bte->name) &&
- (mr->descriptor == bte->descriptor)) {
-
- /* set the values in the instruction */
-
- iptr->opc = bte->opcode;
- iptr->sx.s23.s3.bte = bte;
-
- if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
- iptr->flags.bits |= INS_FLAG_CHECK;
- else
- iptr->flags.bits &= ~INS_FLAG_CHECK;
-
- return true;
- }
- }
-
- return false;
-}
-#endif /* defined(ENABLE_JIT) */
-
-
-/*============================================================================*/
-/* INTERNAL BUILTIN FUNCTIONS */
-/*============================================================================*/
-
-/* builtin_instanceof **********************************************************
-
- Checks if an object is an instance of some given class (or subclass
- of that class). If class is an interface, checks if the interface
- is implemented.
-
- RETURN VALUE:
- 1......o is an instance of class or implements the interface
- 0......otherwise or if o == NULL
-
- NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-bool builtin_instanceof(java_handle_t *o, classinfo *c)
-{
- classinfo *oc;
-
- if (o == NULL)
- return 0;
-
- LLNI_class_get(o, oc);
-
- return class_isanysubclass(oc, c);
-}
-
-
-
-/* builtin_checkcast ***********************************************************
-
- The same as builtin_instanceof but with the exception
- that 1 is returned when (o == NULL).
-
- NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-bool builtin_checkcast(java_handle_t *o, classinfo *c)
-{
- classinfo *oc;
-
- if (o == NULL)
- return 1;
-
- LLNI_class_get(o, oc);
-
- if (class_isanysubclass(oc, c))
- return 1;
-
- return 0;
-}
-
-
-/* builtin_descriptorscompatible ***********************************************
-
- Checks if two array type descriptors are assignment compatible.
-
- RETURN VALUE:
- 1......target = desc is possible
- 0......otherwise
-
-*******************************************************************************/
-
-static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
-{
- if (desc == target)
- return 1;
-
- if (desc->arraytype != target->arraytype)
- return 0;
-
- if (desc->arraytype != ARRAYTYPE_OBJECT)
- return 1;
-
- /* {both arrays are arrays of references} */
-
- if (desc->dimension == target->dimension) {
- if (!desc->elementvftbl)
- return 0;
- /* an array which contains elements of interface types is
- allowed to be casted to Object (JOWENN)*/
-
- if ((desc->elementvftbl->baseval < 0) &&
- (target->elementvftbl->baseval == 1))
- return 1;
-
- return class_isanysubclass(desc->elementvftbl->clazz,
- target->elementvftbl->clazz);
- }
-
- if (desc->dimension < target->dimension)
- return 0;
-
- /* {desc has higher dimension than target} */
-
- return class_isanysubclass(pseudo_class_Arraystub,
- target->elementvftbl->clazz);
-}
-
-
-/* builtin_arraycheckcast ******************************************************
-
- Checks if an object is really a subtype of the requested array
- type. The object has to be an array to begin with. For simple
- arrays (int, short, double, etc.) the types have to match exactly.
- For arrays of objects, the type of elements in the array has to be
- a subtype (or the same type) of the requested element type. For
- arrays of arrays (which in turn can again be arrays of arrays), the
- types at the lowest level have to satisfy the corresponding sub
- class relation.
-
- NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
-{
- arraydescriptor *desc;
-
- if (o == NULL)
- return 1;
-
- desc = o->vftbl->arraydesc;
-
- if (desc == NULL)
- return 0;
-
- return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
-}
-
-
-/* builtin_fast_arrayinstanceof ************************************************
-
- NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
-{
- if (o == NULL)
- return 0;
-
- return builtin_fast_arraycheckcast(o, targetclass);
-}
-
-
-/* builtin_arrayinstanceof *****************************************************
-
- NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
-{
- bool result;
-
- LLNI_CRITICAL_START;
-
- result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
-
- LLNI_CRITICAL_END;
-
- return result;
-}
-
-
-/* builtin_throw_exception *****************************************************
-
- Sets the exception pointer with the thrown exception and prints some
- debugging information.
-
- NOTE: This is a FAST builtin and can be called from JIT code,
- or from asm_vm_call_method.
-
-*******************************************************************************/
-
-void *builtin_throw_exception(java_object_t *xptr)
-{
-#if !defined(NDEBUG)
- /* print exception trace */
-
- if (opt_TraceExceptions)
- trace_exception_builtin(xptr);
-#endif /* !defined(NDEBUG) */
-
- /* actually set the exception */
-
- exceptions_set_exception(LLNI_QUICKWRAP(xptr));
-
- /* Return a NULL pointer. This is required for vm_call_method to
- check for an exception. This is for convenience. */
-
- return NULL;
-}
-
-
-/* builtin_retrieve_exception **************************************************
-
- Gets and clears the exception pointer of the current thread.
-
- RETURN VALUE:
- the exception object, or NULL if no exception was thrown.
-
- NOTE: This is a FAST builtin and can be called from JIT code,
- or from the signal handlers.
-
-*******************************************************************************/
-
-java_object_t *builtin_retrieve_exception(void)
-{
- java_handle_t *h;
- java_object_t *o;
-
- /* actually get and clear the exception */
-
- h = exceptions_get_and_clear_exception();
- o = LLNI_UNWRAP(h);
-
- return o;
-}
-
-
-/* builtin_canstore ************************************************************
-
- Checks, if an object can be stored in an array.
-
- RETURN VALUE:
- 1......possible
- 0......otherwise (throws an ArrayStoreException)
-
- NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
-{
- bool result;
-
- LLNI_CRITICAL_START;
-
- result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
-
- LLNI_CRITICAL_END;
-
- /* if not possible, throw an exception */
-
- if (result == 0)
- exceptions_throw_arraystoreexception();
-
- return result;
-}
-
-
-/* builtin_fast_canstore *******************************************************
-
- Checks, if an object can be stored in an array.
-
- RETURN VALUE:
- 1......possible
- 0......otherwise (no exception thrown!)
-
- NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
-{
- arraydescriptor *desc;
- arraydescriptor *valuedesc;
- vftbl_t *componentvftbl;
- vftbl_t *valuevftbl;
- int32_t baseval;
- uint32_t diffval;
- bool result;
-
- if (o == NULL)
- return 1;
-
- /* The following is guaranteed (by verifier checks):
- *
- * *) oa->...vftbl->arraydesc != NULL
- * *) oa->...vftbl->arraydesc->componentvftbl != NULL
- * *) o->vftbl is not an interface vftbl
- */
-
- desc = oa->header.objheader.vftbl->arraydesc;
- componentvftbl = desc->componentvftbl;
- valuevftbl = o->vftbl;
- valuedesc = valuevftbl->arraydesc;
-
- if ((desc->dimension - 1) == 0) {
- /* {oa is a one-dimensional array} */
- /* {oa is an array of references} */
-
- if (valuevftbl == componentvftbl)
- return 1;
-
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
- baseval = componentvftbl->baseval;
-
- if (baseval <= 0) {
- /* an array of interface references */
-
- result = ((valuevftbl->interfacetablelength > -baseval) &&
- (valuevftbl->interfacetable[baseval] != NULL));
- }
- else {
- diffval = valuevftbl->baseval - componentvftbl->baseval;
- result = diffval <= (uint32_t) componentvftbl->diffval;
- }
-
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
- }
- else if (valuedesc == NULL) {
- /* {oa has dimension > 1} */
- /* {componentvftbl->arraydesc != NULL} */
-
- /* check if o is an array */
-
- return 0;
- }
- else {
- /* {o is an array} */
-
- result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
- }
-
- /* return result */
-
- return result;
-}
-
-
-/* This is an optimized version where a is guaranteed to be one-dimensional */
-bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
-{
- arraydescriptor *desc;
- vftbl_t *elementvftbl;
- vftbl_t *valuevftbl;
- int32_t baseval;
- uint32_t diffval;
- bool result;
-
- if (o == NULL)
- return 1;
-
- /* The following is guaranteed (by verifier checks):
- *
- * *) a->...vftbl->arraydesc != NULL
- * *) a->...vftbl->arraydesc->elementvftbl != NULL
- * *) a->...vftbl->arraydesc->dimension == 1
- * *) o->vftbl is not an interface vftbl
- */
-
- desc = a->header.objheader.vftbl->arraydesc;
- elementvftbl = desc->elementvftbl;
- valuevftbl = o->vftbl;
-
- /* {a is a one-dimensional array} */
-
- if (valuevftbl == elementvftbl)
- return 1;
-
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
- baseval = elementvftbl->baseval;
-
- if (baseval <= 0) {
- /* an array of interface references */
- result = ((valuevftbl->interfacetablelength > -baseval) &&
- (valuevftbl->interfacetable[baseval] != NULL));
- }
- else {
- diffval = valuevftbl->baseval - elementvftbl->baseval;
- result = diffval <= (uint32_t) elementvftbl->diffval;
- }
-
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
- return result;
-}
-
-
-/* This is an optimized version where a is guaranteed to be a
- * one-dimensional array of a class type */
-bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
-{
- vftbl_t *elementvftbl;
- vftbl_t *valuevftbl;
- uint32_t diffval;
- bool result;
-
- if (o == NULL)
- return 1;
-
- /* The following is guaranteed (by verifier checks):
- *
- * *) a->...vftbl->arraydesc != NULL
- * *) a->...vftbl->arraydesc->elementvftbl != NULL
- * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
- * *) a->...vftbl->arraydesc->dimension == 1
- * *) o->vftbl is not an interface vftbl
- */
-
- elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
- valuevftbl = o->vftbl;
-
- /* {a is a one-dimensional array} */
-
- if (valuevftbl == elementvftbl)
- return 1;
-
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
- diffval = valuevftbl->baseval - elementvftbl->baseval;
- result = diffval <= (uint32_t) elementvftbl->diffval;
-
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
- return result;
-}
-
-
-/* builtin_new *****************************************************************
-
- Creates a new instance of class c on the heap.
-
- RETURN VALUE:
- pointer to the object, or NULL if no memory is available
-
- NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_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 = 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;
-}
-
-#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 ************************************************************
-
- NOTE: This is a SLOW builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_java_new(java_handle_t *clazz)
-{
- return builtin_new(LLNI_classinfo_unwrap(clazz));
-}
-
-
-/* builtin_fast_new ************************************************************
-
- Creates a new instance of class c on the heap.
-
- RETURN VALUE:
- pointer to the object, or NULL if no fast return
- is possible for any reason.
-
- NOTE: This is a FAST builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-java_object_t *builtin_fast_new(classinfo *c)
-{
- java_object_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)
- return NULL;
-
- /* is the class linked */
-
- if (!(c->state & CLASS_LINKED))
- return NULL;
-
- if (!(c->state & CLASS_INITIALIZED))
- return NULL;
-
- o = heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
- c->finalizer, false);
-
- if (!o)
- return NULL;
-
- o->vftbl = c->vftbl;
-
-#if defined(ENABLE_THREADS)
- lock_init_object_lock(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;
-}
-
-
-/* builtin_newarray ************************************************************
-
- Creates an array with the given vftbl on the heap. This function
- takes as class argument an array class.
-
- RETURN VALUE:
- pointer to the array or NULL if no memory is available
-
- NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
-{
- arraydescriptor *desc;
- s4 dataoffset;
- s4 componentsize;
- s4 actualsize;
- java_handle_t *a;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_end;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- desc = arrayclass->vftbl->arraydesc;
- dataoffset = desc->dataoffset;
- componentsize = desc->componentsize;
-
- if (size < 0) {
- exceptions_throw_negativearraysizeexception();
- return NULL;
- }
-
- actualsize = dataoffset + size * componentsize;
-
- /* check for overflow */
-
- if (((u4) actualsize) < ((u4) size)) {
- exceptions_throw_outofmemoryerror();
- return NULL;
- }
-
- a = heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
-
- if (a == NULL)
- return NULL;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
- /* XXX this is only a dirty hack to make Boehm work with handles */
-
- a = LLNI_WRAP((java_object_t *) a);
-#endif
-
- LLNI_vftbl_direct(a) = arrayclass->vftbl;
-
-#if defined(ENABLE_THREADS)
- lock_init_object_lock(LLNI_DIRECT(a));
-#endif
-
- LLNI_array_size(a) = size;
-
- RT_TIMING_GET_TIME(time_end);
- RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
-
- return a;
-}
-
-
-/* builtin_java_newarray *******************************************************
-
- NOTE: This is a SLOW builtin and can be called from JIT code only.
-
-*******************************************************************************/
-
-java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
-{
- return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
-}
-
-
-/* builtin_anewarray ***********************************************************
-
- Creates an array of references to the given class type on the heap.
-
- RETURN VALUE:
- pointer to the array or NULL if no memory is
- available
-
- NOTE: This builtin can be called from NATIVE code only.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
-{
- classinfo *arrayclass;
-
- /* is class loaded */
-
- assert(componentclass->state & CLASS_LOADED);
-
- /* is class linked */
-
- if (!(componentclass->state & CLASS_LINKED))
- if (!link_class(componentclass))
- return NULL;
-
- arrayclass = class_array_of(componentclass, true);
-
- if (!arrayclass)
- return NULL;
-
- return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
-}
-
-
-/* builtin_newarray_type ****************************************************
-
- Creates an array of [type]s on the heap.
-
- RETURN VALUE:
- pointer to the array or NULL if no memory is available
-
- NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-#define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
-java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
-{ \
- return (java_handle_##type##array_t *) \
- builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
-}
-
-BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
-BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
-BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
-BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
-BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
-BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
-BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
-BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
-
-
-/* builtin_multianewarray_intern ***********************************************
-
- Creates a multi-dimensional array on the heap. The dimensions are
- passed in an array of longs.
-
- ARGUMENTS:
- n.............number of dimensions to create
- arrayclass....the array class
- dims..........array containing the size of each dimension to create
-
- RETURN VALUE:
- pointer to the array or NULL if no memory is available
-
-******************************************************************************/
-
-static java_handle_t *builtin_multianewarray_intern(int n,
- classinfo *arrayclass,
- long *dims)
-{
- s4 size;
- java_handle_t *a;
- classinfo *componentclass;
- s4 i;
-
- /* create this dimension */
-
- size = (s4) dims[0];
- a = builtin_newarray(size, arrayclass);
-
- if (!a)
- return NULL;
-
- /* if this is the last dimension return */
-
- if (!--n)
- return a;
-
- /* get the class of the components to create */
-
- componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
-
- /* The verifier guarantees that the dimension count is in the range. */
-
- /* create the component arrays */
-
- for (i = 0; i < size; i++) {
- java_handle_t *ea =
-#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
- /* we save an s4 to a s8 slot, 8-byte aligned */
-
- builtin_multianewarray_intern(n, componentclass, dims + 2);
-#else
- builtin_multianewarray_intern(n, componentclass, dims + 1);
-#endif
-
- if (!ea)
- return NULL;
-
- array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
- }
-
- return a;
-}
-
-
-/* builtin_multianewarray ******************************************************
-
- Wrapper for builtin_multianewarray_intern which checks all
- dimensions before we start allocating.
-
- NOTE: This is a SLOW builtin and can be called from JIT code only.
-
-******************************************************************************/
-
-java_handle_objectarray_t *builtin_multianewarray(int n,
- java_handle_t *arrayclazz,
- long *dims)
-{
- classinfo *c;
- s4 i;
- s4 size;
-
- /* check all dimensions before doing anything */
-
- for (i = 0; i < n; i++) {
-#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
- /* we save an s4 to a s8 slot, 8-byte aligned */
- size = (s4) dims[i * 2];
-#else
- size = (s4) dims[i];
-#endif
-
- if (size < 0) {
- exceptions_throw_negativearraysizeexception();
- return NULL;
- }
- }
-
- c = LLNI_classinfo_unwrap(arrayclazz);
-
- /* now call the real function */
-
- return (java_handle_objectarray_t *)
- builtin_multianewarray_intern(n, c, dims);
-}
-
-
-/* builtin_verbosecall_enter ***************************************************
-
- Print method call with arguments for -verbose:call.
-
- XXX: Remove mew once all archs use the new tracer!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-#ifdef TRACE_ARGS_NUM
-void builtin_verbosecall_enter(s8 a0, s8 a1,
-# if TRACE_ARGS_NUM >= 4
- s8 a2, s8 a3,
-# endif
-# if TRACE_ARGS_NUM >= 6
- s8 a4, s8 a5,
-# endif
-# if TRACE_ARGS_NUM == 8
- s8 a6, s8 a7,
-# endif
- methodinfo *m)
-{
- log_text("builtin_verbosecall_enter: Do not call me anymore!");
-}
-#endif
-#endif /* !defined(NDEBUG) */
-
-
-/* builtin_verbosecall_exit ****************************************************
-
- Print method exit for -verbose:call.
-
- XXX: Remove mew once all archs use the new tracer!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
-{
- log_text("builtin_verbosecall_exit: Do not call me anymore!");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/*============================================================================*/
-/* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
-/*============================================================================*/
-
-/*********** Functions for integer divisions *****************************
-
- On some systems (eg. DEC ALPHA), integer division is not supported by the
- CPU. These helper functions implement the missing functionality.
-
-******************************************************************************/
-
-#if !SUPPORT_DIVISION || defined(DISABLE_GC)
-s4 builtin_idiv(s4 a, s4 b)
-{
- s4 c;
-
- c = a / b;
-
- return c;
-}
-
-s4 builtin_irem(s4 a, s4 b)
-{
- s4 c;
-
- c = a % b;
-
- return c;
-}
-#endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
-
-
-/* functions for long arithmetics **********************************************
-
- On systems where 64 bit Integers are not supported by the CPU,
- these functions are needed.
-
-******************************************************************************/
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
-s8 builtin_ladd(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a + b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-
-s8 builtin_lsub(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a - b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-
-s8 builtin_lneg(s8 a)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = -a;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
-s8 builtin_lmul(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a * b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
-
-
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
-s8 builtin_ldiv(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a / b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-
-s8 builtin_lrem(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a % b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
-s8 builtin_lshl(s8 a, s4 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a << (b & 63);
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-
-s8 builtin_lshr(s8 a, s4 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a >> (b & 63);
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-
-s8 builtin_lushr(s8 a, s4 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = ((u8) a) >> (b & 63);
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
-s8 builtin_land(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a & b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-
-s8 builtin_lor(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a | b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-
-s8 builtin_lxor(s8 a, s8 b)
-{
- s8 c;
-
-#if U8_AVAILABLE
- c = a ^ b;
-#else
- c = builtin_i2l(0);
-#endif
-
- return c;
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
-s4 builtin_lcmp(s8 a, s8 b)
-{
-#if U8_AVAILABLE
- if (a < b)
- return -1;
-
- if (a > b)
- return 1;
-
- return 0;
-#else
- return 0;
-#endif
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
-
-
-/* functions for unsupported floating instructions ****************************/
-
-/* used to convert FLT_xxx defines into float values */
-
-static inline float intBitsToFloat(s4 i)
-{
- imm_union imb;
-
- imb.i = i;
- return imb.f;
-}
-
-
-/* used to convert DBL_xxx defines into double values */
-
-static inline float longBitsToDouble(s8 l)
-{
- imm_union imb;
-
- imb.l = l;
- return imb.d;
-}
-
-
-#if !SUPPORT_FLOAT
-float builtin_fadd(float a, float b)
-{
- if (isnanf(a)) return intBitsToFloat(FLT_NAN);
- if (isnanf(b)) return intBitsToFloat(FLT_NAN);
- if (finitef(a)) {
- if (finitef(b))
- return a + b;
- else
- return b;
- }
- else {
- if (finitef(b))
- return a;
- else {
- if (copysignf(1.0, a) == copysignf(1.0, b))
- return a;
- else
- return intBitsToFloat(FLT_NAN);
- }
- }
-}
-
-
-float builtin_fsub(float a, float b)
-{
- return builtin_fadd(a, builtin_fneg(b));
-}
-
-
-float builtin_fmul(float a, float b)
-{
- if (isnanf(a)) return intBitsToFloat(FLT_NAN);
- if (isnanf(b)) return intBitsToFloat(FLT_NAN);
- if (finitef(a)) {
- if (finitef(b)) return a * b;
- else {
- if (a == 0) return intBitsToFloat(FLT_NAN);
- else return copysignf(b, copysignf(1.0, b)*a);
- }
- }
- else {
- if (finitef(b)) {
- if (b == 0) return intBitsToFloat(FLT_NAN);
- else return copysignf(a, copysignf(1.0, a)*b);
- }
- else {
- return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
- }
- }
-}
-
-
-/* builtin_ddiv ****************************************************************
-
- Implementation as described in VM Spec.
-
-*******************************************************************************/
-
-float builtin_fdiv(float a, float b)
-{
- if (finitef(a)) {
- if (finitef(b)) {
- /* If neither value1' nor value2' is NaN, the sign of the result */
- /* is positive if both values have the same sign, negative if the */
- /* values have different signs. */
-
- return a / b;
-
- } else {
- if (isnanf(b)) {
- /* If either value1' or value2' is NaN, the result is NaN. */
-
- return intBitsToFloat(FLT_NAN);
-
- } else {
- /* Division of a finite value by an infinity results in a */
- /* signed zero, with the sign-producing rule just given. */
-
- /* is sign equal? */
-
- if (copysignf(1.0, a) == copysignf(1.0, b))
- return 0.0;
- else
- return -0.0;
- }
- }
-
- } else {
- if (isnanf(a)) {
- /* If either value1' or value2' is NaN, the result is NaN. */
-
- return intBitsToFloat(FLT_NAN);
-
- } else if (finitef(b)) {
- /* Division of an infinity by a finite value results in a signed */
- /* infinity, with the sign-producing rule just given. */
-
- /* is sign equal? */
-
- if (copysignf(1.0, a) == copysignf(1.0, b))
- return intBitsToFloat(FLT_POSINF);
- else
- return intBitsToFloat(FLT_NEGINF);
-
- } else {
- /* Division of an infinity by an infinity results in NaN. */
-
- return intBitsToFloat(FLT_NAN);
- }
- }
-}
-
-
-float builtin_fneg(float a)
-{
- if (isnanf(a)) return a;
- else {
- if (finitef(a)) return -a;
- else return copysignf(a, -copysignf(1.0, a));
- }
-}
-#endif /* !SUPPORT_FLOAT */
-
-
-#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
-s4 builtin_fcmpl(float a, float b)
-{
- if (isnanf(a))
- return -1;
-
- if (isnanf(b))
- return -1;
-
- if (!finitef(a) || !finitef(b)) {
- a = finitef(a) ? 0 : copysignf(1.0, a);
- b = finitef(b) ? 0 : copysignf(1.0, b);
- }
-
- if (a > b)
- return 1;
-
- if (a == b)
- return 0;
-
- return -1;
-}
-
-
-s4 builtin_fcmpg(float a, float b)
-{
- if (isnanf(a)) return 1;
- if (isnanf(b)) return 1;
- if (!finitef(a) || !finitef(b)) {
- a = finitef(a) ? 0 : copysignf(1.0, a);
- b = finitef(b) ? 0 : copysignf(1.0, b);
- }
- if (a > b) return 1;
- if (a == b) return 0;
- return -1;
-}
-#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
-
-
-float builtin_frem(float a, float b)
-{
- return fmodf(a, b);
-}
-
-
-/* functions for unsupported double instructions ******************************/
-
-#if !SUPPORT_DOUBLE
-double builtin_dadd(double a, double b)
-{
- if (isnan(a)) return longBitsToDouble(DBL_NAN);
- if (isnan(b)) return longBitsToDouble(DBL_NAN);
- if (finite(a)) {
- if (finite(b)) return a + b;
- else return b;
- }
- else {
- if (finite(b)) return a;
- else {
- if (copysign(1.0, a)==copysign(1.0, b)) return a;
- else return longBitsToDouble(DBL_NAN);
- }
- }
-}
-
-
-double builtin_dsub(double a, double b)
-{
- return builtin_dadd(a, builtin_dneg(b));
-}
-
-
-double builtin_dmul(double a, double b)
-{
- if (isnan(a)) return longBitsToDouble(DBL_NAN);
- if (isnan(b)) return longBitsToDouble(DBL_NAN);
- if (finite(a)) {
- if (finite(b)) return a * b;
- else {
- if (a == 0) return longBitsToDouble(DBL_NAN);
- else return copysign(b, copysign(1.0, b) * a);
- }
- }
- else {
- if (finite(b)) {
- if (b == 0) return longBitsToDouble(DBL_NAN);
- else return copysign(a, copysign(1.0, a) * b);
- }
- else {
- return copysign(a, copysign(1.0, a) * copysign(1.0, b));
- }
- }
-}
-
-
-/* builtin_ddiv ****************************************************************
-
- Implementation as described in VM Spec.
-
-*******************************************************************************/
-
-double builtin_ddiv(double a, double b)
-{
- if (finite(a)) {
- if (finite(b)) {
- /* If neither value1' nor value2' is NaN, the sign of the result */
- /* is positive if both values have the same sign, negative if the */
- /* values have different signs. */
-
- return a / b;
-
- } else {
- if (isnan(b)) {
- /* If either value1' or value2' is NaN, the result is NaN. */
-
- return longBitsToDouble(DBL_NAN);
-
- } else {
- /* Division of a finite value by an infinity results in a */
- /* signed zero, with the sign-producing rule just given. */
-
- /* is sign equal? */
-
- if (copysign(1.0, a) == copysign(1.0, b))
- return 0.0;
- else
- return -0.0;
- }
- }
-
- } else {
- if (isnan(a)) {
- /* If either value1' or value2' is NaN, the result is NaN. */
-
- return longBitsToDouble(DBL_NAN);
-
- } else if (finite(b)) {
- /* Division of an infinity by a finite value results in a signed */
- /* infinity, with the sign-producing rule just given. */
-
- /* is sign equal? */
-
- if (copysign(1.0, a) == copysign(1.0, b))
- return longBitsToDouble(DBL_POSINF);
- else
- return longBitsToDouble(DBL_NEGINF);
-
- } else {
- /* Division of an infinity by an infinity results in NaN. */
-
- return longBitsToDouble(DBL_NAN);
- }
- }
-}
-
-
-/* builtin_dneg ****************************************************************
-
- Implemented as described in VM Spec.
-
-*******************************************************************************/
-
-double builtin_dneg(double a)
-{
- if (isnan(a)) {
- /* If the operand is NaN, the result is NaN (recall that NaN has no */
- /* sign). */
-
- return a;
-
- } else {
- if (finite(a)) {
- /* If the operand is a zero, the result is the zero of opposite */
- /* sign. */
-
- return -a;
-
- } else {
- /* If the operand is an infinity, the result is the infinity of */
- /* opposite sign. */
-
- return copysign(a, -copysign(1.0, a));
- }
- }
-}
-#endif /* !SUPPORT_DOUBLE */
-
-
-#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
-s4 builtin_dcmpl(double a, double b)
-{
- if (isnan(a))
- return -1;
-
- if (isnan(b))
- return -1;
-
- if (!finite(a) || !finite(b)) {
- a = finite(a) ? 0 : copysign(1.0, a);
- b = finite(b) ? 0 : copysign(1.0, b);
- }
-
- if (a > b)
- return 1;
-
- if (a == b)
- return 0;
-
- return -1;
-}
-
-
-s4 builtin_dcmpg(double a, double b)
-{
- if (isnan(a))
- return 1;
-
- if (isnan(b))
- return 1;
-
- if (!finite(a) || !finite(b)) {
- a = finite(a) ? 0 : copysign(1.0, a);
- b = finite(b) ? 0 : copysign(1.0, b);
- }
-
- if (a > b)
- return 1;
-
- if (a == b)
- return 0;
-
- return -1;
-}
-#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
-
-
-double builtin_drem(double a, double b)
-{
- return fmod(a, b);
-}
-
-
-/* conversion operations ******************************************************/
-
-#if 0
-s8 builtin_i2l(s4 i)
-{
-#if U8_AVAILABLE
- return i;
-#else
- s8 v;
- v.high = 0;
- v.low = i;
- return v;
-#endif
-}
-
-s4 builtin_l2i(s8 l)
-{
-#if U8_AVAILABLE
- return (s4) l;
-#else
- return l.low;
-#endif
-}
-#endif
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_I2F)
-float builtin_i2f(s4 a)
-{
- float f = (float) a;
- return f;
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
-
-
-#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
-double builtin_i2d(s4 a)
-{
- double d = (double) a;
- return d;
-}
-#endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
-float builtin_l2f(s8 a)
-{
-#if U8_AVAILABLE
- float f = (float) a;
- return f;
-#else
- return 0.0;
-#endif
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
-
-
-#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
-double builtin_l2d(s8 a)
-{
-#if U8_AVAILABLE
- double d = (double) a;
- return d;
-#else
- return 0.0;
-#endif
-}
-#endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-s4 builtin_f2i(float a)
-{
- s4 i;
-
- i = builtin_d2i((double) a);
-
- return i;
-
- /* float f;
-
- if (isnanf(a))
- return 0;
- if (finitef(a)) {
- if (a > 2147483647)
- return 2147483647;
- if (a < (-2147483648))
- return (-2147483648);
- return (s4) a;
- }
- f = copysignf((float) 1.0, a);
- if (f > 0)
- return 2147483647;
- return (-2147483648); */
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
-s8 builtin_f2l(float a)
-{
- s8 l;
-
- l = builtin_d2l((double) a);
-
- return l;
-
- /* float f;
-
- if (finitef(a)) {
- if (a > 9223372036854775807L)
- return 9223372036854775807L;
- if (a < (-9223372036854775808L))
- return (-9223372036854775808L);
- return (s8) a;
- }
- if (isnanf(a))
- return 0;
- f = copysignf((float) 1.0, a);
- if (f > 0)
- return 9223372036854775807L;
- return (-9223372036854775808L); */
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
-
-
-#if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
-s4 builtin_d2i(double a)
-{
- double d;
-
- if (finite(a)) {
- if (a >= 2147483647)
- return 2147483647;
- if (a <= (-2147483647-1))
- return (-2147483647-1);
- return (s4) a;
- }
- if (isnan(a))
- return 0;
- d = copysign(1.0, a);
- if (d > 0)
- return 2147483647;
- return (-2147483647-1);
-}
-#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
-
-
-#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
-s8 builtin_d2l(double a)
-{
- double d;
-
- if (finite(a)) {
- if (a >= 9223372036854775807LL)
- return 9223372036854775807LL;
- if (a <= (-9223372036854775807LL-1))
- return (-9223372036854775807LL-1);
- return (s8) a;
- }
- if (isnan(a))
- return 0;
- d = copysign(1.0, a);
- if (d > 0)
- return 9223372036854775807LL;
- return (-9223372036854775807LL-1);
-}
-#endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
-
-
-#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
-double builtin_f2d(float a)
-{
- if (finitef(a)) return (double) a;
- else {
- if (isnanf(a))
- return longBitsToDouble(DBL_NAN);
- else
- return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
- }
-}
-
-float builtin_d2f(double a)
-{
- if (finite(a))
- return (float) a;
- else {
- if (isnan(a))
- return intBitsToFloat(FLT_NAN);
- else
- return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
- }
-}
-#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
-
-
-/*============================================================================*/
-/* AUTOMATICALLY REPLACED FUNCTIONS */
-/*============================================================================*/
-
-/* builtin_arraycopy ***********************************************************
-
- Builtin for java.lang.System.arraycopy.
-
- NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-void builtin_arraycopy(java_handle_t *src, s4 srcStart,
- java_handle_t *dest, s4 destStart, s4 len)
-{
- arraydescriptor *sdesc;
- arraydescriptor *ddesc;
- s4 i;
-
- if ((src == NULL) || (dest == NULL)) {
- exceptions_throw_nullpointerexception();
- return;
- }
-
- sdesc = LLNI_vftbl_direct(src)->arraydesc;
- ddesc = LLNI_vftbl_direct(dest)->arraydesc;
-
- if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
- exceptions_throw_arraystoreexception();
- return;
- }
-
- // Check if offsets and length are positive.
- if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
- exceptions_throw_arrayindexoutofboundsexception();
- return;
- }
-
- // Check if ranges are valid.
- if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
- (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
- exceptions_throw_arrayindexoutofboundsexception();
- return;
- }
-
- // Special case.
- if (len == 0) {
- return;
- }
-
- if (sdesc->componentvftbl == ddesc->componentvftbl) {
- /* We copy primitive values or references of exactly the same type */
-
- s4 dataoffset = sdesc->dataoffset;
- s4 componentsize = sdesc->componentsize;
-
- LLNI_CRITICAL_START;
-
- MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
- ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
- u1, (size_t) len * componentsize);
-
- LLNI_CRITICAL_END;
- }
- else {
- /* We copy references of different type */
-
- java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
- java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
-
- if (destStart <= srcStart) {
- for (i = 0; i < len; i++) {
- java_handle_t *o;
-
- o = array_objectarray_element_get(oas, srcStart + i);
-
- if (!builtin_canstore(oad, o))
- return;
-
- array_objectarray_element_set(oad, destStart + i, o);
- }
- }
- else {
- /* XXX this does not completely obey the specification!
- If an exception is thrown only the elements above the
- current index have been copied. The specification
- requires that only the elements *below* the current
- index have been copied before the throw. */
-
- for (i = len - 1; i >= 0; i--) {
- java_handle_t *o;
-
- o = array_objectarray_element_get(oas, srcStart + i);
-
- if (!builtin_canstore(oad, o))
- return;
-
- array_objectarray_element_set(oad, destStart + i, o);
- }
- }
- }
-}
-
-
-/* builtin_nanotime ************************************************************
-
- Return the current time in nanoseconds.
-
-*******************************************************************************/
-
-s8 builtin_nanotime(void)
-{
- struct timeval tv;
- s8 usecs;
-
- if (gettimeofday(&tv, NULL) == -1)
- vm_abort("gettimeofday failed: %s", strerror(errno));
-
- usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
-
- return usecs * 1000;
-}
-
-
-/* builtin_currenttimemillis ***************************************************
-
- Return the current time in milliseconds.
-
-*******************************************************************************/
-
-s8 builtin_currenttimemillis(void)
-{
- s8 msecs;
-
- msecs = builtin_nanotime() / 1000 / 1000;
-
- return msecs;
-}
-
-
-/* builtin_clone ***************************************************************
-
- Function for cloning objects or arrays.
-
- NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
-
-*******************************************************************************/
-
-java_handle_t *builtin_clone(void *env, java_handle_t *o)
-{
- arraydescriptor *ad;
- u4 size;
- classinfo *c;
- java_handle_t *co; /* cloned object header */
-
- /* get the array descriptor */
-
- ad = LLNI_vftbl_direct(o)->arraydesc;
-
- /* we are cloning an array */
-
- if (ad != NULL) {
- size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
-
- co = heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
-
- if (co == NULL)
- return NULL;
-
-#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
- /* XXX this is only a dirty hack to make Boehm work with handles */
-
- co = LLNI_WRAP((java_object_t *) co);
-#endif
-
- LLNI_CRITICAL_START;
-
- MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
-
-#if defined(ENABLE_GC_CACAO)
- heap_init_objectheader(LLNI_DIRECT(co), size);
-#endif
-
-#if defined(ENABLE_THREADS)
- lock_init_object_lock(LLNI_DIRECT(co));
-#endif
-
- LLNI_CRITICAL_END;
-
- return co;
- }
-
- /* we are cloning a non-array */
-
- if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
- exceptions_throw_clonenotsupportedexception();
- return NULL;
- }
-
- /* get the class of the object */
-
- LLNI_class_get(o, c);
-
- /* create new object */
-
- co = builtin_new(c);
-
- if (co == NULL)
- return NULL;
-
- LLNI_CRITICAL_START;
-
- MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
-
-#if defined(ENABLE_GC_CACAO)
- heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
-#endif
-
-#if defined(ENABLE_THREADS)
- lock_init_object_lock(LLNI_DIRECT(co));
-#endif
-
- LLNI_CRITICAL_END;
-
- return co;
-}
-
-
-#if defined(ENABLE_CYCLES_STATS)
-void builtin_print_cycles_stats(FILE *file)
-{
- fprintf(file,"builtin cylce count statistics:\n");
-
- CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
- CYCLES_STATS_PRINT(builtin_new ,file);
-
- fprintf(file,"\n");
-}
-#endif /* defined(ENABLE_CYCLES_STATS) */
-
-
-#if defined(ENABLE_VMLOG)
-#define NDEBUG
-#include <vmlog_cacao.c>
-#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/builtin.h - prototypes of builtin 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 _BUILTIN_H
-#define _BUILTIN_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct builtintable_entry builtintable_entry;
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "arch.h"
-#include "md-abi.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/descriptor.h"
-#include "vm/utf8.h"
-
-
-/* define infinity for floating point numbers */
-
-#define FLT_NAN 0x7fc00000
-#define FLT_POSINF 0x7f800000
-#define FLT_NEGINF 0xff800000
-
-/* define infinity for double floating point numbers */
-
-#define DBL_NAN 0x7ff8000000000000LL
-#define DBL_POSINF 0x7ff0000000000000LL
-#define DBL_NEGINF 0xfff0000000000000LL
-
-
-/* float versions are not defined in GNU classpath's fdlibm */
-
-#define copysignf copysign
-#define finitef finite
-#define fmodf fmod
-#define isnanf isnan
-
-
-/* builtin functions table ****************************************************/
-
-struct builtintable_entry {
- s4 opcode; /* opcode which is replaced */
- u4 flags; /* e.g. check for exception */
- functionptr fp; /* function pointer of builtin */
- u1 *stub; /* pointer to builtin stub code */
- char *cclassname; /* char name of the class */
- char *cname; /* char name of the function */
- char *cdescriptor; /* char name of the descriptor */
- utf *classname; /* class of the function */
- utf *name; /* name of the function */
- utf *descriptor; /* descriptor of the function */
- methoddesc *md;
-};
-
-
-/* builtin table flag defines *************************************************/
-
-#define BUILTINTABLE_FLAG_STUB 0x0001 /* builtin needs a stub */
-#define BUILTINTABLE_FLAG_EXCEPTION 0x0002 /* check for excepion on return */
-
-
-/* function prototypes ********************************************************/
-
-bool builtin_init(void);
-
-s4 builtintable_get_key(builtintable_entry *);
-builtintable_entry *builtintable_get_by_key(s4 key);
-builtintable_entry *builtintable_get_internal(functionptr fp);
-builtintable_entry *builtintable_get_automatic(s4 opcode);
-
-bool builtintable_replace_function(void *iptr);
-
-
-/**********************************************************************/
-/* BUILTIN FUNCTIONS */
-/**********************************************************************/
-
-/* NOTE: Builtin functions which are used in the BUILTIN* opcodes must
- * have a BUILTIN_... macro defined as seen below. In code dealing
- * with the BUILTIN* opcodes the functions may only be addressed by
- * these macros, never by their actual name! (This helps to make this
- * code more portable.)
- *
- * C and assembler code which does not deal with the BUILTIN* opcodes,
- * can use the builtin functions normally (like all other functions).
- *
- * IMPORTANT:
- * For each builtin function which is used in a BUILTIN* opcode there
- * must be an entry in the tables in vm/builtintable.inc.
- *
- * Below each prototype is either the BUILTIN_ macro definition or a
- * comment specifiying that this function is not used in BUILTIN*
- * opcodes.
- *
- * (The BUILTIN* opcodes are ICMD_BUILTIN1, ICMD_BUILTIN2 and
- * ICMD_BUILTIN3.)
- */
-
-bool builtin_instanceof(java_handle_t *obj, classinfo *c);
-/* NOT AN OP */
-bool builtin_checkcast(java_handle_t *obj, classinfo *c);
-/* NOT AN OP */
-bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass);
-/* NOT AN OP */
-bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass);
-#define BUILTIN_arrayinstanceof (functionptr) builtin_fast_arrayinstanceof
-bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass);
-#define BUILTIN_arraycheckcast (functionptr) builtin_fast_arraycheckcast
-
-bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o);
-/* NOT AN OP */
-bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o);
-#define BUILTIN_FAST_canstore (functionptr) builtin_fast_canstore
-
-void *builtin_throw_exception(java_object_t *exception);
-/* NOT AN OP */
-java_object_t *builtin_retrieve_exception(void);
-/* NOT AN OP */
-
-java_handle_t *builtin_new(classinfo *c);
-/* 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
-
-java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass);
-/* NOT AN OP */
-java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclass);
-#define BUILTIN_newarray (functionptr) builtin_java_newarray
-
-java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass);
-/* NOT AN OP */
-
-java_handle_booleanarray_t *builtin_newarray_boolean(int32_t size);
-#define BUILTIN_newarray_boolean (functionptr) builtin_newarray_boolean
-java_handle_chararray_t *builtin_newarray_char(int32_t size);
-#define BUILTIN_newarray_char (functionptr) builtin_newarray_char
-java_handle_floatarray_t *builtin_newarray_float(int32_t size);
-#define BUILTIN_newarray_float (functionptr) builtin_newarray_float
-java_handle_doublearray_t *builtin_newarray_double(int32_t size);
-#define BUILTIN_newarray_double (functionptr) builtin_newarray_double
-java_handle_bytearray_t *builtin_newarray_byte(int32_t size);
-#define BUILTIN_newarray_byte (functionptr) builtin_newarray_byte
-java_handle_shortarray_t *builtin_newarray_short(int32_t size);
-#define BUILTIN_newarray_short (functionptr) builtin_newarray_short
-java_handle_intarray_t *builtin_newarray_int(int32_t size);
-#define BUILTIN_newarray_int (functionptr) builtin_newarray_int
-java_handle_longarray_t *builtin_newarray_long(int32_t size);
-#define BUILTIN_newarray_long (functionptr) builtin_newarray_long
-
-java_handle_objectarray_t *builtin_multianewarray(int n,
- java_handle_t *arrayclass,
- long *dims);
-#define BUILTIN_multianewarray (functionptr) builtin_multianewarray
-
-#if defined(TRACE_ARGS_NUM)
-void builtin_verbosecall_enter(s8 a0, s8 a1,
-# if TRACE_ARGS_NUM >= 4
- s8 a2, s8 a3,
-# endif
-# if TRACE_ARGS_NUM >= 6
- s8 a4, s8 a5,
-# endif
-# if TRACE_ARGS_NUM == 8
- s8 a6, s8 a7,
-# endif
- methodinfo *m);
-/* NOT AN OP */
-#endif /* defined(TRACE_ARGS_NUM) */
-
-void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
-/* NOT AN OP */
-
-s4 builtin_idiv(s4 a, s4 b);
-#define BUILTIN_idiv (functionptr) builtin_idiv
-s4 builtin_irem(s4 a, s4 b);
-#define BUILTIN_irem (functionptr) builtin_irem
-
-s8 builtin_ladd(s8 a, s8 b);
-#define BUILTIN_ladd (functionptr) builtin_ladd
-s8 builtin_lsub(s8 a, s8 b);
-#define BUILTIN_lsub (functionptr) builtin_lsub
-s8 builtin_lmul(s8 a, s8 b);
-#define BUILTIN_lmul (functionptr) builtin_lmul
-
-s8 builtin_ldiv(s8 a, s8 b);
-#define BUILTIN_ldiv (functionptr) builtin_ldiv
-s8 builtin_lrem(s8 a, s8 b);
-#define BUILTIN_lrem (functionptr) builtin_lrem
-
-s8 builtin_lshl(s8 a, s4 b);
-#define BUILTIN_lshl (functionptr) builtin_lshl
-s8 builtin_lshr(s8 a, s4 b);
-#define BUILTIN_lshr (functionptr) builtin_lshr
-s8 builtin_lushr(s8 a, s4 b);
-#define BUILTIN_lushr (functionptr) builtin_lushr
-s8 builtin_land(s8 a, s8 b);
-#define BUILTIN_land (functionptr) builtin_land
-s8 builtin_lor(s8 a, s8 b);
-#define BUILTIN_lor (functionptr) builtin_lor
-s8 builtin_lxor(s8 a, s8 b);
-#define BUILTIN_lxor (functionptr) builtin_lxor
-s8 builtin_lneg(s8 a);
-#define BUILTIN_lneg (functionptr) builtin_lneg
-s4 builtin_lcmp(s8 a, s8 b);
-#define BUILTIN_lcmp (functionptr) builtin_lcmp
-
-float builtin_fadd(float a, float b);
-#define BUILTIN_fadd (functionptr) builtin_fadd
-float builtin_fsub(float a, float b);
-#define BUILTIN_fsub (functionptr) builtin_fsub
-float builtin_fmul(float a, float b);
-#define BUILTIN_fmul (functionptr) builtin_fmul
-float builtin_fdiv(float a, float b);
-#define BUILTIN_fdiv (functionptr) builtin_fdiv
-float builtin_fneg(float a);
-#define BUILTIN_fneg (functionptr) builtin_fneg
-s4 builtin_fcmpl(float a, float b);
-#define BUILTIN_fcmpl (functionptr) builtin_fcmpl
-s4 builtin_fcmpg(float a, float b);
-#define BUILTIN_fcmpg (functionptr) builtin_fcmpg
-float builtin_frem(float a, float b);
-#define BUILTIN_frem (functionptr) builtin_frem
-
-double builtin_dadd(double a, double b);
-#define BUILTIN_dadd (functionptr) builtin_dadd
-double builtin_dsub(double a, double b);
-#define BUILTIN_dsub (functionptr) builtin_dsub
-double builtin_dmul(double a, double b);
-#define BUILTIN_dmul (functionptr) builtin_dmul
-double builtin_ddiv(double a, double b);
-#define BUILTIN_ddiv (functionptr) builtin_ddiv
-double builtin_dneg(double a);
-#define BUILTIN_dneg (functionptr) builtin_dneg
-s4 builtin_dcmpl(double a, double b);
-#define BUILTIN_dcmpl (functionptr) builtin_dcmpl
-s4 builtin_dcmpg(double a, double b);
-#define BUILTIN_dcmpg (functionptr) builtin_dcmpg
-double builtin_drem(double a, double b);
-#define BUILTIN_drem (functionptr) builtin_drem
-
-s8 builtin_i2l(s4 i);
-/* NOT AN OP */
-float builtin_i2f(s4 i);
-#define BUILTIN_i2f (functionptr) builtin_i2f
-double builtin_i2d(s4 i);
-#define BUILTIN_i2d (functionptr) builtin_i2d
-s4 builtin_l2i(s8 l);
-/* NOT AN OP */
-float builtin_l2f(s8 l);
-#define BUILTIN_l2f (functionptr) builtin_l2f
-double builtin_l2d(s8 l);
-#define BUILTIN_l2d (functionptr) builtin_l2d
-
-s4 builtin_f2i(float a);
-#define BUILTIN_f2i (functionptr) builtin_f2i
-s4 asm_builtin_f2i(float a);
-/* NOT AN OP */
-s8 builtin_f2l(float a);
-#define BUILTIN_f2l (functionptr) builtin_f2l
-s8 asm_builtin_f2l(float a);
-/* NOT AN OP */
-
-double builtin_f2d(float a);
-#define BUILTIN_f2d (functionptr) builtin_f2d
-
-s4 builtin_d2i(double a);
-#define BUILTIN_d2i (functionptr) builtin_d2i
-s4 asm_builtin_d2i(double a);
-/* NOT AN OP */
-s8 builtin_d2l(double a);
-#define BUILTIN_d2l (functionptr) builtin_d2l
-s8 asm_builtin_d2l(double a);
-/* NOT AN OP */
-
-float builtin_d2f(double a);
-#define BUILTIN_d2f (functionptr) builtin_d2f
-
-java_handle_t *builtin_clone(void *env, java_handle_t *o);
-#define BUILTIN_clone (functionptr) builtin_clone
-
-void builtin_arraycopy(java_handle_t *src, s4 srcStart,
- java_handle_t *dest, s4 destStart, s4 len);
-#define BUILTIN_arraycopy (functionptr) builtin_arraycopy
-
-s8 builtin_nanotime(void);
-s8 builtin_currenttimemillis(void);
-#define BUILTIN_currenttimemillis (functionptr) builtin_currenttimemillis
-
-#if defined(ENABLE_CYCLES_STATS)
-void builtin_print_cycles_stats(FILE *file);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _BUILTIN_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/builtintable.inc - tables of builtin 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 "arch.h"
-
-#include "threads/lock-common.h"
-
-#include "vm/builtin.h"
-
-#include "vm/jit/jit.h"
-
-
-/* internal and not automatically replaced functions **************************/
-
-static builtintable_entry builtintable_internal[] = {
-
-#if defined(__ALPHA__) || defined(DISABLE_GC)
- {
- ICMD_F2L,
- 0,
- BUILTIN_f2l,
- NULL,
- NULL,
- "f2l",
- "(F)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_D2L,
- 0,
- BUILTIN_d2l,
- NULL,
- NULL,
- "d2l",
- "(D)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_F2I,
- 0,
- BUILTIN_f2i,
- NULL,
- NULL,
- "f2i",
- "(F)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_D2I,
- 0,
- BUILTIN_d2i,
- NULL,
- NULL,
- "d2i",
- "(D)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !SUPPORT_DIVISION || defined(DISABLE_GC)
- {
- ICMD_IDIV,
- 0,
- BUILTIN_idiv,
- NULL,
- NULL,
- "idiv",
- "(II)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_IREM,
- 0,
- BUILTIN_irem,
- NULL,
- NULL,
- "irem",
- "(II)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined(DISABLE_GC)
- {
- ICMD_LDIV,
- 0,
- BUILTIN_ldiv,
- NULL,
- NULL,
- "ldiv",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_LREM,
- 0,
- BUILTIN_lrem,
- NULL,
- NULL,
- "lrem",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
- {
- ICMD_FREM,
- 0,
- BUILTIN_frem,
- NULL,
- NULL,
- "frem",
- "(FF)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_DREM,
- 0,
- BUILTIN_drem,
- NULL,
- NULL,
- "drem",
- "(DD)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
-
-
- /* internal functions *****************************************************/
-
- {
- ICMD_NEW,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_new,
- NULL,
- NULL,
- "new",
- "(Ljava/lang/Class;)Ljava/lang/Object;",
- NULL,
- NULL,
- 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,
- BUILTIN_FAST_new,
- NULL,
- NULL,
- "fast-new",
- "(Ljava/lang/Class;)Ljava/lang/Object;",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_ANEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray,
- NULL,
- NULL,
- "newarray",
- "(ILjava/lang/Class;)[Ljava/lang/Object;",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_boolean,
- NULL,
- NULL,
- "newarray_boolean",
- "(I)[Z",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_byte,
- NULL,
- NULL,
- "newarray_byte",
- "(I)[B",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_char,
- NULL,
- NULL,
- "newarray_char",
- "(I)[C",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_short,
- NULL,
- NULL,
- "newarray_short",
- "(I)[S",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_int,
- NULL,
- NULL,
- "newarray_int",
- "(I)[I",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_long,
- NULL,
- NULL,
- "newarray_long",
- "(I)[J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_float,
- NULL,
- NULL,
- "newarray_float",
- "(I)[F",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_NEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_newarray_double,
- NULL,
- NULL,
- "newarray_double",
- "(I)[D",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_MULTIANEWARRAY,
- BUILTINTABLE_FLAG_STUB,
- BUILTIN_multianewarray,
- NULL,
- NULL,
- "multianewarray",
- /* XXX it should be: "(ILjava/lang/Class;[I)[Ljava/lang/Object;", */
- "(ILjava/lang/Class;I)[Ljava/lang/Object;",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_CHECKCAST,
- 0,
- BUILTIN_arraycheckcast,
- NULL,
- NULL,
- "arraycheckcast",
- "([Ljava/lang/Object;[Ljava/lang/Object;)[Ljava/lang/Object;",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_INSTANCEOF,
- 0,
- BUILTIN_arrayinstanceof,
- NULL,
- NULL,
- "arrayinstanceof",
- "([Ljava/lang/Object;[Ljava/lang/Object;)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_AASTORE,
- 0,
- BUILTIN_FAST_canstore,
- NULL,
- NULL,
- "fast-canstore",
- "([Ljava/lang/Object;Ljava/lang/Object;)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-
-#if defined(ENABLE_THREADS)
- {
- ICMD_MONITORENTER,
- BUILTINTABLE_FLAG_STUB,
- LOCK_monitor_enter,
- NULL,
- NULL,
- "monitorenter",
- "(Ljava/lang/Object;)V",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_MONITOREXIT,
- BUILTINTABLE_FLAG_STUB,
- LOCK_monitor_exit,
- NULL,
- NULL,
- "monitorexit",
- "(Ljava/lang/Object;)V",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-
- /* stop entry */
-
- {
- 255,
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- },
-};
-
-
-/* automatically replaced functions *******************************************/
-
-static builtintable_entry builtintable_automatic[] = {
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
- {
- ICMD_LCMP,
- 0,
- BUILTIN_lcmp,
- NULL,
- NULL,
- "lcmp",
- "(JJ)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
- {
- ICMD_LAND,
- 0,
- BUILTIN_land,
- NULL,
- NULL,
- "land",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_LOR,
- 0,
- BUILTIN_lor,
- NULL,
- NULL,
- "lor",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_LXOR,
- 0,
- BUILTIN_lxor,
- NULL,
- NULL,
- "lxor",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
- {
- ICMD_LSHL,
- 0,
- BUILTIN_lshl,
- NULL,
- NULL,
- "lshl",
- "(JI)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_LSHR,
- 0,
- BUILTIN_lshr,
- NULL,
- NULL,
- "lshr",
- "(JI)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_LUSHR,
- 0,
- BUILTIN_lushr,
- NULL,
- NULL,
- "lushr",
- "(JI)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
- {
- ICMD_LADD,
- 0,
- BUILTIN_ladd,
- NULL,
- NULL,
- "ladd",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_LSUB,
- 0,
- BUILTIN_lsub,
- NULL,
- NULL,
- "lsub",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_LNEG,
- 0,
- BUILTIN_lneg,
- NULL,
- NULL,
- "lneg",
- "(J)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
-
-#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
- {
- ICMD_LMUL,
- 0,
- BUILTIN_lmul,
- NULL,
- NULL,
- "lmul",
- "(JJ)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_FLOAT && SUPPORT_I2F)
- {
- ICMD_I2F,
- 0,
- BUILTIN_i2f,
- NULL,
- NULL,
- "i2f",
- "(I)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
- {
- ICMD_I2D,
- 0,
- BUILTIN_i2d,
- NULL,
- NULL,
- "i2d",
- "(I)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
- {
- ICMD_L2F,
- 0,
- BUILTIN_l2f,
- NULL,
- NULL,
- "l2f",
- "(J)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
- {
- ICMD_L2D,
- 0,
- BUILTIN_l2d,
- NULL,
- NULL,
- "l2d",
- "(J)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_FLOAT && SUPPORT_F2I)
- {
- ICMD_F2I,
- 0,
- BUILTIN_f2i,
- NULL,
- NULL,
- "f2i",
- "(F)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
- {
- ICMD_F2L,
- 0,
- BUILTIN_f2l,
- NULL,
- NULL,
- "f2l",
- "(F)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_DOUBLE && SUPPORT_D2I)
- {
- ICMD_D2I,
- 0,
- BUILTIN_d2i,
- NULL,
- NULL,
- "d2i",
- "(D)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
- {
- ICMD_D2L,
- 0,
- BUILTIN_d2l,
- NULL,
- NULL,
- "d2l",
- "(D)J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
-
- /* float functions ********************************************************/
-
-#if !SUPPORT_FLOAT
- {
- ICMD_FADD,
- 0,
- BUILTIN_fadd,
- NULL,
- NULL,
- "fadd",
- "(FF)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_FSUB,
- 0,
- BUILTIN_fsub,
- NULL,
- NULL,
- "fsub",
- "(FF)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_FMUL,
- 0,
- BUILTIN_fmul,
- NULL,
- NULL,
- "fmul",
- "(FF)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_FDIV,
- 0,
- BUILTIN_fdiv,
- NULL,
- NULL,
- "fdiv",
- "(FF)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_FNEG,
- 0,
- BUILTIN_fneg,
- NULL,
- NULL,
- "fneg",
- "(F)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !SUPPORT_FLOAT */
-
-#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP
- {
- ICMD_FCMPL,
- 0,
- BUILTIN_fcmpl,
- NULL,
- NULL,
- "fcmpl",
- "(FF)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_FCMPG,
- 0,
- BUILTIN_fcmpg,
- NULL,
- NULL,
- "fcmpg",
- "(FF)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP */
-
-
- /* double functions *******************************************************/
-
-#if !SUPPORT_DOUBLE
- {
- ICMD_DADD,
- 0,
- BUILTIN_dadd,
- NULL,
- NULL,
- "dadd",
- "(DD)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_DSUB,
- 0,
- BUILTIN_dsub,
- NULL,
- NULL,
- "dsub",
- "(DD)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_DMUL,
- 0,
- BUILTIN_dmul,
- NULL,
- NULL,
- "dmul",
- "(DD)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_DDIV,
- 0,
- BUILTIN_ddiv,
- NULL,
- NULL,
- "ddiv",
- "(DD)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_DNEG,
- 0,
- BUILTIN_dneg,
- NULL,
- NULL,
- "dneg",
- "(D)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !SUPPORT_DOUBLE */
-
-#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP
- {
- ICMD_DCMPL,
- 0,
- BUILTIN_dcmpl,
- NULL,
- NULL,
- "dcmpl",
- "(DD)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_DCMPG,
- 0,
- BUILTIN_dcmpg,
- NULL,
- NULL,
- "dcmpg",
- "(DD)I",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP */
-
-
- /* float/double functions *************************************************/
-
-#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
- {
- ICMD_F2D,
- 0,
- BUILTIN_f2d,
- NULL,
- NULL,
- "f2d",
- "(F)D",
- NULL,
- NULL,
- NULL,
- NULL
- },
- {
- ICMD_D2F,
- 0,
- BUILTIN_d2f,
- NULL,
- NULL,
- "d2f",
- "(D)F",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
-
-
- /* prevent a compiler warning if everything is supported (e.g. i386) */
-
- {
- 255,
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL
- },
-};
-
-
-/* automatically replaced functions *******************************************/
-
-static builtintable_entry builtintable_function[] = {
-#if defined(ENABLE_JIT)
-
- /* java.lang.VMSystem.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V STATIC NATIVE */
-
- {
- ICMD_BUILTIN,
- BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
- BUILTIN_arraycopy,
- NULL,
- "java/lang/VMSystem",
- "arraycopy",
- "(Ljava/lang/Object;ILjava/lang/Object;II)V",
- NULL,
- NULL,
- NULL,
- NULL
- },
-
- /* java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V PUBLIC STATIC */
-
-#if 0
- /* We disable this one until we have a fix for the stacktrace
- issue. */
-
- {
- ICMD_BUILTIN,
- BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
- BUILTIN_arraycopy,
- NULL,
- "java/lang/System",
- "arraycopy",
- "(Ljava/lang/Object;ILjava/lang/Object;II)V",
- NULL,
- NULL,
- NULL,
- NULL
- },
-#endif
-
- /* java.lang.VMSystem.currentTimeMillis()J PUBLIC STATIC */
-
- {
- ICMD_BUILTIN,
- 0,
- BUILTIN_currenttimemillis,
- NULL,
- "java/lang/VMSystem",
- "currentTimeMillis",
- "()J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-
- /* java.lang.System.currentTimeMillis()J PUBLIC STATIC */
-
- {
- ICMD_BUILTIN,
- 0,
- BUILTIN_currenttimemillis,
- NULL,
- "java/lang/System",
- "currentTimeMillis",
- "()J",
- NULL,
- NULL,
- NULL,
- NULL
- },
-
-#endif /* defined(ENABLE_JIT) */
-
- /* stop entry */
-
- {
- 255,
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 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:
- * vim:noexpandtab:sw=4:ts=4:
- */
#include "native/llni.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
#include "toolbox/logging.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/javaobjects.hpp"
#include "vm/jit/jitcache.hpp"
#include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/resolve.h"
# include "vm/statistics.h"
#endif
-#include "vm/suck.h"
+#include "vm/suck.hpp"
#include "vm/utf8.h"
#include "vm/jit/asmpart.h"
c->cache_file_fd = 0;
#endif
- LOCK_INIT_OBJECT_LOCK(&c->object.header);
+ Lockword_init(&(c->object.header.lockword));
return c;
}
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 = MNEW(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 = MNEW(char, namelen + 3);
namebuf[0] = '[';
namebuf[1] = 'L';
MCOPY(namebuf + 2, component->name->text, char, namelen);
u = utf_new(namebuf, namelen);
- c = get_array_class(u, cl, cl, link);
+ MFREE(namebuf, char, namelen);
- DRELEASE;
+ c = get_array_class(u, cl, cl, link);
return c;
}
s4 namelen;
char *namebuf;
classinfo *c;
- int32_t dumpmarker;
-
- DMARKER;
if (dim < 1) {
log_text("Invalid array dimension requested");
if (element->name->text[0] == '[') {
/* the element is itself an array */
- namebuf = DMNEW(char, namelen + dim);
+ namebuf = MNEW(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 = MNEW(char, namelen + 2 + dim);
namebuf[dim] = 'L';
memcpy(namebuf + dim + 1, element->name->text, namelen);
namelen += (2 + dim);
}
memset(namebuf, '[', dim);
- c = get_array_class(utf_new(namebuf, namelen),
+ utf* u = utf_new(namebuf, namelen);
+
+ MFREE(namebuf, char, namelen);
+
+ c = get_array_class(u,
element->classloader,
element->classloader,
link);
- DRELEASE;
-
return c;
}
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);
+ namebuf = MNEW(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 = MNEW(char, namelen + 2 + dim);
namebuf[dim] = 'L';
memcpy(namebuf + dim + 1, ref->name->text, namelen);
namelen += (2 + dim);
}
memset(namebuf, '[', dim);
- cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
+ utf* u = utf_new(namebuf, namelen);
+
+ MFREE(namebuf, char, namelen);
- DRELEASE;
+ cr = class_get_classref(ref->referer, u);
return cr;
}
if (sub->flags & ACC_INTERFACE)
return (super == class_java_lang_Object);
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+ Mutex_lock(linker_classrenumber_mutex);
diffval = sub->vftbl->baseval - super->vftbl->baseval;
result = diffval <= (uint32_t) super->vftbl->diffval;
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+ Mutex_unlock(linker_classrenumber_mutex);
}
return result;
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
- }
+ printf ("Long -> %ld", (long int) ((constant_long*)e) -> value);
break;
case CONSTANT_NameAndType:
{
#ifndef _CLASS_H
#define _CLASS_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* forward typedefs ***********************************************************/
typedef struct classinfo classinfo;
#include "vm/types.h"
-#include "toolbox/list.h"
-
#if defined(ENABLE_JAVASE)
# include "vm/annotation.h"
#endif
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/global.h"
#include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/method.h"
#include "vm/references.h"
#include "vm/string.hpp"
/* inline functions ***********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/**
* Returns the classname of the class, where slashes ('/') are
* replaced by dots ('.').
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
#include "toolbox/hashtable.h"
#include "toolbox/logging.h"
/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
#if defined(ENABLE_THREADS)
-# define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
-# define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
+# define CLASSCACHE_LOCK() Mutex_lock(classcache_hashtable_mutex)
+# define CLASSCACHE_UNLOCK() Mutex_unlock(classcache_hashtable_mutex)
#else
# define CLASSCACHE_LOCK()
# define CLASSCACHE_UNLOCK()
hashtable hashtable_classcache;
#if defined(ENABLE_THREADS)
-static java_object_t *lock_hashtable_classcache;
+static Mutex *classcache_hashtable_mutex;
#endif
hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
#if defined(ENABLE_THREADS)
- /* create utf hashtable lock object */
+ /* create utf hashtable mutex */
- lock_hashtable_classcache = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
+ classcache_hashtable_mutex = Mutex_new();
#endif
/* everything's ok */
#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/loader.hpp"
#include "vm/references.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* forward declarations *******************************************************/
typedef struct classcache_name_entry classcache_name_entry;
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
descriptor_pool * descriptor_pool_new(classinfo *referer);
bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
#endif /* !defined(NDEBUG) */
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _DESCRIPTOR_H */
#include "mm/memory.h"
-#include "native/jni.h"
#include "native/llni.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "threads/thread.hpp"
#include "toolbox/util.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#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/loader.hpp"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/os.hpp"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/methodheader.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/show.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/show.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trace.hpp"
log_finish();
- vm_abort("Aborting...");
+ os::abort("Aborting...");
}
java_handle_t *s;
java_handle_t *o;
- if (vm->is_initializing()) {
+ if (VM::get_current()->is_initializing()) {
/* This can happen when global class variables are used which
are not initialized yet. */
classinfo *c;
java_handle_t *o;
- if (vm->is_initializing())
+ if (VM::get_current()->is_initializing())
exceptions_abort(classname, NULL);
c = load_class_bootstrap(classname);
java_handle_t *o;
classinfo *c;
- if (vm->is_initializing())
+ if (VM::get_current()->is_initializing())
exceptions_abort(classname, NULL);
c = load_class_bootstrap(classname);
classinfo *c;
java_handle_t *o;
- if (vm->is_initializing())
+ if (VM::get_current()->is_initializing())
exceptions_abort(classname, message);
c = load_class_bootstrap(classname);
classinfo *c;
methodinfo *m;
- if (vm->is_initializing())
+ if (VM::get_current()->is_initializing())
exceptions_abort(classname, NULL);
java_lang_Throwable jlt(cause);
java_handle_t *o;
methodinfo *m;
- if (vm->is_initializing())
+ if (VM::get_current()->is_initializing())
exceptions_abort(classname, NULL);
c = load_class_bootstrap(classname);
static void exceptions_throw_utf_cause(utf *classname, java_handle_t *cause)
{
- if (vm->is_initializing())
+ if (VM::get_current()->is_initializing())
exceptions_abort(classname, NULL);
java_lang_Throwable jltcause(cause);
false);
if (m == NULL)
- vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+ os::abort("exceptions_print_stacktrace: printStackTrace()V not found");
/* Print message. */
#ifndef _EXCEPTIONS_HPP
#define _EXCEPTIONS_HPP
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "config.h"
#include "vm/types.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
java_handle_t *exceptions_get_exception(void);
void exceptions_set_exception(java_handle_t *o);
void exceptions_clear_exception(void);
+++ /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.cpp - 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.hpp"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.h"
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.hpp"
+#include "vm/global.h"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/references.h"
+#include "vm/string.hpp"
+#include "vm/suck.hpp"
+#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 = (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ f->name = u;
+
+ /* Get descriptor. */
+
+ if (!(u = (utf*) 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 = (utf*) 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 = (constant_integer*) class_getconstant(c, pindex, CONSTANT_Integer)))
+ return false;
+
+ f->value->i = ci->value;
+ }
+ break;
+
+ case TYPE_LNG: {
+ constant_long *cl;
+
+ if (!(cl = (constant_long*) class_getconstant(c, pindex, CONSTANT_Long)))
+ return false;
+
+ f->value->l = cl->value;
+ }
+ break;
+
+ case TYPE_FLT: {
+ constant_float *cf;
+
+ if (!(cf = (constant_float*) class_getconstant(c, pindex, CONSTANT_Float)))
+ return false;
+
+ f->value->f = cf->value;
+ }
+ break;
+
+ case TYPE_DBL: {
+ constant_double *cd;
+
+ if (!(cd = (constant_double*) class_getconstant(c, pindex, CONSTANT_Double)))
+ return false;
+
+ f->value->d = cd->value;
+ }
+ break;
+
+ case TYPE_ADR:
+ if (!(u = (utf*) 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:
- */
--- /dev/null
+/* src/vm/field.hpp - 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_HPP
+#define _FIELD_HPP
+
+/* 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.hpp"
+#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 ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FIELD_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 "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/options.h"
/* global variables ***********************************************************/
#if defined(ENABLE_THREADS)
-static java_object_t *lock_thread_finalizer;
+static Mutex *finalizer_thread_mutex;
+static Condition *finalizer_thread_cond;
#endif
TRACESUBSYSTEMINITIALIZATION("finalizer_init");
#if defined(ENABLE_THREADS)
- lock_thread_finalizer = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(lock_thread_finalizer);
+ finalizer_thread_mutex = Mutex_new();
+ finalizer_thread_cond = Condition_new();
#endif
/* everything's ok */
static void finalizer_thread(void)
{
while (true) {
- /* get the lock on the finalizer lock object, so we can call wait */
+ /* get the lock on the finalizer mutex, so we can call wait */
- LOCK_MONITOR_ENTER(lock_thread_finalizer);
+ Mutex_lock(finalizer_thread_mutex);
- /* wait forever on that object till we are signaled */
+ /* wait forever on that condition till we are signaled */
- LOCK_WAIT_FOREVER(lock_thread_finalizer);
+ Condition_wait(finalizer_thread_cond, finalizer_thread_mutex);
/* leave the lock */
- LOCK_MONITOR_EXIT(lock_thread_finalizer);
+ Mutex_unlock(finalizer_thread_mutex);
#if !defined(NDEBUG)
if (opt_DebugFinalizer)
#if defined(ENABLE_THREADS)
/* get the lock on the finalizer lock object, so we can call wait */
- LOCK_MONITOR_ENTER(lock_thread_finalizer);
+ Mutex_lock(finalizer_thread_mutex);
/* signal the finalizer thread */
-
- LOCK_NOTIFY(lock_thread_finalizer);
+
+ Condition_signal(finalizer_thread_cond);
/* leave the lock */
- LOCK_MONITOR_EXIT(lock_thread_finalizer);
+ Mutex_unlock(finalizer_thread_mutex);
#else
/* if we don't have threads, just run the finalizers */
#define HDRFLAG_HASH_ATTACHED 0x20
#define HDRFLAG_REFERENCING 0x40
+#include "threads/lockword.hpp"
+
struct java_object_t { /* header for all objects */
struct _vftbl *vftbl; /* pointer to virtual function table */
#if defined(ENABLE_THREADS)
- uintptr_t lockword;
+ Lockword lockword;
#endif
#if defined(ENABLE_GC_CACAO)
uintptr_t hdrflags; /* word containing the GC bits */
java_object_t *heap_object;
} java_handle_t;
+typedef struct java_handle_array_t { java_array_t *heap_object; } java_handle_array_t;
typedef struct java_handle_objectarray_t { java_objectarray_t *heap_object; } java_handle_objectarray_t;
typedef struct java_handle_booleanarray_t { java_booleanarray_t *heap_object; } java_handle_booleanarray_t;
typedef struct java_handle_bytearray_t { java_bytearray_t *heap_object; } java_handle_bytearray_t;
typedef struct java_handle_doublearray_t { java_doublearray_t *heap_object; } java_handle_doublearray_t;
#else
typedef java_object_t java_handle_t;
+typedef java_array_t java_handle_array_t;
typedef java_objectarray_t java_handle_objectarray_t;
typedef java_booleanarray_t java_handle_booleanarray_t;
typedef java_bytearray_t java_handle_bytearray_t;
#include "vm/types.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/initialize.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/vm.hpp"
#include "native/vm/reflection.hpp"
#include "vm/access.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/initialize.h"
#include "native/llni.h"
+#include "threads/atomic.hpp"
+
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/method.h"
* afterwards.
*/
class FieldAccess : private RawFieldAccess {
-protected:
+public:
+ // Normal field accessors.
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);
+
+ // Volatile field accessors.
+ template<class T> static inline T get_volatile(java_handle_t* h, const off_t offset);
+ template<class T> static inline void set_volatile(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;
+ // This function is inside a critical section.
+ GCCriticalSection cs;
// XXX This should be _handle->get_object();
- o = LLNI_UNWRAP(h);
-
- result = raw_get<T>(o, offset);
+ java_object_t* ho = LLNI_UNWRAP(h);
+ return raw_get<T>(ho, offset);
+}
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
- return result;
+ // XXX This should be _handle->get_object();
+ java_object_t* o = LLNI_UNWRAP(h);
+ java_object_t* result = raw_get<java_object_t*>(o, offset);
+ return LLNI_WRAP(result);
}
-template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
+
+template<class T> inline void FieldAccess::set(java_handle_t* h, const off_t offset, T value)
{
- 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;
+ // This function is inside a critical section.
+ GCCriticalSection cs;
- // XXX This should be _handle->get_object();
- o = LLNI_UNWRAP(h);
+ java_object_t* ho = LLNI_UNWRAP(h);
+ raw_set(ho, offset, value);
+}
- result = raw_get<java_object_t*>(o, offset);
+template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
- hresult = LLNI_WRAP(result);
+ // XXX This should be h->get_object();
+ java_object_t* o = LLNI_UNWRAP(h);
+ java_object_t* ovalue = LLNI_UNWRAP(value);
+ raw_set(o, offset, ovalue);
+}
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
- return result;
-}
+template<class T> inline T FieldAccess::get_volatile(java_handle_t* h, const off_t offset)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
+ // XXX This should be _handle->get_object();
+ java_object_t* ho = LLNI_UNWRAP(h);
+ return raw_get<volatile T>(ho, offset);
+}
-template<class T> inline void FieldAccess::set(java_handle_t* h, const off_t offset, T value)
+template<> inline java_handle_t* FieldAccess::get_volatile(java_handle_t* h, const off_t offset)
{
- java_object_t* o;
+ // This function is inside a critical section.
+ GCCriticalSection cs;
+
+ // XXX This should be _handle->get_object();
+ java_object_t* o = LLNI_UNWRAP(h);
+ java_object_t* result = (java_object_t*) raw_get<volatile java_object_t*>(o, offset);
+ return LLNI_WRAP(result);
+}
- // 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);
+template<class T> inline void FieldAccess::set_volatile(java_handle_t* h, const off_t offset, T value)
+{
+ // This function is inside a critical section.
+ GCCriticalSection cs;
- raw_set(o, offset, value);
+ java_object_t* ho = LLNI_UNWRAP(h);
+ raw_set(ho, offset, (volatile T) value);
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+ // Memory barrier for the Java Memory Model.
+ Atomic::memory_barrier();
}
-template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
+template<> inline void FieldAccess::set_volatile<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;
+ // This function is inside a critical section.
+ GCCriticalSection cs;
// XXX This should be h->get_object();
- o = LLNI_UNWRAP(h);
- ovalue = LLNI_UNWRAP(value);
+ java_object_t* o = LLNI_UNWRAP(h);
+ java_object_t* ovalue = LLNI_UNWRAP(value);
+ raw_set(o, offset, (volatile java_object_t*) ovalue);
- raw_set(o, offset, ovalue);
-
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
+ // Memory barrier for the Java Memory Model.
+ Atomic::memory_barrier();
}
// Handle of Java object.
java_handle_t* _handle;
-protected:
+public:
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;
+ virtual inline java_handle_t* get_handle () const { return _handle; }
+ inline vftbl_t* get_vftbl () const;
+ inline classinfo* get_Class () const;
+ inline int32_t get_hashcode() 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;
+ // This function is inside a critical section.
+ GCCriticalSection cs;
// 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;
+ return o->vftbl;
}
inline classinfo* java_lang_Object::get_Class() const
return get_vftbl()->clazz;
}
+inline int32_t java_lang_Object::get_hashcode() const
+{
+#if defined(ENABLE_GC_CACAO)
+ return heap_get_hashcode(_handle);
+#else
+ // This function is inside a critical section.
+ GCCriticalSection cs;
+
+ // XXX This should be h->get_object();
+ java_object_t* o = LLNI_UNWRAP(_handle);
+ return (int32_t) (intptr_t) o;
+#endif
+}
+
inline bool java_lang_Object::is_null() const
{
// 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
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 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);
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_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);
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
{
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 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);
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);
};
-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);
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 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);
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 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);
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 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)
{
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);
};
-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);
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
{
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 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);
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);
+ java_lang_Throwable(java_handle_t* h, java_handle_bytearray_t* backtrace);
// Getters.
inline java_handle_bytearray_t* get_backtrace () const;
};
-inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
+inline java_lang_Throwable::java_lang_Throwable(java_handle_t* h, java_handle_bytearray_t* backtrace) : 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);
}
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);
};
-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);
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 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);
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);
};
-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_clazz, m->clazz);
+ set(_handle, offset_slot, (int32_t) (m - m->clazz->methods)); // This cast is important (see PR100).
+ 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_modifiers, (int32_t) (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));
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;
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);
};
-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);
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 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)
{
public:
java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_Thread(jobject h);
// java_lang_Thread(threadobject* t);
// Getters.
};
-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));
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_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);
reg.h
REPLACE_SOURCES += \
- replace.h
+ replace.hpp
STACK_SOURCES = \
stack.c \
if ENABLE_REPLACEMENT
REPLACE_SOURCES += \
- replace.c
+ replace.cpp
endif
if ENABLE_VERIFIER
libjit.la
libjit_la_SOURCES = \
- argument.c \
- argument.h \
- code.c \
- code.h \
- codegen-common.c \
- codegen-common.h \
+ argument.cpp \
+ argument.hpp \
+ builtin.cpp \
+ builtin.hpp \
+ builtintable.inc \
+ code.cpp \
+ code.hpp \
+ codegen-common.cpp \
+ codegen-common.hpp \
disass.h \
$(DISASS_SOURCES) \
dseg.c \
dseg.h \
- emit-common.c \
- emit-common.h \
+ emit-common.cpp \
+ emit-common.hpp \
exceptiontable.c \
exceptiontable.h \
executionstate.c \
executionstate.h \
- icmdtable.inc \
- jit.c \
- jit.h \
- linenumbertable.c \
- linenumbertable.h \
+ jit.cpp \
+ jit.hpp \
+ linenumbertable.cpp \
+ linenumbertable.hpp \
methodtree.c \
methodtree.h \
parse.c \
parse.h \
- patcher-common.c \
- patcher-common.h \
+ patcher-common.cpp \
+ patcher-common.hpp \
$(RECOMPILE_SOURCES) \
$(REG_SOURCES) \
$(JITCACHE_SOURCES) \
$(REPLACE_SOURCES) \
- show.c \
- show.h \
+ show.cpp \
+ show.hpp \
$(STACK_SOURCES) \
stacktrace.cpp \
stacktrace.hpp \
+ stubs.cpp \
+ stubs.hpp \
trace.cpp \
trace.hpp \
$(TRAP_SOURCES) \
#include "arch.h"
#include "vm/jit/abi-asm.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/stack.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* machine dependent descriptor function */
void md_param_alloc(methoddesc *md);
void md_param_alloc_native(methoddesc *md);
/* machine dependent return value handling function */
void md_return_alloc(jitdata *jd, stackelement_t *stackslot);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _ABI_H */
#include "toolbox/logging.h"
#include "toolbox/worklist.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/resolve.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
#include "vm/jit/allocator/lsra.h"
#include "vm/jit/allocator/liveness.h"
#include "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/resolve.h"
#include "vm/options.h"
struct freemem *fmem;
struct stackslot *n;
int lt_index;
-#ifdef HAS_4BYTE_STACKSLOT
- struct freemem *fmem_2;
-#endif
registerdata *rd;
lsradata *ls;
fmem = DNEW(struct freemem);
fmem->off = -1;
fmem->next = NULL;
-#ifdef HAS_4BYTE_STACKSLOT
- fmem_2=DNEW(struct freemem);
- fmem_2->off = -1;
- fmem_2->next = NULL;
-#endif
for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
lt = &(ls->lifetime[lifet[lt_index]]);
#endif
if (lt->reg == -1) {
flags = INMEMORY;
-#ifdef HAS_4BYTE_STACKSLOT
- if (IS_2_WORD_TYPE(lt->type))
- regoff = lsra_getmem(lt, fmem_2, mem_use);
- else
-#endif
regoff = lsra_getmem(lt, fmem, mem_use);
} else {
flags = lt->savedvar;
/* no Memory Slot allocated till now or all are still live */
if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
-#ifdef HAS_4BYTE_STACKSLOT
- if (IS_2_WORD_TYPE(lt->type))
- if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
- (*mem_use)++;
- fm=lsra_getnewmem(mem_use);
- if (IS_2_WORD_TYPE(lt->type))
- /* allocate a second following Slot for 2 Word Types */
- (*mem_use)++;
-#else
fm=lsra_getnewmem(mem_use);
-#endif
} else {
/* Memoryslot free */
fm = fmem->next;
switch (lt->type) {
case TYPE_LNG:
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- flags = 0;
-#else
flags = 1;
-#endif
break;
-
case TYPE_INT:
case TYPE_ADR:
flags=1;
#include "mm/memory.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#include "vm/jit/allocator/simplereg.h"
/* size of a stackslot used by the internal ABI */
-#if defined(HAS_4BYTE_STACKSLOT)
-# define SIZE_OF_STACKSLOT 4
-#else
-# define SIZE_OF_STACKSLOT 8
-#endif
+#define SIZE_OF_STACKSLOT 8
/* total number of registers */
#define NEW_MEM_SLOT(r) \
do { \
(r) = rd->memuse * SIZE_OF_STACKSLOT; \
- rd->memuse += memneeded + 1; \
- } while (0)
-
-#define NEW_MEM_SLOT_ALIGNED(r) \
- do { \
- if ( (memneeded) && (rd->memuse & 1)) \
- rd->memuse++; \
- (r) = rd->memuse * SIZE_OF_STACKSLOT; \
- rd->memuse += memneeded + 1; \
+ rd->memuse += 1; \
} while (0)
-#define NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r) \
- do { \
- if ( (memneeded) && (rd->memuse & 1)) { \
- PUSH_BACK(rd->freemem, rd->freememtop, rd->memuse); \
- rd->memuse++; \
- } \
- (r) = rd->memuse * SIZE_OF_STACKSLOT; \
- rd->memuse += memneeded + 1; \
- } while (0)
-
-#if defined(ALIGN_LONGS_IN_MEMORY)
-#define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT_ALIGNED(r)
-#else
#define NEW_MEM_SLOT_INT_LNG(r) NEW_MEM_SLOT(r)
-#endif
-
-#if defined(ALIGN_DOUBLES_IN_MEMORY)
-#define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT_ALIGNED(r)
-#else
#define NEW_MEM_SLOT_FLT_DBL(r) NEW_MEM_SLOT(r)
-#endif
-
-#if defined(ALIGN_LONGS_IN_MEMORY) || defined(ALIGN_DOUBLES_IN_MEMORY)
-#define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT_ALIGNED_REUSE_PADDING(r)
-#else
#define NEW_MEM_SLOT_REUSE_PADDING(r) NEW_MEM_SLOT(r)
-#endif
/* macros for creating/freeing temporary variables ***************************/
/* regalloc ********************************************************************
Does a simple register allocation.
-
+
*******************************************************************************/
-
+
bool regalloc(jitdata *jd)
{
/* There is a problem with the use of unused float argument
/* simplereg_allocate_interfaces ***********************************************
Allocates registers for all interface variables.
-
+
*******************************************************************************/
-
+
static void simplereg_allocate_interfaces(jitdata *jd)
{
methodinfo *m;
int s, t, tt, saved;
int intalloc, fltalloc; /* Remember allocated Register/Memory offset */
/* in case more vars are packed into this interface slot */
- int memneeded = 0;
- /* Allocate LNG and DBL types first to ensure 2 memory slots or */
- /* registers on HAS_4BYTE_STACKSLOT architectures. */
+ /* Allocate LNG and DBL types first to ensure 2 registers */
+ /* on some architectures. */
int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
int flags, regoff;
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
-
if (!saved) {
#if defined(HAS_ADDRESS_REGISTER_FILE)
if (IS_ADR_TYPE(t)) {
/* simplereg_allocate_locals_leafmethod ****************************************
Allocates registers for all local variables of a leafmethod.
-
+
*******************************************************************************/
-
+
static void simplereg_allocate_locals_leafmethod(jitdata *jd)
{
methodinfo *m;
int intalloc, fltalloc;
varinfo *v;
int intregsneeded = 0;
- int memneeded = 0;
int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
int fargcnt, iargcnt;
#ifdef HAS_ADDRESS_REGISTER_FILE
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
/*
* The order of
/* simplereg_allocate_locals ***************************************************
Allocates registers for all local variables.
-
+
*******************************************************************************/
-
+
static void simplereg_allocate_locals(jitdata *jd)
{
codeinfo *code;
int s, t, tt, varindex;
int intalloc, fltalloc;
varinfo *v;
- int memneeded = 0;
int typeloop[] = { TYPE_LNG, TYPE_DBL, TYPE_INT, TYPE_FLT, TYPE_ADR };
#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
s4 intregsneeded;
intregsneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(t)) ? 1 : 0;
-#endif
-
#ifdef HAS_ADDRESS_REGISTER_FILE
if (IS_ADR_TYPE(t)) {
if (AVAIL_SAV_ADR) {
int i;
rd->freememtop = 0;
-#if defined(HAS_4BYTE_STACKSLOT)
- rd->freememtop_2 = 0;
-#endif
rd->freetmpinttop = 0;
rd->freesavinttop = 0;
#ifdef SUPPORT_COMBINE_INTEGER_REGISTERS
s4 intregsneeded;
#endif
- s4 memneeded;
s4 tryagain;
registerdata *rd;
varinfo *v;
intregsneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- memneeded = (IS_2_WORD_TYPE(v->type)) ? 1 : 0;
-#else
- memneeded = 0;
-#endif
-
for(; tryagain; --tryagain) {
if (tryagain == 1) {
if (!(v->flags & SAVEDVAR))
v->flags |= INMEMORY;
-#if defined(HAS_4BYTE_STACKSLOT)
- if ((memneeded == 1) && (rd->freememtop_2 > 0))
- POP_BACK(rd->freemem_2, rd->freememtop_2, v->vv.regoff);
+ if (rd->freememtop > 0)
+ POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
else
-#endif /*defined(HAS_4BYTE_STACKSLOT) */
- if ((memneeded == 0) && (rd->freememtop > 0))
- POP_BACK(rd->freemem, rd->freememtop, v->vv.regoff);
- else
- NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
+ NEW_MEM_SLOT_REUSE_PADDING(v->vv.regoff);
}
}
if (flags & INMEMORY) {
-#if defined(HAS_4BYTE_STACKSLOT)
- if (IS_2_WORD_TYPE(type))
- PUSH_BACK(rd->freemem_2, rd->freememtop_2, regoff);
- else
-#endif
- PUSH_BACK(rd->freemem, rd->freememtop, regoff);
-
+ PUSH_BACK(rd->freemem, rd->freememtop, regoff);
return;
}
/* src/vm/jit/allocator/simplereg.h - register allocator 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: Christian Ullrich
-
*/
#include "arch.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
#include "vm/jit/inline/inline.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool regalloc(jitdata *jd);
#if defined(ENABLE_STATISTICS)
void simplereg_make_statistics(jitdata *jd);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _SIMPLE_REG_H */
\
md-abi.c \
md-abi.h \
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 0
#define SUPPORT_LONG 1
#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_FADD(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_FADDS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_FADDS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_FADDS(s1, s2, d);
- M_TRAPB;
- }
+ M_FADDS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_DADD(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_DADDS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_DADDS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_DADDS(s1, s2, d);
- M_TRAPB;
- }
+ M_DADDS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_FSUB(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_FSUBS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_FSUBS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_FSUBS(s1, s2, d);
- M_TRAPB;
- }
+ M_FSUBS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_DSUB(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_DSUBS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_DSUBS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_DSUBS(s1, s2, d);
- M_TRAPB;
- }
+ M_DSUBS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_FMUL(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_FMULS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_FMULS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_FMULS(s1, s2, d);
- M_TRAPB;
- }
+ M_FMULS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_DMUL(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_DMULS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_DMULS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_DMULS(s1, s2, d);
- M_TRAPB;
- }
+ M_DMULS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_FDIV(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_FDIVS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_FDIVS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_FDIVS(s1, s2, d);
- M_TRAPB;
- }
+ M_FDIVS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_DDIV(s1, s2, d);
+ if (d == s1 || d == s2) {
+ M_DDIVS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FMOV(REG_FTMP3, d);
} else {
- if (d == s1 || d == s2) {
- M_DDIVS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FMOV(REG_FTMP3, d);
- } else {
- M_DDIVS(s1, s2, d);
- M_TRAPB;
- }
+ M_DDIVS(s1, s2, d);
+ M_TRAPB;
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- if (opt_noieee) {
- M_CVTDF(s1, d);
- } else {
- M_CVTDFS(s1, d);
- M_TRAPB;
- }
+ M_CVTDFS(s1, d);
+ M_TRAPB;
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (opt_noieee) {
- M_LSUB_IMM(REG_ZERO, 1, d);
- M_FCMPEQ(s1, s2, REG_FTMP3);
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
- M_CLR (d);
- M_FCMPLT(s2, s1, REG_FTMP3);
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
- M_LADD_IMM(REG_ZERO, 1, d);
- } else {
- M_LSUB_IMM(REG_ZERO, 1, d);
- M_FCMPEQS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
- M_CLR (d);
- M_FCMPLTS(s2, s1, REG_FTMP3);
- M_TRAPB;
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
- M_LADD_IMM(REG_ZERO, 1, d);
- }
+ M_LSUB_IMM(REG_ZERO, 1, d);
+ M_FCMPEQS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instructions */
+ M_CLR (d);
+ M_FCMPLTS(s2, s1, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LADD_IMM(REG_ZERO, 1, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
s2 = emit_load_s2(jd, iptr, REG_FTMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- if (opt_noieee) {
- M_LADD_IMM(REG_ZERO, 1, d);
- M_FCMPEQ(s1, s2, REG_FTMP3);
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
- M_CLR (d);
- M_FCMPLT(s1, s2, REG_FTMP3);
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
- M_LSUB_IMM(REG_ZERO, 1, d);
- } else {
- M_LADD_IMM(REG_ZERO, 1, d);
- M_FCMPEQS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
- M_CLR (d);
- M_FCMPLTS(s1, s2, REG_FTMP3);
- M_TRAPB;
- M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
- M_LSUB_IMM(REG_ZERO, 1, d);
- }
+ M_LADD_IMM(REG_ZERO, 1, d);
+ M_FCMPEQS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_CLR (d);
+ M_FCMPLTS(s1, s2, REG_FTMP3);
+ M_TRAPB;
+ M_FBEQZ (REG_FTMP3, 1); /* jump over next instruction */
+ M_LSUB_IMM(REG_ZERO, 1, d);
emit_store_dst(jd, iptr, d);
break;
/* src/vm/jit/alpha/codegen.h - code generation macros and definitions for Alpha
- 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
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "config.h"
#include "vm/types.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* additional functions and macros to generate code ***************************/
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 1 * 4
-
-
/* macros to create code ******************************************************/
/* M_MEM - memory instruction format *******************************************
cd->mcodeptr += 4; \
} while (0)
+#define M_OP3_GET_Opcode(x) ( (((x) >> 26) & 0x3f ))
+
/* 3-address-floating-point-operation: M_FOP3
op .... opcode
#define M_FBEQZ(fa,disp) M_BRA (0x31,fa,disp) /* br a == 0.0*/
-/* macros for special commands (see an Alpha-manual for description) **********/
+/* macros for special commands (see an Alpha-manual for description) **********/
#define M_TRAPB M_MEM (0x18,0,0,0x0000) /* trap barrier*/
#define M_CMOVLE_IMM(a,b,c) M_OP3 (0x11,0x64, a,b,c,1) /* a<=0 ? c=b */
#define M_CMOVGT_IMM(a,b,c) M_OP3 (0x11,0x66, a,b,c,1) /* a> 0 ? c=b */
+// 0x04 seems to be the first undefined instruction which does not
+// call PALcode.
+#define M_UNDEFINED M_OP3(0x04, 0, 0, 0, 0, 0)
+
/* macros for unused commands (see an Alpha-manual for description) ***********/
#define M_ANDNOT(a,b,c,const) M_OP3 (0x11,0x08, a,b,c,const) /* c = a &~ b */
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "vm/options.h"
#include "vm/jit/abi-asm.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/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
/* Get machine code which is patched back in later. The
trap is 1 instruction word long. */
- mcode = *((uint32_t *) cd->mcodeptr);
+ mcode = *((uint32_t*) cd->mcodeptr);
- /* Destination register must not be REG_ZERO, because then no
- SIGSEGV is thrown. */
- M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_PATCHER);
+ // Generate a SIGILL.
+ M_UNDEFINED;
return mcode;
}
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/signallocal.h"
#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
#include "vm/jit/executionstate.h"
#include "vm/jit/trap.h"
intptr_t val;
intptr_t addr;
int type;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
- switch (type) {
- case TRAP_COMPILER:
- if (p != NULL) {
- _mc->sc_regs[REG_PV] = (uintptr_t) p;
- _mc->sc_pc = (uintptr_t) p;
- break;
- }
- /* Get and set the PV from the parent Java method. */
+/* md_signal_handler_sigill ****************************************************
- pv = md_codegen_get_pv_from_pc(ra);
+ Illegal Instruction signal handler for hardware exception checks.
- _mc->sc_regs[REG_PV] = (uintptr_t) pv;
+*******************************************************************************/
- /* Get the exception object. */
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t* _uc = (ucontext_t*) _p;
+ mcontext_t* _mc = &_uc->uc_mcontext;
- p = builtin_retrieve_exception();
+ void* pv = (u1 *) _mc->sc_regs[REG_PV];
+ void* sp = (u1 *) _mc->sc_regs[REG_SP];
+ void* ra = (u1 *) _mc->sc_regs[REG_RA]; // RA is correct for leaf methods.
+ void* xpc = (u1 *) _mc->sc_pc;
- assert(p != NULL);
+ // The PC points to the instruction after the illegal instruction.
+ xpc = (void*) (((uintptr_t) xpc) - 4);
- /* fall-through */
+ // Get the exception-throwing instruction.
+ uint32_t mcode = *((uint32_t*) xpc);
- case TRAP_PATCHER:
- if (p == NULL)
- break;
+ int opcode = M_OP3_GET_Opcode(mcode);
- /* fall-through */
-
- default:
- _mc->sc_regs[REG_ITMP1_XPTR] = (uintptr_t) p;
- _mc->sc_regs[REG_ITMP2_XPC] = (uintptr_t) xpc;
- _mc->sc_pc = (uintptr_t) asm_handle_exception;
+ // Check for undefined instruction we use.
+ // TODO Check the whole instruction.
+ if (opcode != 0x4) {
+ log_println("md_signal_handler_sigill: Unknown illegal instruction %x at %p", mcode, xpc);
+#if defined(ENABLE_DISASSEMBLER)
+ (void) disassinstr(xpc);
+#endif
+ vm_abort("Aborting...");
}
+
+ // This signal is always a patcher.
+ int type = TRAP_PATCHER;
+ intptr_t val = 0;
+
+ // Handle the trap.
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
--- /dev/null
+/* src/vm/jit/alpha/md-stubs.hpp - Alpha JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on an Alpha architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 1 * 4;
+}
+
+#endif // _MD_STUBS_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 "vm/jit/alpha/md.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/trap.h"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
/* global variables ***********************************************************/
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#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/patcher-common.hpp"
#include "vm/jit/methodheader.h"
-#define PATCH_BACK_ORIGINAL_MCODE \
- *((u4 *) pr->mpc) = (u4) pr->mcode; \
- md_icacheflush(NULL, 0);
-
-
/* patcher_patch_code **********************************************************
Just patches back the original machine code.
*******************************************************************************/
-void patcher_patch_code(patchref_t *pr)
+void patcher_patch_code(patchref_t* pr)
{
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch back original code.
+ *((uint32_t*) pr->mpc) = pr->mcode;
+
+ // Synchronize instruction cache.
+ md_icacheflush(NULL, 0);
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch the classinfo pointer */
*((ptrint *) datap) = (ptrint) c;
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch super class' vftbl */
*((ptrint *) datap) = (ptrint) c->vftbl;
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch class flags */
*((s4 *) datap) = (s4) c->flags;
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
if (!initialize_class(fi->clazz))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch the field value's address */
*((intptr_t *) datap) = (intptr_t) fi->value;
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_get_putfield(patchref_t *pr)
{
- u1 *ra;
unresolved_field *uf;
fieldinfo *fi;
- ra = (u1 *) pr->mpc;
uf = (unresolved_field *) pr->ref;
/* get the fieldinfo */
if (!(fi = resolve_field_eager(uf)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
-
/* patch the field's offset into the instruction */
- *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
+ pr->mcode |= (s2) (fi->offset & 0x0000ffff);
- md_icacheflush(NULL, 0);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
if (!(m = resolve_method_eager(um)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch stubroutine */
*((ptrint *) datap) = (ptrint) m->stubroutine;
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
if (!(m = resolve_method_eager(um)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
-
/* patch vftbl index */
*((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, table[0]) +
md_icacheflush(NULL, 0);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
if (!(m = resolve_method_eager(um)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
-
/* patch interfacetable index */
*((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
md_icacheflush(NULL, 0);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
-
/* patch super class index */
*((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
md_icacheflush(NULL, 0);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
-
/* patch super class index */
*((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
md_icacheflush(NULL, 0);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
+++ /dev/null
-/* src/vm/jit/argument.c - argument passing from and to JIT methods
-
- 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 "arch.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "vm/array.h"
-#include "vm/descriptor.h"
-#include "vm/global.h"
-#include "vm/method.h"
-#include "vm/primitive.hpp"
-#include "vm/resolve.h"
-#include "vm/vm.hpp"
-
-#include "vm/jit/abi-asm.h"
-
-
-/* argument_jitarray_load ******************************************************
-
- Returns the argument specified by index from one of the passed arrays
- and returns it.
-
-*******************************************************************************/
-
-imm_union argument_jitarray_load(methoddesc *md, int32_t index,
- uint64_t *arg_regs, uint64_t *stack)
-{
- imm_union ret;
- paramdesc *pd;
-
- pd = &md->params[index];
-
- switch (md->paramtypes[index].type) {
- case TYPE_INT:
- case TYPE_ADR:
- if (pd->inmemory) {
-#if (SIZEOF_VOID_P == 8)
- ret.l = (int64_t)stack[pd->index];
-#else
- ret.l = *(int32_t *)(stack + pd->index);
-#endif
- } else {
-#if (SIZEOF_VOID_P == 8)
- ret.l = arg_regs[index];
-#else
- ret.l = *(int32_t *)(arg_regs + index);
-#endif
- }
- break;
- case TYPE_LNG:
- if (pd->inmemory) {
- ret.l = (int64_t)stack[pd->index];
- } else {
- ret.l = (int64_t)arg_regs[index];
- }
- break;
- case TYPE_FLT:
- if (pd->inmemory) {
- ret.l = (int64_t)stack[pd->index];
- } else {
- ret.l = (int64_t)arg_regs[index];
- }
- break;
- case TYPE_DBL:
- if (pd->inmemory) {
- ret.l = (int64_t)stack[pd->index];
- } else {
- ret.l = (int64_t)arg_regs[index];
- }
- break;
- }
-
- return ret;
-}
-
-
-/* argument_jitarray_store *****************************************************
-
- Stores the argument into one of the passed arrays at a slot specified
- by index.
-
-*******************************************************************************/
-
-void argument_jitarray_store(methoddesc *md, int32_t index,
- uint64_t *arg_regs, uint64_t *stack,
- imm_union param)
-{
- paramdesc *pd;
-
- pd = &md->params[index];
-
- switch (md->paramtypes[index].type) {
- case TYPE_ADR:
- if (pd->inmemory) {
-#if (SIZEOF_VOID_P == 8)
- stack[pd->index] = param.l;
-#else
- assert(0);
-#endif
- } else {
- arg_regs[index] = param.l;
- }
- break;
- default:
- vm_abort("argument_jitarray_store: type not implemented");
- break;
- }
-}
-
-
-/* argument_jitreturn_load *****************************************************
-
- Loads the proper return value form the return register and returns it.
-
-*******************************************************************************/
-
-imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
-{
- imm_union ret;
-
- switch (md->returntype.type) {
- case TYPE_INT:
- case TYPE_ADR:
-#if (SIZEOF_VOID_P == 8)
- ret.l = return_regs[0];
-#else
- ret.l = *(int32_t *)return_regs;
-#endif
- break;
- case TYPE_LNG:
- ret.l = *(int64_t *)return_regs;
- break;
- case TYPE_FLT:
- ret.l = *(int64_t *)return_regs;
- break;
- case TYPE_DBL:
- ret.l = *(int64_t *)return_regs;
- break;
- }
-
- return ret;
-}
-
-
-/* argument_jitreturn_store ****************************************************
-
- Stores the proper return value into the return registers.
-
-*******************************************************************************/
-
-void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
-{
- switch (md->returntype.type) {
- case TYPE_ADR:
-#if (SIZEOF_VOID_P == 8)
- return_regs[0] = ret.l;
-#else
- assert(0);
-#endif
- break;
- default:
- vm_abort("argument_jitreturn_store: type not implemented");
- break;
- }
-}
-
-
-/* argument_vmarray_store_int **************************************************
-
- Helper function to store an integer into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
-{
- int32_t index;
-
- if (!pd->inmemory) {
- index = pd->index;
- array[index] = (int64_t) value;
- }
- else {
- index = ARG_CNT + pd->index;
-#if SIZEOF_VOID_P == 8
- array[index] = (int64_t) value;
-#else
-# if WORDS_BIGENDIAN == 1
- array[index] = ((int64_t) value) << 32;
-# else
- array[index] = (int64_t) value;
-# endif
-#endif
- }
-}
-
-
-/* argument_vmarray_store_lng **************************************************
-
- Helper function to store a long into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
-{
- int32_t index;
-
-#if SIZEOF_VOID_P == 8
- if (!pd->inmemory)
- index = pd->index;
- else
- index = ARG_CNT + pd->index;
-
- array[index] = value;
-#else
- if (!pd->inmemory) {
- /* move low and high 32-bits into it's own argument slot */
-
- index = GET_LOW_REG(pd->index);
- array[index] = value & 0x00000000ffffffff;
-
- index = GET_HIGH_REG(pd->index);
- array[index] = value >> 32;
- }
- else {
- index = ARG_CNT + pd->index;
- array[index] = value;
- }
-#endif
-}
-
-
-/* argument_vmarray_store_flt **************************************************
-
- Helper function to store a float into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
-{
- int32_t index;
-
- if (!pd->inmemory) {
-#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- index = pd->index;
-#else
- index = INT_ARG_CNT + pd->index;
-#endif
-#if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
- array[index] = value >> 32;
-#else
- array[index] = value;
-#endif
- }
- else {
- index = ARG_CNT + pd->index;
-#if defined(__SPARC_64__)
- array[index] = value >> 32;
-#else
- array[index] = value;
-#endif
- }
-}
-
-
-/* argument_vmarray_store_dbl **************************************************
-
- Helper function to store a double into the argument array, taking
- care of architecture specific issues.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
-{
- int32_t index;
-
- if (!pd->inmemory) {
-#if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
- index = GET_LOW_REG(pd->index);
- array[index] = value & 0x00000000ffffffff;
-
- index = GET_HIGH_REG(pd->index);
- array[index] = value >> 32;
-#else
- index = INT_ARG_CNT + pd->index;
- array[index] = value;
-#endif
- }
- else {
- index = ARG_CNT + pd->index;
- array[index] = value;
- }
-}
-
-
-/* argument_vmarray_store_adr **************************************************
-
- Helper function to store an address into the argument array, taking
- care of architecture specific issues.
-
- ATTENTION: This function has to be used outside the nativeworld.
-
-*******************************************************************************/
-
-static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
-{
- void *value;
- int32_t index;
-
- /* Take the reference value out of the handle. */
-
- value = LLNI_UNWRAP(h);
-
- if (!pd->inmemory) {
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- /* When the architecture has address registers, place them
- after integer and float registers. */
-
- index = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
-#else
- index = pd->index;
-#endif
- array[index] = (uint64_t) (intptr_t) value;
- }
- else {
- index = ARG_CNT + pd->index;
-#if SIZEOF_VOID_P == 8
- array[index] = (uint64_t) (intptr_t) value;
-#else
-# if WORDS_BIGENDIAN == 1
- array[index] = ((uint64_t) (intptr_t) value) << 32;
-# else
- array[index] = (uint64_t) (intptr_t) value;
-# endif
-#endif
- }
-}
-
-
-/* argument_vmarray_from_valist ************************************************
-
- Creates an argument array which can be passed to asm_vm_call_method.
- The array is created from the passed valist.
-
- ATTENTION: This function has to be used outside the native world.
-
-*******************************************************************************/
-
-uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
-{
- methoddesc *md;
- paramdesc *pd;
- typedesc *td;
- uint64_t *array;
- int32_t i;
- imm_union value;
-
- /* get the descriptors */
-
- md = m->parseddesc;
- pd = md->params;
- td = md->paramtypes;
-
- /* allocate argument array */
-
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-
- /* if method is non-static fill first block and skip `this' pointer */
-
- i = 0;
-
- if (o != NULL) {
- /* the `this' pointer */
- argument_vmarray_store_adr(array, pd, o);
-
- pd++;
- td++;
- i++;
- }
-
- for (; i < md->paramcount; i++, pd++, td++) {
- switch (td->type) {
- case TYPE_INT:
- value.i = va_arg(ap, int32_t);
- argument_vmarray_store_int(array, pd, value.i);
- break;
-
- case TYPE_LNG:
- value.l = va_arg(ap, int64_t);
- argument_vmarray_store_lng(array, pd, value.l);
- break;
-
- case TYPE_FLT:
-#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
- /* This is required to load the correct float value in
- assembler code. */
-
- value.d = (double) va_arg(ap, double);
-#else
- value.f = (float) va_arg(ap, double);
-#endif
- argument_vmarray_store_flt(array, pd, value.l);
- break;
-
- case TYPE_DBL:
- value.d = va_arg(ap, double);
- argument_vmarray_store_dbl(array, pd, value.l);
- break;
-
- case TYPE_ADR:
- value.a = va_arg(ap, void*);
- argument_vmarray_store_adr(array, pd, value.a);
- break;
- }
- }
-
- return array;
-}
-
-
-/* argument_vmarray_from_jvalue ************************************************
-
- Creates an argument array which can be passed to asm_vm_call_method.
- The array is created from the passed jvalue array.
-
- ATTENTION: This function has to be used outside the native world.
-
-*******************************************************************************/
-
-uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
- const jvalue *args)
-{
- methoddesc *md;
- paramdesc *pd;
- typedesc *td;
- uint64_t *array;
- int32_t i;
- int32_t j;
-
- /* get the descriptors */
-
- md = m->parseddesc;
- pd = md->params;
- td = md->paramtypes;
-
- /* allocate argument array */
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse);
-#else
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-#endif
-
- /* if method is non-static fill first block and skip `this' pointer */
-
- i = 0;
-
- if (o != NULL) {
- /* the `this' pointer */
- argument_vmarray_store_adr(array, pd, o);
-
- pd++;
- td++;
- i++;
- }
-
- for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
- switch (td->primitivetype) {
- case TYPE_INT:
- argument_vmarray_store_int(array, pd, args[j].i);
- break;
-
- case TYPE_LNG:
- argument_vmarray_store_lng(array, pd, args[j].j);
- break;
-
- case TYPE_FLT:
- argument_vmarray_store_flt(array, pd, args[j].j);
- break;
-
- case TYPE_DBL:
- argument_vmarray_store_dbl(array, pd, args[j].j);
- break;
-
- case TYPE_ADR:
- argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
- break;
- }
- }
-
- return array;
-}
-
-
-/* argument_vmarray_from_objectarray *******************************************
-
- Creates an argument array which can be passed to asm_vm_call_method.
- The array is created from the passed objectarray of boxed values.
-
- ATTENTION: This function has to be used outside the native world.
-
- RETURN VALUE:
- NULL.........indicates an error while creating the array
- (-1).........no error, but an empty array
- otherwise....array containing the argument values
-
-*******************************************************************************/
-
-uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
- java_handle_objectarray_t *params)
-{
- methoddesc *md;
- paramdesc *pd;
- typedesc *td;
- uint64_t *array;
- java_handle_t *param;
- classinfo *c;
- int type;
- int32_t i;
- int32_t j;
- imm_union value;
-
- /* get the descriptors */
-
- md = m->parseddesc;
- pd = md->params;
- td = md->paramtypes;
-
- /* allocate argument array */
-
- array = DMNEW(uint64_t, INT_ARG_CNT + FLT_ARG_CNT + md->memuse);
-
- /* The array can be NULL if we don't have any arguments to pass
- and the architecture does not have any argument registers
- (e.g. i386). In that case we return (-1) to indicate
- that no exception should be thrown */
-
- if (array == NULL)
- array = (uint64_t *)(-1);
-
- /* if method is non-static fill first block and skip `this' pointer */
-
- i = 0;
-
- if (o != NULL) {
- /* this pointer */
- argument_vmarray_store_adr(array, pd, o);
-
- pd++;
- td++;
- i++;
- }
-
- for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
- /* XXX This function can throw an exception, which should not happend
- here, since we are outside the nativeworld. */
- param = array_objectarray_element_get(params, j);
-
- switch (td->type) {
- case TYPE_INT:
- if (param == NULL)
- return NULL;
-
- /* convert the value according to its declared type */
-
- LLNI_class_get(param, c);
- type = Primitive_get_type_by_wrapperclass(c);
-
- switch (td->primitivetype) {
- case PRIMITIVETYPE_BOOLEAN:
- switch (type) {
- case PRIMITIVETYPE_BOOLEAN:
- /* This type is OK. */
- break;
- default:
- return NULL;
- }
- break;
-
- case PRIMITIVETYPE_BYTE:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- /* This type is OK. */
- break;
- default:
- return NULL;
- }
- break;
-
- case PRIMITIVETYPE_CHAR:
- switch (type) {
- case PRIMITIVETYPE_CHAR:
- /* This type is OK. */
- break;
- default:
- return NULL;
- }
- break;
-
- case PRIMITIVETYPE_SHORT:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- /* These types are OK. */
- break;
- default:
- return NULL;
- }
- break;
-
- case PRIMITIVETYPE_INT:
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- /* These types are OK. */
- break;
- default:
- return NULL;
- }
- break;
-
- default:
- vm_abort("argument_vmarray_from_objectarray: invalid type %d",
- td->primitivetype);
- }
-
- value = Primitive_unbox(param);
- argument_vmarray_store_int(array, pd, value.i);
- break;
-
- case TYPE_LNG:
- if (param == NULL)
- return NULL;
-
- LLNI_class_get(param, c);
- type = Primitive_get_type_by_wrapperclass(c);
-
- assert(td->primitivetype == PRIMITIVETYPE_LONG);
-
- switch (type) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- case PRIMITIVETYPE_LONG:
- /* These types are OK. */
- break;
- default:
- return NULL;
- }
-
- value = Primitive_unbox(param);
- argument_vmarray_store_lng(array, pd, value.l);
- break;
-
- case TYPE_FLT:
- if (param == NULL)
- return NULL;
-
- LLNI_class_get(param, c);
- type = Primitive_get_type_by_wrapperclass(c);
-
- assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
-
- switch (type) {
- case PRIMITIVETYPE_FLOAT:
- /* This type is OK. */
- break;
- default:
- return NULL;
- }
-
- value = Primitive_unbox(param);
- argument_vmarray_store_flt(array, pd, value.l);
- break;
-
- case TYPE_DBL:
- if (param == NULL)
- return NULL;
-
- LLNI_class_get(param, c);
- type = Primitive_get_type_by_wrapperclass(c);
-
- assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
-
- switch (type) {
- case PRIMITIVETYPE_FLOAT:
- case PRIMITIVETYPE_DOUBLE:
- /* These types are OK. */
- break;
- default:
- return NULL;
- }
-
- value = Primitive_unbox(param);
- argument_vmarray_store_dbl(array, pd, value.l);
- break;
-
- case TYPE_ADR:
- if (!resolve_class_from_typedesc(td, true, true, &c))
- return NULL;
-
- if (param != NULL) {
- if (td->arraydim > 0) {
- if (!builtin_arrayinstanceof(param, c))
- return NULL;
- }
- else {
- if (!builtin_instanceof(param, c))
- return NULL;
- }
- }
-
- argument_vmarray_store_adr(array, pd, param);
- break;
-
- default:
- vm_abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
- }
- }
-
- return array;
-}
-
-
-/*
- * These 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/argument.cpp - argument passing from and to JIT methods
+
+ 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 "arch.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "vm/array.hpp"
+#include "vm/descriptor.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/primitive.hpp"
+#include "vm/resolve.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/abi-asm.h"
+
+
+/* argument_jitarray_load ******************************************************
+
+ Returns the argument specified by index from one of the passed arrays
+ and returns it.
+
+*******************************************************************************/
+
+imm_union argument_jitarray_load(methoddesc *md, int32_t index,
+ uint64_t *arg_regs, uint64_t *stack)
+{
+ imm_union ret;
+ paramdesc *pd;
+
+ pd = &md->params[index];
+
+ switch (md->paramtypes[index].type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ if (pd->inmemory) {
+#if (SIZEOF_VOID_P == 8)
+ ret.l = (int64_t)stack[pd->index];
+#else
+ ret.l = *(int32_t *)(stack + pd->index);
+#endif
+ } else {
+#if (SIZEOF_VOID_P == 8)
+ ret.l = arg_regs[index];
+#else
+ ret.l = *(int32_t *)(arg_regs + index);
+#endif
+ }
+ break;
+ case TYPE_LNG:
+ if (pd->inmemory) {
+ ret.l = (int64_t)stack[pd->index];
+ } else {
+ ret.l = (int64_t)arg_regs[index];
+ }
+ break;
+ case TYPE_FLT:
+ if (pd->inmemory) {
+ ret.l = (int64_t)stack[pd->index];
+ } else {
+ ret.l = (int64_t)arg_regs[index];
+ }
+ break;
+ case TYPE_DBL:
+ if (pd->inmemory) {
+ ret.l = (int64_t)stack[pd->index];
+ } else {
+ ret.l = (int64_t)arg_regs[index];
+ }
+ break;
+ }
+
+ return ret;
+}
+
+
+/* argument_jitarray_store *****************************************************
+
+ Stores the argument into one of the passed arrays at a slot specified
+ by index.
+
+*******************************************************************************/
+
+void argument_jitarray_store(methoddesc *md, int32_t index,
+ uint64_t *arg_regs, uint64_t *stack,
+ imm_union param)
+{
+ paramdesc *pd;
+
+ pd = &md->params[index];
+
+ switch (md->paramtypes[index].type) {
+ case TYPE_ADR:
+ if (pd->inmemory) {
+#if (SIZEOF_VOID_P == 8)
+ stack[pd->index] = param.l;
+#else
+ assert(0);
+#endif
+ } else {
+ arg_regs[index] = param.l;
+ }
+ break;
+ default:
+ os::abort("argument_jitarray_store: type not implemented");
+ break;
+ }
+}
+
+
+/* argument_jitreturn_load *****************************************************
+
+ Loads the proper return value form the return register and returns it.
+
+*******************************************************************************/
+
+imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs)
+{
+ imm_union ret;
+
+ switch (md->returntype.type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+#if (SIZEOF_VOID_P == 8)
+ ret.l = return_regs[0];
+#else
+ ret.l = *(int32_t *)return_regs;
+#endif
+ break;
+ case TYPE_LNG:
+ ret.l = *(int64_t *)return_regs;
+ break;
+ case TYPE_FLT:
+ ret.l = *(int64_t *)return_regs;
+ break;
+ case TYPE_DBL:
+ ret.l = *(int64_t *)return_regs;
+ break;
+ }
+
+ return ret;
+}
+
+
+/* argument_jitreturn_store ****************************************************
+
+ Stores the proper return value into the return registers.
+
+*******************************************************************************/
+
+void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs, imm_union ret)
+{
+ switch (md->returntype.type) {
+ case TYPE_ADR:
+#if (SIZEOF_VOID_P == 8)
+ return_regs[0] = ret.l;
+#else
+ assert(0);
+#endif
+ break;
+ default:
+ os::abort("argument_jitreturn_store: type not implemented");
+ break;
+ }
+}
+
+
+/* argument_vmarray_store_int **************************************************
+
+ Helper function to store an integer into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_int(uint64_t *array, paramdesc *pd, int32_t value)
+{
+ int32_t index;
+
+ if (!pd->inmemory) {
+ index = pd->index;
+ array[index] = (int64_t) value;
+ }
+ else {
+ index = ARG_CNT + pd->index;
+#if SIZEOF_VOID_P == 8
+ array[index] = (int64_t) value;
+#else
+# if WORDS_BIGENDIAN == 1
+ array[index] = ((int64_t) value) << 32;
+# else
+ array[index] = (int64_t) value;
+# endif
+#endif
+ }
+}
+
+
+/* argument_vmarray_store_lng **************************************************
+
+ Helper function to store a long into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_lng(uint64_t *array, paramdesc *pd, int64_t value)
+{
+ int32_t index;
+
+#if SIZEOF_VOID_P == 8
+ if (!pd->inmemory)
+ index = pd->index;
+ else
+ index = ARG_CNT + pd->index;
+
+ array[index] = value;
+#else
+ if (!pd->inmemory) {
+ /* move low and high 32-bits into it's own argument slot */
+
+ index = GET_LOW_REG(pd->index);
+ array[index] = value & 0x00000000ffffffff;
+
+ index = GET_HIGH_REG(pd->index);
+ array[index] = value >> 32;
+ }
+ else {
+ index = ARG_CNT + pd->index;
+ array[index] = value;
+ }
+#endif
+}
+
+
+/* argument_vmarray_store_flt **************************************************
+
+ Helper function to store a float into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_flt(uint64_t *array, paramdesc *pd, uint64_t value)
+{
+ int32_t index;
+
+ if (!pd->inmemory) {
+#if defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ index = pd->index;
+#else
+ index = INT_ARG_CNT + pd->index;
+#endif
+#if WORDS_BIGENDIAN == 1 && !defined(__POWERPC__) && !defined(__POWERPC64__) && !defined(__S390__)
+ array[index] = value >> 32;
+#else
+ array[index] = value;
+#endif
+ }
+ else {
+ index = ARG_CNT + pd->index;
+#if defined(__SPARC_64__)
+ array[index] = value >> 32;
+#else
+ array[index] = value;
+#endif
+ }
+}
+
+
+/* argument_vmarray_store_dbl **************************************************
+
+ Helper function to store a double into the argument array, taking
+ care of architecture specific issues.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_dbl(uint64_t *array, paramdesc *pd, uint64_t value)
+{
+ int32_t index;
+
+ if (!pd->inmemory) {
+#if SIZEOF_VOID_P != 8 && defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+ index = GET_LOW_REG(pd->index);
+ array[index] = value & 0x00000000ffffffff;
+
+ index = GET_HIGH_REG(pd->index);
+ array[index] = value >> 32;
+#else
+ index = INT_ARG_CNT + pd->index;
+ array[index] = value;
+#endif
+ }
+ else {
+ index = ARG_CNT + pd->index;
+ array[index] = value;
+ }
+}
+
+
+/* argument_vmarray_store_adr **************************************************
+
+ Helper function to store an address into the argument array, taking
+ care of architecture specific issues.
+
+ ATTENTION: This function has to be used outside the nativeworld.
+
+*******************************************************************************/
+
+static void argument_vmarray_store_adr(uint64_t *array, paramdesc *pd, java_handle_t *h)
+{
+ void *value;
+ int32_t index;
+
+ /* Take the reference value out of the handle. */
+
+ value = LLNI_UNWRAP(h);
+
+ if (!pd->inmemory) {
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ /* When the architecture has address registers, place them
+ after integer and float registers. */
+
+ index = INT_ARG_CNT + FLT_ARG_CNT + pd->index;
+#else
+ index = pd->index;
+#endif
+ array[index] = (uint64_t) (intptr_t) value;
+ }
+ else {
+ index = ARG_CNT + pd->index;
+#if SIZEOF_VOID_P == 8
+ array[index] = (uint64_t) (intptr_t) value;
+#else
+# if WORDS_BIGENDIAN == 1
+ array[index] = ((uint64_t) (intptr_t) value) << 32;
+# else
+ array[index] = (uint64_t) (intptr_t) value;
+# endif
+#endif
+ }
+}
+
+
+/* argument_vmarray_from_valist ************************************************
+
+ Creates an argument array which can be passed to asm_vm_call_method.
+ The array is created from the passed valist.
+
+ ATTENTION: This function has to be used outside the native world.
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o, va_list ap)
+{
+ methoddesc *md;
+ paramdesc *pd;
+ typedesc *td;
+ uint64_t *array;
+ int32_t i;
+ imm_union value;
+
+ /* get the descriptors */
+
+ md = m->parseddesc;
+ pd = md->params;
+ td = md->paramtypes;
+
+ // Allocate argument array.
+ array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* the `this' pointer */
+ argument_vmarray_store_adr(array, pd, o);
+
+ pd++;
+ td++;
+ i++;
+ }
+
+ for (; i < md->paramcount; i++, pd++, td++) {
+ switch (td->type) {
+ case TYPE_INT:
+ value.i = va_arg(ap, int32_t);
+ argument_vmarray_store_int(array, pd, value.i);
+ break;
+
+ case TYPE_LNG:
+ value.l = va_arg(ap, int64_t);
+ argument_vmarray_store_lng(array, pd, value.l);
+ break;
+
+ case TYPE_FLT:
+#if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__)
+ /* This is required to load the correct float value in
+ assembler code. */
+
+ value.d = (double) va_arg(ap, double);
+#else
+ value.f = (float) va_arg(ap, double);
+#endif
+ argument_vmarray_store_flt(array, pd, value.l);
+ break;
+
+ case TYPE_DBL:
+ value.d = va_arg(ap, double);
+ argument_vmarray_store_dbl(array, pd, value.l);
+ break;
+
+ case TYPE_ADR:
+ value.a = va_arg(ap, void*);
+ argument_vmarray_store_adr(array, pd, static_cast<java_handle_t*>(value.a));
+ break;
+ }
+ }
+
+ return array;
+}
+
+
+/* argument_vmarray_from_jvalue ************************************************
+
+ Creates an argument array which can be passed to asm_vm_call_method.
+ The array is created from the passed jvalue array.
+
+ ATTENTION: This function has to be used outside the native world.
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
+ const jvalue *args)
+{
+ methoddesc *md;
+ paramdesc *pd;
+ typedesc *td;
+ uint64_t *array;
+ int32_t i;
+ int32_t j;
+
+ /* get the descriptors */
+
+ md = m->parseddesc;
+ pd = md->params;
+ td = md->paramtypes;
+
+ /* allocate argument array */
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + ADR_ARG_CNT + md->memuse));
+#else
+ array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
+#endif
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* the `this' pointer */
+ argument_vmarray_store_adr(array, pd, o);
+
+ pd++;
+ td++;
+ i++;
+ }
+
+ for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
+ switch (td->primitivetype) {
+ case TYPE_INT:
+ argument_vmarray_store_int(array, pd, args[j].i);
+ break;
+
+ case TYPE_LNG:
+ argument_vmarray_store_lng(array, pd, args[j].j);
+ break;
+
+ case TYPE_FLT:
+ argument_vmarray_store_flt(array, pd, args[j].j);
+ break;
+
+ case TYPE_DBL:
+ argument_vmarray_store_dbl(array, pd, args[j].j);
+ break;
+
+ case TYPE_ADR:
+ argument_vmarray_store_adr(array, pd, (java_handle_t *) args[j].l);
+ break;
+ }
+ }
+
+ return array;
+}
+
+
+/* argument_vmarray_from_objectarray *******************************************
+
+ Creates an argument array which can be passed to asm_vm_call_method.
+ The array is created from the passed objectarray of boxed values.
+
+ ATTENTION: This function has to be used outside the native world.
+
+ RETURN VALUE:
+ NULL.........indicates an error while creating the array
+ (-1).........no error, but an empty array
+ otherwise....array containing the argument values
+
+*******************************************************************************/
+
+uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
+ java_handle_objectarray_t *params)
+{
+ methoddesc *md;
+ paramdesc *pd;
+ typedesc *td;
+ uint64_t *array;
+ java_handle_t *param;
+ classinfo *c;
+ int type;
+ int32_t i;
+ int32_t j;
+ imm_union value;
+
+ /* get the descriptors */
+
+ md = m->parseddesc;
+ pd = md->params;
+ td = md->paramtypes;
+
+ /* allocate argument array */
+
+ array = (uint64_t*) DumpMemory::allocate(sizeof(uint64_t) * (INT_ARG_CNT + FLT_ARG_CNT + md->memuse));
+
+ /* The array can be NULL if we don't have any arguments to pass
+ and the architecture does not have any argument registers
+ (e.g. i386). In that case we return (-1) to indicate
+ that no exception should be thrown */
+
+ if (array == NULL)
+ array = (uint64_t *)(-1);
+
+ /* if method is non-static fill first block and skip `this' pointer */
+
+ i = 0;
+
+ if (o != NULL) {
+ /* this pointer */
+ argument_vmarray_store_adr(array, pd, o);
+
+ pd++;
+ td++;
+ i++;
+ }
+
+ for (j = 0; i < md->paramcount; i++, j++, pd++, td++) {
+ /* XXX This function can throw an exception, which should not happend
+ here, since we are outside the nativeworld. */
+ param = array_objectarray_element_get(params, j);
+
+ switch (td->type) {
+ case TYPE_INT:
+ if (param == NULL)
+ return NULL;
+
+ /* convert the value according to its declared type */
+
+ LLNI_class_get(param, c);
+ type = Primitive::get_type_by_wrapperclass(c);
+
+ switch (td->primitivetype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ switch (type) {
+ case PRIMITIVETYPE_BOOLEAN:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_BYTE:
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_CHAR:
+ switch (type) {
+ case PRIMITIVETYPE_CHAR:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_SHORT:
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ case PRIMITIVETYPE_INT:
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+ break;
+
+ default:
+ os::abort("argument_vmarray_from_objectarray: invalid type %d",
+ td->primitivetype);
+ }
+
+ value = Primitive::unbox(param);
+ argument_vmarray_store_int(array, pd, value.i);
+ break;
+
+ case TYPE_LNG:
+ if (param == NULL)
+ return NULL;
+
+ LLNI_class_get(param, c);
+ type = Primitive::get_type_by_wrapperclass(c);
+
+ assert(td->primitivetype == PRIMITIVETYPE_LONG);
+
+ switch (type) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ case PRIMITIVETYPE_LONG:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+
+ value = Primitive::unbox(param);
+ argument_vmarray_store_lng(array, pd, value.l);
+ break;
+
+ case TYPE_FLT:
+ if (param == NULL)
+ return NULL;
+
+ LLNI_class_get(param, c);
+ type = Primitive::get_type_by_wrapperclass(c);
+
+ assert(td->primitivetype == PRIMITIVETYPE_FLOAT);
+
+ switch (type) {
+ case PRIMITIVETYPE_FLOAT:
+ /* This type is OK. */
+ break;
+ default:
+ return NULL;
+ }
+
+ value = Primitive::unbox(param);
+ argument_vmarray_store_flt(array, pd, value.l);
+ break;
+
+ case TYPE_DBL:
+ if (param == NULL)
+ return NULL;
+
+ LLNI_class_get(param, c);
+ type = Primitive::get_type_by_wrapperclass(c);
+
+ assert(td->primitivetype == PRIMITIVETYPE_DOUBLE);
+
+ switch (type) {
+ case PRIMITIVETYPE_FLOAT:
+ case PRIMITIVETYPE_DOUBLE:
+ /* These types are OK. */
+ break;
+ default:
+ return NULL;
+ }
+
+ value = Primitive::unbox(param);
+ argument_vmarray_store_dbl(array, pd, value.l);
+ break;
+
+ case TYPE_ADR:
+ if (!resolve_class_from_typedesc(td, true, true, &c))
+ return NULL;
+
+ if (param != NULL) {
+ if (td->arraydim > 0) {
+ if (!builtin_arrayinstanceof(param, c))
+ return NULL;
+ }
+ else {
+ if (!builtin_instanceof(param, c))
+ return NULL;
+ }
+ }
+
+ argument_vmarray_store_adr(array, pd, param);
+ break;
+
+ default:
+ os::abort("argument_vmarray_from_objectarray: invalid type %d", td->type);
+ }
+ }
+
+ return array;
+}
+
+
+/*
+ * These 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/argument.h - argument passing from and to JIT methods
-
- 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 _VM_JIT_ARGUMENT_H
-#define _VM_JIT_ARGUMENT_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-imm_union argument_jitarray_load(methoddesc *md, int32_t index,
- uint64_t *arg_regs, uint64_t *stack);
-void argument_jitarray_store(methoddesc *md, int32_t index,
- uint64_t *arg_regs, uint64_t *stack,
- imm_union param);
-
-imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs);
-void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs,
- imm_union ret);
-
-uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o,
- va_list ap);
-uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
- const jvalue *args);
-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 */
-
-
-/*
- * These 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/argument.hpp - argument passing from and to JIT methods
+
+ 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 _VM_JIT_ARGUMENT_HPP
+#define _VM_JIT_ARGUMENT_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/global.h"
+#include "vm/method.h"
+
+
+/* function prototypes ********************************************************/
+
+imm_union argument_jitarray_load(methoddesc *md, int32_t index,
+ uint64_t *arg_regs, uint64_t *stack);
+void argument_jitarray_store(methoddesc *md, int32_t index,
+ uint64_t *arg_regs, uint64_t *stack,
+ imm_union param);
+
+imm_union argument_jitreturn_load(methoddesc *md, uint64_t *return_regs);
+void argument_jitreturn_store(methoddesc *md, uint64_t *return_regs,
+ imm_union ret);
+
+uint64_t *argument_vmarray_from_valist(methodinfo *m, java_handle_t *o,
+ va_list ap);
+uint64_t *argument_vmarray_from_jvalue(methodinfo *m, java_handle_t *o,
+ const jvalue *args);
+uint64_t *argument_vmarray_from_objectarray(methodinfo *m, java_handle_t *o,
+ java_handle_objectarray_t *params);
+
+#endif // _VM_JIT_ARGUMENT_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:
+ */
\
md-abi.c \
md-abi.h \
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
#ifndef _ARCH_H
#define _ARCH_H
+#define JIT_COMPILER_VIA_SIGNAL
+
#include "config.h"
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 0
#define SUPPORT_LONG 1
.globl asm_vm_call_method_exception_handler
.globl asm_vm_call_method_end
- .globl asm_call_jit_compiler
-
.globl asm_handle_exception
.globl asm_handle_nat_exception
asm_vm_call_method_end:
-/****************** function asm_call_jit_compiler *****************************
-* *
-* Invokes the compiler for untranslated JavaVM methods. *
-* What this method does: *
-* - save args and LR *
-* - fire up jit_compile (pass methodinfo pointer) *
-* - try to find out where to write back the new method pointer *
-* - restore args and LR *
-* - check for exceptions *
-* - eventually write back new method pointer *
-* - call jit code (wich will then return to caller) *
-* *
-* These methods can call us: codegen_compilerstub & asm_calljavafunction *
-* ATTENTION: use REG_ITMP1 to pass methodinfo pointer to me! *
-* *
-*******************************************************************************/
-
-#define MYSTACKSIZE (6*4)
-
-asm_call_jit_compiler:
- SAVE_ARGUMENT_REGISTERS /* save our argument registers & LR */
- sub sp, sp, #4 /* keep stack 8-byte aligned */
-
- mov a0, itmp1 /* pass methodinfo pointer */
- mov a1, mptr /* pass method pointer */
- add a2, sp, #MYSTACKSIZE /* pass Java sp */
- mov a3, lr /* pass Java RA (correct for leafs) */
- bl jit_asm_compile
- mov itmp1, res1 /* save pointer to new jit-code */
-
- tst itmp1,itmp1 /* check for exeption */
- beq L_asm_call_jit_compiler_exception
-
- add sp, sp, #4 /* keep stack 8-byte aligned */
- RESTORE_ARGUMENT_REGISTERS /* load our argument registers & LR */
-
- mov ip, itmp1
- mov pc, ip /* call jit-code */
-
-L_asm_call_jit_compiler_exception:
- bl exceptions_get_and_clear_exception
- mov xptr, res1 /* get exception */
-
- add sp, sp, #4 /* keep stack 8-byte aligned */
- RESTORE_ARGUMENT_REGISTERS /* load LR */
-
- sub xpc, lr, #4 /* xpc = instruction that called us */
- b asm_handle_nat_exception
-
-
/********************* function asm_handle_exception ***************************
* *
* This function handles an exception. It does not use the usual calling *
#include "mm/memory.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
#include "vm/jit/jitcache.hpp"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/methodheader.h"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
#if defined(ENABLE_LSRA)
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+#if defined(__VFP_FP__)
+ M_FMSR(s1, d);
+ M_CVTIF(d, d);
+#else
M_CVTIF(s1, d);
+#endif
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+#if defined(__VFP_FP__)
+ M_FMSR(s1, d);
+ M_CVTID(d, d);
+#else
M_CVTID(s1, d);
+#endif
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+#if defined(__VFP_FP__)
+ M_CVTFI(s1, REG_FTMP2);
+ M_FMRS(REG_FTMP2, d);
+#else
/* this uses round towards zero, as Java likes it */
M_CVTFI(s1, d);
-#if !defined(__VFP_FP__)
/* this checks for NaN; to return zero as Java likes it */
M_FCMP(s1, 0x8);
M_MOVVS_IMM(0, d);
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP1);
+#if defined(__VFP_FP__)
+ M_CVTDI(s1, REG_FTMP2);
+ M_FMRS(REG_FTMP2, d);
+#else
/* this uses round towards zero, as Java likes it */
M_CVTDI(s1, d);
-#if !defined(__VFP_FP__)
/* this checks for NaN; to return zero as Java likes it */
M_DCMP(s1, 0x8);
M_MOVVS_IMM(0, d);
}
-/* codegen_emit_stub_compiler **************************************************
-
- Emits a stub routine which calls the compiler.
-
-*******************************************************************************/
-
-void codegen_emit_stub_compiler(jitdata *jd)
-{
- methodinfo *m;
- codegendata *cd;
-
- /* get required compiler data */
-
- m = jd->m;
- cd = jd->cd;
-
- /* code for the stub */
-
- M_LDR_INTERN(REG_ITMP1, REG_PC, -(2 * 4 + 2 * SIZEOF_VOID_P));
- M_LDR_INTERN(REG_PC, REG_PC, -(3 * 4 + 3 * SIZEOF_VOID_P));
-}
-
-
/* codegen_emit_stub_native ****************************************************
Emits a stub routine which calls a native method.
/* src/vm/jit/arm/codegen.h - code generation macros and definitions for ARM
- 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.
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 2 * 4
-
-
/* lazy debugger **************************************************************/
#if !defined(NDEBUG)
#if !defined(ENABLE_SOFTFLOAT)
#if defined(__VFP_FP__)
+
#define M_FADD(a,b,d) M_CPDP(UNCOND,0,1,1,0,10,0,0,0,d,a,b)/* d = a + b */
#define M_FSUB(a,b,d) M_CPDP(UNCOND,0,1,1,1,10,0,0,0,d,a,b)/* d = a - b */
#define M_FMUL(a,b,d) M_CPDP(UNCOND,0,1,0,0,10,0,0,0,d,a,b)/* d = a * b */
#define M_CVTFD(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0x7,a)
#define M_CVTIF(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0x8,a)
#define M_CVTID(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0x8,a)
-#define M_CVTFI(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0xc,a)
-#define M_CVTDI(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0xc,a)
+#define M_CVTFI(a,d) M_CPDP(UNCOND,1,1,1,1,10,0,1,0,d,0xd,a) // ftosis
+#define M_CVTDI(a,d) M_CPDP(UNCOND,1,1,1,1,11,0,1,0,d,0xd,a) // ftosid
#define M_FMSTAT M_CPRT(UNCOND,0x07,1,10,0,0x1,0xf)
#define M_FMRDL(Fa,b) M_CPRT(UNCOND,0x00,1,11,0,Fa,b)
#define M_FMDHR(a,Fb) M_CPRT(UNCOND,0x01,0,11,0,Fb,a)
#define M_FMRDH(Fa,b) M_CPRT(UNCOND,0x01,1,11,0,Fa,b)
+
#else
+
#define M_FADD(a,b,d) M_CPDOS(UNCOND,0x00,0,d,a,b) /* d = a + b */
#define M_FSUB(a,b,d) M_CPDOS(UNCOND,0x02,0,d,a,b) /* d = a - b */
#define M_FMUL(a,b,d) M_CPDOS(UNCOND,0x01,0,d,a,b) /* d = a * b */
#define M_CVTID(a,d) M_CPRTD(UNCOND,0,a,d,0) /* d = (float) a */
#define M_CVTFI(a,d) M_CPRTI(UNCOND,1,d,0,a) /* d = (int) a */
#define M_CVTDI(a,d) M_CPRTI(UNCOND,1,d,0,a) /* d = (int) a */
+
#endif
/* M_RECOMPUTE_PV:
used to recompute our PV (we use the IP for this) out of the current PC
ATTENTION: if you change this, you have to look at other functions as well!
- Following things depend on it: asm_call_jit_compiler(); codegen_findmethod();
+ Following things depend on it: md_codegen_get_pv_from_pc();
*/
#define M_RECOMPUTE_PV(disp) \
disp += 8; /* we use PC relative addr. */ \
assert((disp & 0x03) == 0); \
assert(disp >= 0 && disp <= 0x03ffffff); \
- M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1)); \
- if (disp > 0x000003ff) M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5)); \
- if (disp > 0x0003ffff) M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 18, 9)); \
+ if (disp > 0x0003ffff) { \
+ M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 18, 9)); \
+ M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 10, 5)); \
+ M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); \
+ } else if (disp > 0x000003ff) { \
+ M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 10, 5)); \
+ M_SUB_IMM(REG_PV, REG_PV, IMM_ROTL(disp >> 2, 1)); \
+ } else { \
+ M_SUB_IMM(REG_PV, REG_PC, IMM_ROTL(disp >> 2, 1)); \
+ }
/* M_INTMOVE:
generates an integer-move from register a to b.
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "vm/global.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/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
}
+/* emit_trap_compiler **********************************************************
+
+ Emit a trap instruction which calls the JIT compiler.
+
+*******************************************************************************/
+
+void emit_trap_compiler(codegendata *cd)
+{
+ M_TRAP(REG_METHODPTR, TRAP_COMPILER);
+}
+
+
/* emit_trap *******************************************************************
Emit a trap instruction and return the original machine code.
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include <stdint.h>
-#include "vm/types.h"
-
-#include "vm/jit/disass.h"
-
-#include "vm/jit/arm/md-abi.h"
-
#define ucontext broken_glibc_ucontext
#define ucontext_t broken_glibc_ucontext_t
#include <ucontext.h>
#define scontext_t struct sigcontext
+#include "vm/types.h"
+
+#include "vm/jit/arm/md.h"
+#include "vm/jit/arm/md-abi.h"
+
#include "threads/thread.hpp"
#include "vm/os.hpp"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
#include "vm/jit/executionstate.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/trap.h"
intptr_t addr;
int type;
intptr_t val;
- void *p;
_uc = (ucontext_t*) _p;
_sc = &_uc->uc_mcontext;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* set registers */
-
- _sc->arm_r10 = (uintptr_t) p;
- _sc->arm_fp = (uintptr_t) xpc;
- _sc->arm_pc = (uintptr_t) asm_handle_exception;
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
{
- ucontext_t *_uc;
- scontext_t *_sc;
- u1 *pv;
- u1 *sp;
- u1 *ra;
- u1 *xpc;
- u4 mcode;
- int type;
- intptr_t val;
- void *p;
-
- _uc = (ucontext_t*) _p;
- _sc = &_uc->uc_mcontext;
+ ucontext_t* _uc = (ucontext_t*) _p;
+ scontext_t* _sc = &_uc->uc_mcontext;
/* ATTENTION: glibc included messed up kernel headers we needed a
workaround for the ucontext structure. */
- pv = (u1 *) _sc->arm_ip;
- sp = (u1 *) _sc->arm_sp;
- ra = (u1 *) _sc->arm_lr; /* this is correct for leafs */
- xpc = (u1 *) _sc->arm_pc;
-
- /* get exception-throwing instruction */
-
- mcode = *((u4 *) xpc);
-
- /* check for undefined instruction we use */
-
- if ((mcode & 0x0ff000f0) != 0x07f000f0) {
- log_println("md_signal_handler_sigill: unknown illegal instruction: inst=%x", mcode);
+ void* pv = (void*) _sc->arm_ip;
+ void* sp = (void*) _sc->arm_sp;
+ void* ra = (void*) _sc->arm_lr; // The RA is correct for leaf methods.
+ void* xpc = (void*) _sc->arm_pc;
+
+ // Get the exception-throwing instruction.
+ uint32_t mcode = *((uint32_t*) xpc);
+
+ // Check if the trap instruction is valid.
+ // TODO Move this into patcher_handler.
+ if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+ // Check if the PC has been patched during our way to this
+ // signal handler (see PR85).
+ // NOTE: ARM uses SIGILL for other traps too, but it's OK to
+ // do this check anyway because it will fail.
+ if (patcher_is_patched_at(xpc) == true)
+ return;
+
+ // We have a problem...
+ log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%x", mcode, xpc);
#if defined(ENABLE_DISASSEMBLER)
- DISASSINSTR(xpc);
+ (void) disassinstr(xpc);
#endif
vm_abort("Aborting...");
}
- type = (mcode >> 8) & 0x0fff;
- val = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
-
- /* Handle the trap. */
-
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+ int type = (mcode >> 8) & 0x0fff;
+ intptr_t val = *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
- /* set registers if we have an exception, continue execution
- otherwise (this is needed for patchers to work) */
+ if (type == TRAP_COMPILER) {
+ /* The XPC is the RA minus 4, because the RA points to the
+ instruction after the call. */
- if (p != NULL) {
- _sc->arm_r10 = (uintptr_t) p;
- _sc->arm_fp = (uintptr_t) xpc;
- _sc->arm_pc = (uintptr_t) asm_handle_exception;
+ xpc = (void*) (((uintptr_t) ra) - 4);
}
+
+ // Handle the trap.
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
*/
void md_executionstate_read(executionstate_t *es, void *context)
{
- vm_abort("md_executionstate_read: IMPLEMENT ME!");
-
-#if 0
ucontext_t *_uc;
- mcontext_t *_mc;
+ scontext_t *_sc;
int i;
_uc = (ucontext_t *) context;
- _mc = &_uc->uc_mcontext;
+ _sc = &_uc->uc_mcontext;
+
+ /* ATTENTION: glibc included messed up kernel headers we needed a
+ workaround for the ucontext structure. */
/* read special registers */
- es->pc = (u1 *) _mc->sc_pc;
- es->sp = (u1 *) _mc->sc_regs[REG_SP];
- es->pv = (u1 *) _mc->sc_regs[REG_PV];
- es->ra = (u1 *) _mc->sc_regs[REG_RA];
+
+ es->pc = (u1 *) _sc->arm_pc;
+ es->sp = (u1 *) _sc->arm_sp;
+ es->pv = (u1 *) _sc->arm_ip;
+ es->ra = (u1 *) _sc->arm_lr;
/* read integer registers */
+
for (i = 0; i < INT_REG_CNT; i++)
- es->intregs[i] = _mc->sc_regs[i];
+ es->intregs[i] = *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + i);
/* read float registers */
- /* Do not use the assignment operator '=', as the type of
- * the _mc->sc_fpregs[i] can cause invalid conversions. */
- assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
- os_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
-#endif
+ for (i = 0; i < FLT_REG_CNT; i++)
+ es->fltregs[i] = 0xdeadbeefdeadbeefULL;
}
*/
void md_executionstate_write(executionstate_t *es, void *context)
{
- vm_abort("md_executionstate_write: IMPLEMENT ME!");
-
-#if 0
ucontext_t *_uc;
- mcontext_t *_mc;
+ scontext_t *_sc;
int i;
_uc = (ucontext_t *) context;
- _mc = &_uc->uc_mcontext;
+ _sc = &_uc->uc_mcontext;
- /* write integer registers */
- for (i = 0; i < INT_REG_CNT; i++)
- _mc->sc_regs[i] = es->intregs[i];
+ /* ATTENTION: glibc included messed up kernel headers we needed a
+ workaround for the ucontext structure. */
- /* write float registers */
- /* Do not use the assignment operator '=', as the type of
- * the _mc->sc_fpregs[i] can cause invalid conversions. */
+ /* write integer registers */
- assert(sizeof(_mc->sc_fpregs) == sizeof(es->fltregs));
- os_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
+ for (i = 0; i < INT_REG_CNT; i++)
+ *((int32_t*) _sc + OFFSET(scontext_t, arm_r0)/4 + i) = es->intregs[i];
/* write special registers */
- _mc->sc_pc = (ptrint) es->pc;
- _mc->sc_regs[REG_SP] = (ptrint) es->sp;
- _mc->sc_regs[REG_PV] = (ptrint) es->pv;
- _mc->sc_regs[REG_RA] = (ptrint) es->ra;
-#endif
+
+ _sc->arm_pc = (ptrint) es->pc;
+ _sc->arm_sp = (ptrint) es->sp;
+ _sc->arm_ip = (ptrint) es->pv;
+ _sc->arm_lr = (ptrint) es->ra;
}
--- /dev/null
+/* src/vm/jit/arm/md-stubs.hpp - ARM JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on an ARM architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 2 * 4;
+}
+
+#endif // _MD_STUBS_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 "vm/types.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
/* md_stacktrace_get_returnaddress *********************************************
{
uint32_t* pc;
uintptr_t pv;
- uint32_t mcode1, mcode2, mcode3;
+ uint32_t mcode;
+ int mcode_idx;
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 = pc[0];
- if ((mcode1 & 0xffffff00) == 0xe24fcf00 /*sub ip,pc,#__*/)
- pv -= (uintptr_t) ((mcode1 & 0x000000ff) << 2);
- else if ((mcode1 & 0xffffff00) == 0xe24fc000 /*sub ip,pc,#__*/)
- pv -= (uintptr_t) (mcode1 & 0x000000ff);
+ mcode_idx = 0;
+ mcode = pc[0];
+
+ /* if this was shifted by 18 bits, we have to load additional instructions */
+ if ((mcode & 0xfff0ff00) == 0xe240c700 /*sub ip,??,#__*/) {
+ pv -= (uintptr_t) ((mcode & 0x000000ff) << 18);
+ mcode = pc[++mcode_idx];
+ }
+
+ /* if this was shifted by 10 bits, we have to load additional instructions */
+ if ((mcode & 0xfff0ff00) == 0xe240cb00 /*sub ip,??,#__*/) {
+ pv -= (uintptr_t) ((mcode & 0x000000ff) << 10);
+ mcode = pc[++mcode_idx];
+ }
+
+ /* this is the default path with just one instruction, shifted by 2 or no bits */
+ if ((mcode & 0xfff0ff00) == 0xe240cf00 /*sub ip,??,#__*/)
+ pv -= (uintptr_t) ((mcode & 0x000000ff) << 2);
+ else if ((mcode & 0xffffff00) == 0xe24fc000 /*sub ip,pc,#__*/)
+ pv -= (uintptr_t) (mcode & 0x000000ff);
else {
/* if this happens, we got an unexpected instruction at (*ra) */
- vm_abort("Unable to find method: %p (instr=%x)", ra, mcode1);
+ vm_abort("Unable to find method: %p (instr=%x)", ra, mcode);
}
- /* if we have a RECOMPUTE_IP there can be more than one instruction */
- mcode2 = pc[1];
- mcode3 = pc[2];
- if ((mcode2 & 0xffffff00) == 0xe24ccb00 /*sub ip,ip,#__*/)
- pv -= (uintptr_t) ((mcode2 & 0x000000ff) << 10);
- if ((mcode3 & 0xffffff00) == 0xe24cc700 /*sub ip,ip,#__*/)
- pv -= (uintptr_t) ((mcode3 & 0x000000ff) << 18);
-
/* we used PC-relative adressing; but now it is LR-relative */
pv += 8;
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#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/patcher-common.hpp"
-#define PATCH_BACK_ORIGINAL_MCODE \
- *((u4 *) pr->mpc) = (u4) pr->mcode; \
- md_icacheflush((u1 *) pr->mpc, 1 * 4);
-
#define gen_resolveload(inst,offset) \
assert((offset) >= -0x0fff && (offset) <= 0x0fff); \
assert(!((inst) & 0x0fff)); \
void patcher_patch_code(patchref_t *pr)
{
- PATCH_BACK_ORIGINAL_MCODE;
+ *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
+ md_icacheflush((void*) pr->mpc, 1 * 4);
+}
+
+
+/**
+ * Check if the trap instruction at the given PC is valid.
+ *
+ * @param pc Program counter.
+ *
+ * @return true if valid, false otherwise.
+ */
+bool patcher_is_valid_trap_instruction_at(void* pc)
+{
+ uint32_t mcode = *((uint32_t*) pc);
+
+ // Check for the undefined instruction we use.
+ if ((mcode & 0x0ff000f0) != 0x07f000f0) {
+ return false;
+ }
+
+ return true;
}
bool patcher_get_putstatic(patchref_t *pr)
{
- unresolved_field *uf;
- u1 *datap;
- fieldinfo *fi;
-
- /* get stuff from the stack */
+ unresolved_field* uf = (unresolved_field *) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- uf = (unresolved_field *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- /* get the fieldinfo */
-
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- /* check if the field's class is initialized */
-
+ // Check if the field's class is initialized.
if (!(fi->clazz->state & CLASS_INITIALIZED))
if (!initialize_class(fi->clazz))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch the field value's address */
+ // Patch the field value's address.
+ *datap = (uintptr_t) fi->value;
- *((intptr_t *) datap) = (intptr_t) fi->value;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_get_putfield(patchref_t *pr)
{
- u1 *ra;
- u4 mcode;
- unresolved_field *uf;
- fieldinfo *fi;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
- /* get stuff from the stack */
- ra = (u1*) pr->mpc;
- mcode = pr->mcode;
- uf = (unresolved_field*) pr->ref;
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- /* get the fieldinfo */
-
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 1 * 4;
-
- /* patch the field's offset into the instruction */
+ // Patch the field's offset into the instruction.
switch(fi->type) {
case TYPE_ADR:
case TYPE_FLT:
#endif
assert(fi->offset <= 0x0fff);
- *((u4 *) (ra + 0 * 4)) |= (fi->offset & 0x0fff);
+ pr->mcode |= (fi->offset & 0x0fff);
break;
case TYPE_LNG:
case TYPE_DBL:
#endif
assert((fi->offset + 4) <= 0x0fff);
- *((u4 *) (ra + 0 * 4)) |= ((fi->offset + 0) & 0x0fff);
- *((u4 *) (ra + 1 * 4)) &= 0xfffff000;
- *((u4 *) (ra + 1 * 4)) |= ((fi->offset + 4) & 0x0fff);
+ pr->mcode |= ((fi->offset + 0) & 0x0fff);
+ pc[1] &= 0xfffff000;
+ pc[1] |= ((fi->offset + 4) & 0x0fff);
break;
#if !defined(ENABLE_SOFTFLOAT)
case TYPE_FLT:
case TYPE_DBL:
assert(fi->offset <= 0x03ff);
- *((u4 *) (ra + 0 * 4)) |= ((fi->offset >> 2) & 0x00ff);
+ pr->mcode |= ((fi->offset >> 2) & 0x00ff);
break;
#endif
}
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc, 2 * 4);
- md_icacheflush(ra, 2 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
-
- /* get stuff from the stack */
-
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
+ constant_classref* cr = (constant_classref *) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- /* get the classinfo */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch the classinfo pointer.
+ *datap = (uintptr_t) c;
- /* patch the classinfo pointer */
-
- *((ptrint *) datap) = (ptrint) c;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokestatic_special(patchref_t *pr)
{
- unresolved_method *um;
- u1 *datap;
- methodinfo *m;
-
- /* get stuff from the stack */
+ unresolved_method* um = (unresolved_method*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- um = (unresolved_method*) pr->ref;
- datap = (u1 *) pr->datap;
+ // Reolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the methodinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch stubroutine */
+ // Patch stubroutine.
+ *datap = (uintptr_t) m->stubroutine;
- *((ptrint *) datap) = (ptrint) m->stubroutine;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokevirtual(patchref_t *pr)
{
- u1 *ra;
- unresolved_method *um;
- methodinfo *m;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method *) pr->ref;
- ra = (u1 *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the methodinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 1 * 4;
+ // Patch vftbl index.
+ gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
- /* patch vftbl index */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 1 * 4);
- gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex));
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 1 * 4, 1 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokeinterface(patchref_t *pr)
{
- u1 *ra;
- unresolved_method *um;
- methodinfo *m;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method *) pr->ref;
- ra = (u1 *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the methodinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 1 * 4;
+ // Patch interfacetable index.
+ gen_resolveload(pc[1], (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index));
- /* patch interfacetable index */
+ // Patch method offset.
+ gen_resolveload(pc[2], (int32_t) (sizeof(methodptr) * (m - m->clazz->methods)));
- gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index));
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 2 * 4);
- /* patch method offset */
-
- gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->clazz->methods)));
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 1 * 4, 2 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_resolve_classref_to_flags(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ int32_t* datap = (int32_t*) pr->datap;
- /* get stuff from the stack */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
-
- /* get the classinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch class flags */
+ // Patch class flags.
+ *datap = (int32_t) c->flags;
- *((s4 *) datap) = (s4) c->flags;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_resolve_classref_to_index(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ int32_t* datap = (int32_t*) pr->datap;
- /* get stuff from the stack */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
-
- /* get the classinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch super class index */
+ // Patch super class index.
+ *datap = (int32_t) c->index;
- *((s4 *) datap) = (s4) c->index;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- /* get stuff from the stack */
+ // Resolve the class.
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
+ classinfo* c = resolve_classref_eager(cr);
- /* get the classinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch super class' vftbl */
+ // Patch super class' vftbl.
+ *datap = (uintptr_t) c->vftbl;
- *((ptrint *) datap) = (ptrint) c->vftbl;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
#include <stdint.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "vm/types.h"
#include "vm/global.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* machine dependent initialization */
s4 asm_md_init(void);
#endif
#ifdef __cplusplus
-}
+} // extern "C"
#endif
#endif /* _ASMPART_H */
--- /dev/null
+/* src/vm/jit/builtin.cpp - functions for unsupported operations
+
+ 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.
+
+ Contains C functions for JavaVM Instructions that cannot be
+ translated to machine language directly. Consequently, the
+ generated machine code for these instructions contains function
+ calls instead of machine instructions, using the C calling
+ convention.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "fdlibm/fdlibm.h"
+#if defined(__CYGWIN__) && defined(Bias)
+# undef Bias
+#endif
+
+#include "mm/gc.hpp"
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.h"
+#include "toolbox/util.h"
+
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
+#include "vm/class.h"
+#include "vm/cycles-stats.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/linker.h"
+#include "vm/loader.hpp"
+#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/stubs.hpp"
+#include "vm/jit/trace.hpp"
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+
+/* include builtin tables *****************************************************/
+
+#include "vm/jit/builtintable.inc"
+
+
+CYCLES_STATS_DECLARE(builtin_new ,100,5)
+CYCLES_STATS_DECLARE(builtin_overhead , 80,1)
+
+
+/*============================================================================*/
+/* BUILTIN TABLE MANAGEMENT FUNCTIONS */
+/*============================================================================*/
+
+/* builtintable_init ***********************************************************
+
+ Parse the descriptors of builtin functions and create the parsed
+ descriptors.
+
+*******************************************************************************/
+
+static bool builtintable_init(void)
+{
+ descriptor_pool *descpool;
+ builtintable_entry *bte;
+ methodinfo *m;
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* create a new descriptor pool */
+
+ descpool = descriptor_pool_new(class_java_lang_Object);
+
+ /* add some entries we need */
+
+ if (!descriptor_pool_add_class(descpool, utf_java_lang_Object))
+ return false;
+
+ if (!descriptor_pool_add_class(descpool, utf_java_lang_Class))
+ return false;
+
+ /* first add all descriptors to the pool */
+
+ for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+ bte->name = utf_new_char(bte->cname);
+ bte->descriptor = utf_new_char(bte->cdescriptor);
+
+ if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+ return false;
+ }
+
+ for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
+ bte->descriptor = utf_new_char(bte->cdescriptor);
+
+ if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+ return false;
+ }
+
+ for (bte = builtintable_function; bte->fp != NULL; bte++) {
+ bte->classname = utf_new_char(bte->cclassname);
+ bte->name = utf_new_char(bte->cname);
+ bte->descriptor = utf_new_char(bte->cdescriptor);
+
+ if (!descriptor_pool_add(descpool, bte->descriptor, NULL))
+ return false;
+ }
+
+ /* create the class reference table */
+
+ (void) descriptor_pool_create_classrefs(descpool, NULL);
+
+ /* allocate space for the parsed descriptors */
+
+ descriptor_pool_alloc_parsed_descriptors(descpool);
+
+ /* Now parse all descriptors. NOTE: builtin-functions are treated
+ like static methods (no `this' pointer). */
+
+ for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+ bte->md =
+ descriptor_pool_parse_method_descriptor(descpool,
+ bte->descriptor,
+ ACC_STATIC | ACC_METHOD_BUILTIN,
+ NULL);
+
+ /* generate a builtin stub if we need one */
+
+ if (bte->flags & BUILTINTABLE_FLAG_STUB) {
+ m = method_new_builtin(bte);
+ BuiltinStub::generate(m, bte);
+ }
+ }
+
+ for (bte = builtintable_automatic; bte->fp != NULL; bte++) {
+ bte->md =
+ descriptor_pool_parse_method_descriptor(descpool,
+ bte->descriptor,
+ ACC_STATIC | ACC_METHOD_BUILTIN,
+ NULL);
+
+ /* no stubs should be needed for this table */
+
+ assert(!bte->flags & BUILTINTABLE_FLAG_STUB);
+ }
+
+ for (bte = builtintable_function; bte->fp != NULL; bte++) {
+ bte->md =
+ descriptor_pool_parse_method_descriptor(descpool,
+ bte->descriptor,
+ ACC_STATIC | ACC_METHOD_BUILTIN,
+ NULL);
+
+ /* generate a builtin stub if we need one */
+
+ if (bte->flags & BUILTINTABLE_FLAG_STUB) {
+ m = method_new_builtin(bte);
+ BuiltinStub::generate(m, bte);
+ }
+ }
+
+ return true;
+}
+
+
+/* builtintable_comparator *****************************************************
+
+ qsort comparator for the automatic builtin table.
+
+*******************************************************************************/
+
+static int builtintable_comparator(const void *a, const void *b)
+{
+ builtintable_entry *bte1;
+ builtintable_entry *bte2;
+
+ bte1 = (builtintable_entry *) a;
+ bte2 = (builtintable_entry *) b;
+
+ return (bte1->opcode < bte2->opcode) ? -1 : (bte1->opcode > bte2->opcode);
+}
+
+
+/* builtintable_sort_automatic *************************************************
+
+ Sorts the automatic builtin table.
+
+*******************************************************************************/
+
+static void builtintable_sort_automatic(void)
+{
+ s4 entries;
+
+ /* calculate table size statically (`- 1' comment see builtintable.inc) */
+
+ entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+
+ qsort(builtintable_automatic, entries, sizeof(builtintable_entry),
+ builtintable_comparator);
+}
+
+
+/* builtin_init ****************************************************************
+
+ Initialize the global table of builtin functions.
+
+*******************************************************************************/
+
+bool builtin_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("builtin_init");
+
+ /* initialize the builtin tables */
+
+ if (!builtintable_init())
+ return false;
+
+ /* sort builtin tables */
+
+ builtintable_sort_automatic();
+
+ return true;
+}
+
+
+/* builtintable_get_by_key *****************************************************
+
+ Returns a key for the given builtintable_entry object which is suitable
+ for retrieving the instance again by calling builtintable_get_by_key.
+
+ The key can be regarded fixed between multiple runs of the JVM.
+
+*******************************************************************************/
+
+s4 builtintable_get_key(builtintable_entry *bte)
+{
+ s4 entries;
+/*
+ int i;
+ entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+ for (i = 0; i < entries; i++)
+ if (&builtintable_internal[i] == bte)
+ return i + 1;
+
+ entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+ for (i = 0; i < entries; i++)
+ if (&builtintable_automatic[i] == bte)
+ return -i;
+
+ entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+ for (i = 0; i < entries; i++)
+ if (&builtintable_function[i] == bte)
+ return -1000 - i;
+*/
+
+ entries = sizeof(builtintable_internal) / sizeof(builtintable_entry) - 1;
+ if (&builtintable_internal[0] <= bte
+ && &builtintable_internal[entries - 1] >= bte)
+ {
+ return (s4) (bte - &builtintable_internal[0]) + 1;
+ }
+
+ entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+ if (&builtintable_automatic[0] <= bte
+ && &builtintable_automatic[entries - 1] >= bte)
+ {
+ return -(s4) (bte - &builtintable_automatic[0]);
+ }
+
+ entries = sizeof(builtintable_function) / sizeof(builtintable_entry) - 1;
+ if (&builtintable_function[0] <= bte
+ && &builtintable_function[entries - 1] >= bte)
+ {
+ return -1000 - (s4) (bte - &builtintable_function[0]);
+ }
+
+ /* builtintable_entry is not in our tables. */
+ assert (0);
+
+ return 0;
+}
+
+/* builtintable_get_by_key *****************************************************
+
+ Retrieves an entry in the internal and automatic builtin functions tables
+ using a key that was retrived previously with builtintable_get_key()
+
+*******************************************************************************/
+
+builtintable_entry *builtintable_get_by_key(s4 key)
+{
+ /* If key is positive it is the index into builtintable_internal. If it is
+ * negative it is the index into builtintable_automatic. If it is <= -1000
+ * it is the index into builtintable_function.
+ */
+ return (key > 0)
+ ? &builtintable_internal[key - 1]
+ : (key > -1000 ? &builtintable_automatic[-key] : &builtintable_function[-(1000 + key)]);
+}
+
+/* builtintable_get_internal ***************************************************
+
+ Finds an entry in the builtintable for internal functions and
+ returns the a pointer to the structure.
+
+*******************************************************************************/
+
+builtintable_entry *builtintable_get_internal(functionptr fp)
+{
+ builtintable_entry *bte;
+
+ for (bte = builtintable_internal; bte->fp != NULL; bte++) {
+ if (bte->fp == fp)
+ return bte;
+ }
+
+ return NULL;
+}
+
+
+/* builtintable_get_automatic **************************************************
+
+ Finds an entry in the builtintable for functions which are replaced
+ automatically and returns the a pointer to the structure.
+
+*******************************************************************************/
+
+builtintable_entry *builtintable_get_automatic(s4 opcode)
+{
+ builtintable_entry *first;
+ builtintable_entry *last;
+ builtintable_entry *middle;
+ s4 half;
+ s4 entries;
+
+ /* calculate table size statically (`- 1' comment see builtintable.inc) */
+
+ entries = sizeof(builtintable_automatic) / sizeof(builtintable_entry) - 1;
+
+ first = builtintable_automatic;
+ last = builtintable_automatic + entries;
+
+ while (entries > 0) {
+ half = entries / 2;
+ middle = first + half;
+
+ if (middle->opcode < opcode) {
+ first = middle + 1;
+ entries -= half + 1;
+ }
+ else
+ entries = half;
+ }
+
+ return (first != last ? first : NULL);
+}
+
+
+/* builtintable_replace_function ***********************************************
+
+ XXX
+
+*******************************************************************************/
+
+#if defined(ENABLE_JIT)
+bool builtintable_replace_function(void *iptr_)
+{
+ constant_FMIref *mr;
+ builtintable_entry *bte;
+ instruction *iptr;
+
+ iptr = (instruction *) iptr_; /* twisti will kill me ;) */
+
+ /* get name and descriptor of the function */
+
+ switch (iptr->opc) {
+ case ICMD_INVOKESTATIC:
+ /* The instruction MUST be resolved, otherwise we run into
+ lazy loading troubles. Anyway, we should/can only replace
+ very VM-close functions. */
+
+ if (INSTRUCTION_IS_UNRESOLVED(iptr))
+ return false;
+
+ mr = iptr->sx.s23.s3.fmiref;
+ break;
+
+ default:
+ return false;
+ }
+
+ /* search the function table */
+
+ for (bte = builtintable_function; bte->fp != NULL; bte++) {
+ if ((METHODREF_CLASSNAME(mr) == bte->classname) &&
+ (mr->name == bte->name) &&
+ (mr->descriptor == bte->descriptor)) {
+
+ /* set the values in the instruction */
+
+ iptr->opc = bte->opcode;
+ iptr->sx.s23.s3.bte = bte;
+
+ if (bte->flags & BUILTINTABLE_FLAG_EXCEPTION)
+ iptr->flags.bits |= INS_FLAG_CHECK;
+ else
+ iptr->flags.bits &= ~INS_FLAG_CHECK;
+
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif /* defined(ENABLE_JIT) */
+
+
+/*============================================================================*/
+/* INTERNAL BUILTIN FUNCTIONS */
+/*============================================================================*/
+
+/* builtin_instanceof **********************************************************
+
+ Checks if an object is an instance of some given class (or subclass
+ of that class). If class is an interface, checks if the interface
+ is implemented.
+
+ RETURN VALUE:
+ 1......o is an instance of class or implements the interface
+ 0......otherwise or if o == NULL
+
+ NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+bool builtin_instanceof(java_handle_t *o, classinfo *c)
+{
+ classinfo *oc;
+
+ if (o == NULL)
+ return 0;
+
+ LLNI_class_get(o, oc);
+
+ return class_isanysubclass(oc, c);
+}
+
+
+
+/* builtin_checkcast ***********************************************************
+
+ The same as builtin_instanceof but with the exception
+ that 1 is returned when (o == NULL).
+
+ NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+bool builtin_checkcast(java_handle_t *o, classinfo *c)
+{
+ classinfo *oc;
+
+ if (o == NULL)
+ return 1;
+
+ LLNI_class_get(o, oc);
+
+ if (class_isanysubclass(oc, c))
+ return 1;
+
+ return 0;
+}
+
+
+/* builtin_descriptorscompatible ***********************************************
+
+ Checks if two array type descriptors are assignment compatible.
+
+ RETURN VALUE:
+ 1......target = desc is possible
+ 0......otherwise
+
+*******************************************************************************/
+
+static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
+{
+ if (desc == target)
+ return 1;
+
+ if (desc->arraytype != target->arraytype)
+ return 0;
+
+ if (desc->arraytype != ARRAYTYPE_OBJECT)
+ return 1;
+
+ /* {both arrays are arrays of references} */
+
+ if (desc->dimension == target->dimension) {
+ if (!desc->elementvftbl)
+ return 0;
+ /* an array which contains elements of interface types is
+ allowed to be casted to Object (JOWENN)*/
+
+ if ((desc->elementvftbl->baseval < 0) &&
+ (target->elementvftbl->baseval == 1))
+ return 1;
+
+ return class_isanysubclass(desc->elementvftbl->clazz,
+ target->elementvftbl->clazz);
+ }
+
+ if (desc->dimension < target->dimension)
+ return 0;
+
+ /* {desc has higher dimension than target} */
+
+ return class_isanysubclass(pseudo_class_Arraystub,
+ target->elementvftbl->clazz);
+}
+
+
+/* builtin_arraycheckcast ******************************************************
+
+ Checks if an object is really a subtype of the requested array
+ type. The object has to be an array to begin with. For simple
+ arrays (int, short, double, etc.) the types have to match exactly.
+ For arrays of objects, the type of elements in the array has to be
+ a subtype (or the same type) of the requested element type. For
+ arrays of arrays (which in turn can again be arrays of arrays), the
+ types at the lowest level have to satisfy the corresponding sub
+ class relation.
+
+ NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
+{
+ arraydescriptor *desc;
+
+ if (o == NULL)
+ return 1;
+
+ desc = o->vftbl->arraydesc;
+
+ if (desc == NULL)
+ return 0;
+
+ return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
+}
+
+
+/* builtin_fast_arrayinstanceof ************************************************
+
+ NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
+{
+ if (o == NULL)
+ return 0;
+
+ return builtin_fast_arraycheckcast(o, targetclass);
+}
+
+
+/* builtin_arrayinstanceof *****************************************************
+
+ NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
+{
+ bool result;
+
+ LLNI_CRITICAL_START;
+
+ result = builtin_fast_arrayinstanceof(LLNI_UNWRAP(h), targetclass);
+
+ LLNI_CRITICAL_END;
+
+ return result;
+}
+
+
+/* builtin_throw_exception *****************************************************
+
+ Sets the exception pointer with the thrown exception and prints some
+ debugging information.
+
+ NOTE: This is a FAST builtin and can be called from JIT code,
+ or from asm_vm_call_method.
+
+*******************************************************************************/
+
+void *builtin_throw_exception(java_object_t *xptr)
+{
+#if !defined(NDEBUG)
+ /* print exception trace */
+
+ if (opt_TraceExceptions)
+ trace_exception_builtin(xptr);
+#endif /* !defined(NDEBUG) */
+
+ /* actually set the exception */
+
+ exceptions_set_exception(LLNI_QUICKWRAP(xptr));
+
+ /* Return a NULL pointer. This is required for vm_call_method to
+ check for an exception. This is for convenience. */
+
+ return NULL;
+}
+
+
+/* builtin_retrieve_exception **************************************************
+
+ Gets and clears the exception pointer of the current thread.
+
+ RETURN VALUE:
+ the exception object, or NULL if no exception was thrown.
+
+ NOTE: This is a FAST builtin and can be called from JIT code,
+ or from the signal handlers.
+
+*******************************************************************************/
+
+java_object_t *builtin_retrieve_exception(void)
+{
+ java_handle_t *h;
+ java_object_t *o;
+
+ /* actually get and clear the exception */
+
+ h = exceptions_get_and_clear_exception();
+ o = LLNI_UNWRAP(h);
+
+ return o;
+}
+
+
+/* builtin_canstore ************************************************************
+
+ Checks, if an object can be stored in an array.
+
+ RETURN VALUE:
+ 1......possible
+ 0......otherwise (throws an ArrayStoreException)
+
+ NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
+{
+ bool result;
+
+ LLNI_CRITICAL_START;
+
+ result = builtin_fast_canstore(LLNI_DIRECT(oa), LLNI_UNWRAP(o));
+
+ LLNI_CRITICAL_END;
+
+ /* if not possible, throw an exception */
+
+ if (result == 0)
+ exceptions_throw_arraystoreexception();
+
+ return result;
+}
+
+
+/* builtin_fast_canstore *******************************************************
+
+ Checks, if an object can be stored in an array.
+
+ RETURN VALUE:
+ 1......possible
+ 0......otherwise (no exception thrown!)
+
+ NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
+{
+ arraydescriptor *desc;
+ arraydescriptor *valuedesc;
+ vftbl_t *componentvftbl;
+ vftbl_t *valuevftbl;
+ int32_t baseval;
+ uint32_t diffval;
+ bool result;
+
+ if (o == NULL)
+ return 1;
+
+ /* The following is guaranteed (by verifier checks):
+ *
+ * *) oa->...vftbl->arraydesc != NULL
+ * *) oa->...vftbl->arraydesc->componentvftbl != NULL
+ * *) o->vftbl is not an interface vftbl
+ */
+
+ desc = oa->header.objheader.vftbl->arraydesc;
+ componentvftbl = desc->componentvftbl;
+ valuevftbl = o->vftbl;
+ valuedesc = valuevftbl->arraydesc;
+
+ if ((desc->dimension - 1) == 0) {
+ /* {oa is a one-dimensional array} */
+ /* {oa is an array of references} */
+
+ if (valuevftbl == componentvftbl)
+ return 1;
+
+ linker_classrenumber_mutex->lock();
+
+ baseval = componentvftbl->baseval;
+
+ if (baseval <= 0) {
+ /* an array of interface references */
+
+ result = ((valuevftbl->interfacetablelength > -baseval) &&
+ (valuevftbl->interfacetable[baseval] != NULL));
+ }
+ else {
+ diffval = valuevftbl->baseval - componentvftbl->baseval;
+ result = diffval <= (uint32_t) componentvftbl->diffval;
+ }
+
+ linker_classrenumber_mutex->unlock();
+ }
+ else if (valuedesc == NULL) {
+ /* {oa has dimension > 1} */
+ /* {componentvftbl->arraydesc != NULL} */
+
+ /* check if o is an array */
+
+ return 0;
+ }
+ else {
+ /* {o is an array} */
+
+ result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+ }
+
+ /* return result */
+
+ return result;
+}
+
+
+/* This is an optimized version where a is guaranteed to be one-dimensional */
+bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
+{
+ arraydescriptor *desc;
+ vftbl_t *elementvftbl;
+ vftbl_t *valuevftbl;
+ int32_t baseval;
+ uint32_t diffval;
+ bool result;
+
+ if (o == NULL)
+ return 1;
+
+ /* The following is guaranteed (by verifier checks):
+ *
+ * *) a->...vftbl->arraydesc != NULL
+ * *) a->...vftbl->arraydesc->elementvftbl != NULL
+ * *) a->...vftbl->arraydesc->dimension == 1
+ * *) o->vftbl is not an interface vftbl
+ */
+
+ desc = a->header.objheader.vftbl->arraydesc;
+ elementvftbl = desc->elementvftbl;
+ valuevftbl = o->vftbl;
+
+ /* {a is a one-dimensional array} */
+
+ if (valuevftbl == elementvftbl)
+ return 1;
+
+ linker_classrenumber_mutex->lock();
+
+ baseval = elementvftbl->baseval;
+
+ if (baseval <= 0) {
+ /* an array of interface references */
+ result = ((valuevftbl->interfacetablelength > -baseval) &&
+ (valuevftbl->interfacetable[baseval] != NULL));
+ }
+ else {
+ diffval = valuevftbl->baseval - elementvftbl->baseval;
+ result = diffval <= (uint32_t) elementvftbl->diffval;
+ }
+
+ linker_classrenumber_mutex->unlock();
+
+ return result;
+}
+
+
+/* This is an optimized version where a is guaranteed to be a
+ * one-dimensional array of a class type */
+bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
+{
+ vftbl_t *elementvftbl;
+ vftbl_t *valuevftbl;
+ uint32_t diffval;
+ bool result;
+
+ if (o == NULL)
+ return 1;
+
+ /* The following is guaranteed (by verifier checks):
+ *
+ * *) a->...vftbl->arraydesc != NULL
+ * *) a->...vftbl->arraydesc->elementvftbl != NULL
+ * *) a->...vftbl->arraydesc->elementvftbl is not an interface vftbl
+ * *) a->...vftbl->arraydesc->dimension == 1
+ * *) o->vftbl is not an interface vftbl
+ */
+
+ elementvftbl = a->header.objheader.vftbl->arraydesc->elementvftbl;
+ valuevftbl = o->vftbl;
+
+ /* {a is a one-dimensional array} */
+
+ if (valuevftbl == elementvftbl)
+ return 1;
+
+ linker_classrenumber_mutex->lock();
+
+ diffval = valuevftbl->baseval - elementvftbl->baseval;
+ result = diffval <= (uint32_t) elementvftbl->diffval;
+
+ linker_classrenumber_mutex->unlock();
+
+ return result;
+}
+
+
+/* builtin_new *****************************************************************
+
+ Creates a new instance of class c on the heap.
+
+ RETURN VALUE:
+ pointer to the object, or NULL if no memory is available
+
+ NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_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 = (java_handle_t*) 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)
+ LLNI_DIRECT(o)->lockword.init();
+#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;
+}
+
+#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 = (java_handle_t*) 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)
+ LLNI_DIRECT(o)->lockword.init();
+# 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 ************************************************************
+
+ NOTE: This is a SLOW builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_java_new(java_handle_t *clazz)
+{
+ return builtin_new(LLNI_classinfo_unwrap(clazz));
+}
+
+
+/* builtin_fast_new ************************************************************
+
+ Creates a new instance of class c on the heap.
+
+ RETURN VALUE:
+ pointer to the object, or NULL if no fast return
+ is possible for any reason.
+
+ NOTE: This is a FAST builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+java_object_t *builtin_fast_new(classinfo *c)
+{
+ java_object_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)
+ return NULL;
+
+ /* is the class linked */
+
+ if (!(c->state & CLASS_LINKED))
+ return NULL;
+
+ if (!(c->state & CLASS_INITIALIZED))
+ return NULL;
+
+ o = (java_handle_t*) heap_alloc(c->instancesize, c->flags & ACC_CLASS_HAS_POINTERS,
+ c->finalizer, false);
+
+ if (!o)
+ return NULL;
+
+ o->vftbl = c->vftbl;
+
+#if defined(ENABLE_THREADS)
+ LLNI_DIRECT(o)->lockword.init();
+#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;
+}
+
+
+/* builtin_newarray ************************************************************
+
+ Creates an array with the given vftbl on the heap. This function
+ takes as class argument an array class.
+
+ RETURN VALUE:
+ pointer to the array or NULL if no memory is available
+
+ NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
+{
+ arraydescriptor *desc;
+ s4 dataoffset;
+ s4 componentsize;
+ s4 actualsize;
+ java_handle_t *a;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_end;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ desc = arrayclass->vftbl->arraydesc;
+ dataoffset = desc->dataoffset;
+ componentsize = desc->componentsize;
+
+ if (size < 0) {
+ exceptions_throw_negativearraysizeexception();
+ return NULL;
+ }
+
+ actualsize = dataoffset + size * componentsize;
+
+ /* check for overflow */
+
+ if (((u4) actualsize) < ((u4) size)) {
+ exceptions_throw_outofmemoryerror();
+ return NULL;
+ }
+
+ a = (java_handle_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
+
+ if (a == NULL)
+ return NULL;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+ /* XXX this is only a dirty hack to make Boehm work with handles */
+
+ a = LLNI_WRAP((java_object_t *) a);
+#endif
+
+ LLNI_vftbl_direct(a) = arrayclass->vftbl;
+
+#if defined(ENABLE_THREADS)
+ LLNI_DIRECT(a)->lockword.init();
+#endif
+
+ LLNI_array_size(a) = size;
+
+ RT_TIMING_GET_TIME(time_end);
+ RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_NEW_ARRAY);
+
+ return a;
+}
+
+
+/* builtin_java_newarray *******************************************************
+
+ NOTE: This is a SLOW builtin and can be called from JIT code only.
+
+*******************************************************************************/
+
+java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
+{
+ return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
+}
+
+
+/* builtin_anewarray ***********************************************************
+
+ Creates an array of references to the given class type on the heap.
+
+ RETURN VALUE:
+ pointer to the array or NULL if no memory is
+ available
+
+ NOTE: This builtin can be called from NATIVE code only.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
+{
+ classinfo *arrayclass;
+
+ /* is class loaded */
+
+ assert(componentclass->state & CLASS_LOADED);
+
+ /* is class linked */
+
+ if (!(componentclass->state & CLASS_LINKED))
+ if (!link_class(componentclass))
+ return NULL;
+
+ arrayclass = class_array_of(componentclass, true);
+
+ if (!arrayclass)
+ return NULL;
+
+ return (java_handle_objectarray_t *) builtin_newarray(size, arrayclass);
+}
+
+
+/* builtin_newarray_type ****************************************************
+
+ Creates an array of [type]s on the heap.
+
+ RETURN VALUE:
+ pointer to the array or NULL if no memory is available
+
+ NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+#define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
+java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
+{ \
+ return (java_handle_##type##array_t *) \
+ builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
+}
+
+BUILTIN_NEWARRAY_TYPE(boolean, ARRAYTYPE_BOOLEAN)
+BUILTIN_NEWARRAY_TYPE(byte, ARRAYTYPE_BYTE)
+BUILTIN_NEWARRAY_TYPE(char, ARRAYTYPE_CHAR)
+BUILTIN_NEWARRAY_TYPE(short, ARRAYTYPE_SHORT)
+BUILTIN_NEWARRAY_TYPE(int, ARRAYTYPE_INT)
+BUILTIN_NEWARRAY_TYPE(long, ARRAYTYPE_LONG)
+BUILTIN_NEWARRAY_TYPE(float, ARRAYTYPE_FLOAT)
+BUILTIN_NEWARRAY_TYPE(double, ARRAYTYPE_DOUBLE)
+
+
+/* builtin_multianewarray_intern ***********************************************
+
+ Creates a multi-dimensional array on the heap. The dimensions are
+ passed in an array of longs.
+
+ ARGUMENTS:
+ n.............number of dimensions to create
+ arrayclass....the array class
+ dims..........array containing the size of each dimension to create
+
+ RETURN VALUE:
+ pointer to the array or NULL if no memory is available
+
+******************************************************************************/
+
+static java_handle_t *builtin_multianewarray_intern(int n,
+ classinfo *arrayclass,
+ long *dims)
+{
+ s4 size;
+ java_handle_t *a;
+ classinfo *componentclass;
+ s4 i;
+
+ /* create this dimension */
+
+ size = (s4) dims[0];
+ a = builtin_newarray(size, arrayclass);
+
+ if (!a)
+ return NULL;
+
+ /* if this is the last dimension return */
+
+ if (!--n)
+ return a;
+
+ /* get the class of the components to create */
+
+ componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
+
+ /* The verifier guarantees that the dimension count is in the range. */
+
+ /* create the component arrays */
+
+ for (i = 0; i < size; i++) {
+ java_handle_t *ea =
+#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+ /* we save an s4 to a s8 slot, 8-byte aligned */
+
+ builtin_multianewarray_intern(n, componentclass, dims + 2);
+#else
+ builtin_multianewarray_intern(n, componentclass, dims + 1);
+#endif
+
+ if (!ea)
+ return NULL;
+
+ array_objectarray_element_set((java_handle_objectarray_t *) a, i, ea);
+ }
+
+ return a;
+}
+
+
+/* builtin_multianewarray ******************************************************
+
+ Wrapper for builtin_multianewarray_intern which checks all
+ dimensions before we start allocating.
+
+ NOTE: This is a SLOW builtin and can be called from JIT code only.
+
+******************************************************************************/
+
+java_handle_objectarray_t *builtin_multianewarray(int n,
+ java_handle_t *arrayclazz,
+ long *dims)
+{
+ classinfo *c;
+ s4 i;
+ s4 size;
+
+ /* check all dimensions before doing anything */
+
+ for (i = 0; i < n; i++) {
+#if defined(__MIPS__) && (SIZEOF_VOID_P == 4)
+ /* we save an s4 to a s8 slot, 8-byte aligned */
+ size = (s4) dims[i * 2];
+#else
+ size = (s4) dims[i];
+#endif
+
+ if (size < 0) {
+ exceptions_throw_negativearraysizeexception();
+ return NULL;
+ }
+ }
+
+ c = LLNI_classinfo_unwrap(arrayclazz);
+
+ /* now call the real function */
+
+ return (java_handle_objectarray_t *)
+ builtin_multianewarray_intern(n, c, dims);
+}
+
+
+/* builtin_verbosecall_enter ***************************************************
+
+ Print method call with arguments for -verbose:call.
+
+ XXX: Remove mew once all archs use the new tracer!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+#ifdef TRACE_ARGS_NUM
+void builtin_verbosecall_enter(s8 a0, s8 a1,
+# if TRACE_ARGS_NUM >= 4
+ s8 a2, s8 a3,
+# endif
+# if TRACE_ARGS_NUM >= 6
+ s8 a4, s8 a5,
+# endif
+# if TRACE_ARGS_NUM == 8
+ s8 a6, s8 a7,
+# endif
+ methodinfo *m)
+{
+ log_text("builtin_verbosecall_enter: Do not call me anymore!");
+}
+#endif
+#endif /* !defined(NDEBUG) */
+
+
+/* builtin_verbosecall_exit ****************************************************
+
+ Print method exit for -verbose:call.
+
+ XXX: Remove mew once all archs use the new tracer!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m)
+{
+ log_text("builtin_verbosecall_exit: Do not call me anymore!");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/*============================================================================*/
+/* MISCELLANEOUS MATHEMATICAL HELPER FUNCTIONS */
+/*============================================================================*/
+
+/*********** Functions for integer divisions *****************************
+
+ On some systems (eg. DEC ALPHA), integer division is not supported by the
+ CPU. These helper functions implement the missing functionality.
+
+******************************************************************************/
+
+#if !SUPPORT_DIVISION || defined(DISABLE_GC)
+s4 builtin_idiv(s4 a, s4 b)
+{
+ s4 c;
+
+ c = a / b;
+
+ return c;
+}
+
+s4 builtin_irem(s4 a, s4 b)
+{
+ s4 c;
+
+ c = a % b;
+
+ return c;
+}
+#endif /* !SUPPORT_DIVISION || defined(DISABLE_GC) */
+
+
+/* functions for long arithmetics **********************************************
+
+ On systems where 64 bit Integers are not supported by the CPU,
+ these functions are needed.
+
+******************************************************************************/
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
+s8 builtin_ladd(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a + b;
+
+ return c;
+}
+
+s8 builtin_lsub(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a - b;
+
+ return c;
+}
+
+s8 builtin_lneg(s8 a)
+{
+ s8 c;
+
+ c = -a;
+
+ return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
+s8 builtin_lmul(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a * b;
+
+ return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_MUL) */
+
+
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined (DISABLE_GC)
+s8 builtin_ldiv(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a / b;
+
+ return c;
+}
+
+s8 builtin_lrem(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a % b;
+
+ return c;
+}
+#endif /* !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
+s8 builtin_lshl(s8 a, s4 b)
+{
+ s8 c;
+
+ c = a << (b & 63);
+
+ return c;
+}
+
+s8 builtin_lshr(s8 a, s4 b)
+{
+ s8 c;
+
+ c = a >> (b & 63);
+
+ return c;
+}
+
+s8 builtin_lushr(s8 a, s4 b)
+{
+ s8 c;
+
+ c = ((u8) a) >> (b & 63);
+
+ return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
+s8 builtin_land(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a & b;
+
+ return c;
+}
+
+s8 builtin_lor(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a | b;
+
+ return c;
+}
+
+s8 builtin_lxor(s8 a, s8 b)
+{
+ s8 c;
+
+ c = a ^ b;
+
+ return c;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
+s4 builtin_lcmp(s8 a, s8 b)
+{
+ if (a < b)
+ return -1;
+
+ if (a > b)
+ return 1;
+
+ return 0;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_CMP) */
+
+
+/* functions for unsupported floating instructions ****************************/
+
+/* used to convert FLT_xxx defines into float values */
+
+static inline float intBitsToFloat(s4 i)
+{
+ imm_union imb;
+
+ imb.i = i;
+ return imb.f;
+}
+
+
+/* used to convert DBL_xxx defines into double values */
+
+static inline float longBitsToDouble(s8 l)
+{
+ imm_union imb;
+
+ imb.l = l;
+ return imb.d;
+}
+
+
+#if !SUPPORT_FLOAT
+float builtin_fadd(float a, float b)
+{
+ if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+ if (isnanf(b)) return intBitsToFloat(FLT_NAN);
+ if (finitef(a)) {
+ if (finitef(b))
+ return a + b;
+ else
+ return b;
+ }
+ else {
+ if (finitef(b))
+ return a;
+ else {
+ if (copysignf(1.0, a) == copysignf(1.0, b))
+ return a;
+ else
+ return intBitsToFloat(FLT_NAN);
+ }
+ }
+}
+
+
+float builtin_fsub(float a, float b)
+{
+ return builtin_fadd(a, builtin_fneg(b));
+}
+
+
+float builtin_fmul(float a, float b)
+{
+ if (isnanf(a)) return intBitsToFloat(FLT_NAN);
+ if (isnanf(b)) return intBitsToFloat(FLT_NAN);
+ if (finitef(a)) {
+ if (finitef(b)) return a * b;
+ else {
+ if (a == 0) return intBitsToFloat(FLT_NAN);
+ else return copysignf(b, copysignf(1.0, b)*a);
+ }
+ }
+ else {
+ if (finitef(b)) {
+ if (b == 0) return intBitsToFloat(FLT_NAN);
+ else return copysignf(a, copysignf(1.0, a)*b);
+ }
+ else {
+ return copysignf(a, copysignf(1.0, a)*copysignf(1.0, b));
+ }
+ }
+}
+
+
+/* builtin_ddiv ****************************************************************
+
+ Implementation as described in VM Spec.
+
+*******************************************************************************/
+
+float builtin_fdiv(float a, float b)
+{
+ if (finitef(a)) {
+ if (finitef(b)) {
+ /* If neither value1' nor value2' is NaN, the sign of the result */
+ /* is positive if both values have the same sign, negative if the */
+ /* values have different signs. */
+
+ return a / b;
+
+ } else {
+ if (isnanf(b)) {
+ /* If either value1' or value2' is NaN, the result is NaN. */
+
+ return intBitsToFloat(FLT_NAN);
+
+ } else {
+ /* Division of a finite value by an infinity results in a */
+ /* signed zero, with the sign-producing rule just given. */
+
+ /* is sign equal? */
+
+ if (copysignf(1.0, a) == copysignf(1.0, b))
+ return 0.0;
+ else
+ return -0.0;
+ }
+ }
+
+ } else {
+ if (isnanf(a)) {
+ /* If either value1' or value2' is NaN, the result is NaN. */
+
+ return intBitsToFloat(FLT_NAN);
+
+ } else if (finitef(b)) {
+ /* Division of an infinity by a finite value results in a signed */
+ /* infinity, with the sign-producing rule just given. */
+
+ /* is sign equal? */
+
+ if (copysignf(1.0, a) == copysignf(1.0, b))
+ return intBitsToFloat(FLT_POSINF);
+ else
+ return intBitsToFloat(FLT_NEGINF);
+
+ } else {
+ /* Division of an infinity by an infinity results in NaN. */
+
+ return intBitsToFloat(FLT_NAN);
+ }
+ }
+}
+
+
+float builtin_fneg(float a)
+{
+ if (isnanf(a)) return a;
+ else {
+ if (finitef(a)) return -a;
+ else return copysignf(a, -copysignf(1.0, a));
+ }
+}
+#endif /* !SUPPORT_FLOAT */
+
+
+#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP)
+s4 builtin_fcmpl(float a, float b)
+{
+ if (isnanf(a))
+ return -1;
+
+ if (isnanf(b))
+ return -1;
+
+ if (!finitef(a) || !finitef(b)) {
+ a = finitef(a) ? 0 : copysignf(1.0, a);
+ b = finitef(b) ? 0 : copysignf(1.0, b);
+ }
+
+ if (a > b)
+ return 1;
+
+ if (a == b)
+ return 0;
+
+ return -1;
+}
+
+
+s4 builtin_fcmpg(float a, float b)
+{
+ if (isnanf(a)) return 1;
+ if (isnanf(b)) return 1;
+ if (!finitef(a) || !finitef(b)) {
+ a = finitef(a) ? 0 : copysignf(1.0, a);
+ b = finitef(b) ? 0 : copysignf(1.0, b);
+ }
+ if (a > b) return 1;
+ if (a == b) return 0;
+ return -1;
+}
+#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP || defined(ENABLE_INTRP) */
+
+
+float builtin_frem(float a, float b)
+{
+ return fmodf(a, b);
+}
+
+
+/* functions for unsupported double instructions ******************************/
+
+#if !SUPPORT_DOUBLE
+double builtin_dadd(double a, double b)
+{
+ if (isnan(a)) return longBitsToDouble(DBL_NAN);
+ if (isnan(b)) return longBitsToDouble(DBL_NAN);
+ if (finite(a)) {
+ if (finite(b)) return a + b;
+ else return b;
+ }
+ else {
+ if (finite(b)) return a;
+ else {
+ if (copysign(1.0, a)==copysign(1.0, b)) return a;
+ else return longBitsToDouble(DBL_NAN);
+ }
+ }
+}
+
+
+double builtin_dsub(double a, double b)
+{
+ return builtin_dadd(a, builtin_dneg(b));
+}
+
+
+double builtin_dmul(double a, double b)
+{
+ if (isnan(a)) return longBitsToDouble(DBL_NAN);
+ if (isnan(b)) return longBitsToDouble(DBL_NAN);
+ if (finite(a)) {
+ if (finite(b)) return a * b;
+ else {
+ if (a == 0) return longBitsToDouble(DBL_NAN);
+ else return copysign(b, copysign(1.0, b) * a);
+ }
+ }
+ else {
+ if (finite(b)) {
+ if (b == 0) return longBitsToDouble(DBL_NAN);
+ else return copysign(a, copysign(1.0, a) * b);
+ }
+ else {
+ return copysign(a, copysign(1.0, a) * copysign(1.0, b));
+ }
+ }
+}
+
+
+/* builtin_ddiv ****************************************************************
+
+ Implementation as described in VM Spec.
+
+*******************************************************************************/
+
+double builtin_ddiv(double a, double b)
+{
+ if (finite(a)) {
+ if (finite(b)) {
+ /* If neither value1' nor value2' is NaN, the sign of the result */
+ /* is positive if both values have the same sign, negative if the */
+ /* values have different signs. */
+
+ return a / b;
+
+ } else {
+ if (isnan(b)) {
+ /* If either value1' or value2' is NaN, the result is NaN. */
+
+ return longBitsToDouble(DBL_NAN);
+
+ } else {
+ /* Division of a finite value by an infinity results in a */
+ /* signed zero, with the sign-producing rule just given. */
+
+ /* is sign equal? */
+
+ if (copysign(1.0, a) == copysign(1.0, b))
+ return 0.0;
+ else
+ return -0.0;
+ }
+ }
+
+ } else {
+ if (isnan(a)) {
+ /* If either value1' or value2' is NaN, the result is NaN. */
+
+ return longBitsToDouble(DBL_NAN);
+
+ } else if (finite(b)) {
+ /* Division of an infinity by a finite value results in a signed */
+ /* infinity, with the sign-producing rule just given. */
+
+ /* is sign equal? */
+
+ if (copysign(1.0, a) == copysign(1.0, b))
+ return longBitsToDouble(DBL_POSINF);
+ else
+ return longBitsToDouble(DBL_NEGINF);
+
+ } else {
+ /* Division of an infinity by an infinity results in NaN. */
+
+ return longBitsToDouble(DBL_NAN);
+ }
+ }
+}
+
+
+/* builtin_dneg ****************************************************************
+
+ Implemented as described in VM Spec.
+
+*******************************************************************************/
+
+double builtin_dneg(double a)
+{
+ if (isnan(a)) {
+ /* If the operand is NaN, the result is NaN (recall that NaN has no */
+ /* sign). */
+
+ return a;
+
+ } else {
+ if (finite(a)) {
+ /* If the operand is a zero, the result is the zero of opposite */
+ /* sign. */
+
+ return -a;
+
+ } else {
+ /* If the operand is an infinity, the result is the infinity of */
+ /* opposite sign. */
+
+ return copysign(a, -copysign(1.0, a));
+ }
+ }
+}
+#endif /* !SUPPORT_DOUBLE */
+
+
+#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP)
+s4 builtin_dcmpl(double a, double b)
+{
+ if (isnan(a))
+ return -1;
+
+ if (isnan(b))
+ return -1;
+
+ if (!finite(a) || !finite(b)) {
+ a = finite(a) ? 0 : copysign(1.0, a);
+ b = finite(b) ? 0 : copysign(1.0, b);
+ }
+
+ if (a > b)
+ return 1;
+
+ if (a == b)
+ return 0;
+
+ return -1;
+}
+
+
+s4 builtin_dcmpg(double a, double b)
+{
+ if (isnan(a))
+ return 1;
+
+ if (isnan(b))
+ return 1;
+
+ if (!finite(a) || !finite(b)) {
+ a = finite(a) ? 0 : copysign(1.0, a);
+ b = finite(b) ? 0 : copysign(1.0, b);
+ }
+
+ if (a > b)
+ return 1;
+
+ if (a == b)
+ return 0;
+
+ return -1;
+}
+#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP || defined(ENABLE_INTRP) */
+
+
+double builtin_drem(double a, double b)
+{
+ return fmod(a, b);
+}
+
+
+/* conversion operations ******************************************************/
+
+#if !(SUPPORT_FLOAT && SUPPORT_I2F)
+float builtin_i2f(s4 a)
+{
+ float f = (float) a;
+ return f;
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_I2F) */
+
+
+#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
+double builtin_i2d(s4 a)
+{
+ double d = (double) a;
+ return d;
+}
+#endif /* !(SUPPORT_DOUBLE && SUPPORT_I2D) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
+float builtin_l2f(s8 a)
+{
+ float f = (float) a;
+ return f;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F) */
+
+
+#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
+double builtin_l2d(s8 a)
+{
+ double d = (double) a;
+ return d;
+}
+#endif /* !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D) */
+
+
+#if !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
+s4 builtin_f2i(float a)
+{
+ s4 i;
+
+ i = builtin_d2i((double) a);
+
+ return i;
+
+ /* float f;
+
+ if (isnanf(a))
+ return 0;
+ if (finitef(a)) {
+ if (a > 2147483647)
+ return 2147483647;
+ if (a < (-2147483648))
+ return (-2147483648);
+ return (s4) a;
+ }
+ f = copysignf((float) 1.0, a);
+ if (f > 0)
+ return 2147483647;
+ return (-2147483648); */
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_F2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
+
+#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) || defined(DISABLE_GC)
+s8 builtin_f2l(float a)
+{
+ s8 l;
+
+ l = builtin_d2l((double) a);
+
+ return l;
+
+ /* float f;
+
+ if (finitef(a)) {
+ if (a > 9223372036854775807L)
+ return 9223372036854775807L;
+ if (a < (-9223372036854775808L))
+ return (-9223372036854775808L);
+ return (s8) a;
+ }
+ if (isnanf(a))
+ return 0;
+ f = copysignf((float) 1.0, a);
+ if (f > 0)
+ return 9223372036854775807L;
+ return (-9223372036854775808L); */
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L) */
+
+
+#if !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC)
+s4 builtin_d2i(double a)
+{
+ double d;
+
+ if (finite(a)) {
+ if (a >= 2147483647)
+ return 2147483647;
+ if (a <= (-2147483647-1))
+ return (-2147483647-1);
+ return (s4) a;
+ }
+ if (isnan(a))
+ return 0;
+ d = copysign(1.0, a);
+ if (d > 0)
+ return 2147483647;
+ return (-2147483647-1);
+}
+#endif /* !(SUPPORT_DOUBLE && SUPPORT_D2I) || defined(ENABLE_INTRP) || defined(DISABLE_GC) */
+
+
+#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) || defined(DISABLE_GC)
+s8 builtin_d2l(double a)
+{
+ double d;
+
+ if (finite(a)) {
+ if (a >= 9223372036854775807LL)
+ return 9223372036854775807LL;
+ if (a <= (-9223372036854775807LL-1))
+ return (-9223372036854775807LL-1);
+ return (s8) a;
+ }
+ if (isnan(a))
+ return 0;
+ d = copysign(1.0, a);
+ if (d > 0)
+ return 9223372036854775807LL;
+ return (-9223372036854775807LL-1);
+}
+#endif /* !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L) */
+
+
+#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
+double builtin_f2d(float a)
+{
+ if (finitef(a)) return (double) a;
+ else {
+ if (isnanf(a))
+ return longBitsToDouble(DBL_NAN);
+ else
+ return copysign(longBitsToDouble(DBL_POSINF), (double) copysignf(1.0, a) );
+ }
+}
+
+float builtin_d2f(double a)
+{
+ if (finite(a))
+ return (float) a;
+ else {
+ if (isnan(a))
+ return intBitsToFloat(FLT_NAN);
+ else
+ return copysignf(intBitsToFloat(FLT_POSINF), (float) copysign(1.0, a));
+ }
+}
+#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
+
+
+/*============================================================================*/
+/* AUTOMATICALLY REPLACED FUNCTIONS */
+/*============================================================================*/
+
+/* builtin_arraycopy ***********************************************************
+
+ Builtin for java.lang.System.arraycopy.
+
+ NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+void builtin_arraycopy(java_handle_t *src, s4 srcStart,
+ java_handle_t *dest, s4 destStart, s4 len)
+{
+ arraydescriptor *sdesc;
+ arraydescriptor *ddesc;
+ s4 i;
+
+ if ((src == NULL) || (dest == NULL)) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ sdesc = LLNI_vftbl_direct(src)->arraydesc;
+ ddesc = LLNI_vftbl_direct(dest)->arraydesc;
+
+ if (!sdesc || !ddesc || (sdesc->arraytype != ddesc->arraytype)) {
+ exceptions_throw_arraystoreexception();
+ return;
+ }
+
+ // Check if offsets and length are positive.
+ if ((srcStart < 0) || (destStart < 0) || (len < 0)) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return;
+ }
+
+ // Check if ranges are valid.
+ if ((((uint32_t) srcStart + (uint32_t) len) > (uint32_t) LLNI_array_size(src)) ||
+ (((uint32_t) destStart + (uint32_t) len) > (uint32_t) LLNI_array_size(dest))) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return;
+ }
+
+ // Special case.
+ if (len == 0) {
+ return;
+ }
+
+ if (sdesc->componentvftbl == ddesc->componentvftbl) {
+ /* We copy primitive values or references of exactly the same type */
+
+ s4 dataoffset = sdesc->dataoffset;
+ s4 componentsize = sdesc->componentsize;
+
+ LLNI_CRITICAL_START;
+
+ MMOVE(((u1 *) LLNI_DIRECT(dest)) + dataoffset + componentsize * destStart,
+ ((u1 *) LLNI_DIRECT(src)) + dataoffset + componentsize * srcStart,
+ u1, (size_t) len * componentsize);
+
+ LLNI_CRITICAL_END;
+ }
+ else {
+ /* We copy references of different type */
+
+ java_handle_objectarray_t *oas = (java_handle_objectarray_t *) src;
+ java_handle_objectarray_t *oad = (java_handle_objectarray_t *) dest;
+
+ if (destStart <= srcStart) {
+ for (i = 0; i < len; i++) {
+ java_handle_t *o;
+
+ o = array_objectarray_element_get(oas, srcStart + i);
+
+ if (!builtin_canstore(oad, o))
+ return;
+
+ array_objectarray_element_set(oad, destStart + i, o);
+ }
+ }
+ else {
+ /* XXX this does not completely obey the specification!
+ If an exception is thrown only the elements above the
+ current index have been copied. The specification
+ requires that only the elements *below* the current
+ index have been copied before the throw. */
+
+ for (i = len - 1; i >= 0; i--) {
+ java_handle_t *o;
+
+ o = array_objectarray_element_get(oas, srcStart + i);
+
+ if (!builtin_canstore(oad, o))
+ return;
+
+ array_objectarray_element_set(oad, destStart + i, o);
+ }
+ }
+ }
+}
+
+
+/* builtin_nanotime ************************************************************
+
+ Return the current time in nanoseconds.
+
+*******************************************************************************/
+
+s8 builtin_nanotime(void)
+{
+ struct timeval tv;
+ s8 usecs;
+
+ if (gettimeofday(&tv, NULL) == -1)
+ vm_abort("gettimeofday failed: %s", strerror(errno));
+
+ usecs = (s8) tv.tv_sec * (1000 * 1000) + (s8) tv.tv_usec;
+
+ return usecs * 1000;
+}
+
+
+/* builtin_currenttimemillis ***************************************************
+
+ Return the current time in milliseconds.
+
+*******************************************************************************/
+
+s8 builtin_currenttimemillis(void)
+{
+ s8 msecs;
+
+ msecs = builtin_nanotime() / 1000 / 1000;
+
+ return msecs;
+}
+
+
+/* builtin_clone ***************************************************************
+
+ Function for cloning objects or arrays.
+
+ NOTE: This is a SLOW builtin and can be called from JIT & NATIVE code.
+
+*******************************************************************************/
+
+java_handle_t *builtin_clone(void *env, java_handle_t *o)
+{
+ arraydescriptor *ad;
+ u4 size;
+ classinfo *c;
+ java_handle_t *co; /* cloned object header */
+
+ /* get the array descriptor */
+
+ ad = LLNI_vftbl_direct(o)->arraydesc;
+
+ /* we are cloning an array */
+
+ if (ad != NULL) {
+ size = ad->dataoffset + ad->componentsize * LLNI_array_size(o);
+
+ co = (java_handle_t*) heap_alloc(size, (ad->arraytype == ARRAYTYPE_OBJECT), NULL, true);
+
+ if (co == NULL)
+ return NULL;
+
+#if !defined(ENABLE_GC_CACAO) && defined(ENABLE_HANDLES)
+ /* XXX this is only a dirty hack to make Boehm work with handles */
+
+ co = LLNI_WRAP((java_object_t *) co);
+#endif
+
+ LLNI_CRITICAL_START;
+
+ MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, size);
+
+#if defined(ENABLE_GC_CACAO)
+ heap_init_objectheader(LLNI_DIRECT(co), size);
+#endif
+
+#if defined(ENABLE_THREADS)
+ LLNI_DIRECT(co)->lockword.init();
+#endif
+
+ LLNI_CRITICAL_END;
+
+ return co;
+ }
+
+ /* we are cloning a non-array */
+
+ if (!builtin_instanceof(o, class_java_lang_Cloneable)) {
+ exceptions_throw_clonenotsupportedexception();
+ return NULL;
+ }
+
+ /* get the class of the object */
+
+ LLNI_class_get(o, c);
+
+ /* create new object */
+
+ co = builtin_new(c);
+
+ if (co == NULL)
+ return NULL;
+
+ LLNI_CRITICAL_START;
+
+ MCOPY(LLNI_DIRECT(co), LLNI_DIRECT(o), u1, c->instancesize);
+
+#if defined(ENABLE_GC_CACAO)
+ heap_init_objectheader(LLNI_DIRECT(co), c->instancesize);
+#endif
+
+#if defined(ENABLE_THREADS)
+ LLNI_DIRECT(co)->lockword.init();
+#endif
+
+ LLNI_CRITICAL_END;
+
+ return co;
+}
+
+
+#if defined(ENABLE_CYCLES_STATS)
+void builtin_print_cycles_stats(FILE *file)
+{
+ fprintf(file,"builtin cylce count statistics:\n");
+
+ CYCLES_STATS_PRINT_OVERHEAD(builtin_overhead,file);
+ CYCLES_STATS_PRINT(builtin_new ,file);
+
+ fprintf(file,"\n");
+}
+#endif /* defined(ENABLE_CYCLES_STATS) */
+
+
+#if defined(ENABLE_VMLOG)
+#define NDEBUG
+#include <vmlog_cacao.c>
+#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/builtin.hpp - prototypes of builtin 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 _BUILTIN_HPP
+#define _BUILTIN_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct builtintable_entry builtintable_entry;
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/descriptor.h"
+#include "vm/utf8.h"
+
+
+/* define infinity for floating point numbers */
+
+#define FLT_NAN 0x7fc00000
+#define FLT_POSINF 0x7f800000
+#define FLT_NEGINF 0xff800000
+
+/* define infinity for double floating point numbers */
+
+#define DBL_NAN 0x7ff8000000000000LL
+#define DBL_POSINF 0x7ff0000000000000LL
+#define DBL_NEGINF 0xfff0000000000000LL
+
+
+/* float versions are not defined in GNU classpath's fdlibm */
+
+#define copysignf copysign
+#define finitef finite
+#define fmodf fmod
+#define isnanf isnan
+
+
+/* builtin functions table ****************************************************/
+
+struct builtintable_entry {
+ s4 opcode; /* opcode which is replaced */
+ u4 flags; /* e.g. check for exception */
+ functionptr fp; /* function pointer of builtin */
+ u1 *stub; /* pointer to builtin stub code */
+ const char* cclassname; /* char name of the class */
+ const char* cname; /* char name of the function */
+ const char* cdescriptor; /* char name of the descriptor */
+ utf *classname; /* class of the function */
+ utf *name; /* name of the function */
+ utf *descriptor; /* descriptor of the function */
+ methoddesc *md;
+};
+
+
+/* builtin table flag defines *************************************************/
+
+#define BUILTINTABLE_FLAG_STUB 0x0001 /* builtin needs a stub */
+#define BUILTINTABLE_FLAG_EXCEPTION 0x0002 /* check for excepion on return */
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool builtin_init(void);
+
+s4 builtintable_get_key(builtintable_entry *);
+builtintable_entry *builtintable_get_by_key(s4 key);
+builtintable_entry *builtintable_get_internal(functionptr fp);
+builtintable_entry *builtintable_get_automatic(s4 opcode);
+
+bool builtintable_replace_function(void *iptr);
+
+
+/**********************************************************************/
+/* BUILTIN FUNCTIONS */
+/**********************************************************************/
+
+/* NOTE: Builtin functions which are used in the BUILTIN* opcodes must
+ * have a BUILTIN_... macro defined as seen below. In code dealing
+ * with the BUILTIN* opcodes the functions may only be addressed by
+ * these macros, never by their actual name! (This helps to make this
+ * code more portable.)
+ *
+ * C and assembler code which does not deal with the BUILTIN* opcodes,
+ * can use the builtin functions normally (like all other functions).
+ *
+ * IMPORTANT:
+ * For each builtin function which is used in a BUILTIN* opcode there
+ * must be an entry in the tables in vm/builtintable.inc.
+ *
+ * Below each prototype is either the BUILTIN_ macro definition or a
+ * comment specifiying that this function is not used in BUILTIN*
+ * opcodes.
+ *
+ * (The BUILTIN* opcodes are ICMD_BUILTIN1, ICMD_BUILTIN2 and
+ * ICMD_BUILTIN3.)
+ */
+
+bool builtin_instanceof(java_handle_t *obj, classinfo *c);
+/* NOT AN OP */
+bool builtin_checkcast(java_handle_t *obj, classinfo *c);
+/* NOT AN OP */
+bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass);
+/* NOT AN OP */
+bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass);
+#define BUILTIN_arrayinstanceof (functionptr) builtin_fast_arrayinstanceof
+bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass);
+#define BUILTIN_arraycheckcast (functionptr) builtin_fast_arraycheckcast
+
+bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o);
+/* NOT AN OP */
+bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o);
+#define BUILTIN_FAST_canstore (functionptr) builtin_fast_canstore
+
+void *builtin_throw_exception(java_object_t *exception);
+/* NOT AN OP */
+java_object_t *builtin_retrieve_exception(void);
+/* NOT AN OP */
+
+java_handle_t *builtin_new(classinfo *c);
+/* 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
+
+java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass);
+/* NOT AN OP */
+java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclass);
+#define BUILTIN_newarray (functionptr) builtin_java_newarray
+
+java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass);
+/* NOT AN OP */
+
+java_handle_booleanarray_t *builtin_newarray_boolean(int32_t size);
+#define BUILTIN_newarray_boolean (functionptr) builtin_newarray_boolean
+java_handle_chararray_t *builtin_newarray_char(int32_t size);
+#define BUILTIN_newarray_char (functionptr) builtin_newarray_char
+java_handle_floatarray_t *builtin_newarray_float(int32_t size);
+#define BUILTIN_newarray_float (functionptr) builtin_newarray_float
+java_handle_doublearray_t *builtin_newarray_double(int32_t size);
+#define BUILTIN_newarray_double (functionptr) builtin_newarray_double
+java_handle_bytearray_t *builtin_newarray_byte(int32_t size);
+#define BUILTIN_newarray_byte (functionptr) builtin_newarray_byte
+java_handle_shortarray_t *builtin_newarray_short(int32_t size);
+#define BUILTIN_newarray_short (functionptr) builtin_newarray_short
+java_handle_intarray_t *builtin_newarray_int(int32_t size);
+#define BUILTIN_newarray_int (functionptr) builtin_newarray_int
+java_handle_longarray_t *builtin_newarray_long(int32_t size);
+#define BUILTIN_newarray_long (functionptr) builtin_newarray_long
+
+java_handle_objectarray_t *builtin_multianewarray(int n,
+ java_handle_t *arrayclass,
+ long *dims);
+#define BUILTIN_multianewarray (functionptr) builtin_multianewarray
+
+#if defined(TRACE_ARGS_NUM)
+void builtin_verbosecall_enter(s8 a0, s8 a1,
+# if TRACE_ARGS_NUM >= 4
+ s8 a2, s8 a3,
+# endif
+# if TRACE_ARGS_NUM >= 6
+ s8 a4, s8 a5,
+# endif
+# if TRACE_ARGS_NUM == 8
+ s8 a6, s8 a7,
+# endif
+ methodinfo *m);
+/* NOT AN OP */
+#endif /* defined(TRACE_ARGS_NUM) */
+
+void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
+/* NOT AN OP */
+
+s4 builtin_idiv(s4 a, s4 b);
+#define BUILTIN_idiv (functionptr) builtin_idiv
+s4 builtin_irem(s4 a, s4 b);
+#define BUILTIN_irem (functionptr) builtin_irem
+
+s8 builtin_ladd(s8 a, s8 b);
+#define BUILTIN_ladd (functionptr) builtin_ladd
+s8 builtin_lsub(s8 a, s8 b);
+#define BUILTIN_lsub (functionptr) builtin_lsub
+s8 builtin_lmul(s8 a, s8 b);
+#define BUILTIN_lmul (functionptr) builtin_lmul
+
+s8 builtin_ldiv(s8 a, s8 b);
+#define BUILTIN_ldiv (functionptr) builtin_ldiv
+s8 builtin_lrem(s8 a, s8 b);
+#define BUILTIN_lrem (functionptr) builtin_lrem
+
+s8 builtin_lshl(s8 a, s4 b);
+#define BUILTIN_lshl (functionptr) builtin_lshl
+s8 builtin_lshr(s8 a, s4 b);
+#define BUILTIN_lshr (functionptr) builtin_lshr
+s8 builtin_lushr(s8 a, s4 b);
+#define BUILTIN_lushr (functionptr) builtin_lushr
+s8 builtin_land(s8 a, s8 b);
+#define BUILTIN_land (functionptr) builtin_land
+s8 builtin_lor(s8 a, s8 b);
+#define BUILTIN_lor (functionptr) builtin_lor
+s8 builtin_lxor(s8 a, s8 b);
+#define BUILTIN_lxor (functionptr) builtin_lxor
+s8 builtin_lneg(s8 a);
+#define BUILTIN_lneg (functionptr) builtin_lneg
+s4 builtin_lcmp(s8 a, s8 b);
+#define BUILTIN_lcmp (functionptr) builtin_lcmp
+
+float builtin_fadd(float a, float b);
+#define BUILTIN_fadd (functionptr) builtin_fadd
+float builtin_fsub(float a, float b);
+#define BUILTIN_fsub (functionptr) builtin_fsub
+float builtin_fmul(float a, float b);
+#define BUILTIN_fmul (functionptr) builtin_fmul
+float builtin_fdiv(float a, float b);
+#define BUILTIN_fdiv (functionptr) builtin_fdiv
+float builtin_fneg(float a);
+#define BUILTIN_fneg (functionptr) builtin_fneg
+s4 builtin_fcmpl(float a, float b);
+#define BUILTIN_fcmpl (functionptr) builtin_fcmpl
+s4 builtin_fcmpg(float a, float b);
+#define BUILTIN_fcmpg (functionptr) builtin_fcmpg
+float builtin_frem(float a, float b);
+#define BUILTIN_frem (functionptr) builtin_frem
+
+double builtin_dadd(double a, double b);
+#define BUILTIN_dadd (functionptr) builtin_dadd
+double builtin_dsub(double a, double b);
+#define BUILTIN_dsub (functionptr) builtin_dsub
+double builtin_dmul(double a, double b);
+#define BUILTIN_dmul (functionptr) builtin_dmul
+double builtin_ddiv(double a, double b);
+#define BUILTIN_ddiv (functionptr) builtin_ddiv
+double builtin_dneg(double a);
+#define BUILTIN_dneg (functionptr) builtin_dneg
+s4 builtin_dcmpl(double a, double b);
+#define BUILTIN_dcmpl (functionptr) builtin_dcmpl
+s4 builtin_dcmpg(double a, double b);
+#define BUILTIN_dcmpg (functionptr) builtin_dcmpg
+double builtin_drem(double a, double b);
+#define BUILTIN_drem (functionptr) builtin_drem
+
+float builtin_i2f(s4 i);
+#define BUILTIN_i2f (functionptr) builtin_i2f
+double builtin_i2d(s4 i);
+#define BUILTIN_i2d (functionptr) builtin_i2d
+float builtin_l2f(s8 l);
+#define BUILTIN_l2f (functionptr) builtin_l2f
+double builtin_l2d(s8 l);
+#define BUILTIN_l2d (functionptr) builtin_l2d
+
+s4 builtin_f2i(float a);
+#define BUILTIN_f2i (functionptr) builtin_f2i
+s4 asm_builtin_f2i(float a);
+/* NOT AN OP */
+s8 builtin_f2l(float a);
+#define BUILTIN_f2l (functionptr) builtin_f2l
+s8 asm_builtin_f2l(float a);
+/* NOT AN OP */
+
+double builtin_f2d(float a);
+#define BUILTIN_f2d (functionptr) builtin_f2d
+
+s4 builtin_d2i(double a);
+#define BUILTIN_d2i (functionptr) builtin_d2i
+s4 asm_builtin_d2i(double a);
+/* NOT AN OP */
+s8 builtin_d2l(double a);
+#define BUILTIN_d2l (functionptr) builtin_d2l
+s8 asm_builtin_d2l(double a);
+/* NOT AN OP */
+
+float builtin_d2f(double a);
+#define BUILTIN_d2f (functionptr) builtin_d2f
+
+java_handle_t *builtin_clone(void *env, java_handle_t *o);
+#define BUILTIN_clone (functionptr) builtin_clone
+
+void builtin_arraycopy(java_handle_t *src, s4 srcStart,
+ java_handle_t *dest, s4 destStart, s4 len);
+#define BUILTIN_arraycopy (functionptr) builtin_arraycopy
+
+s8 builtin_nanotime(void);
+s8 builtin_currenttimemillis(void);
+#define BUILTIN_currenttimemillis (functionptr) builtin_currenttimemillis
+
+#if defined(ENABLE_CYCLES_STATS)
+void builtin_print_cycles_stats(FILE *file);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _BUILTIN_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/builtintable.inc - tables of builtin 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 "arch.h"
+
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/jit/jit.hpp"
+
+
+/* internal and not automatically replaced functions **************************/
+
+static builtintable_entry builtintable_internal[] = {
+
+#if defined(__ALPHA__) || defined(DISABLE_GC)
+ {
+ ICMD_F2L,
+ 0,
+ BUILTIN_f2l,
+ NULL,
+ NULL,
+ "f2l",
+ "(F)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_D2L,
+ 0,
+ BUILTIN_d2l,
+ NULL,
+ NULL,
+ "d2l",
+ "(D)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_F2I,
+ 0,
+ BUILTIN_f2i,
+ NULL,
+ NULL,
+ "f2i",
+ "(F)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_D2I,
+ 0,
+ BUILTIN_d2i,
+ NULL,
+ NULL,
+ "d2i",
+ "(D)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !SUPPORT_DIVISION || defined(DISABLE_GC)
+ {
+ ICMD_IDIV,
+ 0,
+ BUILTIN_idiv,
+ NULL,
+ NULL,
+ "idiv",
+ "(II)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_IREM,
+ 0,
+ BUILTIN_irem,
+ NULL,
+ NULL,
+ "irem",
+ "(II)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV) || defined(DISABLE_GC)
+ {
+ ICMD_LDIV,
+ 0,
+ BUILTIN_ldiv,
+ NULL,
+ NULL,
+ "ldiv",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_LREM,
+ 0,
+ BUILTIN_lrem,
+ NULL,
+ NULL,
+ "lrem",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+ {
+ ICMD_FREM,
+ 0,
+ BUILTIN_frem,
+ NULL,
+ NULL,
+ "frem",
+ "(FF)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_DREM,
+ 0,
+ BUILTIN_drem,
+ NULL,
+ NULL,
+ "drem",
+ "(DD)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+
+
+ /* internal functions *****************************************************/
+
+ {
+ ICMD_NEW,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_new,
+ NULL,
+ NULL,
+ "new",
+ "(Ljava/lang/Class;)Ljava/lang/Object;",
+ NULL,
+ NULL,
+ 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,
+ BUILTIN_FAST_new,
+ NULL,
+ NULL,
+ "fast-new",
+ "(Ljava/lang/Class;)Ljava/lang/Object;",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_ANEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray,
+ NULL,
+ NULL,
+ "newarray",
+ "(ILjava/lang/Class;)[Ljava/lang/Object;",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_boolean,
+ NULL,
+ NULL,
+ "newarray_boolean",
+ "(I)[Z",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_byte,
+ NULL,
+ NULL,
+ "newarray_byte",
+ "(I)[B",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_char,
+ NULL,
+ NULL,
+ "newarray_char",
+ "(I)[C",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_short,
+ NULL,
+ NULL,
+ "newarray_short",
+ "(I)[S",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_int,
+ NULL,
+ NULL,
+ "newarray_int",
+ "(I)[I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_long,
+ NULL,
+ NULL,
+ "newarray_long",
+ "(I)[J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_float,
+ NULL,
+ NULL,
+ "newarray_float",
+ "(I)[F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_NEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_newarray_double,
+ NULL,
+ NULL,
+ "newarray_double",
+ "(I)[D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_MULTIANEWARRAY,
+ BUILTINTABLE_FLAG_STUB,
+ BUILTIN_multianewarray,
+ NULL,
+ NULL,
+ "multianewarray",
+ /* XXX it should be: "(ILjava/lang/Class;[I)[Ljava/lang/Object;", */
+ "(ILjava/lang/Class;I)[Ljava/lang/Object;",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_CHECKCAST,
+ 0,
+ BUILTIN_arraycheckcast,
+ NULL,
+ NULL,
+ "arraycheckcast",
+ "([Ljava/lang/Object;[Ljava/lang/Object;)[Ljava/lang/Object;",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_INSTANCEOF,
+ 0,
+ BUILTIN_arrayinstanceof,
+ NULL,
+ NULL,
+ "arrayinstanceof",
+ "([Ljava/lang/Object;[Ljava/lang/Object;)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_AASTORE,
+ 0,
+ BUILTIN_FAST_canstore,
+ NULL,
+ NULL,
+ "fast-canstore",
+ "([Ljava/lang/Object;Ljava/lang/Object;)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+
+#if defined(ENABLE_THREADS)
+ {
+ ICMD_MONITORENTER,
+ BUILTINTABLE_FLAG_STUB,
+ LOCK_monitor_enter,
+ NULL,
+ NULL,
+ "monitorenter",
+ "(Ljava/lang/Object;)V",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_MONITOREXIT,
+ BUILTINTABLE_FLAG_STUB,
+ LOCK_monitor_exit,
+ NULL,
+ NULL,
+ "monitorexit",
+ "(Ljava/lang/Object;)V",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+
+ /* stop entry */
+
+ {
+ 255,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+};
+
+
+/* automatically replaced functions *******************************************/
+
+static builtintable_entry builtintable_automatic[] = {
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_CMP)
+ {
+ ICMD_LCMP,
+ 0,
+ BUILTIN_lcmp,
+ NULL,
+ NULL,
+ "lcmp",
+ "(JJ)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL)
+ {
+ ICMD_LAND,
+ 0,
+ BUILTIN_land,
+ NULL,
+ NULL,
+ "land",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_LOR,
+ 0,
+ BUILTIN_lor,
+ NULL,
+ NULL,
+ "lor",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_LXOR,
+ 0,
+ BUILTIN_lxor,
+ NULL,
+ NULL,
+ "lxor",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_LOGICAL) */
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_SHIFT)
+ {
+ ICMD_LSHL,
+ 0,
+ BUILTIN_lshl,
+ NULL,
+ NULL,
+ "lshl",
+ "(JI)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_LSHR,
+ 0,
+ BUILTIN_lshr,
+ NULL,
+ NULL,
+ "lshr",
+ "(JI)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_LUSHR,
+ 0,
+ BUILTIN_lushr,
+ NULL,
+ NULL,
+ "lushr",
+ "(JI)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_SHIFT) */
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_ADD)
+ {
+ ICMD_LADD,
+ 0,
+ BUILTIN_ladd,
+ NULL,
+ NULL,
+ "ladd",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_LSUB,
+ 0,
+ BUILTIN_lsub,
+ NULL,
+ NULL,
+ "lsub",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_LNEG,
+ 0,
+ BUILTIN_lneg,
+ NULL,
+ NULL,
+ "lneg",
+ "(J)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !(SUPPORT_LONG && SUPPORT_LONG_ADD) */
+
+#if !(SUPPORT_LONG && SUPPORT_LONG_MUL)
+ {
+ ICMD_LMUL,
+ 0,
+ BUILTIN_lmul,
+ NULL,
+ NULL,
+ "lmul",
+ "(JJ)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_I2F)
+ {
+ ICMD_I2F,
+ 0,
+ BUILTIN_i2f,
+ NULL,
+ NULL,
+ "i2f",
+ "(I)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_I2D)
+ {
+ ICMD_I2D,
+ 0,
+ BUILTIN_i2d,
+ NULL,
+ NULL,
+ "i2d",
+ "(I)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_LONG && SUPPORT_FLOAT && SUPPORT_L2F)
+ {
+ ICMD_L2F,
+ 0,
+ BUILTIN_l2f,
+ NULL,
+ NULL,
+ "l2f",
+ "(J)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_LONG && SUPPORT_DOUBLE && SUPPORT_L2D)
+ {
+ ICMD_L2D,
+ 0,
+ BUILTIN_l2d,
+ NULL,
+ NULL,
+ "l2d",
+ "(J)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_F2I)
+ {
+ ICMD_F2I,
+ 0,
+ BUILTIN_f2i,
+ NULL,
+ NULL,
+ "f2i",
+ "(F)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_FLOAT && SUPPORT_LONG && SUPPORT_F2L)
+ {
+ ICMD_F2L,
+ 0,
+ BUILTIN_f2l,
+ NULL,
+ NULL,
+ "f2l",
+ "(F)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_D2I)
+ {
+ ICMD_D2I,
+ 0,
+ BUILTIN_d2i,
+ NULL,
+ NULL,
+ "d2i",
+ "(D)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+#if !(SUPPORT_DOUBLE && SUPPORT_LONG && SUPPORT_D2L)
+ {
+ ICMD_D2L,
+ 0,
+ BUILTIN_d2l,
+ NULL,
+ NULL,
+ "d2l",
+ "(D)J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+
+ /* float functions ********************************************************/
+
+#if !SUPPORT_FLOAT
+ {
+ ICMD_FADD,
+ 0,
+ BUILTIN_fadd,
+ NULL,
+ NULL,
+ "fadd",
+ "(FF)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_FSUB,
+ 0,
+ BUILTIN_fsub,
+ NULL,
+ NULL,
+ "fsub",
+ "(FF)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_FMUL,
+ 0,
+ BUILTIN_fmul,
+ NULL,
+ NULL,
+ "fmul",
+ "(FF)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_FDIV,
+ 0,
+ BUILTIN_fdiv,
+ NULL,
+ NULL,
+ "fdiv",
+ "(FF)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_FNEG,
+ 0,
+ BUILTIN_fneg,
+ NULL,
+ NULL,
+ "fneg",
+ "(F)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !SUPPORT_FLOAT */
+
+#if !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP
+ {
+ ICMD_FCMPL,
+ 0,
+ BUILTIN_fcmpl,
+ NULL,
+ NULL,
+ "fcmpl",
+ "(FF)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_FCMPG,
+ 0,
+ BUILTIN_fcmpg,
+ NULL,
+ NULL,
+ "fcmpg",
+ "(FF)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !SUPPORT_FLOAT || !SUPPORT_FLOAT_CMP */
+
+
+ /* double functions *******************************************************/
+
+#if !SUPPORT_DOUBLE
+ {
+ ICMD_DADD,
+ 0,
+ BUILTIN_dadd,
+ NULL,
+ NULL,
+ "dadd",
+ "(DD)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_DSUB,
+ 0,
+ BUILTIN_dsub,
+ NULL,
+ NULL,
+ "dsub",
+ "(DD)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_DMUL,
+ 0,
+ BUILTIN_dmul,
+ NULL,
+ NULL,
+ "dmul",
+ "(DD)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_DDIV,
+ 0,
+ BUILTIN_ddiv,
+ NULL,
+ NULL,
+ "ddiv",
+ "(DD)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_DNEG,
+ 0,
+ BUILTIN_dneg,
+ NULL,
+ NULL,
+ "dneg",
+ "(D)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !SUPPORT_DOUBLE */
+
+#if !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP
+ {
+ ICMD_DCMPL,
+ 0,
+ BUILTIN_dcmpl,
+ NULL,
+ NULL,
+ "dcmpl",
+ "(DD)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_DCMPG,
+ 0,
+ BUILTIN_dcmpg,
+ NULL,
+ NULL,
+ "dcmpg",
+ "(DD)I",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !SUPPORT_DOUBLE || !SUPPORT_DOUBLE_CMP */
+
+
+ /* float/double functions *************************************************/
+
+#if !(SUPPORT_FLOAT && SUPPORT_DOUBLE)
+ {
+ ICMD_F2D,
+ 0,
+ BUILTIN_f2d,
+ NULL,
+ NULL,
+ "f2d",
+ "(F)D",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+ {
+ ICMD_D2F,
+ 0,
+ BUILTIN_d2f,
+ NULL,
+ NULL,
+ "d2f",
+ "(D)F",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif /* !(SUPPORT_FLOAT && SUPPORT_DOUBLE) */
+
+
+ /* prevent a compiler warning if everything is supported (e.g. i386) */
+
+ {
+ 255,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+};
+
+
+/* automatically replaced functions *******************************************/
+
+static builtintable_entry builtintable_function[] = {
+#if defined(ENABLE_JIT)
+
+ /* java.lang.VMSystem.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V STATIC NATIVE */
+
+ {
+ ICMD_BUILTIN,
+ BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
+ BUILTIN_arraycopy,
+ NULL,
+ "java/lang/VMSystem",
+ "arraycopy",
+ "(Ljava/lang/Object;ILjava/lang/Object;II)V",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+
+ /* java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V PUBLIC STATIC */
+
+#if 0
+ /* We disable this one until we have a fix for the stacktrace
+ issue. */
+
+ {
+ ICMD_BUILTIN,
+ BUILTINTABLE_FLAG_STUB | BUILTINTABLE_FLAG_EXCEPTION,
+ BUILTIN_arraycopy,
+ NULL,
+ "java/lang/System",
+ "arraycopy",
+ "(Ljava/lang/Object;ILjava/lang/Object;II)V",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+#endif
+
+ /* java.lang.VMSystem.currentTimeMillis()J PUBLIC STATIC */
+
+ {
+ ICMD_BUILTIN,
+ 0,
+ BUILTIN_currenttimemillis,
+ NULL,
+ "java/lang/VMSystem",
+ "currentTimeMillis",
+ "()J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+
+ /* java.lang.System.currentTimeMillis()J PUBLIC STATIC */
+
+ {
+ ICMD_BUILTIN,
+ 0,
+ BUILTIN_currenttimemillis,
+ NULL,
+ "java/lang/System",
+ "currentTimeMillis",
+ "()J",
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ },
+
+#endif /* defined(ENABLE_JIT) */
+
+ /* stop entry */
+
+ {
+ 255,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/stack.h"
/* src/vm/jit/cfg.h - build a control-flow graph
- 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,
- 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.
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* defines ********************************************************************/
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool cfg_build(jitdata *jd);
void cfg_add_root(jitdata *jd);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _CFG_H */
+++ /dev/null
-/* src/vm/jit/code.c - codeinfo struct for representing compiled 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 <assert.h>
-#include <stdint.h>
-
-#include "arch.h"
-
-#include "mm/memory.h"
-
-#include "vm/options.h"
-#include "vm/vm.hpp"
-
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jitcache.hpp"
-#include "vm/jit/methodtree.h"
-#include "vm/jit/patcher-common.h"
-
-
-/* code_init *******************************************************************
-
- Initialize the code-subsystem.
-
-*******************************************************************************/
-
-void code_init(void)
-{
- /* Check if offset of codeinfo.m == 0 (see comment in code.h). */
-
- if (OFFSET(codeinfo, m) != 0)
- vm_abort("code_init: offset of codeinfo.m != 0: %d != 0", OFFSET(codeinfo, m));
-}
-
-
-/* code_codeinfo_new ***********************************************************
-
- Create a new codeinfo for the given method.
-
- IN:
- m................method to create a new codeinfo for
-
- The following fields are set in codeinfo:
- m
- patchers
- cachedrefs
-
- RETURN VALUE:
- a new, initialized codeinfo, or
- NULL if an exception occurred.
-
-*******************************************************************************/
-
-codeinfo *code_codeinfo_new(methodinfo *m)
-{
- codeinfo *code;
-
- code = NEW(codeinfo);
-
- code->m = m;
-
- patcher_list_create(code);
-
-#if defined (ENABLE_JITCACHE)
- jitcache_list_create(code);
-#endif
-
-#if defined (ENABLE_STATISTICS)
- if (opt_stat)
- size_codeinfo += sizeof(codeinfo);
-#endif
-
- return code;
-}
-
-
-/* code_find_codeinfo_for_pc ***************************************************
-
- Return the codeinfo for the compilation unit that contains the
- given PC.
-
- ARGUMENTS:
- pc...............machine code position
-
- RETURN VALUE:
- the codeinfo * for the given PC
-
-*******************************************************************************/
-
-codeinfo *code_find_codeinfo_for_pc(void *pc)
-{
- void *pv;
-
- pv = methodtree_find(pc);
-
- return code_get_codeinfo_for_pv(pv);
-}
-
-
-/* code_find_codeinfo_for_pc ***************************************************
-
- Return the codeinfo for the compilation unit that contains the
- given PC. This method does not check the return value and is used
- by the GC.
-
- IN:
- pc...............machine code position
-
- RETURN VALUE:
- the codeinfo * for the given PC, or NULL
-
-*******************************************************************************/
-
-codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc)
-{
- void *pv;
-
- pv = methodtree_find_nocheck(pc);
-
- if (pv == NULL)
- return NULL;
-
- return code_get_codeinfo_for_pv(pv);
-}
-
-
-/* code_get_methodinfo_for_pv **************************************************
-
- Return the methodinfo for the given PV.
-
- IN:
- pv...............PV
-
- RETURN VALUE:
- the methodinfo *
-
-*******************************************************************************/
-
-methodinfo *code_get_methodinfo_for_pv(void *pv)
-{
- codeinfo *code;
-
- code = code_get_codeinfo_for_pv(pv);
-
- /* This is the case for asm_vm_call_method. */
-
- if (code == NULL)
- return NULL;
-
- return code->m;
-}
-
-
-/* code_get_sync_slot_count ****************************************************
-
- Return the number of stack slots used for storing the synchronized object
- (and the return value around lock_monitor_exit calls) by the given code.
-
- IN:
- code.............the codeinfo of the code in question
- (must be != NULL)
-
- RETURN VALUE:
- the number of stack slots used for synchronization
-
-*******************************************************************************/
-
-#if defined(ENABLE_REPLACEMENT)
-int code_get_sync_slot_count(codeinfo *code)
-{
-#ifdef ENABLE_THREADS
- int count;
-
- assert(code);
-
- if (!checksync)
- return 0;
-
- if (!code_is_synchronized(code))
- return 0;
-
- count = 1;
-
-#ifdef HAS_4BYTE_STACKSLOT
- /* long and double need 2 4-byte slots */
- if (IS_2_WORD_TYPE(code->m->parseddesc->returntype.type))
- count++;
-#endif
-
-#if defined(__POWERPC__)
- /* powerpc needs an extra slot */
- count++;
-#endif
-
- return count;
-
-#else /* !ENABLE_THREADS */
-
- return 0;
-
-#endif /* ENABLE_THREADS */
-}
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-
-/* code_codeinfo_free **********************************************************
-
- Free the memory used by a codeinfo.
-
- IN:
- code.............the codeinfo to free
-
-*******************************************************************************/
-
-void code_codeinfo_free(codeinfo *code)
-{
- if (code == NULL)
- return;
-
- if (code->mcode != NULL)
- CFREE((void *) (ptrint) code->mcode, code->mcodelength);
-
- patcher_list_free(code);
-
-#if defined(ENABLE_JITCACHE)
- jitcache_list_free(code);
-#endif
-
-#if defined(ENABLE_REPLACEMENT)
- replace_free_replacement_points(code);
-#endif
-
- FREE(code, codeinfo);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_codeinfo -= sizeof(codeinfo);
-#endif
-}
-
-
-/* code_free_code_of_method ****************************************************
-
- Free all codeinfos of the given method
-
- IN:
- m................the method of which the codeinfos are to be freed
-
-*******************************************************************************/
-
-void code_free_code_of_method(methodinfo *m)
-{
- codeinfo *nextcode;
- codeinfo *code;
-
- if (!m)
- return;
-
- nextcode = m->code;
- while (nextcode) {
- code = nextcode;
- nextcode = code->prev;
- code_codeinfo_free(code);
- }
-
- m->code = 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:
- * vim:noexpandtab:sw=4:ts=4:
- */
--- /dev/null
+/* src/vm/jit/code.cpp - codeinfo struct for representing compiled 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 <assert.h>
+#include <stdint.h>
+
+#include "arch.h"
+
+#include "mm/memory.h"
+
+#include "vm/options.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jitcache.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/methodtree.h"
+
+
+/* code_init *******************************************************************
+
+ Initialize the code-subsystem.
+
+*******************************************************************************/
+
+void code_init(void)
+{
+ /* Check if offset of codeinfo.m == 0 (see comment in code.h). */
+
+ if (OFFSET(codeinfo, m) != 0)
+ vm_abort("code_init: offset of codeinfo.m != 0: %d != 0", OFFSET(codeinfo, m));
+}
+
+
+/* code_codeinfo_new ***********************************************************
+
+ Create a new codeinfo for the given method.
+
+ IN:
+ m................method to create a new codeinfo for
+
+ The following fields are set in codeinfo:
+ m
+ patchers
+ cachedrefs
+
+ RETURN VALUE:
+ a new, initialized codeinfo, or
+ NULL if an exception occurred.
+
+*******************************************************************************/
+
+codeinfo *code_codeinfo_new(methodinfo *m)
+{
+ codeinfo *code;
+
+ code = NEW(codeinfo);
+
+ code->m = m;
+
+ patcher_list_create(code);
+
+#if defined (ENABLE_JITCACHE)
+ jitcache_list_create(code);
+#endif
+
+#if defined (ENABLE_STATISTICS)
+ if (opt_stat)
+ size_codeinfo += sizeof(codeinfo);
+#endif
+
+ return code;
+}
+
+
+/* code_find_codeinfo_for_pc ***************************************************
+
+ Return the codeinfo for the compilation unit that contains the
+ given PC.
+
+ ARGUMENTS:
+ pc...............machine code position
+
+ RETURN VALUE:
+ the codeinfo * for the given PC
+
+*******************************************************************************/
+
+codeinfo *code_find_codeinfo_for_pc(void *pc)
+{
+ void *pv;
+
+ pv = methodtree_find(pc);
+
+ return code_get_codeinfo_for_pv(pv);
+}
+
+
+/* code_find_codeinfo_for_pc ***************************************************
+
+ Return the codeinfo for the compilation unit that contains the
+ given PC. This method does not check the return value and is used
+ by the GC.
+
+ IN:
+ pc...............machine code position
+
+ RETURN VALUE:
+ the codeinfo * for the given PC, or NULL
+
+*******************************************************************************/
+
+codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc)
+{
+ void *pv;
+
+ pv = methodtree_find_nocheck(pc);
+
+ if (pv == NULL)
+ return NULL;
+
+ return code_get_codeinfo_for_pv(pv);
+}
+
+
+/* code_get_methodinfo_for_pv **************************************************
+
+ Return the methodinfo for the given PV.
+
+ IN:
+ pv...............PV
+
+ RETURN VALUE:
+ the methodinfo *
+
+*******************************************************************************/
+
+methodinfo *code_get_methodinfo_for_pv(void *pv)
+{
+ codeinfo *code;
+
+ code = code_get_codeinfo_for_pv(pv);
+
+ /* This is the case for asm_vm_call_method. */
+
+ if (code == NULL)
+ return NULL;
+
+ return code->m;
+}
+
+
+/* code_get_sync_slot_count ****************************************************
+
+ Return the number of stack slots used for storing the synchronized object
+ (and the return value around lock_monitor_exit calls) by the given code.
+
+ IN:
+ code.............the codeinfo of the code in question
+ (must be != NULL)
+
+ RETURN VALUE:
+ the number of stack slots used for synchronization
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+int code_get_sync_slot_count(codeinfo *code)
+{
+#ifdef ENABLE_THREADS
+ int count;
+
+ assert(code);
+
+ if (!checksync)
+ return 0;
+
+ if (!code_is_synchronized(code))
+ return 0;
+
+ count = 1;
+
+#if defined(__POWERPC__)
+ /* powerpc needs an extra slot */
+ count++;
+#endif
+
+ return count;
+
+#else /* !ENABLE_THREADS */
+
+ return 0;
+
+#endif /* ENABLE_THREADS */
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* code_codeinfo_free **********************************************************
+
+ Free the memory used by a codeinfo.
+
+ IN:
+ code.............the codeinfo to free
+
+*******************************************************************************/
+
+void code_codeinfo_free(codeinfo *code)
+{
+ if (code == NULL)
+ return;
+
+ if (code->mcode != NULL)
+ CFREE((void *) (ptrint) code->mcode, code->mcodelength);
+
+ patcher_list_free(code);
+
+#if defined(ENABLE_JITCACHE)
+ jitcache_list_free(code);
+#endif
+
+#if defined(ENABLE_REPLACEMENT)
+ replace_free_replacement_points(code);
+#endif
+
+ FREE(code, codeinfo);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_codeinfo -= sizeof(codeinfo);
+#endif
+}
+
+
+/* code_free_code_of_method ****************************************************
+
+ Free all codeinfos of the given method
+
+ IN:
+ m................the method of which the codeinfos are to be freed
+
+*******************************************************************************/
+
+void code_free_code_of_method(methodinfo *m)
+{
+ codeinfo *nextcode;
+ codeinfo *code;
+
+ if (!m)
+ return;
+
+ nextcode = m->code;
+ while (nextcode) {
+ code = nextcode;
+ nextcode = code->prev;
+ code_codeinfo_free(code);
+ }
+
+ m->code = 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+++ /dev/null
-/* src/vm/jit/code.h - codeinfo struct for representing compiled 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 _CODE_H
-#define _CODE_H
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#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"
-
-
-/* constants ******************************************************************/
-
-#define CODE_FLAG_INVALID 0x0001
-#define CODE_FLAG_LEAFMETHOD 0x0002
-#define CODE_FLAG_SYNCHRONIZED 0x0004
-#define CODE_FLAG_TLH 0x0008
-
-
-/* codeinfo *******************************************************************
-
- A codeinfo represents a particular realization of a method in
- machine code.
-
- ATTENTION: The methodinfo entry in the code-structure MUST have the
- offset 0, otherwise we have a problem in our compiler stub. This is
- checked with an assert in code_init().
-
-*******************************************************************************/
-
-struct codeinfo {
- methodinfo *m; /* method this is a realization of */
- codeinfo *prev; /* previous codeinfo of this method */
-
- uint32_t flags; /* OR of CODE_FLAG_ constants */
-
- u1 optlevel; /* optimization level of this code */
- s4 basicblockcount; /* number of basic blocks */
-
- int32_t synchronizedoffset; /* stack offset of synchronized obj. */
-
- /* machine code */
- u1 *mcode; /* pointer to machine code */
- u1 *entrypoint; /* machine code entry point */
- s4 mcodelength; /* length of generated machine code */
-
- exceptiontable_t *exceptiontable;
- linenumbertable_t *linenumbertable;
-
- /* patcher list */
- list_t *patchers;
-
-#if defined (ENABLE_JITCACHE)
- list_t *cachedrefs;
-#endif
-
- /* replacement */
- s4 stackframesize; /* size of the stackframe in slots */
-
-#if defined(ENABLE_REPLACEMENT)
- rplpoint *rplpoints; /* replacement points */
- rplalloc *regalloc; /* register allocation info */
- s4 rplpointcount; /* number of replacement points */
- s4 globalcount; /* number of global allocations */
- s4 regalloccount; /* number of total allocations */
- s4 memuse; /* number of arg + local slots */
- u1 savedintcount; /* number of callee saved int regs */
- u1 savedfltcount; /* number of callee saved flt regs */
-# if defined(HAS_ADDRESS_REGISTER_FILE)
- u1 savedadrcount; /* number of callee saved adr regs */
-# endif
- u1 *savedmcode; /* saved code under patches */
-#endif
-
-#if defined(ENABLE_PROFILING)
- u4 frequency; /* number of method invocations */
- u4 *bbfrequency;
- s8 cycles; /* number of cpu cycles */
-#endif
-};
-
-
-/* inline functions ***********************************************************/
-
-/* code_xxx_invalid ************************************************************
-
- Functions for CODE_FLAG_INVALID.
-
-*******************************************************************************/
-
-inline static int code_is_invalid(codeinfo *code)
-{
- return (code->flags & CODE_FLAG_INVALID);
-}
-
-inline static void code_flag_invalid(codeinfo *code)
-{
- code->flags |= CODE_FLAG_INVALID;
-}
-
-inline static void code_unflag_invalid(codeinfo *code)
-{
- code->flags &= ~CODE_FLAG_INVALID;
-}
-
-
-/* code_xxx_leafmethod *********************************************************
-
- Functions for CODE_FLAG_LEAFMETHOD.
-
-*******************************************************************************/
-
-inline static int code_is_leafmethod(codeinfo *code)
-{
- return (code->flags & CODE_FLAG_LEAFMETHOD);
-}
-
-inline static void code_flag_leafmethod(codeinfo *code)
-{
- code->flags |= CODE_FLAG_LEAFMETHOD;
-}
-
-inline static void code_unflag_leafmethod(codeinfo *code)
-{
- code->flags &= ~CODE_FLAG_LEAFMETHOD;
-}
-
-
-/* code_xxx_synchronized *******************************************************
-
- Functions for CODE_FLAG_SYNCHRONIZED.
-
-*******************************************************************************/
-
-inline static int code_is_synchronized(codeinfo *code)
-{
- return (code->flags & CODE_FLAG_SYNCHRONIZED);
-}
-
-inline static void code_flag_synchronized(codeinfo *code)
-{
- code->flags |= CODE_FLAG_SYNCHRONIZED;
-}
-
-inline static void code_unflag_synchronized(codeinfo *code)
-{
- code->flags &= ~CODE_FLAG_SYNCHRONIZED;
-}
-
-
-/* code_get_codeinfo_for_pv ****************************************************
-
- Return the codeinfo for the given PV.
-
- IN:
- pv...............PV
-
- RETURN VALUE:
- the codeinfo *
-
-*******************************************************************************/
-
-inline static codeinfo *code_get_codeinfo_for_pv(void *pv)
-{
- codeinfo *code;
-
- assert(pv != NULL);
-
- code = *((codeinfo **) (((uintptr_t) pv) + CodeinfoPointer));
-
- return code;
-}
-
-
-/* function prototypes ********************************************************/
-
-void code_init(void);
-
-codeinfo *code_codeinfo_new(methodinfo *m);
-void code_codeinfo_free(codeinfo *code);
-
-codeinfo *code_find_codeinfo_for_pc(void *pc);
-codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc);
-
-methodinfo *code_get_methodinfo_for_pv(void *pv);
-
-#if defined(ENABLE_REPLACEMENT)
-int code_get_sync_slot_count(codeinfo *code);
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-void code_free_code_of_method(methodinfo *m);
-
-#endif /* _CODE_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/code.hpp - codeinfo struct for representing compiled 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 _CODE_HPP
+#define _CODE_HPP
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/global.h"
+#include "vm/method.h"
+
+#include "vm/jit/exceptiontable.h"
+#if defined (ENABLE_JITCACHE)
+#include "vm/jit/jitcache.hpp"
+#endif
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
+
+
+/* constants ******************************************************************/
+
+#define CODE_FLAG_INVALID 0x0001
+#define CODE_FLAG_LEAFMETHOD 0x0002
+#define CODE_FLAG_SYNCHRONIZED 0x0004
+#define CODE_FLAG_TLH 0x0008
+
+
+/* codeinfo *******************************************************************
+
+ A codeinfo represents a particular realization of a method in
+ machine code.
+
+ ATTENTION: The methodinfo entry in the code-structure MUST have the
+ offset 0, otherwise we have a problem in our compiler stub. This is
+ checked with an assert in code_init().
+
+*******************************************************************************/
+
+struct codeinfo {
+ methodinfo *m; /* method this is a realization of */
+ codeinfo *prev; /* previous codeinfo of this method */
+
+ uint32_t flags; /* OR of CODE_FLAG_ constants */
+
+ u1 optlevel; /* optimization level of this code */
+ s4 basicblockcount; /* number of basic blocks */
+
+ int32_t synchronizedoffset; /* stack offset of synchronized obj. */
+
+ /* machine code */
+ u1 *mcode; /* pointer to machine code */
+ u1 *entrypoint; /* machine code entry point */
+ s4 mcodelength; /* length of generated machine code */
+
+ exceptiontable_t *exceptiontable;
+ LinenumberTable* linenumbertable;
+
+ /* patcher list */
+#ifdef __cplusplus
+ List<patchref_t>* patchers;
+#else
+ List* patchers;
+#endif
+
+#if defined (ENABLE_JITCACHE)
+#ifdef __cplusplus
+ List<cachedref_t>* cachedrefs;
+#else
+ List* cachedrefs;
+#endif
+#endif
+
+ /* replacement */
+ s4 stackframesize; /* size of the stackframe in slots */
+
+#if defined(ENABLE_REPLACEMENT)
+ rplpoint *rplpoints; /* replacement points */
+ rplalloc *regalloc; /* register allocation info */
+ s4 rplpointcount; /* number of replacement points */
+ s4 globalcount; /* number of global allocations */
+ s4 regalloccount; /* number of total allocations */
+ s4 memuse; /* number of arg + local slots */
+ u1 savedintcount; /* number of callee saved int regs */
+ u1 savedfltcount; /* number of callee saved flt regs */
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+ u1 savedadrcount; /* number of callee saved adr regs */
+# endif
+ u1 *savedmcode; /* saved code under patches */
+#endif
+
+#if defined(ENABLE_PROFILING)
+ u4 frequency; /* number of method invocations */
+ u4 *bbfrequency;
+ s8 cycles; /* number of cpu cycles */
+#endif
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* inline functions ***********************************************************/
+
+/* code_xxx_invalid ************************************************************
+
+ Functions for CODE_FLAG_INVALID.
+
+*******************************************************************************/
+
+inline static int code_is_invalid(codeinfo *code)
+{
+ return (code->flags & CODE_FLAG_INVALID);
+}
+
+inline static void code_flag_invalid(codeinfo *code)
+{
+ code->flags |= CODE_FLAG_INVALID;
+}
+
+inline static void code_unflag_invalid(codeinfo *code)
+{
+ code->flags &= ~CODE_FLAG_INVALID;
+}
+
+
+/* code_xxx_leafmethod *********************************************************
+
+ Functions for CODE_FLAG_LEAFMETHOD.
+
+*******************************************************************************/
+
+inline static int code_is_leafmethod(codeinfo *code)
+{
+ return (code->flags & CODE_FLAG_LEAFMETHOD);
+}
+
+inline static void code_flag_leafmethod(codeinfo *code)
+{
+ code->flags |= CODE_FLAG_LEAFMETHOD;
+}
+
+inline static void code_unflag_leafmethod(codeinfo *code)
+{
+ code->flags &= ~CODE_FLAG_LEAFMETHOD;
+}
+
+
+/* code_xxx_synchronized *******************************************************
+
+ Functions for CODE_FLAG_SYNCHRONIZED.
+
+*******************************************************************************/
+
+inline static int code_is_synchronized(codeinfo *code)
+{
+ return (code->flags & CODE_FLAG_SYNCHRONIZED);
+}
+
+inline static void code_flag_synchronized(codeinfo *code)
+{
+ code->flags |= CODE_FLAG_SYNCHRONIZED;
+}
+
+inline static void code_unflag_synchronized(codeinfo *code)
+{
+ code->flags &= ~CODE_FLAG_SYNCHRONIZED;
+}
+
+
+/* code_get_codeinfo_for_pv ****************************************************
+
+ Return the codeinfo for the given PV.
+
+ IN:
+ pv...............PV
+
+ RETURN VALUE:
+ the codeinfo *
+
+*******************************************************************************/
+
+inline static codeinfo *code_get_codeinfo_for_pv(void *pv)
+{
+ codeinfo *code;
+
+ assert(pv != NULL);
+
+ code = *((codeinfo **) (((uintptr_t) pv) + CodeinfoPointer));
+
+ return code;
+}
+
+
+/* function prototypes ********************************************************/
+
+void code_init(void);
+
+codeinfo *code_codeinfo_new(methodinfo *m);
+void code_codeinfo_free(codeinfo *code);
+
+codeinfo *code_find_codeinfo_for_pc(void *pc);
+codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc);
+
+methodinfo *code_get_methodinfo_for_pv(void *pv);
+
+#if defined(ENABLE_REPLACEMENT)
+int code_get_sync_slot_count(codeinfo *code);
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+void code_free_code_of_method(methodinfo *m);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CODE_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/codegen-common.c - architecture independent code generator stuff
-
- 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.
-
- All functions assume the following code area / data area layout:
-
- +-----------+
- | |
- | code area | code area grows to higher addresses
- | |
- +-----------+ <-- start of procedure
- | |
- | data area | data area grows to lower addresses
- | |
- +-----------+
-
- The functions first write into a temporary code/data area allocated by
- "codegen_init". "codegen_finish" copies the code and data area into permanent
- memory. All functions writing values into the data area return the offset
- relative the begin of the code area (start of procedure).
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "vm/jit/jitcache.hpp"
-
-#include "vm/types.h"
-
-#include "codegen.h"
-#include "md.h"
-#include "md-abi.h"
-
-#include "mm/memory.h"
-
-#include "toolbox/avl.h"
-#include "toolbox/list.h"
-#include "toolbox/logging.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
-
-#include "threads/thread.hpp"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.hpp"
-#include "vm/method.h"
-#include "vm/options.h"
-#include "vm/string.hpp"
-
-# include "vm/statistics.h"
-
-
-#include "vm/jit/abi.h"
-#include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
-
-#if defined(ENABLE_DISASSEMBLER)
-# include "vm/jit/disass.h"
-#endif
-
-#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/methodheader.h"
-#include "vm/jit/methodtree.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
-#if defined(ENABLE_SSA)
-# include "vm/jit/optimizing/lsra.h"
-# include "vm/jit/optimizing/ssa.h"
-#endif
-#include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trace.hpp"
-
-#if defined(ENABLE_INTRP)
-#include "vm/jit/intrp/intrp.h"
-#endif
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-#include "show.h"
-
-
-/* codegen_init ****************************************************************
-
- TODO
-
-*******************************************************************************/
-
-void codegen_init(void)
-{
-}
-
-
-/* codegen_setup ***************************************************************
-
- Allocates and initialises code area, data area and references.
-
-*******************************************************************************/
-
-void codegen_setup(jitdata *jd)
-{
- methodinfo *m;
- codegendata *cd;
-
- /* get required compiler data */
-
- m = jd->m;
- cd = jd->cd;
-
- /* initialize members */
-
- cd->flags = 0;
-
- cd->mcodebase = DMNEW(u1, MCODEINITSIZE);
- cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
- cd->mcodesize = MCODEINITSIZE;
-
- /* initialize mcode variables */
-
- cd->mcodeptr = cd->mcodebase;
- cd->lastmcodeptr = cd->mcodebase;
-
-#if defined(ENABLE_INTRP)
- /* native dynamic superinstructions variables */
-
- if (opt_intrp) {
- cd->ncodebase = DMNEW(u1, NCODEINITSIZE);
- cd->ncodesize = NCODEINITSIZE;
-
- /* initialize ncode variables */
-
- cd->ncodeptr = cd->ncodebase;
-
- cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
- cd->superstarts = NULL;
- }
-#endif
-
- cd->dseg = NULL;
- cd->dseglen = 0;
-
- cd->jumpreferences = NULL;
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
- cd->datareferences = NULL;
-#endif
-
- cd->brancheslabel = list_create_dump(OFFSET(branch_label_ref_t, linkage));
- cd->linenumbers = list_create_dump(OFFSET(linenumbertable_list_entry_t, linkage));
-}
-
-
-/* codegen_reset ***************************************************************
-
- Resets the codegen data structure so we can recompile the method.
-
-*******************************************************************************/
-
-static void codegen_reset(jitdata *jd)
-{
- codeinfo *code;
- codegendata *cd;
- basicblock *bptr;
-
- /* get required compiler data */
-
- code = jd->code;
- cd = jd->cd;
-
- /* reset error flag */
-
- cd->flags &= ~CODEGENDATA_FLAG_ERROR;
-
- /* reset some members, we reuse the code memory already allocated
- as this should have almost the correct size */
-
- cd->mcodeptr = cd->mcodebase;
- cd->lastmcodeptr = cd->mcodebase;
-
- cd->dseg = NULL;
- cd->dseglen = 0;
-
- cd->jumpreferences = NULL;
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
- cd->datareferences = NULL;
-#endif
-
- cd->brancheslabel = list_create_dump(OFFSET(branch_label_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
- basic blocks as they will definitely change. */
-
- for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
- bptr->mpc = -1;
- bptr->branchrefs = NULL;
- }
-
- /* We need to clear all the patcher references from the codeinfo
- since they all will be regenerated */
-
- patcher_list_reset(code);
-
-#if defined(ENABLE_REPLACEMENT)
- code->rplpoints = NULL;
- code->rplpointcount = 0;
- code->regalloc = NULL;
- code->regalloccount = 0;
- code->globalcount = 0;
-#endif
-}
-
-
-/* codegen_generate ************************************************************
-
- Generates the code for the currently compiled method.
-
-*******************************************************************************/
-
-bool codegen_generate(jitdata *jd)
-{
- codegendata *cd;
-
- /* get required compiler data */
-
- cd = jd->cd;
-
- /* call the machine-dependent code generation function */
-
- if (!codegen_emit(jd))
- return false;
-
- /* check for an error */
-
- if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
- /* check for long-branches flag, if it is set we recompile the
- method */
-
-#if !defined(NDEBUG)
- if (compileverbose)
- log_message_method("Re-generating code: ", jd->m);
-#endif
-
- /* XXX maybe we should tag long-branches-methods for recompilation */
-
- if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
- /* we have to reset the codegendata structure first */
-
- codegen_reset(jd);
-
- /* and restart the compiler run */
-
- if (!codegen_emit(jd))
- return false;
- }
- else {
- vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
- }
-
-#if !defined(NDEBUG)
- if (compileverbose)
- log_message_method("Re-generating code done: ", jd->m);
-#endif
- }
-
- /* reallocate the memory and finish the code generation */
-
- codegen_finish(jd);
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* codegen_close ***************************************************************
-
- TODO
-
-*******************************************************************************/
-
-void codegen_close(void)
-{
- /* TODO: release avl tree on i386 and x86_64 */
-}
-
-
-/* codegen_increase ************************************************************
-
- Doubles code area.
-
-*******************************************************************************/
-
-void codegen_increase(codegendata *cd)
-{
- u1 *oldmcodebase;
-
- /* save old mcodebase pointer */
-
- oldmcodebase = cd->mcodebase;
-
- /* reallocate to new, doubled memory */
-
- cd->mcodebase = DMREALLOC(cd->mcodebase,
- u1,
- cd->mcodesize,
- cd->mcodesize * 2);
- cd->mcodesize *= 2;
- cd->mcodeend = cd->mcodebase + cd->mcodesize;
-
- /* set new mcodeptr */
-
- cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
-
-#if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
- || defined(__SPARC_64__)
- /* adjust the pointer to the last patcher position */
-
- if (cd->lastmcodeptr != NULL)
- cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
-#endif
-}
-
-
-/* codegen_ncode_increase ******************************************************
-
- Doubles code area.
-
-*******************************************************************************/
-
-#if defined(ENABLE_INTRP)
-u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
-{
- u1 *oldncodebase;
-
- /* save old ncodebase pointer */
-
- oldncodebase = cd->ncodebase;
-
- /* reallocate to new, doubled memory */
-
- cd->ncodebase = DMREALLOC(cd->ncodebase,
- u1,
- cd->ncodesize,
- cd->ncodesize * 2);
- cd->ncodesize *= 2;
-
- /* return the new ncodeptr */
-
- return (cd->ncodebase + (ncodeptr - oldncodebase));
-}
-#endif
-
-
-/* codegen_add_branch_ref ******************************************************
-
- Prepends an branch to the list.
-
-*******************************************************************************/
-
-void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
-{
- branchref *br;
- s4 branchmpc;
-
- STATISTICS(count_branches_unresolved++);
-
- /* calculate the mpc of the branch instruction */
-
- branchmpc = cd->mcodeptr - cd->mcodebase;
-
- br = DNEW(branchref);
-
- br->branchmpc = branchmpc;
- br->condition = condition;
- br->reg = reg;
- br->options = options;
- br->next = target->branchrefs;
-
- target->branchrefs = br;
-}
-
-
-/* codegen_resolve_branchrefs **************************************************
-
- Resolves and patches the branch references of a given basic block.
-
-*******************************************************************************/
-
-void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
-{
- branchref *br;
- u1 *mcodeptr;
-
- /* Save the mcodeptr because in the branch emitting functions
- we generate code somewhere inside already generated code,
- but we're still in the actual code generation phase. */
-
- mcodeptr = cd->mcodeptr;
-
- /* just to make sure */
-
- assert(bptr->mpc >= 0);
-
- for (br = bptr->branchrefs; br != NULL; br = br->next) {
- /* temporary set the mcodeptr */
-
- cd->mcodeptr = cd->mcodebase + br->branchmpc;
-
- /* emit_bccz and emit_branch emit the correct code, even if we
- pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
-
- emit_bccz(cd, bptr, br->condition, br->reg, br->options);
- }
-
- /* restore mcodeptr */
-
- cd->mcodeptr = mcodeptr;
-}
-
-
-/* codegen_branch_label_add ****************************************************
-
- Append an branch to the label-branch list.
-
-*******************************************************************************/
-
-void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
-{
- list_t *l;
- branch_label_ref_t *br;
- s4 mpc;
-
- /* Get the label list. */
-
- l = cd->brancheslabel;
-
- /* calculate the current mpc */
-
- mpc = cd->mcodeptr - cd->mcodebase;
-
- br = DNEW(branch_label_ref_t);
-
- br->mpc = mpc;
- br->label = label;
- br->condition = condition;
- br->reg = reg;
- br->options = options;
-
- /* Add the branch to the list. */
-
- list_add_last(l, br);
-}
-
-
-/* codegen_set_replacement_point_notrap ****************************************
-
- Record the position of a non-trappable replacement point.
-
-*******************************************************************************/
-
-#if defined(ENABLE_REPLACEMENT)
-#if !defined(NDEBUG)
-void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
-#else
-void codegen_set_replacement_point_notrap(codegendata *cd)
-#endif
-{
- assert(cd->replacementpoint);
- assert(cd->replacementpoint->type == type);
- assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
-
- cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
-
- cd->replacementpoint++;
-}
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-
-/* codegen_set_replacement_point ***********************************************
-
- Record the position of a trappable replacement point.
-
-*******************************************************************************/
-
-#if defined(ENABLE_REPLACEMENT)
-#if !defined(NDEBUG)
-void codegen_set_replacement_point(codegendata *cd, s4 type)
-#else
-void codegen_set_replacement_point(codegendata *cd)
-#endif
-{
- assert(cd->replacementpoint);
- assert(cd->replacementpoint->type == type);
- assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
-
- cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
-
- cd->replacementpoint++;
-
-#if !defined(NDEBUG)
- /* XXX actually we should use an own REPLACEMENT_NOPS here! */
- if (opt_TestReplacement)
- PATCHER_NOPS;
-#endif
-
- /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
-
- cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
-}
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-
-/* codegen_finish **************************************************************
-
- Finishes the code generation. A new memory, large enough for both
- data and code, is allocated and data and code are copied together
- to their final layout, unresolved jumps are resolved, ...
-
-*******************************************************************************/
-
-void codegen_finish(jitdata *jd)
-{
- codeinfo *code;
- codegendata *cd;
- s4 mcodelen;
-#if defined(ENABLE_INTRP)
- s4 ncodelen;
-#endif
- s4 alignedmcodelen;
- jumpref *jr;
- u1 *epoint;
- s4 alignedlen;
-
- /* get required compiler data */
-
- code = jd->code;
- cd = jd->cd;
-
- /* prevent compiler warning */
-
-#if defined(ENABLE_INTRP)
- ncodelen = 0;
-#endif
-
- /* calculate the code length */
-
- mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- count_code_len += mcodelen;
- count_data_len += cd->dseglen;
- }
-#endif
-
- alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
-
-#if defined(ENABLE_INTRP)
- if (opt_intrp)
- ncodelen = cd->ncodeptr - cd->ncodebase;
- else {
- ncodelen = 0; /* avoid compiler warning */
- }
-#endif
-
- cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
- alignedlen = alignedmcodelen + cd->dseglen;
-
-#if defined(ENABLE_INTRP)
- if (opt_intrp) {
- alignedlen += ncodelen;
- }
-#endif
-
- /* allocate new memory */
-
- code->mcodelength = mcodelen + cd->dseglen;
- code->mcode = CNEW(u1, alignedlen);
-
- /* set the entrypoint of the method */
-
- assert(code->entrypoint == NULL);
- code->entrypoint = epoint = (code->mcode + cd->dseglen);
-
- /* fill the data segment (code->entrypoint must already be set!) */
-
- dseg_finish(jd);
-
- /* copy code to the new location */
-
- MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
-
-#if defined(ENABLE_INTRP)
- /* relocate native dynamic superinstruction code (if any) */
-
- if (opt_intrp) {
- cd->mcodebase = code->entrypoint;
-
- if (ncodelen > 0) {
- u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
-
- MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
-
- /* flush the instruction and data caches */
-
- md_cacheflush(ncodebase, ncodelen);
-
- /* set some cd variables for dynamic_super_rerwite */
-
- cd->ncodebase = ncodebase;
-
- } else {
- cd->ncodebase = NULL;
- }
-
- dynamic_super_rewrite(cd);
- }
-#endif
-
- /* Create the exception table. */
-
- exceptiontable_create(jd);
-
- /* Create the linenumber table. */
-
- linenumbertable_create(jd);
-
- /* jump table resolving */
-
- for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
- {
- *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
- (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
-
- JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
- }
-
- /* patcher resolving */
-
- patcher_resolve(jd);
-
-#if defined(ENABLE_REPLACEMENT)
- /* replacement point resolving */
- {
- int i;
- rplpoint *rp;
-
- rp = code->rplpoints;
- for (i=0; i<code->rplpointcount; ++i, ++rp) {
- rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
- }
- }
-#endif /* defined(ENABLE_REPLACEMENT) */
-
- /* Insert method into methodtree to find the entrypoint. */
-
- methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
- /* resolve data segment references */
-
- dseg_resolve_datareferences(jd);
-#endif
-
- /* flush the instruction and data caches */
-
- md_cacheflush(code->mcode, code->mcodelength);
-}
-
-
-/* codegen_generate_stub_compiler **********************************************
-
- Wrapper for codegen_emit_stub_compiler.
-
- Returns:
- pointer to the compiler stub code.
-
-*******************************************************************************/
-
-u1 *codegen_generate_stub_compiler(methodinfo *m)
-{
- jitdata *jd;
- codegendata *cd;
- ptrint *d; /* pointer to data memory */
- u1 *c; /* pointer to code memory */
- int32_t dumpmarker;
-
- /* mark dump memory */
-
- DMARKER;
-
- /* allocate required data structures */
-
- jd = DNEW(jitdata);
-
- jd->m = m;
- jd->cd = DNEW(codegendata);
- jd->flags = 0;
-
- /* get required compiler data */
-
- cd = jd->cd;
-
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
- /* allocate code memory */
-
- c = CNEW(u1, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-
- /* set pointers correctly */
-
- d = (ptrint *) c;
-
- cd->mcodebase = c;
-
- c = c + 3 * SIZEOF_VOID_P;
- cd->mcodeptr = c;
-
- /* NOTE: The codeinfo pointer is actually a pointer to the
- methodinfo (this fakes a codeinfo structure). */
-
- d[0] = (ptrint) asm_call_jit_compiler;
- d[1] = (ptrint) m;
- d[2] = (ptrint) &d[1]; /* fake code->m */
-
- /* call the emit function */
-
- codegen_emit_stub_compiler(jd);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_cstub_len += 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
-#endif
-
- /* flush caches */
-
- md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-#else
- /* Allocate code memory. */
-
- c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-
- /* Set pointers correctly. */
-
- d = (ptrint *) c;
-
- cd->mcodebase = c;
-
- c = c + 2 * SIZEOF_VOID_P;
- cd->mcodeptr = c;
-
- /* NOTE: The codeinfo pointer is actually a pointer to the
- methodinfo (this fakes a codeinfo structure). */
-
- d[0] = (ptrint) m;
- d[1] = (ptrint) &d[0]; /* fake code->m */
-
- /* Emit the trap instruction. */
-
- emit_trap_compiler(cd);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_cstub_len += 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE;
-#endif
-
- /* Flush caches. */
-
- md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + COMPILERSTUB_CODESIZE);
-#endif
-
- /* release dump memory */
-
- DRELEASE;
-
- /* return native stub code */
-
- return c;
-}
-
-
-/* codegen_generate_stub_builtin ***********************************************
-
- Wrapper for codegen_emit_stub_native.
-
-*******************************************************************************/
-
-void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte)
-{
- jitdata *jd;
- codeinfo *code;
- int skipparams;
- int32_t dumpmarker;
-
- /* mark dump memory */
-
- DMARKER;
-
- /* Create JIT data structure. */
-
- jd = jit_jitdata_new(m);
-
- /* Get required compiler data. */
-
- code = jd->code;
-
- /* Stubs are non-leaf methods. */
-
- code_unflag_leafmethod(code);
-
- /* setup code generation stuff */
-
- codegen_setup(jd);
-
- /* Set the number of native arguments we need to skip. */
-
- skipparams = 0;
-
- /* generate the code */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- assert(bte->fp != NULL);
- codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif
-
- /* reallocate the memory and finish the code generation */
-
- codegen_finish(jd);
-
- /* set the stub entry point in the builtin table */
-
- bte->stub = code->entrypoint;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_stub_native += code->mcodelength;
-#endif
-
-#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
- /* disassemble native stub */
-
- if (opt_DisassembleStubs) {
- codegen_disassemble_stub(m,
- (u1 *) (ptrint) code->entrypoint,
- (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
-
- /* show data segment */
-
- if (opt_showddatasegment)
- dseg_display(jd);
- }
-#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
-
- /* release memory */
-
- DRELEASE;
-}
-
-
-/* codegen_generate_stub_native ************************************************
-
- Wrapper for codegen_emit_stub_native.
-
- Returns:
- the codeinfo representing the stub code.
-
-*******************************************************************************/
-
-codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f)
-{
- jitdata *jd;
- codeinfo *code;
- methoddesc *md;
- methoddesc *nmd;
- int skipparams;
- int32_t dumpmarker;
-
- /* mark dump memory */
-
- DMARKER;
-
- /* Create JIT data structure. */
-
- jd = jit_jitdata_new(m);
-
- /* Get required compiler data. */
-
- code = jd->code;
-
- /* Stubs are non-leaf methods. */
-
- code_unflag_leafmethod(code);
-
- /* set the flags for the current JIT run */
-
-#if defined(ENABLE_PROFILING)
- if (opt_prof)
- jd->flags |= JITDATA_FLAG_INSTRUMENT;
-#endif
-
- if (opt_verbosecall)
- jd->flags |= JITDATA_FLAG_VERBOSECALL;
-
- /* setup code generation stuff */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- reg_setup(jd);
-#endif
-
- codegen_setup(jd);
-
- /* create new method descriptor with additional native parameters */
-
- md = m->parseddesc;
-
- /* Set the number of native arguments we need to skip. */
-
- if (m->flags & ACC_STATIC)
- skipparams = 2;
- else
- skipparams = 1;
-
- nmd = (methoddesc *) DMNEW(u1, sizeof(methoddesc) - sizeof(typedesc) +
- md->paramcount * sizeof(typedesc) +
- skipparams * sizeof(typedesc));
-
- nmd->paramcount = md->paramcount + skipparams;
-
- nmd->params = DMNEW(paramdesc, nmd->paramcount);
-
- nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
-
- if (m->flags & ACC_STATIC)
- nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
-
- MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
- md->paramcount);
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- /* pre-allocate the arguments for the native ABI */
-
- md_param_alloc_native(nmd);
-#endif
-
- /* generate the code */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- intrp_createnativestub(f, jd, nmd);
- else
-# endif
- codegen_emit_stub_native(jd, nmd, f, skipparams);
-#else
- intrp_createnativestub(f, jd, nmd);
-#endif
-
- /* reallocate the memory and finish the code generation */
-
- codegen_finish(jd);
-
-#if defined(ENABLE_STATISTICS)
- /* must be done after codegen_finish() */
-
- if (opt_stat)
- size_stub_native += code->mcodelength;
-#endif
-
-#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
- /* disassemble native stub */
-
- if (opt_DisassembleStubs) {
-# if defined(ENABLE_DEBUG_FILTER)
- if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
-# endif
- {
- codegen_disassemble_stub(m,
- (u1 *) (ptrint) code->entrypoint,
- (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
-
- /* show data segment */
-
- if (opt_showddatasegment)
- dseg_display(jd);
- }
- }
-#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
-
- /* release memory */
-
- DRELEASE;
-
- /* return native stub code */
-
- return code;
-}
-
-
-/* codegen_disassemble_nativestub **********************************************
-
- Disassembles the generated builtin or native stub.
-
-*******************************************************************************/
-
-#if defined(ENABLE_DISASSEMBLER)
-void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
-{
- printf("Stub code: ");
- if (m->clazz != NULL)
- utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
- else
- printf("NULL");
- printf(".");
- utf_fprint_printable_ascii(stdout, m->name);
- utf_fprint_printable_ascii(stdout, m->descriptor);
- printf("\nLength: %d\n\n", (s4) (end - start));
-
- DISASSEMBLE(start, end);
-}
-#endif
-
-
-/* codegen_start_native_call ***************************************************
-
- Prepares the stuff required for a native (JNI) function call:
-
- - adds a stackframe info structure to the chain, for stacktraces
- - prepares the local references table on the stack
-
- The layout of the native stub stackframe should look like this:
-
- +---------------------------+ <- java SP (of parent Java function)
- | return address |
- +---------------------------+ <- data SP
- | |
- | stackframe info structure |
- | |
- +---------------------------+
- | |
- | local references table |
- | |
- +---------------------------+
- | |
- | saved registers (if any) |
- | |
- +---------------------------+
- | |
- | arguments (if any) |
- | |
- +---------------------------+ <- current SP (native stub)
-
-*******************************************************************************/
-
-java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
-{
- stackframeinfo_t *sfi;
- localref_table *lrt;
- methodinfo *m;
- int32_t framesize;
-
- uint8_t *datasp;
- uint8_t *javasp;
- uint64_t *arg_regs;
- uint64_t *arg_stack;
-
- STATISTICS(count_calls_java_to_native++);
-
- /* Get the methodinfo. */
-
- m = code_get_methodinfo_for_pv(pv);
-
- assert(m);
-
- framesize = *((int32_t *) (pv + FrameSize));
-
- assert(framesize >= sizeof(stackframeinfo_t) + sizeof(localref_table));
-
- /* calculate needed values */
-
-#if defined(__ALPHA__) || defined(__ARM__)
- datasp = sp + framesize - SIZEOF_VOID_P;
- javasp = sp + framesize;
- arg_regs = (uint64_t *) sp;
- arg_stack = (uint64_t *) javasp;
-#elif defined(__MIPS__)
- /* MIPS always uses 8 bytes to store the RA */
- datasp = sp + framesize - 8;
- javasp = sp + framesize;
-#elif defined(__S390__)
- datasp = sp + framesize - 8;
- javasp = sp + framesize;
- arg_regs = (uint64_t *) (sp + 96);
- arg_stack = (uint64_t *) javasp;
-#elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
- datasp = sp + framesize;
- javasp = sp + framesize + SIZEOF_VOID_P;
- arg_regs = (uint64_t *) sp;
- arg_stack = (uint64_t *) javasp;
-#elif defined(__POWERPC__)
- datasp = sp + framesize;
- javasp = sp + framesize;
- arg_regs = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
- arg_stack = (uint64_t *) javasp;
-#elif defined(__POWERPC64__)
- datasp = sp + framesize;
- javasp = sp + framesize;
- arg_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
- arg_stack = (uint64_t *) javasp;
-#else
- /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
- /* XXX maybe we need to pass the RA as argument there */
- vm_abort("codegen_start_native_call: unsupported architecture");
-#endif
-
- /* get data structures from stack */
-
- sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
- lrt = (localref_table *) (datasp - sizeof(stackframeinfo_t) -
- sizeof(localref_table));
-
-#if defined(ENABLE_JNI)
- /* add current JNI local references table to this thread */
-
- localref_table_add(lrt);
-#endif
-
-#if !defined(NDEBUG)
-# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
- /* print the call-trace if necesarry */
- /* BEFORE: filling the local reference table */
-
- if (opt_TraceJavaCalls)
- trace_java_call_enter(m, arg_regs, arg_stack);
-# endif
-#endif
-
-#if defined(ENABLE_HANDLES)
- /* place all references into the local reference table */
- /* BEFORE: creating stackframeinfo */
-
- localref_native_enter(m, arg_regs, arg_stack);
-#endif
-
- /* Add a stackframeinfo for this native method. We don't have RA
- and XPC here. These are determined in
- stacktrace_stackframeinfo_add. */
-
- stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
-
- /* Return a wrapped classinfo for static methods. */
-
- if (m->flags & ACC_STATIC)
- return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
- else
- return NULL;
-}
-
-
-/* codegen_finish_native_call **************************************************
-
- Removes the stuff required for a native (JNI) function call.
- Additionally it checks for an exceptions and in case, get the
- exception object and clear the pointer.
-
-*******************************************************************************/
-
-java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
-{
- stackframeinfo_t *sfi;
- java_handle_t *e;
- java_object_t *o;
- codeinfo *code;
- methodinfo *m;
- int32_t framesize;
-
- uint8_t *datasp;
- uint64_t *ret_regs;
-
- /* get information from method header */
-
- code = code_get_codeinfo_for_pv(pv);
-
- framesize = *((int32_t *) (pv + FrameSize));
-
- assert(code);
-
- /* get the methodinfo */
-
- m = code->m;
- assert(m);
-
- /* calculate needed values */
-
-#if defined(__ALPHA__) || defined(__ARM__)
- datasp = sp + framesize - SIZEOF_VOID_P;
- ret_regs = (uint64_t *) sp;
-#elif defined(__MIPS__)
- /* MIPS always uses 8 bytes to store the RA */
- datasp = sp + framesize - 8;
-#elif defined(__S390__)
- datasp = sp + framesize - 8;
- ret_regs = (uint64_t *) (sp + 96);
-#elif defined(__I386__)
- datasp = sp + framesize;
- ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
-#elif defined(__M68K__)
- datasp = sp + framesize;
- ret_regs = (uint64_t *) (sp + 2 * 8);
-#elif defined(__X86_64__)
- datasp = sp + framesize;
- ret_regs = (uint64_t *) sp;
-#elif defined(__POWERPC__)
- datasp = sp + framesize;
- ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
-#elif defined(__POWERPC64__)
- datasp = sp + framesize;
- ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
-#else
- vm_abort("codegen_finish_native_call: unsupported architecture");
-#endif
-
- /* get data structures from stack */
-
- sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
-
- /* Remove current stackframeinfo from chain. */
-
- stacktrace_stackframeinfo_remove(sfi);
-
-#if defined(ENABLE_HANDLES)
- /* unwrap the return value from the local reference table */
- /* AFTER: removing the stackframeinfo */
- /* BEFORE: releasing the local reference table */
-
- localref_native_exit(m, ret_regs);
-#endif
-
- /* get and unwrap the exception */
- /* AFTER: removing the stackframe info */
- /* BEFORE: releasing the local reference table */
-
- e = exceptions_get_and_clear_exception();
- o = LLNI_UNWRAP(e);
-
-#if defined(ENABLE_JNI)
- /* release JNI local references table for this thread */
-
- localref_frame_pop_all();
- localref_table_remove();
-#endif
-
-#if !defined(NDEBUG)
-# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
- /* print the call-trace if necesarry */
- /* AFTER: unwrapping the return value */
-
- if (opt_TraceJavaCalls)
- trace_java_call_exit(m, ret_regs);
-# endif
-#endif
-
- return o;
-}
-
-
-/* removecompilerstub **********************************************************
-
- Deletes a compilerstub from memory (simply by freeing it).
-
-*******************************************************************************/
-
-void removecompilerstub(u1 *stub)
-{
- /* pass size 1 to keep the intern function happy */
-
- CFREE((void *) stub, 1);
-}
-
-
-/* removenativestub ************************************************************
-
- Removes a previously created native-stub from memory.
-
-*******************************************************************************/
-
-void removenativestub(u1 *stub)
-{
- /* pass size 1 to keep the intern function happy */
-
- CFREE((void *) stub, 1);
-}
-
-
-/* codegen_reg_of_var **********************************************************
-
- This function determines a register, to which the result of an
- operation should go, when it is ultimatively intended to store the
- result in pseudoregister v. If v is assigned to an actual
- register, this register will be returned. Otherwise (when v is
- spilled) this function returns tempregnum. If not already done,
- regoff and flags are set in the stack location.
-
-*******************************************************************************/
-
-s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
-{
- if (!(v->flags & INMEMORY))
- return v->vv.regoff;
-
- return tempregnum;
-}
-
-
-/* codegen_reg_of_dst **********************************************************
-
- This function determines a register, to which the result of an
- operation should go, when it is ultimatively intended to store the
- result in iptr->dst.var. If dst.var is assigned to an actual
- register, this register will be returned. Otherwise (when it is
- spilled) this function returns tempregnum. If not already done,
- regoff and flags are set in the stack location.
-
-*******************************************************************************/
-
-s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
-{
- return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
-}
-
-
-/* codegen_emit_phi_moves ****************************************************
-
- Emits phi moves at the end of the basicblock.
-
-*******************************************************************************/
-
-#if defined(ENABLE_SSA)
-void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
-{
- int lt_d,lt_s,i;
- lsradata *ls;
- codegendata *cd;
- varinfo *s, *d;
- instruction tmp_i;
-
- cd = jd->cd;
- ls = jd->ls;
-
- MCODECHECK(512);
-
- /* Moves from phi functions with highest indices have to be */
- /* inserted first, since this is the order as is used for */
- /* conflict resolution */
-
- for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
- lt_d = ls->phi_moves[bptr->nr][i][0];
- lt_s = ls->phi_moves[bptr->nr][i][1];
-#if defined(SSA_DEBUG_VERBOSE)
- if (compileverbose)
- printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
-#endif
- if (lt_s == UNUSED) {
-#if defined(SSA_DEBUG_VERBOSE)
- if (compileverbose)
- printf(" ... not processed \n");
-#endif
- continue;
- }
-
- d = VAR(ls->lifetime[lt_d].v_index);
- s = VAR(ls->lifetime[lt_s].v_index);
-
-
- if (d->type == -1) {
-#if defined(SSA_DEBUG_VERBOSE)
- if (compileverbose)
- printf("...returning - phi lifetimes where joined\n");
-#endif
- continue;
- }
-
- if (s->type == -1) {
-#if defined(SSA_DEBUG_VERBOSE)
- if (compileverbose)
- printf("...returning - phi lifetimes where joined\n");
-#endif
- continue;
- }
-
- tmp_i.opc = 0;
- tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
- tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
- emit_copy(jd, &tmp_i);
-
-#if defined(SSA_DEBUG_VERBOSE)
- if (compileverbose) {
- if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
- /* mem -> mem */
- printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
- }
- else if (IS_INMEMORY(s->flags)) {
- /* mem -> reg */
- printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
- }
- else if (IS_INMEMORY(d->flags)) {
- /* reg -> mem */
- printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
- }
- else {
- /* reg -> reg */
- printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
- }
- printf("\n");
- }
-#endif /* defined(SSA_DEBUG_VERBOSE) */
- }
-}
-#endif /* defined(ENABLE_SSA) */
-
-
-/* REMOVEME When we have exception handling in C. */
-
-void *md_asm_codegen_get_pv_from_pc(void *ra)
-{
- return md_codegen_get_pv_from_pc(ra);
-}
-
-
-/*
- * These 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/codegen-common.cpp - architecture independent code generator stuff
+
+ 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.
+
+ All functions assume the following code area / data area layout:
+
+ +-----------+
+ | |
+ | code area | code area grows to higher addresses
+ | |
+ +-----------+ <-- start of procedure
+ | |
+ | data area | data area grows to lower addresses
+ | |
+ +-----------+
+
+ The functions first write into a temporary code/data area allocated by
+ "codegen_init". "codegen_finish" copies the code and data area into permanent
+ memory. All functions writing values into the data area return the offset
+ relative the begin of the code area (start of procedure).
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "vm/jit/jitcache.hpp"
+
+#include "vm/types.h"
+
+#include "codegen.h"
+#include "md.h"
+#include "md-abi.h"
+
+#include "mm/memory.h"
+
+#include "toolbox/avl.h"
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"
+
+#include "native/llni.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
+
+#include "threads/thread.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/exceptions.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/string.hpp"
+
+# include "vm/statistics.h"
+
+
+#include "vm/jit/abi.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+
+#if defined(ENABLE_DISASSEMBLER)
+# include "vm/jit/disass.h"
+#endif
+
+#include "vm/jit/dseg.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/methodtree.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#endif
+#include "vm/jit/stacktrace.hpp"
+#include "vm/jit/trace.hpp"
+
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+#include "show.hpp"
+
+
+/* codegen_init ****************************************************************
+
+ TODO
+
+*******************************************************************************/
+
+void codegen_init(void)
+{
+}
+
+
+/* codegen_setup ***************************************************************
+
+ Allocates and initialises code area, data area and references.
+
+*******************************************************************************/
+
+void codegen_setup(jitdata *jd)
+{
+ methodinfo *m;
+ codegendata *cd;
+
+ /* get required compiler data */
+
+ m = jd->m;
+ cd = jd->cd;
+
+ /* initialize members */
+
+ cd->flags = 0;
+
+ cd->mcodebase = (u1*) DumpMemory::allocate(MCODEINITSIZE);
+ cd->mcodeend = cd->mcodebase + MCODEINITSIZE;
+ cd->mcodesize = MCODEINITSIZE;
+
+ /* initialize mcode variables */
+
+ cd->mcodeptr = cd->mcodebase;
+ cd->lastmcodeptr = cd->mcodebase;
+
+#if defined(ENABLE_INTRP)
+ /* native dynamic superinstructions variables */
+
+ if (opt_intrp) {
+ cd->ncodebase = (u1*) DumpMemory::allocate(NCODEINITSIZE);
+ cd->ncodesize = NCODEINITSIZE;
+
+ /* initialize ncode variables */
+
+ cd->ncodeptr = cd->ncodebase;
+
+ cd->lastinstwithoutdispatch = ~0; /* no inst without dispatch */
+ cd->superstarts = NULL;
+ }
+#endif
+
+ cd->dseg = NULL;
+ cd->dseglen = 0;
+
+ cd->jumpreferences = NULL;
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+ cd->datareferences = NULL;
+#endif
+
+ cd->brancheslabel = new DumpList<branch_label_ref_t*>();
+ cd->linenumbers = new DumpList<Linenumber>();
+}
+
+
+/* codegen_reset ***************************************************************
+
+ Resets the codegen data structure so we can recompile the method.
+
+*******************************************************************************/
+
+static void codegen_reset(jitdata *jd)
+{
+ codeinfo *code;
+ codegendata *cd;
+ basicblock *bptr;
+
+ /* get required compiler data */
+
+ code = jd->code;
+ cd = jd->cd;
+
+ /* reset error flag */
+
+ cd->flags &= ~CODEGENDATA_FLAG_ERROR;
+
+ /* reset some members, we reuse the code memory already allocated
+ as this should have almost the correct size */
+
+ cd->mcodeptr = cd->mcodebase;
+ cd->lastmcodeptr = cd->mcodebase;
+
+ cd->dseg = NULL;
+ cd->dseglen = 0;
+
+ cd->jumpreferences = NULL;
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+ cd->datareferences = NULL;
+#endif
+
+ cd->brancheslabel = new DumpList<branch_label_ref_t*>();
+ cd->linenumbers = new DumpList<Linenumber>();
+
+ /* We need to clear the mpc and the branch references from all
+ basic blocks as they will definitely change. */
+
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+ bptr->mpc = -1;
+ bptr->branchrefs = NULL;
+ }
+
+ /* We need to clear all the patcher references from the codeinfo
+ since they all will be regenerated */
+
+ patcher_list_reset(code);
+
+#if defined(ENABLE_REPLACEMENT)
+ code->rplpoints = NULL;
+ code->rplpointcount = 0;
+ code->regalloc = NULL;
+ code->regalloccount = 0;
+ code->globalcount = 0;
+#endif
+}
+
+
+/* codegen_generate ************************************************************
+
+ Generates the code for the currently compiled method.
+
+*******************************************************************************/
+
+bool codegen_generate(jitdata *jd)
+{
+ codegendata *cd;
+
+ /* get required compiler data */
+
+ cd = jd->cd;
+
+ /* call the machine-dependent code generation function */
+
+ if (!codegen_emit(jd))
+ return false;
+
+ /* check for an error */
+
+ if (CODEGENDATA_HAS_FLAG_ERROR(cd)) {
+ /* check for long-branches flag, if it is set we recompile the
+ method */
+
+#if !defined(NDEBUG)
+ if (compileverbose)
+ log_message_method("Re-generating code: ", jd->m);
+#endif
+
+ /* XXX maybe we should tag long-branches-methods for recompilation */
+
+ if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+ /* we have to reset the codegendata structure first */
+
+ codegen_reset(jd);
+
+ /* and restart the compiler run */
+
+ if (!codegen_emit(jd))
+ return false;
+ }
+ else {
+ vm_abort("codegen_generate: unknown error occurred during codegen_emit: flags=%x\n", cd->flags);
+ }
+
+#if !defined(NDEBUG)
+ if (compileverbose)
+ log_message_method("Re-generating code done: ", jd->m);
+#endif
+ }
+
+ /* reallocate the memory and finish the code generation */
+
+ codegen_finish(jd);
+
+ /* everything's ok */
+
+ return true;
+}
+
+
+/* codegen_close ***************************************************************
+
+ TODO
+
+*******************************************************************************/
+
+void codegen_close(void)
+{
+ /* TODO: release avl tree on i386 and x86_64 */
+}
+
+
+/* codegen_increase ************************************************************
+
+ Doubles code area.
+
+*******************************************************************************/
+
+void codegen_increase(codegendata *cd)
+{
+ u1 *oldmcodebase;
+
+ /* save old mcodebase pointer */
+
+ oldmcodebase = cd->mcodebase;
+
+ /* reallocate to new, doubled memory */
+
+ cd->mcodebase = (u1*) DumpMemory::reallocate(cd->mcodebase,
+ cd->mcodesize,
+ cd->mcodesize * 2);
+ cd->mcodesize *= 2;
+ cd->mcodeend = cd->mcodebase + cd->mcodesize;
+
+ /* set new mcodeptr */
+
+ cd->mcodeptr = cd->mcodebase + (cd->mcodeptr - oldmcodebase);
+
+#if defined(__I386__) || defined(__MIPS__) || defined(__X86_64__) || defined(__M68K__) || defined(ENABLE_INTRP) \
+ || defined(__SPARC_64__)
+ /* adjust the pointer to the last patcher position */
+
+ if (cd->lastmcodeptr != NULL)
+ cd->lastmcodeptr = cd->mcodebase + (cd->lastmcodeptr - oldmcodebase);
+#endif
+}
+
+
+/* codegen_ncode_increase ******************************************************
+
+ Doubles code area.
+
+*******************************************************************************/
+
+#if defined(ENABLE_INTRP)
+u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr)
+{
+ u1 *oldncodebase;
+
+ /* save old ncodebase pointer */
+
+ oldncodebase = cd->ncodebase;
+
+ /* reallocate to new, doubled memory */
+
+ cd->ncodebase = DMREALLOC(cd->ncodebase,
+ u1,
+ cd->ncodesize,
+ cd->ncodesize * 2);
+ cd->ncodesize *= 2;
+
+ /* return the new ncodeptr */
+
+ return (cd->ncodebase + (ncodeptr - oldncodebase));
+}
+#endif
+
+
+/* codegen_add_branch_ref ******************************************************
+
+ Prepends an branch to the list.
+
+*******************************************************************************/
+
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
+{
+ branchref *br;
+ s4 branchmpc;
+
+ STATISTICS(count_branches_unresolved++);
+
+ /* calculate the mpc of the branch instruction */
+
+ branchmpc = cd->mcodeptr - cd->mcodebase;
+
+ br = (branchref*) DumpMemory::allocate(sizeof(branchref));
+
+ br->branchmpc = branchmpc;
+ br->condition = condition;
+ br->reg = reg;
+ br->options = options;
+ br->next = target->branchrefs;
+
+ target->branchrefs = br;
+}
+
+
+/* codegen_resolve_branchrefs **************************************************
+
+ Resolves and patches the branch references of a given basic block.
+
+*******************************************************************************/
+
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr)
+{
+ branchref *br;
+ u1 *mcodeptr;
+
+ /* Save the mcodeptr because in the branch emitting functions
+ we generate code somewhere inside already generated code,
+ but we're still in the actual code generation phase. */
+
+ mcodeptr = cd->mcodeptr;
+
+ /* just to make sure */
+
+ assert(bptr->mpc >= 0);
+
+ for (br = bptr->branchrefs; br != NULL; br = br->next) {
+ /* temporary set the mcodeptr */
+
+ cd->mcodeptr = cd->mcodebase + br->branchmpc;
+
+ /* emit_bccz and emit_branch emit the correct code, even if we
+ pass condition == BRANCH_UNCONDITIONAL or reg == -1. */
+
+ emit_bccz(cd, bptr, br->condition, br->reg, br->options);
+ }
+
+ /* restore mcodeptr */
+
+ cd->mcodeptr = mcodeptr;
+}
+
+
+/* codegen_branch_label_add ****************************************************
+
+ Append an branch to the label-branch list.
+
+*******************************************************************************/
+
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+{
+ // Calculate the current mpc.
+ int32_t mpc = cd->mcodeptr - cd->mcodebase;
+
+ branch_label_ref_t* br = (branch_label_ref_t*) DumpMemory::allocate(sizeof(branch_label_ref_t));
+
+ br->mpc = mpc;
+ br->label = label;
+ br->condition = condition;
+ br->reg = reg;
+ br->options = options;
+
+ // Add the branch to the list.
+ cd->brancheslabel->push_back(br);
+}
+
+
+/* codegen_set_replacement_point_notrap ****************************************
+
+ Record the position of a non-trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point_notrap(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point_notrap(codegendata *cd)
+#endif
+{
+ assert(cd->replacementpoint);
+ assert(cd->replacementpoint->type == type);
+ assert(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP);
+
+ cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+ cd->replacementpoint++;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* codegen_set_replacement_point ***********************************************
+
+ Record the position of a trappable replacement point.
+
+*******************************************************************************/
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point(codegendata *cd, s4 type)
+#else
+void codegen_set_replacement_point(codegendata *cd)
+#endif
+{
+ assert(cd->replacementpoint);
+ assert(cd->replacementpoint->type == type);
+ assert(!(cd->replacementpoint->flags & RPLPOINT_FLAG_NOTRAP));
+
+ cd->replacementpoint->pc = (u1*) (ptrint) (cd->mcodeptr - cd->mcodebase);
+
+ cd->replacementpoint++;
+
+#if !defined(NDEBUG)
+ /* XXX actually we should use an own REPLACEMENT_NOPS here! */
+ if (opt_TestReplacement)
+ PATCHER_NOPS;
+#endif
+
+ /* XXX assert(cd->lastmcodeptr <= cd->mcodeptr); */
+
+ cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+}
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+
+/* codegen_finish **************************************************************
+
+ Finishes the code generation. A new memory, large enough for both
+ data and code, is allocated and data and code are copied together
+ to their final layout, unresolved jumps are resolved, ...
+
+*******************************************************************************/
+
+void codegen_finish(jitdata *jd)
+{
+ codeinfo *code;
+ codegendata *cd;
+ s4 mcodelen;
+#if defined(ENABLE_INTRP)
+ s4 ncodelen;
+#endif
+ s4 alignedmcodelen;
+ jumpref *jr;
+ u1 *epoint;
+ s4 alignedlen;
+
+ /* get required compiler data */
+
+ code = jd->code;
+ cd = jd->cd;
+
+ /* prevent compiler warning */
+
+#if defined(ENABLE_INTRP)
+ ncodelen = 0;
+#endif
+
+ /* calculate the code length */
+
+ mcodelen = (s4) (cd->mcodeptr - cd->mcodebase);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ count_code_len += mcodelen;
+ count_data_len += cd->dseglen;
+ }
+#endif
+
+ alignedmcodelen = MEMORY_ALIGN(mcodelen, MAX_ALIGN);
+
+#if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ ncodelen = cd->ncodeptr - cd->ncodebase;
+ else {
+ ncodelen = 0; /* avoid compiler warning */
+ }
+#endif
+
+ cd->dseglen = MEMORY_ALIGN(cd->dseglen, MAX_ALIGN);
+ alignedlen = alignedmcodelen + cd->dseglen;
+
+#if defined(ENABLE_INTRP)
+ if (opt_intrp) {
+ alignedlen += ncodelen;
+ }
+#endif
+
+ /* allocate new memory */
+
+ code->mcodelength = mcodelen + cd->dseglen;
+ code->mcode = CNEW(u1, alignedlen);
+
+ /* set the entrypoint of the method */
+
+ assert(code->entrypoint == NULL);
+ code->entrypoint = epoint = (code->mcode + cd->dseglen);
+
+ /* fill the data segment (code->entrypoint must already be set!) */
+
+ dseg_finish(jd);
+
+ /* copy code to the new location */
+
+ MCOPY((void *) code->entrypoint, cd->mcodebase, u1, mcodelen);
+
+#if defined(ENABLE_INTRP)
+ /* relocate native dynamic superinstruction code (if any) */
+
+ if (opt_intrp) {
+ cd->mcodebase = code->entrypoint;
+
+ if (ncodelen > 0) {
+ u1 *ncodebase = code->mcode + cd->dseglen + alignedmcodelen;
+
+ MCOPY((void *) ncodebase, cd->ncodebase, u1, ncodelen);
+
+ /* flush the instruction and data caches */
+
+ md_cacheflush(ncodebase, ncodelen);
+
+ /* set some cd variables for dynamic_super_rerwite */
+
+ cd->ncodebase = ncodebase;
+
+ } else {
+ cd->ncodebase = NULL;
+ }
+
+ dynamic_super_rewrite(cd);
+ }
+#endif
+
+ /* Create the exception table. */
+
+ exceptiontable_create(jd);
+
+ /* Create the linenumber table. */
+
+ code->linenumbertable = new LinenumberTable(jd);
+
+ /* jump table resolving */
+
+ for (jr = cd->jumpreferences; jr != NULL; jr = jr->next)
+ {
+ *((functionptr *) ((ptrint) epoint + jr->tablepos)) =
+ (functionptr) ((ptrint) epoint + (ptrint) jr->target->mpc);
+
+ JITCACHE_ADD_CACHED_REF(code, CRT_JUMPREFERENCE, jr->target->mpc, jr->tablepos);
+ }
+
+ /* patcher resolving */
+
+ patcher_resolve(jd);
+
+#if defined(ENABLE_REPLACEMENT)
+ /* replacement point resolving */
+ {
+ int i;
+ rplpoint *rp;
+
+ rp = code->rplpoints;
+ for (i=0; i<code->rplpointcount; ++i, ++rp) {
+ rp->pc = (u1*) ((ptrint) epoint + (ptrint) rp->pc);
+ }
+ }
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+ /* Insert method into methodtree to find the entrypoint. */
+
+ methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
+ /* resolve data segment references */
+
+ dseg_resolve_datareferences(jd);
+#endif
+
+ /* flush the instruction and data caches */
+
+ md_cacheflush(code->mcode, code->mcodelength);
+}
+
+
+/* codegen_start_native_call ***************************************************
+
+ Prepares the stuff required for a native (JNI) function call:
+
+ - adds a stackframe info structure to the chain, for stacktraces
+ - prepares the local references table on the stack
+
+ The layout of the native stub stackframe should look like this:
+
+ +---------------------------+ <- java SP (of parent Java function)
+ | return address |
+ +---------------------------+ <- data SP
+ | |
+ | stackframe info structure |
+ | |
+ +---------------------------+
+ | |
+ | local references table |
+ | |
+ +---------------------------+
+ | |
+ | saved registers (if any) |
+ | |
+ +---------------------------+
+ | |
+ | arguments (if any) |
+ | |
+ +---------------------------+ <- current SP (native stub)
+
+*******************************************************************************/
+
+java_handle_t *codegen_start_native_call(u1 *sp, u1 *pv)
+{
+ stackframeinfo_t *sfi;
+ localref_table *lrt;
+ methodinfo *m;
+ int32_t framesize;
+
+ uint8_t *datasp;
+ uint8_t *javasp;
+ uint64_t *arg_regs;
+ uint64_t *arg_stack;
+
+ STATISTICS(count_calls_java_to_native++);
+
+ /* Get the methodinfo. */
+
+ m = code_get_methodinfo_for_pv(pv);
+
+ assert(m);
+
+ framesize = *((int32_t *) (pv + FrameSize));
+
+ assert(framesize >= (int32_t) (sizeof(stackframeinfo_t) + sizeof(localref_table)));
+
+ /* calculate needed values */
+
+#if defined(__ALPHA__) || defined(__ARM__)
+ datasp = sp + framesize - SIZEOF_VOID_P;
+ javasp = sp + framesize;
+ arg_regs = (uint64_t *) sp;
+ arg_stack = (uint64_t *) javasp;
+#elif defined(__MIPS__)
+ /* MIPS always uses 8 bytes to store the RA */
+ datasp = sp + framesize - 8;
+ javasp = sp + framesize;
+#elif defined(__S390__)
+ datasp = sp + framesize - 8;
+ javasp = sp + framesize;
+ arg_regs = (uint64_t *) (sp + 96);
+ arg_stack = (uint64_t *) javasp;
+#elif defined(__I386__) || defined(__M68K__) || defined(__X86_64__)
+ datasp = sp + framesize;
+ javasp = sp + framesize + SIZEOF_VOID_P;
+ arg_regs = (uint64_t *) sp;
+ arg_stack = (uint64_t *) javasp;
+#elif defined(__POWERPC__)
+ datasp = sp + framesize;
+ javasp = sp + framesize;
+ arg_regs = (uint64_t *) (sp + LA_SIZE + 4 * SIZEOF_VOID_P);
+ arg_stack = (uint64_t *) javasp;
+#elif defined(__POWERPC64__)
+ datasp = sp + framesize;
+ javasp = sp + framesize;
+ arg_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 4 * SIZEOF_VOID_P);
+ arg_stack = (uint64_t *) javasp;
+#else
+ /* XXX is was unable to do this port for SPARC64, sorry. (-michi) */
+ /* XXX maybe we need to pass the RA as argument there */
+ vm_abort("codegen_start_native_call: unsupported architecture");
+#endif
+
+ /* get data structures from stack */
+
+ sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
+ lrt = (localref_table *) (datasp - sizeof(stackframeinfo_t) -
+ sizeof(localref_table));
+
+#if defined(ENABLE_JNI)
+ /* add current JNI local references table to this thread */
+
+ localref_table_add(lrt);
+#endif
+
+#if !defined(NDEBUG)
+# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
+ /* print the call-trace if necesarry */
+ /* BEFORE: filling the local reference table */
+
+ if (opt_TraceJavaCalls)
+ trace_java_call_enter(m, arg_regs, arg_stack);
+# endif
+#endif
+
+#if defined(ENABLE_HANDLES)
+ /* place all references into the local reference table */
+ /* BEFORE: creating stackframeinfo */
+
+ localref_native_enter(m, arg_regs, arg_stack);
+#endif
+
+ /* Add a stackframeinfo for this native method. We don't have RA
+ and XPC here. These are determined in
+ stacktrace_stackframeinfo_add. */
+
+ stacktrace_stackframeinfo_add(sfi, pv, sp, NULL, NULL);
+
+ /* Return a wrapped classinfo for static methods. */
+
+ if (m->flags & ACC_STATIC)
+ return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
+ else
+ return NULL;
+}
+
+
+/* codegen_finish_native_call **************************************************
+
+ Removes the stuff required for a native (JNI) function call.
+ Additionally it checks for an exceptions and in case, get the
+ exception object and clear the pointer.
+
+*******************************************************************************/
+
+java_object_t *codegen_finish_native_call(u1 *sp, u1 *pv)
+{
+ stackframeinfo_t *sfi;
+ java_handle_t *e;
+ java_object_t *o;
+ codeinfo *code;
+ methodinfo *m;
+ int32_t framesize;
+
+ uint8_t *datasp;
+ uint64_t *ret_regs;
+
+ /* get information from method header */
+
+ code = code_get_codeinfo_for_pv(pv);
+
+ framesize = *((int32_t *) (pv + FrameSize));
+
+ assert(code);
+
+ /* get the methodinfo */
+
+ m = code->m;
+ assert(m);
+
+ /* calculate needed values */
+
+#if defined(__ALPHA__) || defined(__ARM__)
+ datasp = sp + framesize - SIZEOF_VOID_P;
+ ret_regs = (uint64_t *) sp;
+#elif defined(__MIPS__)
+ /* MIPS always uses 8 bytes to store the RA */
+ datasp = sp + framesize - 8;
+#elif defined(__S390__)
+ datasp = sp + framesize - 8;
+ ret_regs = (uint64_t *) (sp + 96);
+#elif defined(__I386__)
+ datasp = sp + framesize;
+ ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
+#elif defined(__M68K__)
+ datasp = sp + framesize;
+ ret_regs = (uint64_t *) (sp + 2 * 8);
+#elif defined(__X86_64__)
+ datasp = sp + framesize;
+ ret_regs = (uint64_t *) sp;
+#elif defined(__POWERPC__)
+ datasp = sp + framesize;
+ ret_regs = (uint64_t *) (sp + LA_SIZE + 2 * SIZEOF_VOID_P);
+#elif defined(__POWERPC64__)
+ datasp = sp + framesize;
+ ret_regs = (uint64_t *) (sp + PA_SIZE + LA_SIZE + 2 * SIZEOF_VOID_P);
+#else
+ vm_abort("codegen_finish_native_call: unsupported architecture");
+#endif
+
+ /* get data structures from stack */
+
+ sfi = (stackframeinfo_t *) (datasp - sizeof(stackframeinfo_t));
+
+ /* Remove current stackframeinfo from chain. */
+
+ stacktrace_stackframeinfo_remove(sfi);
+
+#if defined(ENABLE_HANDLES)
+ /* unwrap the return value from the local reference table */
+ /* AFTER: removing the stackframeinfo */
+ /* BEFORE: releasing the local reference table */
+
+ localref_native_exit(m, ret_regs);
+#endif
+
+ /* get and unwrap the exception */
+ /* AFTER: removing the stackframe info */
+ /* BEFORE: releasing the local reference table */
+
+ e = exceptions_get_and_clear_exception();
+ o = LLNI_UNWRAP(e);
+
+#if defined(ENABLE_JNI)
+ /* release JNI local references table for this thread */
+
+ localref_frame_pop_all();
+ localref_table_remove();
+#endif
+
+#if !defined(NDEBUG)
+# if defined(__ALPHA__) || defined(__I386__) || defined(__M68K__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__)
+ /* print the call-trace if necesarry */
+ /* AFTER: unwrapping the return value */
+
+ if (opt_TraceJavaCalls)
+ trace_java_call_exit(m, ret_regs);
+# endif
+#endif
+
+ return o;
+}
+
+
+/* codegen_reg_of_var **********************************************************
+
+ This function determines a register, to which the result of an
+ operation should go, when it is ultimatively intended to store the
+ result in pseudoregister v. If v is assigned to an actual
+ register, this register will be returned. Otherwise (when v is
+ spilled) this function returns tempregnum. If not already done,
+ regoff and flags are set in the stack location.
+
+*******************************************************************************/
+
+s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
+{
+ if (!(v->flags & INMEMORY))
+ return v->vv.regoff;
+
+ return tempregnum;
+}
+
+
+/* codegen_reg_of_dst **********************************************************
+
+ This function determines a register, to which the result of an
+ operation should go, when it is ultimatively intended to store the
+ result in iptr->dst.var. If dst.var is assigned to an actual
+ register, this register will be returned. Otherwise (when it is
+ spilled) this function returns tempregnum. If not already done,
+ regoff and flags are set in the stack location.
+
+*******************************************************************************/
+
+s4 codegen_reg_of_dst(jitdata *jd, instruction *iptr, s4 tempregnum)
+{
+ return codegen_reg_of_var(iptr->opc, VAROP(iptr->dst), tempregnum);
+}
+
+
+/* codegen_emit_phi_moves ****************************************************
+
+ Emits phi moves at the end of the basicblock.
+
+*******************************************************************************/
+
+#if defined(ENABLE_SSA)
+void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr)
+{
+ int lt_d,lt_s,i;
+ lsradata *ls;
+ codegendata *cd;
+ varinfo *s, *d;
+ instruction tmp_i;
+
+ cd = jd->cd;
+ ls = jd->ls;
+
+ MCODECHECK(512);
+
+ /* Moves from phi functions with highest indices have to be */
+ /* inserted first, since this is the order as is used for */
+ /* conflict resolution */
+
+ for(i = ls->num_phi_moves[bptr->nr] - 1; i >= 0 ; i--) {
+ lt_d = ls->phi_moves[bptr->nr][i][0];
+ lt_s = ls->phi_moves[bptr->nr][i][1];
+#if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose)
+ printf("BB %3i Move %3i <- %3i ", bptr->nr, lt_d, lt_s);
+#endif
+ if (lt_s == UNUSED) {
+#if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose)
+ printf(" ... not processed \n");
+#endif
+ continue;
+ }
+
+ d = VAR(ls->lifetime[lt_d].v_index);
+ s = VAR(ls->lifetime[lt_s].v_index);
+
+
+ if (d->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose)
+ printf("...returning - phi lifetimes where joined\n");
+#endif
+ continue;
+ }
+
+ if (s->type == -1) {
+#if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose)
+ printf("...returning - phi lifetimes where joined\n");
+#endif
+ continue;
+ }
+
+ tmp_i.opc = 0;
+ tmp_i.s1.varindex = ls->lifetime[lt_s].v_index;
+ tmp_i.dst.varindex = ls->lifetime[lt_d].v_index;
+ emit_copy(jd, &tmp_i);
+
+#if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose) {
+ if (IS_INMEMORY(d->flags) && IS_INMEMORY(s->flags)) {
+ /* mem -> mem */
+ printf("M%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+ }
+ else if (IS_INMEMORY(s->flags)) {
+ /* mem -> reg */
+ printf("R%3i <- M%3i",d->vv.regoff,s->vv.regoff);
+ }
+ else if (IS_INMEMORY(d->flags)) {
+ /* reg -> mem */
+ printf("M%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+ }
+ else {
+ /* reg -> reg */
+ printf("R%3i <- R%3i",d->vv.regoff,s->vv.regoff);
+ }
+ printf("\n");
+ }
+#endif /* defined(SSA_DEBUG_VERBOSE) */
+ }
+}
+#endif /* defined(ENABLE_SSA) */
+
+
+/* REMOVEME When we have exception handling in C. */
+
+void *md_asm_codegen_get_pv_from_pc(void *ra)
+{
+ return md_codegen_get_pv_from_pc(ra);
+}
+
+
+/*
+ * These 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/codegen-common.h - architecture independent code generator stuff
-
- 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 _CODEGEN_COMMON_H
-#define _CODEGEN_COMMON_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct codegendata codegendata;
-typedef struct branchref branchref;
-typedef struct branch_label_ref_t branch_label_ref_t;
-typedef struct jumpref jumpref;
-typedef struct dataref dataref;
-typedef struct exceptionref exceptionref;
-typedef struct linenumberref linenumberref;
-
-
-#include "config.h"
-#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/reg.h"
-#include "vm/jit/code.h"
-#include "vm/jit/replace.h"
-
-
-#define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
-#define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
-
-#define NCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
-
-
-/* Register Pack/Unpack Macros ************************************************/
-
-/* ATTENTION: Don't change the order where low and high bits are
- stored! At least mips32 relies in one case on that order. */
-
-#define PACK_REGS(low,high) \
- ( (((high) & 0x0000ffff) << 16) | ((low) & 0x0000ffff) )
-
-#define GET_LOW_REG(a) ((a) & 0x0000ffff)
-#define GET_HIGH_REG(a) (((a) & 0xffff0000) >> 16)
-
-
-/* branch conditions **********************************************************/
-
-#define BRANCH_UNCONDITIONAL -1
-
-#define BRANCH_EQ (ICMD_IFEQ - ICMD_IFEQ)
-#define BRANCH_NE (ICMD_IFNE - ICMD_IFEQ)
-#define BRANCH_LT (ICMD_IFLT - ICMD_IFEQ)
-#define BRANCH_GE (ICMD_IFGE - ICMD_IFEQ)
-#define BRANCH_GT (ICMD_IFGT - ICMD_IFEQ)
-#define BRANCH_LE (ICMD_IFLE - ICMD_IFEQ)
-
-#define BRANCH_ULT 256
-#define BRANCH_ULE 257
-#define BRANCH_UGE 258
-#define BRANCH_UGT 259
-
-#define BRANCH_NAN 260
-
-
-/* common branch options ******************************************************/
-
-#define BRANCH_OPT_NONE 0
-
-
-/* codegendata ****************************************************************/
-
-struct codegendata {
- u4 flags; /* code generator flags */
- u1 *mcodebase; /* base pointer of code area */
- u1 *mcodeend; /* pointer to end of code area */
- s4 mcodesize; /* complete size of code area (bytes) */
- u1 *mcodeptr; /* code generation pointer */
- u1 *lastmcodeptr; /* last patcher position of basic block */
-
-#if defined(ENABLE_INTRP)
- u1 *ncodebase; /* base pointer of native code area */
- s4 ncodesize; /* complete size of native code area */
- u1 *ncodeptr; /* native code generation pointer */
-
- u4 lastinstwithoutdispatch; /* ~0 if there was a dispatch */
-
- s4 lastpatcheroffset; /* -1 if current super has no patcher */
- s4 dynsuperm; /* offsets of start of current dynamic ...*/
- s4 dynsupern; /* ... superinstruction starts */
- struct superstart *superstarts; /* list of supers without patchers */
-#endif
-
- dsegentry *dseg; /* chain of data segment entries */
- s4 dseglen; /* used size of data area (bytes) */
- /* data area grows from top to bottom */
-
- jumpref *jumpreferences; /* list of jumptable target addresses */
-
-#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP) || defined(__S390__)
- dataref *datareferences; /* list of data segment references */
-#endif
-
- list_t *brancheslabel;
- list_t *linenumbers; /* list of line numbers */
-
- methodinfo *method;
-
- s4 stackframesize; /* stackframe size of this method */
-
-#if defined(ENABLE_REPLACEMENT)
- rplpoint *replacementpoint; /* current replacement point */
-#endif
-};
-
-
-#define CODEGENDATA_FLAG_ERROR 0x00000001
-#define CODEGENDATA_FLAG_LONGBRANCHES 0x00000002
-
-
-#define CODEGENDATA_HAS_FLAG_ERROR(cd) \
- ((cd)->flags & CODEGENDATA_FLAG_ERROR)
-
-#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) \
- ((cd)->flags & CODEGENDATA_FLAG_LONGBRANCHES)
-
-
-/* branchref *****************************************************************/
-
-struct branchref {
- s4 branchmpc; /* patching position in code segment */
- s4 condition; /* conditional branch condition */
- s4 reg; /* register number to check */
- u4 options; /* branch options */
- branchref *next; /* next element in branchref list */
-};
-
-
-/* branch_label_ref_t *********************************************************/
-
-struct branch_label_ref_t {
- s4 mpc; /* position in code segment */
- s4 label; /* label number */
- s4 condition; /* conditional branch condition */
- s4 reg; /* register number to check */
- u4 options; /* branch options */
- listnode_t linkage;
-};
-
-
-/* jumpref ********************************************************************/
-
-struct jumpref {
- s4 tablepos; /* patching position in data segment */
- basicblock *target; /* target basic block */
- jumpref *next; /* next element in jumpref list */
-};
-
-
-/* dataref ********************************************************************/
-
-struct dataref {
- s4 datapos; /* patching position in generated code */
- dataref *next; /* next element in dataref list */
-};
-
-
-/* linenumberref **************************************************************/
-
-struct linenumberref {
- s4 tablepos; /* patching position in data segment */
- s4 linenumber; /* line number, used for inserting into the */
- /* table and for validity checking */
- /* -1......start of inlined body */
- /* -2......end of inlined body */
- /* <= -3...special entry with methodinfo * */
- /* (see doc/inlining_stacktrace.txt) */
- ptrint targetmpc; /* machine code program counter of first */
- /* instruction for given line */
- /* NOTE: for linenumber <= -3 this is a the */
- /* (methodinfo *) of the inlined method */
- linenumberref *next; /* next element in linenumberref list */
-};
-
-
-/* function prototypes ********************************************************/
-
-void codegen_init(void);
-void codegen_setup(jitdata *jd);
-
-bool codegen_generate(jitdata *jd);
-bool codegen_emit(jitdata *jd);
-
-#if defined(ENABLE_INTRP)
-bool intrp_codegen(jitdata *jd);
-#endif
-
-void codegen_close(void);
-
-void codegen_increase(codegendata *cd);
-
-#if defined(ENABLE_INTRP)
-u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr);
-#endif
-
-void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
-void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr);
-
-void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
-
-#if defined(ENABLE_REPLACEMENT)
-#if !defined(NDEBUG)
-void codegen_set_replacement_point_notrap(codegendata *cd, s4 type);
-void codegen_set_replacement_point(codegendata *cd, s4 type);
-#else
-void codegen_set_replacement_point_notrap(codegendata *cd);
-void codegen_set_replacement_point(codegendata *cd);
-#endif
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-void codegen_finish(jitdata *jd);
-
-#if defined(ENABLE_DISASSEMBLER)
-void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end);
-#endif
-
-/* stub functions */
-
-u1 *codegen_generate_stub_compiler(methodinfo *m);
-void codegen_generate_stub_builtin(methodinfo *m, builtintable_entry *bte);
-codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f);
-
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
-void codegen_emit_stub_compiler(jitdata *jd);
-#endif
-void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams);
-
-#if defined(ENABLE_INTRP)
-u1 *intrp_createcompilerstub(methodinfo *m);
-u1 *intrp_createnativestub(functionptr f, jitdata *jd, methoddesc *md);
-#endif
-
-void removecompilerstub(u1 *stub);
-void removenativestub(u1 *stub);
-
-java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv);
-java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv);
-
-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_SSA)
-void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr);
-#endif
-
-#endif /* _CODEGEN_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:
- * vim:noexpandtab:sw=4:ts=4:
- */
--- /dev/null
+/* src/vm/jit/codegen-common.hpp - architecture independent code generator stuff
+
+ 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 _CODEGEN_COMMON_HPP
+#define _CODEGEN_COMMON_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct codegendata codegendata;
+typedef struct branchref branchref;
+typedef struct branch_label_ref_t branch_label_ref_t;
+typedef struct jumpref jumpref;
+typedef struct dataref dataref;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/jit/builtin.hpp"
+#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.hpp"
+#include "vm/jit/reg.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/replace.hpp"
+
+
+#define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
+#define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
+
+#define NCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
+
+
+/* Register Pack/Unpack Macros ************************************************/
+
+/* ATTENTION: Don't change the order where low and high bits are
+ stored! At least mips32 relies in one case on that order. */
+
+#define PACK_REGS(low,high) \
+ ( (((high) & 0x0000ffff) << 16) | ((low) & 0x0000ffff) )
+
+#define GET_LOW_REG(a) ((a) & 0x0000ffff)
+#define GET_HIGH_REG(a) (((a) & 0xffff0000) >> 16)
+
+
+/* branch conditions **********************************************************/
+
+#define BRANCH_UNCONDITIONAL -1
+
+#define BRANCH_EQ (ICMD_IFEQ - ICMD_IFEQ)
+#define BRANCH_NE (ICMD_IFNE - ICMD_IFEQ)
+#define BRANCH_LT (ICMD_IFLT - ICMD_IFEQ)
+#define BRANCH_GE (ICMD_IFGE - ICMD_IFEQ)
+#define BRANCH_GT (ICMD_IFGT - ICMD_IFEQ)
+#define BRANCH_LE (ICMD_IFLE - ICMD_IFEQ)
+
+#define BRANCH_ULT 256
+#define BRANCH_ULE 257
+#define BRANCH_UGE 258
+#define BRANCH_UGT 259
+
+#define BRANCH_NAN 260
+
+
+/* common branch options ******************************************************/
+
+#define BRANCH_OPT_NONE 0
+
+
+/* codegendata ****************************************************************/
+
+struct codegendata {
+ u4 flags; /* code generator flags */
+ u1 *mcodebase; /* base pointer of code area */
+ u1 *mcodeend; /* pointer to end of code area */
+ s4 mcodesize; /* complete size of code area (bytes) */
+ u1 *mcodeptr; /* code generation pointer */
+ u1 *lastmcodeptr; /* last patcher position of basic block */
+
+#if defined(ENABLE_INTRP)
+ u1 *ncodebase; /* base pointer of native code area */
+ s4 ncodesize; /* complete size of native code area */
+ u1 *ncodeptr; /* native code generation pointer */
+
+ u4 lastinstwithoutdispatch; /* ~0 if there was a dispatch */
+
+ s4 lastpatcheroffset; /* -1 if current super has no patcher */
+ s4 dynsuperm; /* offsets of start of current dynamic ...*/
+ s4 dynsupern; /* ... superinstruction starts */
+ struct superstart *superstarts; /* list of supers without patchers */
+#endif
+
+ dsegentry *dseg; /* chain of data segment entries */
+ s4 dseglen; /* used size of data area (bytes) */
+ /* data area grows from top to bottom */
+
+ jumpref *jumpreferences; /* list of jumptable target addresses */
+
+#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP) || defined(__S390__)
+ dataref *datareferences; /* list of data segment references */
+#endif
+
+#ifdef __cplusplus
+ DumpList<branch_label_ref_t*>* brancheslabel;
+ DumpList<Linenumber>* linenumbers; ///< List of line numbers.
+#else
+ // REMOVEME
+ DumpList* brancheslabel;
+ DumpList* linenumbers;
+#endif
+
+ methodinfo *method;
+
+ s4 stackframesize; /* stackframe size of this method */
+
+#if defined(ENABLE_REPLACEMENT)
+ rplpoint *replacementpoint; /* current replacement point */
+#endif
+};
+
+
+#define CODEGENDATA_FLAG_ERROR 0x00000001
+#define CODEGENDATA_FLAG_LONGBRANCHES 0x00000002
+
+
+#define CODEGENDATA_HAS_FLAG_ERROR(cd) \
+ ((cd)->flags & CODEGENDATA_FLAG_ERROR)
+
+#define CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) \
+ ((cd)->flags & CODEGENDATA_FLAG_LONGBRANCHES)
+
+
+/* branchref *****************************************************************/
+
+struct branchref {
+ s4 branchmpc; /* patching position in code segment */
+ s4 condition; /* conditional branch condition */
+ s4 reg; /* register number to check */
+ u4 options; /* branch options */
+ branchref *next; /* next element in branchref list */
+};
+
+
+/* branch_label_ref_t *********************************************************/
+
+struct branch_label_ref_t {
+ s4 mpc; /* position in code segment */
+ s4 label; /* label number */
+ s4 condition; /* conditional branch condition */
+ s4 reg; /* register number to check */
+ u4 options; /* branch options */
+/* listnode_t linkage; */
+};
+
+
+/* jumpref ********************************************************************/
+
+struct jumpref {
+ s4 tablepos; /* patching position in data segment */
+ basicblock *target; /* target basic block */
+ jumpref *next; /* next element in jumpref list */
+};
+
+
+/* dataref ********************************************************************/
+
+struct dataref {
+ s4 datapos; /* patching position in generated code */
+ dataref *next; /* next element in dataref list */
+};
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void codegen_init(void);
+void codegen_setup(jitdata *jd);
+
+bool codegen_generate(jitdata *jd);
+bool codegen_emit(jitdata *jd);
+
+#if defined(ENABLE_INTRP)
+bool intrp_codegen(jitdata *jd);
+#endif
+
+void codegen_close(void);
+
+void codegen_increase(codegendata *cd);
+
+#if defined(ENABLE_INTRP)
+u1 *codegen_ncode_increase(codegendata *cd, u1 *ncodeptr);
+#endif
+
+void codegen_add_branch_ref(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
+void codegen_resolve_branchrefs(codegendata *cd, basicblock *bptr);
+
+void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
+
+#if defined(ENABLE_REPLACEMENT)
+#if !defined(NDEBUG)
+void codegen_set_replacement_point_notrap(codegendata *cd, s4 type);
+void codegen_set_replacement_point(codegendata *cd, s4 type);
+#else
+void codegen_set_replacement_point_notrap(codegendata *cd);
+void codegen_set_replacement_point(codegendata *cd);
+#endif
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+void codegen_finish(jitdata *jd);
+
+java_handle_t *codegen_start_native_call(u1 *currentsp, u1 *pv);
+java_object_t *codegen_finish_native_call(u1 *currentsp, u1 *pv);
+
+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_SSA)
+void codegen_emit_phi_moves(jitdata *jd, basicblock *bptr);
+#endif
+
+// REMOVEME
+void codegen_emit_stub_compiler(jitdata *jd);
+void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int skipparams);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CODEGEN_COMMON_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:
+ */
#ifndef _DISASS_H
#define _DISASS_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "config.h"
#if defined(WITH_BINUTILS_DISASSEMBLER)
#define DISASSINSTR(code) \
do { \
if (opt_intrp) \
- (code) = intrp_disassinstr((code)); \
+ (code) = intrp_disassinstr((u1*) (code)); \
else \
- (code) = disassinstr((code)); \
+ (code) = disassinstr((u1*) (code)); \
} while (0)
#define DISASSEMBLE(start,end) \
# else /* defined(ENABLE_INTRP) */
#define DISASSINSTR(code) \
- (code) = disassinstr((code))
+ (code) = disassinstr((u1*) (code))
#define DISASSEMBLE(start,end) \
disassemble((start), (end))
#else /* defined(ENABLE_JIT) */
#define DISASSINSTR(code) \
- (code) = intrp_disassinstr((code))
+ (code) = intrp_disassinstr((u1*) (code))
#define DISASSEMBLE(start,end) \
intrp_disassemble((start), (end))
/* function prototypes *******************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#if defined(ENABLE_JIT)
void disassemble(u1 *start, u1 *end);
#endif
void intrp_disassemble(u1 *start, u1 *end);
#endif
-#endif /* defined(ENABLE_DISASSEMBLER) */
-
#ifdef __cplusplus
-}
+} // extern "C"
#endif
+#endif /* defined(ENABLE_DISASSEMBLER) */
+
#endif // _DISASS_H
#include "vm/options.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/methodheader.h"
#include "config.h"
#include "vm/types.h"
-#include "toolbox/list.h"
-
#include "vm/references.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/codegen-common.hpp"
/* convenience macros *********************************************************/
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void dseg_finish(jitdata *jd);
s4 dseg_add_unique_s4(codegendata *cd, s4 value);
void dseg_display(jitdata *jd);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _DSEG_H */
+++ /dev/null
-/* src/vm/jit/emit-common.c - common code emitter functions
-
- 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 "vm/types.h"
-
-#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"
-
-
-/* emit_load_s1 ****************************************************************
-
- Emits a possible load of the first source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->s1);
-
- reg = emit_load(jd, iptr, src, tempreg);
-
- return reg;
-}
-
-
-/* emit_load_s2 ****************************************************************
-
- Emits a possible load of the second source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->sx.s23.s2);
-
- reg = emit_load(jd, iptr, src, tempreg);
-
- return reg;
-}
-
-
-/* emit_load_s3 ****************************************************************
-
- Emits a possible load of the third source operand.
-
-*******************************************************************************/
-
-s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->sx.s23.s3);
-
- reg = emit_load(jd, iptr, src, tempreg);
-
- return reg;
-}
-
-
-/* emit_load_s1_low ************************************************************
-
- Emits a possible load of the low 32-bits of the first long source
- operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->s1);
-
- reg = emit_load_low(jd, iptr, src, tempreg);
-
- return reg;
-}
-#endif
-
-
-/* emit_load_s2_low ************************************************************
-
- Emits a possible load of the low 32-bits of the second long source
- operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->sx.s23.s2);
-
- reg = emit_load_low(jd, iptr, src, tempreg);
-
- return reg;
-}
-#endif
-
-
-/* emit_load_s3_low ************************************************************
-
- Emits a possible load of the low 32-bits of the third long source
- operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->sx.s23.s3);
-
- reg = emit_load_low(jd, iptr, src, tempreg);
-
- return reg;
-}
-#endif
-
-
-/* emit_load_s1_high ***********************************************************
-
- Emits a possible load of the high 32-bits of the first long source
- operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->s1);
-
- reg = emit_load_high(jd, iptr, src, tempreg);
-
- return reg;
-}
-#endif
-
-
-/* emit_load_s2_high ***********************************************************
-
- Emits a possible load of the high 32-bits of the second long source
- operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->sx.s23.s2);
-
- reg = emit_load_high(jd, iptr, src, tempreg);
-
- return reg;
-}
-#endif
-
-
-/* emit_load_s3_high ***********************************************************
-
- Emits a possible load of the high 32-bits of the third long source
- operand.
-
-*******************************************************************************/
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg)
-{
- varinfo *src;
- s4 reg;
-
- src = VAROP(iptr->sx.s23.s3);
-
- reg = emit_load_high(jd, iptr, src, tempreg);
-
- return reg;
-}
-#endif
-
-
-/* emit_store_dst **************************************************************
-
- This function generates the code to store the result of an
- operation back into a spilled pseudo-variable. If the
- pseudo-variable has not been spilled in the first place, this
- function will generate nothing.
-
-*******************************************************************************/
-
-void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
-{
- emit_store(jd, iptr, VAROP(iptr->dst), d);
-}
-
-
-/* emit_patcher_traps **********************************************************
-
- Generates the code for the patcher traps.
-
-*******************************************************************************/
-
-void emit_patcher_traps(jitdata *jd)
-{
- codegendata *cd;
- codeinfo *code;
- patchref_t *pr;
- u1 *savedmcodeptr;
- u1 *tmpmcodeptr;
- uint32_t mcode;
-
- /* get required compiler data */
-
- cd = jd->cd;
- code = jd->code;
-
- /* generate patcher traps code */
-
- for (pr = list_first(code->patchers); pr != NULL; pr = list_next(code->patchers, pr)) {
-
- /* Calculate the patch position where the original machine
- code is located and the trap should be placed. */
-
- tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
-
- /* Patch in the trap to call the signal handler (done at
- compile time). */
-
- savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
- cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
-
- mcode = emit_trap(cd);
-
- cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
-
- /* Remember the original machine code which is patched
- back in later (done at runtime). */
-
- pr->mcode = mcode;
- }
-}
-
-
-/* emit_bccz *******************************************************************
-
- Emit conditional and unconditional branch instructions on integer
- regiseters.
-
-*******************************************************************************/
-
-void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
-{
- s4 branchmpc;
- s4 disp;
-
- /* Target basic block already has an PC, so we can generate the
- branch immediately. */
-
- if ((target->mpc >= 0)) {
- STATISTICS(count_branches_resolved++);
-
- /* calculate the mpc of the branch instruction */
-
- branchmpc = cd->mcodeptr - cd->mcodebase;
- disp = target->mpc - branchmpc;
-
-#if defined(ENABLE_STATISTICS)
- count_emit_branch++;
- if ((int8_t)disp == disp) count_emit_branch_8bit++;
- else if ((int16_t)disp == disp) count_emit_branch_16bit++;
- else if ((int32_t)disp == disp) count_emit_branch_32bit++;
-# if SIZEOF_VOID_P == 8
- else if ((int64_t)disp == disp) count_emit_branch_64bit++;
-# endif
-#endif
-
- emit_branch(cd, disp, condition, reg, options);
- }
- else {
- /* current mcodeptr is the correct position,
- afterwards emit the NOPs */
-
- codegen_add_branch_ref(cd, target, condition, reg, options);
-
- /* generate NOPs as placeholder for branch code */
-
- BRANCH_NOPS;
- }
-}
-
-
-/* emit_bcc ********************************************************************
-
- Emit conditional and unconditional branch instructions on condition
- codes.
-
-*******************************************************************************/
-
-void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
-{
- emit_bccz(cd, target, condition, -1, options);
-}
-
-
-/* emit_br *********************************************************************
-
- Wrapper for unconditional branches.
-
-*******************************************************************************/
-
-void emit_br(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
-}
-
-
-/* emit_bxxz *******************************************************************
-
- Wrappers for branches on one integer register.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-
-void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
-{
- emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
-{
- emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
-{
- emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
-{
- emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
-}
-
-void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
-{
- emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
-}
-
-void emit_blez(codegendata *cd, basicblock *target, s4 reg)
-{
- emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
-
-
-/* emit_bxx ********************************************************************
-
- Wrappers for branches on two integer registers.
-
- We use PACK_REGS here, so we don't have to change the branchref
- data structure and the emit_bccz function.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
-
-void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
-{
- emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
-}
-
-void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
-{
- emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
-
-
-/* emit_bxx ********************************************************************
-
- Wrappers for branches on condition codes.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-
-void emit_beq(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
-}
-
-void emit_bne(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
-}
-
-void emit_blt(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
-}
-
-void emit_bge(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
-}
-
-void emit_bgt(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
-}
-
-void emit_ble(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
-}
-
-#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
-void emit_bult(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
-}
-
-void emit_bule(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
-}
-
-void emit_buge(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
-}
-
-void emit_bugt(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
-}
-#endif
-
-#if defined(__POWERPC__) || defined(__POWERPC64__)
-void emit_bnan(codegendata *cd, basicblock *target)
-{
- emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
-}
-#endif
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
-
-
-/* emit_label_bccz *************************************************************
-
- Emit a branch to a label. Possibly emit the branch, if it is a
- backward branch.
-
-*******************************************************************************/
-
-void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
-{
- list_t *list;
- branch_label_ref_t *br;
- s4 mpc;
- s4 disp;
-
- /* get the label list */
-
- list = cd->brancheslabel;
-
- /* search if the label is already in the list */
-
- for (br = list_first(list); br != NULL; br = list_next(list, br)) {
- /* is this entry the correct label? */
-
- if (br->label == label)
- break;
- }
-
- if (br == NULL) {
- /* current mcodeptr is the correct position,
- afterwards emit the NOPs */
-
- codegen_branch_label_add(cd, label, condition, reg, options);
-
- /* generate NOPs as placeholder for branch code */
-
- BRANCH_NOPS;
- return;
- }
-
- /* Branch reference was found. */
-
- /* calculate the mpc of the branch instruction */
-
- mpc = cd->mcodeptr - cd->mcodebase;
- disp = br->mpc - mpc;
-
-#if defined(ENABLE_STATISTICS)
- count_emit_branch++;
- if ((int8_t)disp == disp) count_emit_branch_8bit++;
- else if ((int16_t)disp == disp) count_emit_branch_16bit++;
- else if ((int32_t)disp == disp) count_emit_branch_32bit++;
-# if SIZEOF_VOID_P == 8
- else if ((int64_t)disp == disp) count_emit_branch_64bit++;
-# endif
-#endif
-
- emit_branch(cd, disp, condition, reg, options);
-
- /* now remove the branch reference */
-
- list_remove(list, br);
-}
-
-
-/* emit_label ******************************************************************
-
- Emit a label for a branch. Possibly emit the branch, if it is a
- forward branch.
-
-*******************************************************************************/
-
-void emit_label(codegendata *cd, s4 label)
-{
- list_t *list;
- branch_label_ref_t *br;
- s4 mpc;
- s4 disp;
- u1 *mcodeptr;
-
- /* get the label list */
-
- list = cd->brancheslabel;
-
- /* search if the label is already in the list */
-
- for (br = list_first(list); br != NULL; br = list_next(list, br)) {
- /* is this entry the correct label? */
-
- if (br->label == label)
- break;
- }
-
- if (br == NULL) {
- /* No branch reference found, add the label to the list (use
- invalid values for condition and register). */
-
- codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
- return;
- }
-
- /* Branch reference was found. */
-
- /* calculate the mpc of the branch instruction */
-
- mpc = cd->mcodeptr - cd->mcodebase;
- disp = mpc - br->mpc;
-
- /* temporary set the mcodeptr */
-
- mcodeptr = cd->mcodeptr;
- cd->mcodeptr = cd->mcodebase + br->mpc;
-
-#if defined(ENABLE_STATISTICS)
- count_emit_branch++;
- if ((int8_t)disp == disp) count_emit_branch_8bit++;
- else if ((int16_t)disp == disp) count_emit_branch_16bit++;
- else if ((int32_t)disp == disp) count_emit_branch_32bit++;
-# if SIZEOF_VOID_P == 8
- else if ((int64_t)disp == disp) count_emit_branch_64bit++;
-# endif
-#endif
-
- emit_branch(cd, disp, br->condition, br->reg, br->options);
-
- /* restore mcodeptr */
-
- cd->mcodeptr = mcodeptr;
-
- /* now remove the branch reference */
-
- list_remove(list, br);
-}
-
-
-/* emit_label_bcc **************************************************************
-
- Emit conditional and unconditional label-branch instructions on
- condition codes.
-
-*******************************************************************************/
-
-void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
-{
- emit_label_bccz(cd, label, condition, -1, options);
-}
-
-
-/* emit_label_br ***************************************************************
-
- Wrapper for unconditional label-branches.
-
-*******************************************************************************/
-
-void emit_label_br(codegendata *cd, s4 label)
-{
- emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
-}
-
-
-/* emit_label_bxxz *************************************************************
-
- Wrappers for label-branches on one integer register.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-
-void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
-{
- emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
-
-
-/* emit_label_bxx **************************************************************
-
- Wrappers for label-branches on condition codes.
-
-*******************************************************************************/
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-
-void emit_label_beq(codegendata *cd, s4 label)
-{
- emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
-}
-
-void emit_label_bne(codegendata *cd, s4 label)
-{
- emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
-}
-
-void emit_label_blt(codegendata *cd, s4 label)
-{
- emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
-}
-
-void emit_label_bge(codegendata *cd, s4 label)
-{
- emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
-}
-
-void emit_label_bgt(codegendata *cd, s4 label)
-{
- emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
-}
-
-void emit_label_ble(codegendata *cd, s4 label)
-{
- emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
-}
-
-#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
-
-
-/*
- * These 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/emit-common.cpp - common code emitter functions
+
+ 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 <algorithm>
+
+#include "vm/types.h"
+
+#include "arch.h"
+#include "codegen.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/options.h"
+#include "vm/statistics.h"
+
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+
+
+/* emit_load_s1 ****************************************************************
+
+ Emits a possible load of the first source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->s1);
+
+ reg = emit_load(jd, iptr, src, tempreg);
+
+ return reg;
+}
+
+
+/* emit_load_s2 ****************************************************************
+
+ Emits a possible load of the second source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->sx.s23.s2);
+
+ reg = emit_load(jd, iptr, src, tempreg);
+
+ return reg;
+}
+
+
+/* emit_load_s3 ****************************************************************
+
+ Emits a possible load of the third source operand.
+
+*******************************************************************************/
+
+s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->sx.s23.s3);
+
+ reg = emit_load(jd, iptr, src, tempreg);
+
+ return reg;
+}
+
+
+/* emit_load_s1_low ************************************************************
+
+ Emits a possible load of the low 32-bits of the first long source
+ operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->s1);
+
+ reg = emit_load_low(jd, iptr, src, tempreg);
+
+ return reg;
+}
+#endif
+
+
+/* emit_load_s2_low ************************************************************
+
+ Emits a possible load of the low 32-bits of the second long source
+ operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->sx.s23.s2);
+
+ reg = emit_load_low(jd, iptr, src, tempreg);
+
+ return reg;
+}
+#endif
+
+
+/* emit_load_s3_low ************************************************************
+
+ Emits a possible load of the low 32-bits of the third long source
+ operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->sx.s23.s3);
+
+ reg = emit_load_low(jd, iptr, src, tempreg);
+
+ return reg;
+}
+#endif
+
+
+/* emit_load_s1_high ***********************************************************
+
+ Emits a possible load of the high 32-bits of the first long source
+ operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->s1);
+
+ reg = emit_load_high(jd, iptr, src, tempreg);
+
+ return reg;
+}
+#endif
+
+
+/* emit_load_s2_high ***********************************************************
+
+ Emits a possible load of the high 32-bits of the second long source
+ operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->sx.s23.s2);
+
+ reg = emit_load_high(jd, iptr, src, tempreg);
+
+ return reg;
+}
+#endif
+
+
+/* emit_load_s3_high ***********************************************************
+
+ Emits a possible load of the high 32-bits of the third long source
+ operand.
+
+*******************************************************************************/
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg)
+{
+ varinfo *src;
+ s4 reg;
+
+ src = VAROP(iptr->sx.s23.s3);
+
+ reg = emit_load_high(jd, iptr, src, tempreg);
+
+ return reg;
+}
+#endif
+
+
+/* emit_store_dst **************************************************************
+
+ This function generates the code to store the result of an
+ operation back into a spilled pseudo-variable. If the
+ pseudo-variable has not been spilled in the first place, this
+ function will generate nothing.
+
+*******************************************************************************/
+
+void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
+{
+ emit_store(jd, iptr, VAROP(iptr->dst), d);
+}
+
+
+/* emit_patcher_traps **********************************************************
+
+ Generates the code for the patcher traps.
+
+*******************************************************************************/
+
+void emit_patcher_traps(jitdata *jd)
+{
+ codegendata *cd;
+ codeinfo *code;
+ u1 *savedmcodeptr;
+ u1 *tmpmcodeptr;
+ uint32_t mcode;
+
+ /* get required compiler data */
+
+ cd = jd->cd;
+ code = jd->code;
+
+ // Generate patcher traps code.
+ for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
+ patchref_t& pr = *it;
+
+ /* Calculate the patch position where the original machine
+ code is located and the trap should be placed. */
+
+ tmpmcodeptr = (u1 *) (cd->mcodebase + pr.mpc);
+
+ /* Patch in the trap to call the signal handler (done at
+ compile time). */
+
+ savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
+ cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
+
+ mcode = emit_trap(cd);
+
+ cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
+
+ /* Remember the original machine code which is patched
+ back in later (done at runtime). */
+
+ pr.mcode = mcode;
+ }
+}
+
+
+/* emit_bccz *******************************************************************
+
+ Emit conditional and unconditional branch instructions on integer
+ regiseters.
+
+*******************************************************************************/
+
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
+{
+ s4 branchmpc;
+ s4 disp;
+
+ /* Target basic block already has an PC, so we can generate the
+ branch immediately. */
+
+ if ((target->mpc >= 0)) {
+ STATISTICS(count_branches_resolved++);
+
+ /* calculate the mpc of the branch instruction */
+
+ branchmpc = cd->mcodeptr - cd->mcodebase;
+ disp = target->mpc - branchmpc;
+
+#if defined(ENABLE_STATISTICS)
+ count_emit_branch++;
+ if ((int8_t)disp == disp) count_emit_branch_8bit++;
+ else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+ else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+ emit_branch(cd, disp, condition, reg, options);
+ }
+ else {
+ /* current mcodeptr is the correct position,
+ afterwards emit the NOPs */
+
+ codegen_add_branch_ref(cd, target, condition, reg, options);
+
+ /* generate NOPs as placeholder for branch code */
+
+ BRANCH_NOPS;
+ }
+}
+
+
+/* emit_bcc ********************************************************************
+
+ Emit conditional and unconditional branch instructions on condition
+ codes.
+
+*******************************************************************************/
+
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
+{
+ emit_bccz(cd, target, condition, -1, options);
+}
+
+
+/* emit_br *********************************************************************
+
+ Wrapper for unconditional branches.
+
+*******************************************************************************/
+
+void emit_br(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
+}
+
+
+/* emit_bxxz *******************************************************************
+
+ Wrappers for branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
+}
+
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
+}
+
+void emit_blez(codegendata *cd, basicblock *target, s4 reg)
+{
+ emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
+
+
+/* emit_bxx ********************************************************************
+
+ Wrappers for branches on two integer registers.
+
+ We use PACK_REGS here, so we don't have to change the branchref
+ data structure and the emit_bccz function.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
+{
+ emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
+{
+ emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
+
+
+/* emit_bxx ********************************************************************
+
+ Wrappers for branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_beq(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_bne(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_blt(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_bge(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_bgt(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
+}
+
+void emit_ble(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
+}
+
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
+}
+
+void emit_bule(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
+}
+
+void emit_buge(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
+}
+
+void emit_bugt(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
+}
+#endif
+
+#if defined(__POWERPC__) || defined(__POWERPC64__)
+void emit_bnan(codegendata *cd, basicblock *target)
+{
+ emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
+}
+#endif
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
+/* emit_label_bccz *************************************************************
+
+ Emit a branch to a label. Possibly emit the branch, if it is a
+ backward branch.
+
+*******************************************************************************/
+
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
+{
+ // Search if the label is already in the list.
+ DumpList<branch_label_ref_t*>::iterator it;
+ for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
+ branch_label_ref_t* br = *it;
+
+ /* is this entry the correct label? */
+
+ if (br->label == label)
+ break;
+ }
+
+ if (it == cd->brancheslabel->end()) {
+ /* current mcodeptr is the correct position,
+ afterwards emit the NOPs */
+
+ codegen_branch_label_add(cd, label, condition, reg, options);
+
+ /* generate NOPs as placeholder for branch code */
+
+ BRANCH_NOPS;
+ return;
+ }
+
+ // Branch reference was found.
+ branch_label_ref_t* br = *it;
+
+ /* calculate the mpc of the branch instruction */
+
+ int32_t mpc = cd->mcodeptr - cd->mcodebase;
+ int32_t disp = br->mpc - mpc;
+
+#if defined(ENABLE_STATISTICS)
+ count_emit_branch++;
+ if ((int8_t)disp == disp) count_emit_branch_8bit++;
+ else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+ else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+ emit_branch(cd, disp, condition, reg, options);
+
+ // Now remove the branch reference.
+ cd->brancheslabel->remove(br);
+}
+
+
+/* emit_label ******************************************************************
+
+ Emit a label for a branch. Possibly emit the branch, if it is a
+ forward branch.
+
+*******************************************************************************/
+
+void emit_label(codegendata *cd, s4 label)
+{
+ u1* mcodeptr;
+
+ // Search if the label is already in the list.
+ DumpList<branch_label_ref_t*>::iterator it;
+ for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
+ branch_label_ref_t* br = *it;
+
+ /* is this entry the correct label? */
+
+ if (br->label == label)
+ break;
+ }
+
+ if (it == cd->brancheslabel->end()) {
+ /* No branch reference found, add the label to the list (use
+ invalid values for condition and register). */
+
+ codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
+ return;
+ }
+
+ // Branch reference was found.
+ branch_label_ref_t* br = *it;
+
+ // Calculate the mpc of the branch instruction.
+ int32_t mpc = cd->mcodeptr - cd->mcodebase;
+ int32_t disp = mpc - br->mpc;
+
+ /* temporary set the mcodeptr */
+
+ mcodeptr = cd->mcodeptr;
+ cd->mcodeptr = cd->mcodebase + br->mpc;
+
+#if defined(ENABLE_STATISTICS)
+ count_emit_branch++;
+ if ((int8_t)disp == disp) count_emit_branch_8bit++;
+ else if ((int16_t)disp == disp) count_emit_branch_16bit++;
+ else if ((int32_t)disp == disp) count_emit_branch_32bit++;
+# if SIZEOF_VOID_P == 8
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
+# endif
+#endif
+
+ emit_branch(cd, disp, br->condition, br->reg, br->options);
+
+ /* restore mcodeptr */
+
+ cd->mcodeptr = mcodeptr;
+
+ // Now remove the branch reference.
+ cd->brancheslabel->remove(br);
+}
+
+
+/* emit_label_bcc **************************************************************
+
+ Emit conditional and unconditional label-branch instructions on
+ condition codes.
+
+*******************************************************************************/
+
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
+{
+ emit_label_bccz(cd, label, condition, -1, options);
+}
+
+
+/* emit_label_br ***************************************************************
+
+ Wrapper for unconditional label-branches.
+
+*******************************************************************************/
+
+void emit_label_br(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
+}
+
+
+/* emit_label_bxxz *************************************************************
+
+ Wrappers for label-branches on one integer register.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
+{
+ emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
+
+
+/* emit_label_bxx **************************************************************
+
+ Wrappers for label-branches on condition codes.
+
+*******************************************************************************/
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+
+void emit_label_beq(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
+}
+
+void emit_label_bne(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
+}
+
+void emit_label_blt(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
+}
+
+void emit_label_bge(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
+}
+
+void emit_label_bgt(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
+}
+
+void emit_label_ble(codegendata *cd, s4 label)
+{
+ emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
+}
+
+#endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
+
+
+/*
+ * These 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/emit-common.h - common code emitter functions
-
- 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 _EMIT_COMMON_H
-#define _EMIT_COMMON_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "arch.h"
-
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
-
-
-/* branch labels **************************************************************/
-
-#define BRANCH_LABEL_1 1
-#define BRANCH_LABEL_2 2
-#define BRANCH_LABEL_3 3
-#define BRANCH_LABEL_4 4
-#define BRANCH_LABEL_5 5
-#define BRANCH_LABEL_6 6
-
-
-/* constant range macros ******************************************************/
-
-#if SIZEOF_VOID_P == 8
-
-# define IS_IMM8(c) \
- (((s8) (c) >= -128) && ((s8) (c) <= 127))
-
-# define IS_IMM32(c) \
- (((s8) (c) >= (-2147483647-1)) && ((s8) (c) <= 2147483647))
-
-#else
-
-# define IS_IMM8(c) \
- (((s4) (c) >= -128) && ((s4) (c) <= 127))
-
-# define IS_IMM16(c) \
- (((s4) (c) >= -32768) && ((s4) (c) <= 32767))
-
-#endif
-
-
-/* code generation functions **************************************************/
-
-s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
-s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg);
-
-#if SIZEOF_VOID_P == 4
-s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
-s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg);
-
-s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
-s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg);
-s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg);
-#endif
-
-void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
-void emit_store_dst(jitdata *jd, instruction *iptr, s4 d);
-
-#if SIZEOF_VOID_P == 4
-void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
-void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
-#endif
-
-void emit_copy(jitdata *jd, instruction *iptr);
-
-void emit_iconst(codegendata *cd, s4 d, s4 value);
-void emit_lconst(codegendata *cd, s4 d, s8 value);
-
-/* branch-emitting functions */
-void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
-void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
-
-/* wrapper for unconditional branches */
-void emit_br(codegendata *cd, basicblock *target);
-
-/* wrappers for branches on one integer register */
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-void emit_beqz(codegendata *cd, basicblock *target, s4 reg);
-void emit_bnez(codegendata *cd, basicblock *target, s4 reg);
-void emit_bltz(codegendata *cd, basicblock *target, s4 reg);
-void emit_bgez(codegendata *cd, basicblock *target, s4 reg);
-void emit_bgtz(codegendata *cd, basicblock *target, s4 reg);
-void emit_blez(codegendata *cd, basicblock *target, s4 reg);
-#endif
-
-/* wrappers for branches on two integer registers */
-
-#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
-void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2);
-void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2);
-#endif
-
-/* wrappers for branches on condition codes */
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-void emit_beq(codegendata *cd, basicblock *target);
-void emit_bne(codegendata *cd, basicblock *target);
-void emit_blt(codegendata *cd, basicblock *target);
-void emit_bge(codegendata *cd, basicblock *target);
-void emit_bgt(codegendata *cd, basicblock *target);
-void emit_ble(codegendata *cd, basicblock *target);
-#endif
-
-#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
-void emit_bult(codegendata *cd, basicblock *target);
-void emit_bule(codegendata *cd, basicblock *target);
-void emit_buge(codegendata *cd, basicblock *target);
-void emit_bugt(codegendata *cd, basicblock *target);
-#endif
-
-#if defined(__POWERPC__) || defined(__POWERPC64__)
-void emit_bnan(codegendata *cd, basicblock *target);
-#endif
-
-/* label-branches */
-void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
-void emit_label(codegendata *cd, s4 label);
-void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
-
-void emit_label_br(codegendata *cd, s4 label);
-
-#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
-void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
-#endif
-
-#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
-void emit_label_beq(codegendata *cd, s4 label);
-void emit_label_bne(codegendata *cd, s4 label);
-void emit_label_blt(codegendata *cd, s4 label);
-void emit_label_bge(codegendata *cd, s4 label);
-void emit_label_bgt(codegendata *cd, s4 label);
-void emit_label_ble(codegendata *cd, s4 label);
-#endif
-
-/* machine dependent branch-emitting function */
-void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options);
-
-void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg);
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
-void emit_arraystore_check(codegendata *cd, instruction *iptr);
-void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1);
-void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
-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);
-
-void emit_verbosecall_enter(jitdata *jd);
-void emit_verbosecall_exit(jitdata *jd);
-
-#endif /* _EMIT_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:
- * vim:noexpandtab:sw=4:ts=4:
- */
--- /dev/null
+/* src/vm/jit/emit-common.hpp - common code emitter functions
+
+ 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 _EMIT_COMMON_H
+#define _EMIT_COMMON_H
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "arch.h"
+
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
+
+
+/* branch labels **************************************************************/
+
+#define BRANCH_LABEL_1 1
+#define BRANCH_LABEL_2 2
+#define BRANCH_LABEL_3 3
+#define BRANCH_LABEL_4 4
+#define BRANCH_LABEL_5 5
+#define BRANCH_LABEL_6 6
+
+
+/* constant range macros ******************************************************/
+
+#if SIZEOF_VOID_P == 8
+
+# define IS_IMM8(c) \
+ (((s8) (c) >= -128) && ((s8) (c) <= 127))
+
+# define IS_IMM32(c) \
+ (((s8) (c) >= (-2147483647-1)) && ((s8) (c) <= 2147483647))
+
+#else
+
+# define IS_IMM8(c) \
+ (((s4) (c) >= -128) && ((s4) (c) <= 127))
+
+# define IS_IMM16(c) \
+ (((s4) (c) >= -32768) && ((s4) (c) <= 32767))
+
+#endif
+
+
+/* code generation functions **************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
+s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg);
+
+#if SIZEOF_VOID_P == 4
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
+s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg);
+
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg);
+s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg);
+s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg);
+#endif
+
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
+void emit_store_dst(jitdata *jd, instruction *iptr, s4 d);
+
+#if SIZEOF_VOID_P == 4
+void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
+void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d);
+#endif
+
+void emit_copy(jitdata *jd, instruction *iptr);
+
+void emit_iconst(codegendata *cd, s4 d, s4 value);
+void emit_lconst(codegendata *cd, s4 d, s8 value);
+
+/* branch-emitting functions */
+void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options);
+void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options);
+
+/* wrapper for unconditional branches */
+void emit_br(codegendata *cd, basicblock *target);
+
+/* wrappers for branches on one integer register */
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_beqz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bnez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bltz(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgez(codegendata *cd, basicblock *target, s4 reg);
+void emit_bgtz(codegendata *cd, basicblock *target, s4 reg);
+void emit_blez(codegendata *cd, basicblock *target, s4 reg);
+#endif
+
+/* wrappers for branches on two integer registers */
+
+#if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2);
+#endif
+
+/* wrappers for branches on condition codes */
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+void emit_beq(codegendata *cd, basicblock *target);
+void emit_bne(codegendata *cd, basicblock *target);
+void emit_blt(codegendata *cd, basicblock *target);
+void emit_bge(codegendata *cd, basicblock *target);
+void emit_bgt(codegendata *cd, basicblock *target);
+void emit_ble(codegendata *cd, basicblock *target);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
+void emit_bult(codegendata *cd, basicblock *target);
+void emit_bule(codegendata *cd, basicblock *target);
+void emit_buge(codegendata *cd, basicblock *target);
+void emit_bugt(codegendata *cd, basicblock *target);
+#endif
+
+#if defined(__POWERPC__) || defined(__POWERPC64__)
+void emit_bnan(codegendata *cd, basicblock *target);
+#endif
+
+/* label-branches */
+void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
+void emit_label(codegendata *cd, s4 label);
+void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options);
+
+void emit_label_br(codegendata *cd, s4 label);
+
+#if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
+void emit_label_beqz(codegendata *cd, s4 label, s4 reg);
+#endif
+
+#if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
+void emit_label_beq(codegendata *cd, s4 label);
+void emit_label_bne(codegendata *cd, s4 label);
+void emit_label_blt(codegendata *cd, s4 label);
+void emit_label_bge(codegendata *cd, s4 label);
+void emit_label_bgt(codegendata *cd, s4 label);
+void emit_label_ble(codegendata *cd, s4 label);
+#endif
+
+/* machine dependent branch-emitting function */
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options);
+
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg);
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2);
+void emit_arraystore_check(codegendata *cd, instruction *iptr);
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1);
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg);
+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);
+
+void emit_verbosecall_enter(jitdata *jd);
+void emit_verbosecall_exit(jitdata *jd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _EMIT_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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "mm/memory.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
#include "vm/jit/exceptiontable.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* exceptiontable_create *******************************************************
#include <stdint.h>
-#include "vm/jit/code.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/jit.hpp"
/* exceptiontable_t ***********************************************************/
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void exceptiontable_create(jitdata *jd);
void exceptiontable_free(codeinfo *code);
void exceptiontable_print(codeinfo *code);
#endif
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
#endif /* _EXCEPTIONTABLE_H */
if (i%4 == 0)
printf("\n\t\t");
printf("M%02d%c", i, (i >= slots) ? '(' : ' ');
-#ifdef HAS_4BYTE_STACKSLOT
- printf("%08lx",(unsigned long)*sp++);
-#else
printf("%016llx",(unsigned long long)*sp++);
-#endif
printf("%c", (i >= slots) ? ')' : ' ');
}
printf("\n");
#include "arch.h"
#include "md-abi.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
/* executionstate_t ************************************************************
/* prototypes *****************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#if !defined(NDEBUG)
void executionstate_sanity_check(void *context);
void executionstate_println(executionstate_t *es);
void md_executionstate_read(executionstate_t *es, void *ucontext);
void md_executionstate_write(executionstate_t *es, void *ucontext);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _EXECUTIONSTATE_H */
\
md-abi.c \
md-abi.h \
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 1
#define SUPPORT_LONG 1
#include "vm/jit/i386/emit.h"
#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
-#include "threads/lock-common.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/utf8.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
#include "vm/jit/jitcache.hpp"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
/* src/vm/jit/i386/codegen.h - code generation macros and definitions for i386
- 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/i386/emit.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#if defined(ENABLE_LSRA)
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 6
-
-
/* macros to create code ******************************************************/
#define M_BYTE1(a) \
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/global.h"
#include "vm/signallocal.h"
intptr_t val;
int type;
void *p;
- java_object_t *o;
_uc = (ucontext_t *) _p;
_mc = _uc->uc_mcontext;
/* Set registers. */
if (type == TRAP_COMPILER) {
- if (p == NULL) {
- o = builtin_retrieve_exception();
-
+ if (p == NULL) {
_ss->__esp = (uintptr_t) sp; /* Remove RA from stack. */
-
- _ss->__eax = (uintptr_t) o;
- _ss->__ecx = (uintptr_t) xpc; /* REG_ITMP2_XPC */
- _ss->__eip = (uintptr_t) asm_handle_exception;
}
- else {
- _ss->__eip = (uintptr_t) p;
- }
- }
- else {
- _ss->__eax = (uintptr_t) p;
- _ss->__ecx = (uintptr_t) xpc; /* REG_ITMP2_XPC */
- _ss->__eip = (uintptr_t) asm_handle_exception;
}
}
u1 *xpc;
int type;
intptr_t val;
- void *p;
_uc = (ucontext_t *) _p;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
-
- _ss->__eax = (uintptr_t) p;
- _ss->__ecx = (uintptr_t) xpc; /* REG_ITMP2_XPC */
- _ss->__eip = (uintptr_t) asm_handle_exception;
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
u1 *xpc;
int type;
intptr_t val;
- void *p;
_uc = (ucontext_t *) _p;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
-
- if (p != NULL) {
- _ss->__eax = (uintptr_t) p;
- _ss->__ecx = (uintptr_t) xpc; /* REG_ITMP2_XPC */
- _ss->__eip = (uintptr_t) asm_handle_exception;
- }
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
/* md_executionstate_read ******************************************************
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "vm/options.h"
#include "vm/statistics.h"
#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/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
#include "vm/types.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#define REG_AL 0
/* src/vm/jit/i386/freebsd/md-os.c - machine dependent i386 FreeBSD functions
- Copyright (C) 1996-2005, 2006, 2008
+ 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"
+#include <stdint.h>
#include <ucontext.h>
-#include "vm/jit/i386/md-abi.h"
+#include "vm/types.h"
+#include "vm/jit/i386/codegen.h"
+#include "vm/jit/i386/md.h"
+
+#include "threads/thread.hpp"
+
+#include "vm/jit/builtin.hpp"
#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 ***************************************************
- NullPointerException signal handler for hardware null pointer
- check.
+ Signal handler for hardware exceptions.
*******************************************************************************/
void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
{
- ucontext_t *_uc;
- mcontext_t *_mc;
- u1 *sp;
- u1 *ra;
- u1 *xpc;
+ 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;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
-
+
+ pv = NULL; /* is resolved during stackframeinfo creation */
sp = (u1 *) _mc->mc_esp;
xpc = (u1 *) _mc->mc_eip;
- ra = xpc; /* return address is equal to xpc */
+ 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;
+
+ switch (d) {
+ case EAX:
+ val = _mc->mc_eax;
+ break;
+ case ECX:
+ val = _mc->mc_ecx;
+ break;
+ case EDX:
+ val = _mc->mc_edx;
+ break;
+ case EBX:
+ val = _mc->mc_ebx;
+ break;
+ case ESP:
+ val = _mc->mc_esp;
+ break;
+ case EBP:
+ val = _mc->mc_ebp;
+ break;
+ case ESI:
+ val = _mc->mc_esi;
+ break;
+ case EDI:
+ val = _mc->mc_edi;
+ break;
+ default:
+ vm_abort("md_signal_handler_sigsegv: Unkown register %d", 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;
+ }
- _mc->mc_eax =
- (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
-
- _mc->mc_ecx = (ptrint) xpc; /* REG_ITMP2_XPC */
- _mc->mc_eip = (ptrint) asm_handle_exception;
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* Set registers. */
+
+ if (type == TRAP_COMPILER) {
+ if (p == NULL) {
+ _mc->mc_esp = (uintptr_t) sp; // Remove RA from stack.
+ }
+ }
}
void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
{
- ucontext_t *_uc;
- mcontext_t *_mc;
- u1 *sp;
- u1 *ra;
- u1 *xpc;
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ u1 *pv;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ s4 type;
+ ptrint val;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
+ pv = NULL; /* is resolved during stackframeinfo creation */
sp = (u1 *) _mc->mc_esp;
xpc = (u1 *) _mc->mc_eip;
ra = xpc; /* return address is equal to xpc */
- _mc->mc_eax =
- (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
-
- _mc->mc_ecx = (ptrint) xpc; /* REG_ITMP2_XPC */
- _mc->mc_eip = (ptrint) asm_handle_exception;
+ /* This is an ArithmeticException. */
+
+ type = TRAP_ArithmeticException;
+ val = 0;
+
+ /* Handle the trap. */
+
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
+
+
+/* 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;
+
+ _uc = (ucontext_t *) _p;
+ _mc = &_uc->uc_mcontext;
+
+ pv = NULL; /* is resolved during stackframeinfo creation */
+ sp = (u1 *) _mc->mc_esp;
+ xpc = (u1 *) _mc->mc_eip;
+ ra = xpc; /* return address is equal to xpc */
+
+ type = TRAP_PATCHER;
+ val = 0;
+
+ /* Handle the trap. */
+
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
+
+
+/* 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->mc_eip;
+ sp = (u1 *) _mc->mc_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->mc_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 = (ucontext_t*) context;
+ mcontext_t* _mc = &_uc->uc_mcontext;
+
+ // Read special registers.
+ es->pc = (u1 *) _mc->mc_eip;
+ es->sp = (u1 *) _mc->mc_esp;
+ es->pv = NULL; /* pv must be looked up via AVL tree */
+
+ // Read integer registers.
+ es->intregs[EAX] = _mc->mc_eax;
+ es->intregs[ECX] = _mc->mc_ecx;
+ es->intregs[EDX] = _mc->mc_edx;
+ es->intregs[EBX] = _mc->mc_ebx;
+ es->intregs[ESP] = _mc->mc_esp;
+ es->intregs[EBP] = _mc->mc_ebp;
+ es->intregs[ESI] = _mc->mc_esi;
+ es->intregs[EDI] = _mc->mc_edi;
+
+ // Read float registers.
+ for (int 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 = (ucontext_t*) context;
+ mcontext_t* _mc = &_uc->uc_mcontext;
+
+ // Write integer registers.
+ _mc->mc_eax = es->intregs[EAX];
+ _mc->mc_ecx = es->intregs[ECX];
+ _mc->mc_edx = es->intregs[EDX];
+ _mc->mc_ebx = es->intregs[EBX];
+ _mc->mc_esp = es->intregs[ESP];
+ _mc->mc_ebp = es->intregs[EBP];
+ _mc->mc_esi = es->intregs[ESI];
+ _mc->mc_edi = es->intregs[EDI];
+
+ // Write special registers.
+ _mc->mc_eip = (uintptr_t) es->pc;
+ _mc->mc_esp = (uintptr_t) es->sp;
}
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
ptrint val;
s4 type;
void *p;
- java_object_t *o;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
if (type == TRAP_COMPILER) {
if (p == NULL) {
- o = builtin_retrieve_exception();
-
_mc->gregs[REG_ESP] = (uintptr_t) sp; /* Remove RA from stack. */
-
- _mc->gregs[REG_EAX] = (uintptr_t) o;
- _mc->gregs[REG_ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
- _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
- }
- else {
- _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 */
- _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
- }
}
u1 *xpc;
s4 type;
ptrint val;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
-
- _mc->gregs[REG_EAX] = (uintptr_t) p;
- _mc->gregs[REG_ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
- _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
u1 *xpc;
s4 type;
ptrint val;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
-
- if (p != NULL) {
- _mc->gregs[REG_EAX] = (uintptr_t) p;
- _mc->gregs[REG_ECX] = (uintptr_t) xpc; /* REG_ITMP2_XPC */
- _mc->gregs[REG_EIP] = (uintptr_t) asm_handle_exception;
- }
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
--- /dev/null
+/* src/vm/jit/i386/md-stubs.hpp - i386 JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on an i386 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 6;
+}
+
+#endif // _MD_STUBS_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 "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* md_init *********************************************************************
#include <assert.h>
#include <stdint.h>
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/methodtree.h"
inline static void md_cacheflush(void *addr, int nbytes)
{
- /* do nothing */
+ // Compiler optimization barrier (see PR97).
+ __asm__ __volatile__ ("" : : : "memory");
}
inline static void md_icacheflush(void *addr, int nbytes)
{
- /* do nothing */
+ // Compiler optimization barrier (see PR97).
+ __asm__ __volatile__ ("" : : : "memory");
}
inline static void md_dcacheflush(void *addr, int nbytes)
{
- /* do nothing */
+ // Compiler optimization barrier (see PR97).
+ __asm__ __volatile__ ("" : : : "memory");
}
#endif /* _VM_JIT_I386_MD_H */
#include "vm/types.h"
#include "vm/jit/i386/codegen.h"
+#include "vm/jit/i386/md.h"
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#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/patcher-common.hpp"
-#define PATCH_BACK_ORIGINAL_MCODE *((u2 *) pr->mpc) = (u2) pr->mcode
+#define PATCH_BACK_ORIGINAL_MCODE \
+ do { \
+ *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode; \
+ md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE); \
+ } while (0)
/* patcher_patch_code **********************************************************
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch the field value's address */
*((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch the field's offset */
*((u4 *) (ra + 2)) = (u4) (fi->offset);
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch the field's offset */
if (fi->type != TYPE_LNG) {
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch the field's offset */
if (!IS_2_WORD_TYPE(fi->type)) {
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch the classinfo pointer */
*((ptrint *) (ra + 1)) = (ptrint) c;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch the classinfo pointer */
*((ptrint *) (ra + 7 + 4)) = (ptrint) c;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch the classinfo pointer */
*((ptrint *) (ra + 4)) = (ptrint) c;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch stubroutine */
*((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch vftbl index */
*((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch interfacetable index */
*((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch class flags */
*((s4 *) (ra + 1)) = (s4) c->flags;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch super class index */
*((s4 *) (ra + 6 + 2)) = (s4) c->index;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch super class index */
*((s4 *) (ra + 6 + 2)) = (s4) c->index;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch super class' vftbl */
*((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch super class' vftbl */
*((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
ptrint val;
s4 type;
void *p;
- java_object_t *o;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
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;
- }
}
u1 *xpc;
s4 type;
ptrint val;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
/* 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;
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
u1 *xpc;
s4 type;
ptrint val;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
/* 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;
- }
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
+++ /dev/null
-/*** The ICMD Table ***/
-
-/* IMPORTANT: This file must be in a fixed format, as it is both included in */
-/* src/vm/jit/jit.c, and parsed by src/vm/jit/verify/generate.pl! */
-/* */
-/* The comments at the start of the line and inside the braces are */
-/* significant. If you want to add a comment to an ICMD, do that after the */
-/* comma, or brace, at the end of the line. */
-/* */
-/* The format is as follows (slashes reversed for obvious reasons): */
-/* */
-/* \*#*\ { N( name ) data-flow, control-flow, flags \* stage (action) *\ } */
-/* */
-/* ^^^ */
-/* opcode */
-/* */
-/* where */
-/* opcode...........is the opcode number (decimal) */
-/* name.............is the quoted name without the ICMD_ prefix */
-/* data-flow........is one of the DF_ constants (see jit.h) */
-/* control-flow.....is one of the CF_ constants (see jit.h) */
-/* flags............is 0 or a |-combination of */
-/* PEI........may throw an exception */
-/* CALLS......needs saved registers (calls out) */
-/* *_CALLS....see jit.h for architecture specific */
-/* constants to put here */
-/* */
-/* stage............is either empty, or one of */
-/* -- ICMD is not used anywhere after parse */
-/* -S ICMD is eliminated by stack_analyse */
-/* S+ ICMD is introduced by stack_analyse */
-/* */
-/* action...........is the stack action of the ICMD in the notation */
-/* instack--outstack, TOS being rightmost. */
-/* */
-/* Valid type characters are */
-/* I, L, F, D, and A the basic types */
-/* 1 a category 1 type */
-/* 2 a category 2 type */
-/* . variable number of slots */
-/* */
-/* Whitespace is not allowed within the action. */
-/* */
-/* Some ICMDs may have several variants. In this case */
-/* the action is build by joining the individual */
-/* actions of the variants with |. */
-/* */
-/* */
-/* CAUTION: Do not use preprocessor directives in this file! They will */
-/* confuse the generator. */
-/* */
-
-
-/* 0*/ {N("NOP ") DF_0_TO_0 , CF_NORMAL, 0 /* (--) */},
-/* 1*/ {N("ACONST ") DF_0_TO_1 , CF_NORMAL, PEI /* (--A) */},
-/* 2*/ {N("CHECKNULL ") DF_1_TO_1 , CF_NORMAL, PEI /* (A--A) */},
-/* 3*/ {N("ICONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--I) */},
-/* 4*/ {N("UNDEF4 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 5*/ {N("IDIVPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 6*/ {N("LDIVPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 7*/ {N("UNDEF7 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 8*/ {N("UNDEF8 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 9*/ {N("LCONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--L) */},
-/* 10*/ {N("LCMPCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--I) */},
-/* 11*/ {N("FCONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--F) */},
-/* 12*/ {N("UNDEF12 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 13*/ {N("UNDEF13 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 14*/ {N("DCONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--D) */},
-/* 15*/ {N("COPY ") DF_COPY , CF_NORMAL, 0 /* S+ (1--1) */},
-/* 16*/ {N("MOVE ") DF_MOVE , CF_NORMAL, 0 /* S+ (1--1) */},
-/* 17*/ {N("UNDEF17 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 18*/ {N("UNDEF18 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 19*/ {N("UNDEF19 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 20*/ {N("UNDEF20 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 21*/ {N("ILOAD ") DF_LOAD , CF_NORMAL, 0 /* (--I) */},
-/* 22*/ {N("LLOAD ") DF_LOAD , CF_NORMAL, 0 /* (--L) */},
-/* 23*/ {N("FLOAD ") DF_LOAD , CF_NORMAL, 0 /* (--F) */},
-/* 24*/ {N("DLOAD ") DF_LOAD , CF_NORMAL, 0 /* (--D) */},
-/* 25*/ {N("ALOAD ") DF_LOAD , CF_NORMAL, 0 /* (--A) */},
-/* 26*/ {N("IADDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 27*/ {N("ISUBCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 28*/ {N("IMULCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 29*/ {N("IANDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 30*/ {N("IORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 31*/ {N("IXORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 32*/ {N("ISHLCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 33*/ {N("ISHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 34*/ {N("IUSHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 35*/ {N("IREMPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/* 36*/ {N("LADDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 37*/ {N("LSUBCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 38*/ {N("LMULCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 39*/ {N("LANDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 40*/ {N("LORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 41*/ {N("LXORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 42*/ {N("LSHLCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 43*/ {N("LSHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 44*/ {N("LUSHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 45*/ {N("LREMPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/* 46*/ {N("IALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
-/* 47*/ {N("LALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--L) */},
-/* 48*/ {N("FALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--F) */},
-/* 49*/ {N("DALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--D) */},
-/* 50*/ {N("AALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--A) */},
-/* 51*/ {N("BALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
-/* 52*/ {N("CALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
-/* 53*/ {N("SALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
-/* 54*/ {N("ISTORE ") DF_STORE , CF_NORMAL, 0 /* (I--) */},
-/* 55*/ {N("LSTORE ") DF_STORE , CF_NORMAL, 0 /* (L--) */},
-/* 56*/ {N("FSTORE ") DF_STORE , CF_NORMAL, 0 /* (F--) */},
-/* 57*/ {N("DSTORE ") DF_STORE , CF_NORMAL, 0 /* (D--) */},
-/* 58*/ {N("ASTORE ") DF_STORE , CF_NORMAL, 0 /* (A--|R--) */},
-/* 59*/ {N("IF_LEQ ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
-/* 60*/ {N("IF_LNE ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
-/* 61*/ {N("IF_LLT ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
-/* 62*/ {N("IF_LGE ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
-/* 63*/ {N("IF_LGT ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
-/* 64*/ {N("IF_LLE ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
-/* 65*/ {N("IF_LCMPEQ ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
-/* 66*/ {N("IF_LCMPNE ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
-/* 67*/ {N("IF_LCMPLT ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
-/* 68*/ {N("IF_LCMPGE ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
-/* 69*/ {N("IF_LCMPGT ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
-/* 70*/ {N("IF_LCMPLE ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
-/* 71*/ {N("UNDEF71 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 72*/ {N("UNDEF72 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 73*/ {N("UNDEF73 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 74*/ {N("UNDEF74 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 75*/ {N("UNDEF75 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 76*/ {N("UNDEF76 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 77*/ {N("UNDEF77 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 78*/ {N("UNDEF78 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/* 79*/ {N("IASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
-/* 80*/ {N("LASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AIL--) */},
-/* 81*/ {N("FASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AIF--) */},
-/* 82*/ {N("DASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AID--) */},
-/* 83*/ {N("AASTORE ") DF_3_TO_0 , CF_NORMAL, PEI|CALLS /* (AIA--) */},
-/* 84*/ {N("BASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
-/* 85*/ {N("CASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
-/* 86*/ {N("SASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
-/* 87*/ {N("POP ") DF_POP , CF_NORMAL, 0 /* (1--) */},
-/* 88*/ {N("POP2 ") DF_POP2 , CF_NORMAL, 0 /* (11--|2--) */},
-/* 89*/ {N("DUP ") DF_DUP , CF_NORMAL, 0 /* -S (1--11) */},
-/* 90*/ {N("DUP_X1 ") DF_DUP_X1 , CF_NORMAL, 0 /* -S (11--111) */},
-/* 91*/ {N("DUP_X2 ") DF_DUP_X2 , CF_NORMAL, 0 /* -S (111--1111|21--121) */},
-/* 92*/ {N("DUP2 ") DF_DUP2 , CF_NORMAL, 0 /* -S (11--1111|2--22) */},
-/* 93*/ {N("DUP2_X1 ") DF_DUP2_X1, CF_NORMAL, 0 /* -S (111--11111|12--212) */},
-/* 94*/ {N("DUP2_X2 ") DF_DUP2_X2, CF_NORMAL, 0 /* -S (1111--111111|112--2112|22--222|211--11211) */},
-/* 95*/ {N("SWAP ") DF_SWAP , CF_NORMAL, 0 /* -S (11--11) */},
-/* 96*/ {N("IADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/* 97*/ {N("LADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
-/* 98*/ {N("FADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
-/* 99*/ {N("DADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
-/*100*/ {N("ISUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*101*/ {N("LSUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
-/*102*/ {N("FSUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
-/*103*/ {N("DSUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
-/*104*/ {N("IMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*105*/ {N("LMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
-/*106*/ {N("FMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
-/*107*/ {N("DMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
-/*108*/ {N("IDIV ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /* (II--I) */},
-/*109*/ {N("LDIV ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /* (LL--L) */},
-/*110*/ {N("FDIV ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
-/*111*/ {N("DDIV ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
-/*112*/ {N("IREM ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /* (II--I) */},
-/*113*/ {N("LREM ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /* (LL--L) */},
-/*114*/ {N("FREM ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
-/*115*/ {N("DREM ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
-/*116*/ {N("INEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
-/*117*/ {N("LNEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--L) */},
-/*118*/ {N("FNEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--F) */},
-/*119*/ {N("DNEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--D) */},
-/*120*/ {N("ISHL ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*121*/ {N("LSHL ") DF_2_TO_1 , CF_NORMAL, 0 /* (LI--L) */},
-/*122*/ {N("ISHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*123*/ {N("LSHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LI--L) */},
-/*124*/ {N("IUSHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*125*/ {N("LUSHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LI--L) */},
-/*126*/ {N("IAND ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*127*/ {N("LAND ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
-/*128*/ {N("IOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*129*/ {N("LOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
-/*130*/ {N("IXOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
-/*131*/ {N("LXOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
-/*132*/ {N("IINC ") DF_IINC , CF_NORMAL, 0 /* (--) */},
-/*133*/ {N("I2L ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--L) */},
-/*134*/ {N("I2F ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--F) */},
-/*135*/ {N("I2D ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--D) */},
-/*136*/ {N("L2I ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--I) */},
-/*137*/ {N("L2F ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--F) */},
-/*138*/ {N("L2D ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--D) */},
-/*139*/ {N("F2I ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--I) */},
-/*140*/ {N("F2L ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--L) */},
-/*141*/ {N("F2D ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--D) */},
-/*142*/ {N("D2I ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--I) */},
-/*143*/ {N("D2L ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--L) */},
-/*144*/ {N("D2F ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--F) */},
-/*145*/ {N("INT2BYTE ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
-/*146*/ {N("INT2CHAR ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
-/*147*/ {N("INT2SHORT ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
-/*148*/ {N("LCMP ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--I) */},
-/*149*/ {N("FCMPL ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--I) */},
-/*150*/ {N("FCMPG ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--I) */},
-/*151*/ {N("DCMPL ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--I) */},
-/*152*/ {N("DCMPG ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--I) */},
-/*153*/ {N("IFEQ ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
-/*154*/ {N("IFNE ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
-/*155*/ {N("IFLT ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
-/*156*/ {N("IFGE ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
-/*157*/ {N("IFGT ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
-/*158*/ {N("IFLE ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
-/*159*/ {N("IF_ICMPEQ ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
-/*160*/ {N("IF_ICMPNE ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
-/*161*/ {N("IF_ICMPLT ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
-/*162*/ {N("IF_ICMPGE ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
-/*163*/ {N("IF_ICMPGT ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
-/*164*/ {N("IF_ICMPLE ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
-/*165*/ {N("IF_ACMPEQ ") DF_2_TO_0 , CF_IF , 0 /* (AA--) */},
-/*166*/ {N("IF_ACMPNE ") DF_2_TO_0 , CF_IF , 0 /* (AA--) */},
-/*167*/ {N("GOTO ") DF_0_TO_0 , CF_GOTO , 0 /* (--) */},
-/*168*/ {N("JSR ") DF_0_TO_1 , CF_JSR , 0 /* (--R) */},
-/*169*/ {N("RET ") DF_0_TO_0 , CF_RET , 0 /* (--) */},
-/*170*/ {N("TABLESWITCH ") DF_1_TO_0 , CF_TABLE , 0 /* (I--) */},
-/*171*/ {N("LOOKUPSWITCH ") DF_1_TO_0 , CF_LOOKUP, 0 /* (I--) */},
-/*172*/ {N("IRETURN ") DF_1_TO_0 , CF_END , 0 /* (I--) */},
-/*173*/ {N("LRETURN ") DF_1_TO_0 , CF_END , 0 /* (L--) */},
-/*174*/ {N("FRETURN ") DF_1_TO_0 , CF_END , 0 /* (F--) */},
-/*175*/ {N("DRETURN ") DF_1_TO_0 , CF_END , 0 /* (D--) */},
-/*176*/ {N("ARETURN ") DF_1_TO_0 , CF_END , PEI /* (A--) */},
-/*177*/ {N("RETURN ") DF_0_TO_0 , CF_END , 0 /* (--) */},
-/*178*/ {N("GETSTATIC ") DF_0_TO_1 , CF_NORMAL, PEI /* (--1|--2) */},
-/*179*/ {N("PUTSTATIC ") DF_1_TO_0 , CF_NORMAL, PEI /* (1--|2--) */},
-/*180*/ {N("GETFIELD ") DF_1_TO_1 , CF_NORMAL, PEI /* (A--1|A--2) */},
-/*181*/ {N("PUTFIELD ") DF_2_TO_0 , CF_NORMAL, PEI /* (A1--|A2--) */},
-/*182*/ {N("INVOKEVIRTUAL ") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
-/*183*/ {N("INVOKESPECIAL ") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
-/*184*/ {N("INVOKESTATIC ") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
-/*185*/ {N("INVOKEINTERFACE") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
-/*186*/ {N("UNDEF186 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*187*/ {N("NEW ") DF_0_TO_1 , CF_NORMAL, PEI /* -- (--A) */},
-/*188*/ {N("NEWARRAY ") DF_0_TO_1 , CF_NORMAL, PEI /* -- (--A) */},
-/*189*/ {N("ANEWARRAY ") DF_0_TO_1 , CF_NORMAL, PEI /* -- (--A) */},
-/*190*/ {N("ARRAYLENGTH ") DF_1_TO_1 , CF_NORMAL, PEI /* (A--I) */},
-/*191*/ {N("ATHROW ") DF_1_TO_0 , CF_END , PEI /* (A--) */},
-/*192*/ {N("CHECKCAST ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS /* (A--A) */},
-/*193*/ {N("INSTANCEOF ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS /* (A--I) */},
-/*194*/ {N("MONITORENTER ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS /* -- (A--) */},
-/*195*/ {N("MONITOREXIT ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS /* -- (A--) */},
-/*196*/ {N("UNDEF196 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*197*/ {N("MULTIANEWARRAY ") DF_N_TO_1 , CF_NORMAL, PEI|CALLS /* (.--A) */},
-/*198*/ {N("IFNULL ") DF_1_TO_0 , CF_IF , 0 /* (A--) */},
-/*199*/ {N("IFNONNULL ") DF_1_TO_0 , CF_IF , 0 /* (A--) */},
-/*200*/ {N("UNDEF200 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*201*/ {N("UNDEF201 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*202*/ {N("UNDEF202 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*203*/ {N("UNDEF203 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*204*/ {N("IASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*205*/ {N("LASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*206*/ {N("FASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*207*/ {N("DASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*208*/ {N("AASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*209*/ {N("BASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*210*/ {N("CASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*211*/ {N("SASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
-/*212*/ {N("PUTSTATICCONST ") DF_0_TO_0 , CF_NORMAL, PEI /* S+ (--) */},
-/*213*/ {N("PUTFIELDCONST ") DF_1_TO_0 , CF_NORMAL, PEI /* S+ (A--) */},
-/*214*/ {N("IMULPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
-/*215*/ {N("LMULPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
-/*216*/ {N("IF_FCMPEQ ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*217*/ {N("IF_FCMPNE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*218*/ {N("IF_FCMPL_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*219*/ {N("IF_FCMPL_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*220*/ {N("IF_FCMPL_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*221*/ {N("IF_FCMPL_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*222*/ {N("IF_FCMPG_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*223*/ {N("IF_FCMPG_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*224*/ {N("IF_FCMPG_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*225*/ {N("IF_FCMPG_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*226*/ {N("IF_DCMPEQ ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*227*/ {N("IF_DCMPNE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*228*/ {N("IF_DCMPL_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*229*/ {N("IF_DCMPL_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*230*/ {N("IF_DCMPL_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*231*/ {N("IF_DCMPL_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*232*/ {N("IF_DCMPG_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*233*/ {N("IF_DCMPG_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*234*/ {N("IF_DCMPG_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*235*/ {N("IF_DCMPG_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
-/*236*/ {N("UNDEF236 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*237*/ {N("UNDEF237 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*238*/ {N("UNDEF238 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*239*/ {N("UNDEF239 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*240*/ {N("UNDEF240 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*241*/ {N("UNDEF241 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*242*/ {N("UNDEF242 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*243*/ {N("UNDEF243 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*244*/ {N("UNDEF244 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*245*/ {N("UNDEF245 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*246*/ {N("UNDEF246 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*247*/ {N("UNDEF247 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*248*/ {N("UNDEF248 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*249*/ {N("GETEXCEPTION ") DF_0_TO_1 , CF_NORMAL, 0 /* -- () */},
-/*250*/ {N("PHI ") DF_N_TO_1 , CF_NORMAL, 0 /* -- () */},
-/*251*/ {N("INLINE_START ") DF_0_TO_0 , CF_NORMAL, 0 /* S+ (--) */},
-/*252*/ {N("INLINE_END ") DF_0_TO_0 , CF_NORMAL, 0 /* S+ (--) */},
-/*253*/ {N("INLINE_BODY ") DF_0_TO_0 , CF_NORMAL, 0 /* S+ (--) */},
-/*254*/ {N("UNDEF254 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
-/*255*/ {N("BUILTIN ") DF_BUILTIN, CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */}
-
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/global.h"
#include "vm/initialize.h"
#include "vm/options.h"
#include "vm/statistics.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/reg.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#include "vm/jit/stack.h"
#include "vm/jit/inline/inline.h"
/* enter a monitor on the method */
- LOCK_MONITOR_ENTER(m);
+ Mutex_lock(m->mutex);
/* allocate jitdata structure and fill it */
/* leave the monitor */
- LOCK_MONITOR_EXIT(m);
+ Mutex_unlock(m->mutex);
return r;
}
/* we need bigger free memory stacks (XXX these should not be allocated in reg_setup) */
n_jd->rd->freemem = DMNEW(s4, iln->ctx->maxinoutdepth + 1000) /* XXX max vars/block */;
-#if defined(HAS_4BYTE_STACKSLOT)
- n_jd->rd->freemem_2 = DMNEW(s4, iln->ctx->maxinoutdepth + 1000) /* XXX max vars/block */;
-#endif
#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
if ( (n_jd->instructioncount >= opt_InlineMinSize)
/* src/vm/jit/inline/inline.h - code inliner
- 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"
-#include "vm/global.h"
+#include <stdbool.h>
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool inline_inline(jitdata *jd);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _INLINE_H */
/*
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/jit/asmpart.h"
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
#include "vm/jit/stack.h"
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "toolbox/hashtable.h"
#include "toolbox/logging.h"
#include "threads/thread.hpp"
-#include "vm/builtin.h"
-#include "vm/loader.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/jit/methodheader.h"
#include "vm/references.h"
#include "vm/resolve.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
typedef void *Label;
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/initialize.h"
#include "vm/options.h"
#include "vm/references.h"
## src/vm/jit/ir/Makefile.am
##
-## Copyright (C) 2007
+## Copyright (C) 2007, 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.
-## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
libir_la_SOURCES = \
bytecode.c \
- bytecode.h
+ bytecode.h \
+ icmd.cpp \
+ icmd.hpp \
+ icmdtable.inc \
+ instruction.cpp \
+ instruction.hpp
## Local variables:
--- /dev/null
+/* src/vm/jit/ir/icmd.cpp - Intermediate Commands
+
+ 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/jit/ir/icmd.hpp"
+
+
+/* the ICMD table ************************************************************/
+
+#if !defined(NDEBUG)
+#define N(name) name,
+#else
+#define N(name)
+#endif
+
+/* abbreviations for flags */
+
+#define PEI ICMDTABLE_PEI
+#define CALLS ICMDTABLE_CALLS
+
+/* some machine dependent values */
+
+#if SUPPORT_DIVISION
+#define IDIV_CALLS 0
+#else
+#define IDIV_CALLS ICMDTABLE_CALLS
+#endif
+
+#if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
+#define LDIV_CALLS 0
+#else
+#define LDIV_CALLS ICMDTABLE_CALLS
+#endif
+
+/* include the actual table */
+
+icmdtable_entry_t icmd_table[256] = {
+#include "vm/jit/ir/icmdtable.inc"
+};
+
+
+/*
+ * These 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/ir/icmd.hpp - Intermediate Commands
+
+ 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 _ICMD_HPP
+#define _ICMD_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/jit/ir/bytecode.h"
+
+
+// JavaVM operation codes (sorted).
+enum {
+ ICMD_NOP = BC_nop,
+
+ ICMD_ACONST = BC_aconst_null,
+
+ ICMD_CHECKNULL = 2,
+
+ ICMD_ICONST = BC_iconst_0,
+
+ /* 3 */
+ /* 4 */
+
+ ICMD_IDIVPOW2 = 5,
+ ICMD_LDIVPOW2 = 6,
+
+ /* 7 */
+ /* 8 */
+
+ ICMD_LCONST = BC_lconst_0,
+
+ ICMD_LCMPCONST = 10,
+
+ ICMD_FCONST = BC_fconst_0,
+
+ /* 12 */
+ /* 13 */
+
+ ICMD_DCONST = BC_dconst_0,
+
+ ICMD_COPY = 15,
+ ICMD_MOVE = 16,
+
+ /* 17 */
+ /* 18 */
+ /* 19 */
+ /* 20 */
+
+ /* Order of LOAD instructions must be equal to order of TYPE_*
+ defines. */
+
+ ICMD_ILOAD = BC_iload,
+ ICMD_LLOAD = BC_lload,
+ ICMD_FLOAD = BC_fload,
+ ICMD_DLOAD = BC_dload,
+ ICMD_ALOAD = BC_aload,
+
+ ICMD_IADDCONST = 26,
+ ICMD_ISUBCONST = 27,
+ ICMD_IMULCONST = 28,
+ ICMD_IANDCONST = 29,
+ ICMD_IORCONST = 30,
+ ICMD_IXORCONST = 31,
+
+ ICMD_ISHLCONST = 32,
+ ICMD_ISHRCONST = 33,
+ ICMD_IUSHRCONST = 34,
+
+ ICMD_IREMPOW2 = 35,
+
+ ICMD_LADDCONST = 36,
+ ICMD_LSUBCONST = 37,
+ ICMD_LMULCONST = 38,
+ ICMD_LANDCONST = 39,
+ ICMD_LORCONST = 40,
+ ICMD_LXORCONST = 41,
+
+ ICMD_LSHLCONST = 42,
+ ICMD_LSHRCONST = 43,
+ ICMD_LUSHRCONST = 44,
+
+ ICMD_LREMPOW2 = 45,
+
+ ICMD_IALOAD = BC_iaload,
+ ICMD_LALOAD = BC_laload,
+ ICMD_FALOAD = BC_faload,
+ ICMD_DALOAD = BC_daload,
+ ICMD_AALOAD = BC_aaload,
+ ICMD_BALOAD = BC_baload,
+ ICMD_CALOAD = BC_caload,
+ ICMD_SALOAD = BC_saload,
+
+ /* Order of STORE instructions must be equal to order of TYPE_*
+ defines. */
+
+ ICMD_ISTORE = BC_istore,
+ ICMD_LSTORE = BC_lstore,
+ ICMD_FSTORE = BC_fstore,
+ ICMD_DSTORE = BC_dstore,
+ ICMD_ASTORE = BC_astore,
+
+ ICMD_IF_LEQ = 59,
+ ICMD_IF_LNE = 60,
+ ICMD_IF_LLT = 61,
+ ICMD_IF_LGE = 62,
+ ICMD_IF_LGT = 63,
+ ICMD_IF_LLE = 64,
+
+ ICMD_IF_LCMPEQ = 65,
+ ICMD_IF_LCMPNE = 66,
+ ICMD_IF_LCMPLT = 67,
+ ICMD_IF_LCMPGE = 68,
+ ICMD_IF_LCMPGT = 69,
+ ICMD_IF_LCMPLE = 70,
+
+ /* 71 */
+ /* 72 */
+ /* 73 */
+ /* 74 */
+ /* 75 */
+ /* 76 */
+ /* 77 */
+ /* 78 */
+
+ ICMD_IASTORE = BC_iastore,
+ ICMD_LASTORE = BC_lastore,
+ ICMD_FASTORE = BC_fastore,
+ ICMD_DASTORE = BC_dastore,
+ ICMD_AASTORE = BC_aastore,
+ ICMD_BASTORE = BC_bastore,
+ ICMD_CASTORE = BC_castore,
+ ICMD_SASTORE = BC_sastore,
+
+ ICMD_POP = BC_pop,
+ ICMD_POP2 = BC_pop2,
+ ICMD_DUP = BC_dup,
+ ICMD_DUP_X1 = BC_dup_x1,
+ ICMD_DUP_X2 = BC_dup_x2,
+ ICMD_DUP2 = BC_dup2,
+ ICMD_DUP2_X1 = BC_dup2_x1,
+ ICMD_DUP2_X2 = BC_dup2_x2,
+ ICMD_SWAP = BC_swap,
+
+ ICMD_IADD = BC_iadd,
+ ICMD_LADD = BC_ladd,
+ ICMD_FADD = BC_fadd,
+ ICMD_DADD = BC_dadd,
+
+ ICMD_ISUB = BC_isub,
+ ICMD_LSUB = BC_lsub,
+ ICMD_FSUB = BC_fsub,
+ ICMD_DSUB = BC_dsub,
+
+ ICMD_IMUL = BC_imul,
+ ICMD_LMUL = BC_lmul,
+ ICMD_FMUL = BC_fmul,
+ ICMD_DMUL = BC_dmul,
+
+ ICMD_IDIV = BC_idiv,
+ ICMD_LDIV = BC_ldiv,
+ ICMD_FDIV = BC_fdiv,
+ ICMD_DDIV = BC_ddiv,
+
+ ICMD_IREM = BC_irem,
+ ICMD_LREM = BC_lrem,
+ ICMD_FREM = BC_frem,
+ ICMD_DREM = BC_drem,
+
+ ICMD_INEG = BC_ineg,
+ ICMD_LNEG = BC_lneg,
+ ICMD_FNEG = BC_fneg,
+ ICMD_DNEG = BC_dneg,
+
+ ICMD_ISHL = BC_ishl,
+ ICMD_LSHL = BC_lshl,
+ ICMD_ISHR = BC_ishr,
+ ICMD_LSHR = BC_lshr,
+ ICMD_IUSHR = BC_iushr,
+ ICMD_LUSHR = BC_lushr,
+
+ ICMD_IAND = BC_iand,
+ ICMD_LAND = BC_land,
+ ICMD_IOR = BC_ior,
+ ICMD_LOR = BC_lor,
+ ICMD_IXOR = BC_ixor,
+ ICMD_LXOR = BC_lxor,
+
+ ICMD_IINC = BC_iinc,
+
+ ICMD_I2L = BC_i2l,
+ ICMD_I2F = BC_i2f,
+ ICMD_I2D = BC_i2d,
+ ICMD_L2I = BC_l2i,
+ ICMD_L2F = BC_l2f,
+ ICMD_L2D = BC_l2d,
+ ICMD_F2I = BC_f2i,
+ ICMD_F2L = BC_f2l,
+ ICMD_F2D = BC_f2d,
+ ICMD_D2I = BC_d2i,
+ ICMD_D2L = BC_d2l,
+ ICMD_D2F = BC_d2f,
+
+ ICMD_INT2BYTE = BC_int2byte,
+ ICMD_INT2CHAR = BC_int2char,
+ ICMD_INT2SHORT = BC_int2short,
+
+ ICMD_LCMP = BC_lcmp,
+ ICMD_FCMPL = BC_fcmpl,
+ ICMD_FCMPG = BC_fcmpg,
+ ICMD_DCMPL = BC_dcmpl,
+ ICMD_DCMPG = BC_dcmpg,
+
+ ICMD_IFEQ = BC_ifeq,
+ ICMD_IFNE = BC_ifne,
+ ICMD_IFLT = BC_iflt,
+ ICMD_IFGE = BC_ifge,
+ ICMD_IFGT = BC_ifgt,
+ ICMD_IFLE = BC_ifle,
+
+ ICMD_IF_ICMPEQ = BC_if_icmpeq,
+ ICMD_IF_ICMPNE = BC_if_icmpne,
+ ICMD_IF_ICMPLT = BC_if_icmplt,
+ ICMD_IF_ICMPGE = BC_if_icmpge,
+ ICMD_IF_ICMPGT = BC_if_icmpgt,
+ ICMD_IF_ICMPLE = BC_if_icmple,
+ ICMD_IF_ACMPEQ = BC_if_acmpeq,
+ ICMD_IF_ACMPNE = BC_if_acmpne,
+
+ ICMD_GOTO = BC_goto,
+ ICMD_JSR = BC_jsr,
+ ICMD_RET = BC_ret,
+
+ ICMD_TABLESWITCH = BC_tableswitch,
+ ICMD_LOOKUPSWITCH = BC_lookupswitch,
+
+ ICMD_IRETURN = BC_ireturn,
+ ICMD_LRETURN = BC_lreturn,
+ ICMD_FRETURN = BC_freturn,
+ ICMD_DRETURN = BC_dreturn,
+ ICMD_ARETURN = BC_areturn,
+ ICMD_RETURN = BC_return,
+
+ ICMD_GETSTATIC = BC_getstatic,
+ ICMD_PUTSTATIC = BC_putstatic,
+ ICMD_GETFIELD = BC_getfield,
+ ICMD_PUTFIELD = BC_putfield,
+
+ ICMD_INVOKEVIRTUAL = BC_invokevirtual,
+ ICMD_INVOKESPECIAL = BC_invokespecial,
+ ICMD_INVOKESTATIC = BC_invokestatic,
+ ICMD_INVOKEINTERFACE = BC_invokeinterface,
+
+ /* 186 */
+
+ ICMD_NEW = BC_new,
+ ICMD_NEWARRAY = BC_newarray,
+ ICMD_ANEWARRAY = BC_anewarray,
+
+ ICMD_ARRAYLENGTH = BC_arraylength,
+
+ ICMD_ATHROW = BC_athrow,
+
+ ICMD_CHECKCAST = BC_checkcast,
+ ICMD_INSTANCEOF = BC_instanceof,
+
+ ICMD_MONITORENTER = BC_monitorenter,
+ ICMD_MONITOREXIT = BC_monitorexit,
+
+ /* 196 */
+
+ ICMD_MULTIANEWARRAY = BC_multianewarray,
+
+ ICMD_IFNULL = BC_ifnull,
+ ICMD_IFNONNULL = BC_ifnonnull,
+
+ /* 200 */
+ /* 201 */
+ /* 202 */
+
+ ICMD_IASTORECONST = 204,
+ ICMD_LASTORECONST = 205,
+ ICMD_FASTORECONST = 206,
+ ICMD_DASTORECONST = 207,
+ ICMD_AASTORECONST = 208,
+ ICMD_BASTORECONST = 209,
+ ICMD_CASTORECONST = 210,
+ ICMD_SASTORECONST = 211,
+
+ ICMD_PUTSTATICCONST = 212,
+ ICMD_PUTFIELDCONST = 213,
+
+ ICMD_IMULPOW2 = 214,
+ ICMD_LMULPOW2 = 215,
+
+ ICMD_GETEXCEPTION = 249,
+ ICMD_PHI = 250,
+
+ ICMD_INLINE_START = 251, /* instruction before inlined method */
+ ICMD_INLINE_END = 252, /* instruction after inlined method */
+ ICMD_INLINE_BODY = 253, /* start of inlined body */
+
+ ICMD_BUILTIN = 255 /* internal opcode */
+};
+
+
+/* data-flow constants for the ICMD table ************************************/
+
+#define DF_0_TO_0 0
+#define DF_1_TO_0 1
+#define DF_2_TO_0 2
+#define DF_3_TO_0 3
+
+#define DF_DST_BASE 4 /* from this value on, iptr->dst is a variable */
+
+#define DF_0_TO_1 (DF_DST_BASE + 0)
+#define DF_1_TO_1 (DF_DST_BASE + 1)
+#define DF_2_TO_1 (DF_DST_BASE + 2)
+#define DF_3_TO_1 (DF_DST_BASE + 3)
+#define DF_N_TO_1 (DF_DST_BASE + 4)
+
+#define DF_INVOKE (DF_DST_BASE + 5)
+#define DF_BUILTIN (DF_DST_BASE + 6)
+
+#define DF_COPY (DF_DST_BASE + 7)
+#define DF_MOVE (DF_DST_BASE + 8)
+
+#define DF_DUP -1
+#define DF_DUP_X1 -1
+#define DF_DUP_X2 -1
+#define DF_DUP2 -1
+#define DF_DUP2_X1 -1
+#define DF_DUP2_X2 -1
+#define DF_SWAP -1
+
+/* special data-flow recognized by verify/generate.pl: */
+#define DF_LOAD DF_COPY
+#define DF_STORE DF_MOVE
+#define DF_IINC DF_1_TO_1
+#define DF_POP DF_1_TO_0
+#define DF_POP2 DF_2_TO_0
+
+
+// Control-flow constants for the ICMD table.
+#define CF_NORMAL 0
+#define CF_IF 1
+
+#define CF_END_BASE 2 /* from here on, they mark the end of a superblock */
+
+#define CF_END (CF_END_BASE + 0)
+#define CF_GOTO (CF_END_BASE + 1)
+#define CF_TABLE (CF_END_BASE + 2)
+#define CF_LOOKUP (CF_END_BASE + 3)
+#define CF_JSR (CF_END_BASE + 4)
+#define CF_RET (CF_END_BASE + 5)
+
+
+// Flag constants for the ICMD table.
+#define ICMDTABLE_PEI 0x0001 /* ICMD may throw an exception */
+#define ICMDTABLE_CALLS 0x0002 /* needs registers to be saved, may call */
+
+
+// ICMD table entry.
+typedef struct icmdtable_entry_t icmdtable_entry_t;
+
+struct icmdtable_entry_t {
+#if !defined(NDEBUG)
+ const char* name; /* name, without ICMD_ prefix */
+#endif
+ int32_t dataflow; /* a DF_ constant, see above */
+ int32_t controlflow; /* a CF_ constant, see above */
+ int32_t flags; /* a combination of ICMDTABLE_ flags */
+};
+
+
+// The ICMD table.
+extern icmdtable_entry_t icmd_table[256];
+
+#endif // _ICMD_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
+/*** The ICMD Table ***/
+
+/* IMPORTANT: This file must be in a fixed format, as it is both included in */
+/* src/vm/jit/jit.c, and parsed by src/vm/jit/verify/generate.pl! */
+/* */
+/* The comments at the start of the line and inside the braces are */
+/* significant. If you want to add a comment to an ICMD, do that after the */
+/* comma, or brace, at the end of the line. */
+/* */
+/* The format is as follows (slashes reversed for obvious reasons): */
+/* */
+/* \*#*\ { N( name ) data-flow, control-flow, flags \* stage (action) *\ } */
+/* */
+/* ^^^ */
+/* opcode */
+/* */
+/* where */
+/* opcode...........is the opcode number (decimal) */
+/* name.............is the quoted name without the ICMD_ prefix */
+/* data-flow........is one of the DF_ constants (see jit.h) */
+/* control-flow.....is one of the CF_ constants (see jit.h) */
+/* flags............is 0 or a |-combination of */
+/* PEI........may throw an exception */
+/* CALLS......needs saved registers (calls out) */
+/* *_CALLS....see jit.h for architecture specific */
+/* constants to put here */
+/* */
+/* stage............is either empty, or one of */
+/* -- ICMD is not used anywhere after parse */
+/* -S ICMD is eliminated by stack_analyse */
+/* S+ ICMD is introduced by stack_analyse */
+/* */
+/* action...........is the stack action of the ICMD in the notation */
+/* instack--outstack, TOS being rightmost. */
+/* */
+/* Valid type characters are */
+/* I, L, F, D, and A the basic types */
+/* 1 a category 1 type */
+/* 2 a category 2 type */
+/* . variable number of slots */
+/* */
+/* Whitespace is not allowed within the action. */
+/* */
+/* Some ICMDs may have several variants. In this case */
+/* the action is build by joining the individual */
+/* actions of the variants with |. */
+/* */
+/* */
+/* CAUTION: Do not use preprocessor directives in this file! They will */
+/* confuse the generator. */
+/* */
+
+
+/* 0*/ {N("NOP ") DF_0_TO_0 , CF_NORMAL, 0 /* (--) */},
+/* 1*/ {N("ACONST ") DF_0_TO_1 , CF_NORMAL, PEI /* (--A) */},
+/* 2*/ {N("CHECKNULL ") DF_1_TO_1 , CF_NORMAL, PEI /* (A--A) */},
+/* 3*/ {N("ICONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--I) */},
+/* 4*/ {N("UNDEF4 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 5*/ {N("IDIVPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 6*/ {N("LDIVPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 7*/ {N("UNDEF7 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 8*/ {N("UNDEF8 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 9*/ {N("LCONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--L) */},
+/* 10*/ {N("LCMPCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--I) */},
+/* 11*/ {N("FCONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--F) */},
+/* 12*/ {N("UNDEF12 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 13*/ {N("UNDEF13 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 14*/ {N("DCONST ") DF_0_TO_1 , CF_NORMAL, 0 /* (--D) */},
+/* 15*/ {N("COPY ") DF_COPY , CF_NORMAL, 0 /* S+ (1--1) */},
+/* 16*/ {N("MOVE ") DF_MOVE , CF_NORMAL, 0 /* S+ (1--1) */},
+/* 17*/ {N("UNDEF17 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 18*/ {N("UNDEF18 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 19*/ {N("UNDEF19 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 20*/ {N("UNDEF20 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 21*/ {N("ILOAD ") DF_LOAD , CF_NORMAL, 0 /* (--I) */},
+/* 22*/ {N("LLOAD ") DF_LOAD , CF_NORMAL, 0 /* (--L) */},
+/* 23*/ {N("FLOAD ") DF_LOAD , CF_NORMAL, 0 /* (--F) */},
+/* 24*/ {N("DLOAD ") DF_LOAD , CF_NORMAL, 0 /* (--D) */},
+/* 25*/ {N("ALOAD ") DF_LOAD , CF_NORMAL, 0 /* (--A) */},
+/* 26*/ {N("IADDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 27*/ {N("ISUBCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 28*/ {N("IMULCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 29*/ {N("IANDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 30*/ {N("IORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 31*/ {N("IXORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 32*/ {N("ISHLCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 33*/ {N("ISHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 34*/ {N("IUSHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 35*/ {N("IREMPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/* 36*/ {N("LADDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 37*/ {N("LSUBCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 38*/ {N("LMULCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 39*/ {N("LANDCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 40*/ {N("LORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 41*/ {N("LXORCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 42*/ {N("LSHLCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 43*/ {N("LSHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 44*/ {N("LUSHRCONST ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 45*/ {N("LREMPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/* 46*/ {N("IALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
+/* 47*/ {N("LALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--L) */},
+/* 48*/ {N("FALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--F) */},
+/* 49*/ {N("DALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--D) */},
+/* 50*/ {N("AALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--A) */},
+/* 51*/ {N("BALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
+/* 52*/ {N("CALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
+/* 53*/ {N("SALOAD ") DF_2_TO_1 , CF_NORMAL, PEI /* (AI--I) */},
+/* 54*/ {N("ISTORE ") DF_STORE , CF_NORMAL, 0 /* (I--) */},
+/* 55*/ {N("LSTORE ") DF_STORE , CF_NORMAL, 0 /* (L--) */},
+/* 56*/ {N("FSTORE ") DF_STORE , CF_NORMAL, 0 /* (F--) */},
+/* 57*/ {N("DSTORE ") DF_STORE , CF_NORMAL, 0 /* (D--) */},
+/* 58*/ {N("ASTORE ") DF_STORE , CF_NORMAL, 0 /* (A--|R--) */},
+/* 59*/ {N("IF_LEQ ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
+/* 60*/ {N("IF_LNE ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
+/* 61*/ {N("IF_LLT ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
+/* 62*/ {N("IF_LGE ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
+/* 63*/ {N("IF_LGT ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
+/* 64*/ {N("IF_LLE ") DF_1_TO_0 , CF_IF , 0 /* S+ (L--) */},
+/* 65*/ {N("IF_LCMPEQ ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
+/* 66*/ {N("IF_LCMPNE ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
+/* 67*/ {N("IF_LCMPLT ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
+/* 68*/ {N("IF_LCMPGE ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
+/* 69*/ {N("IF_LCMPGT ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
+/* 70*/ {N("IF_LCMPLE ") DF_2_TO_0 , CF_IF , 0 /* S+ (LL--) */},
+/* 71*/ {N("UNDEF71 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 72*/ {N("UNDEF72 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 73*/ {N("UNDEF73 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 74*/ {N("UNDEF74 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 75*/ {N("UNDEF75 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 76*/ {N("UNDEF76 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 77*/ {N("UNDEF77 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 78*/ {N("UNDEF78 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/* 79*/ {N("IASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
+/* 80*/ {N("LASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AIL--) */},
+/* 81*/ {N("FASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AIF--) */},
+/* 82*/ {N("DASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AID--) */},
+/* 83*/ {N("AASTORE ") DF_3_TO_0 , CF_NORMAL, PEI|CALLS /* (AIA--) */},
+/* 84*/ {N("BASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
+/* 85*/ {N("CASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
+/* 86*/ {N("SASTORE ") DF_3_TO_0 , CF_NORMAL, PEI /* (AII--) */},
+/* 87*/ {N("POP ") DF_POP , CF_NORMAL, 0 /* (1--) */},
+/* 88*/ {N("POP2 ") DF_POP2 , CF_NORMAL, 0 /* (11--|2--) */},
+/* 89*/ {N("DUP ") DF_DUP , CF_NORMAL, 0 /* -S (1--11) */},
+/* 90*/ {N("DUP_X1 ") DF_DUP_X1 , CF_NORMAL, 0 /* -S (11--111) */},
+/* 91*/ {N("DUP_X2 ") DF_DUP_X2 , CF_NORMAL, 0 /* -S (111--1111|21--121) */},
+/* 92*/ {N("DUP2 ") DF_DUP2 , CF_NORMAL, 0 /* -S (11--1111|2--22) */},
+/* 93*/ {N("DUP2_X1 ") DF_DUP2_X1, CF_NORMAL, 0 /* -S (111--11111|12--212) */},
+/* 94*/ {N("DUP2_X2 ") DF_DUP2_X2, CF_NORMAL, 0 /* -S (1111--111111|112--2112|22--222|211--11211) */},
+/* 95*/ {N("SWAP ") DF_SWAP , CF_NORMAL, 0 /* -S (11--11) */},
+/* 96*/ {N("IADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/* 97*/ {N("LADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
+/* 98*/ {N("FADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
+/* 99*/ {N("DADD ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
+/*100*/ {N("ISUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*101*/ {N("LSUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
+/*102*/ {N("FSUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
+/*103*/ {N("DSUB ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
+/*104*/ {N("IMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*105*/ {N("LMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
+/*106*/ {N("FMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
+/*107*/ {N("DMUL ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
+/*108*/ {N("IDIV ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /* (II--I) */},
+/*109*/ {N("LDIV ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /* (LL--L) */},
+/*110*/ {N("FDIV ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
+/*111*/ {N("DDIV ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
+/*112*/ {N("IREM ") DF_2_TO_1 , CF_NORMAL, PEI|IDIV_CALLS /* (II--I) */},
+/*113*/ {N("LREM ") DF_2_TO_1 , CF_NORMAL, PEI|LDIV_CALLS /* (LL--L) */},
+/*114*/ {N("FREM ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--F) */},
+/*115*/ {N("DREM ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--D) */},
+/*116*/ {N("INEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
+/*117*/ {N("LNEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--L) */},
+/*118*/ {N("FNEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--F) */},
+/*119*/ {N("DNEG ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--D) */},
+/*120*/ {N("ISHL ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*121*/ {N("LSHL ") DF_2_TO_1 , CF_NORMAL, 0 /* (LI--L) */},
+/*122*/ {N("ISHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*123*/ {N("LSHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LI--L) */},
+/*124*/ {N("IUSHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*125*/ {N("LUSHR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LI--L) */},
+/*126*/ {N("IAND ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*127*/ {N("LAND ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
+/*128*/ {N("IOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*129*/ {N("LOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
+/*130*/ {N("IXOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (II--I) */},
+/*131*/ {N("LXOR ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--L) */},
+/*132*/ {N("IINC ") DF_IINC , CF_NORMAL, 0 /* (--) */},
+/*133*/ {N("I2L ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--L) */},
+/*134*/ {N("I2F ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--F) */},
+/*135*/ {N("I2D ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--D) */},
+/*136*/ {N("L2I ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--I) */},
+/*137*/ {N("L2F ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--F) */},
+/*138*/ {N("L2D ") DF_1_TO_1 , CF_NORMAL, 0 /* (L--D) */},
+/*139*/ {N("F2I ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--I) */},
+/*140*/ {N("F2L ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--L) */},
+/*141*/ {N("F2D ") DF_1_TO_1 , CF_NORMAL, 0 /* (F--D) */},
+/*142*/ {N("D2I ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--I) */},
+/*143*/ {N("D2L ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--L) */},
+/*144*/ {N("D2F ") DF_1_TO_1 , CF_NORMAL, 0 /* (D--F) */},
+/*145*/ {N("INT2BYTE ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
+/*146*/ {N("INT2CHAR ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
+/*147*/ {N("INT2SHORT ") DF_1_TO_1 , CF_NORMAL, 0 /* (I--I) */},
+/*148*/ {N("LCMP ") DF_2_TO_1 , CF_NORMAL, 0 /* (LL--I) */},
+/*149*/ {N("FCMPL ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--I) */},
+/*150*/ {N("FCMPG ") DF_2_TO_1 , CF_NORMAL, 0 /* (FF--I) */},
+/*151*/ {N("DCMPL ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--I) */},
+/*152*/ {N("DCMPG ") DF_2_TO_1 , CF_NORMAL, 0 /* (DD--I) */},
+/*153*/ {N("IFEQ ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
+/*154*/ {N("IFNE ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
+/*155*/ {N("IFLT ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
+/*156*/ {N("IFGE ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
+/*157*/ {N("IFGT ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
+/*158*/ {N("IFLE ") DF_1_TO_0 , CF_IF , 0 /* (I--) */},
+/*159*/ {N("IF_ICMPEQ ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
+/*160*/ {N("IF_ICMPNE ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
+/*161*/ {N("IF_ICMPLT ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
+/*162*/ {N("IF_ICMPGE ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
+/*163*/ {N("IF_ICMPGT ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
+/*164*/ {N("IF_ICMPLE ") DF_2_TO_0 , CF_IF , 0 /* (II--) */},
+/*165*/ {N("IF_ACMPEQ ") DF_2_TO_0 , CF_IF , 0 /* (AA--) */},
+/*166*/ {N("IF_ACMPNE ") DF_2_TO_0 , CF_IF , 0 /* (AA--) */},
+/*167*/ {N("GOTO ") DF_0_TO_0 , CF_GOTO , 0 /* (--) */},
+/*168*/ {N("JSR ") DF_0_TO_1 , CF_JSR , 0 /* (--R) */},
+/*169*/ {N("RET ") DF_0_TO_0 , CF_RET , 0 /* (--) */},
+/*170*/ {N("TABLESWITCH ") DF_1_TO_0 , CF_TABLE , 0 /* (I--) */},
+/*171*/ {N("LOOKUPSWITCH ") DF_1_TO_0 , CF_LOOKUP, 0 /* (I--) */},
+/*172*/ {N("IRETURN ") DF_1_TO_0 , CF_END , 0 /* (I--) */},
+/*173*/ {N("LRETURN ") DF_1_TO_0 , CF_END , 0 /* (L--) */},
+/*174*/ {N("FRETURN ") DF_1_TO_0 , CF_END , 0 /* (F--) */},
+/*175*/ {N("DRETURN ") DF_1_TO_0 , CF_END , 0 /* (D--) */},
+/*176*/ {N("ARETURN ") DF_1_TO_0 , CF_END , PEI /* (A--) */},
+/*177*/ {N("RETURN ") DF_0_TO_0 , CF_END , 0 /* (--) */},
+/*178*/ {N("GETSTATIC ") DF_0_TO_1 , CF_NORMAL, PEI /* (--1|--2) */},
+/*179*/ {N("PUTSTATIC ") DF_1_TO_0 , CF_NORMAL, PEI /* (1--|2--) */},
+/*180*/ {N("GETFIELD ") DF_1_TO_1 , CF_NORMAL, PEI /* (A--1|A--2) */},
+/*181*/ {N("PUTFIELD ") DF_2_TO_0 , CF_NORMAL, PEI /* (A1--|A2--) */},
+/*182*/ {N("INVOKEVIRTUAL ") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
+/*183*/ {N("INVOKESPECIAL ") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
+/*184*/ {N("INVOKESTATIC ") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
+/*185*/ {N("INVOKEINTERFACE") DF_INVOKE , CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */},
+/*186*/ {N("UNDEF186 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*187*/ {N("NEW ") DF_0_TO_1 , CF_NORMAL, PEI /* -- (--A) */},
+/*188*/ {N("NEWARRAY ") DF_0_TO_1 , CF_NORMAL, PEI /* -- (--A) */},
+/*189*/ {N("ANEWARRAY ") DF_0_TO_1 , CF_NORMAL, PEI /* -- (--A) */},
+/*190*/ {N("ARRAYLENGTH ") DF_1_TO_1 , CF_NORMAL, PEI /* (A--I) */},
+/*191*/ {N("ATHROW ") DF_1_TO_0 , CF_END , PEI /* (A--) */},
+/*192*/ {N("CHECKCAST ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS /* (A--A) */},
+/*193*/ {N("INSTANCEOF ") DF_1_TO_1 , CF_NORMAL, PEI|CALLS /* (A--I) */},
+/*194*/ {N("MONITORENTER ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS /* -- (A--) */},
+/*195*/ {N("MONITOREXIT ") DF_1_TO_0 , CF_NORMAL, PEI|CALLS /* -- (A--) */},
+/*196*/ {N("UNDEF196 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*197*/ {N("MULTIANEWARRAY ") DF_N_TO_1 , CF_NORMAL, PEI|CALLS /* (.--A) */},
+/*198*/ {N("IFNULL ") DF_1_TO_0 , CF_IF , 0 /* (A--) */},
+/*199*/ {N("IFNONNULL ") DF_1_TO_0 , CF_IF , 0 /* (A--) */},
+/*200*/ {N("UNDEF200 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*201*/ {N("UNDEF201 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*202*/ {N("UNDEF202 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*203*/ {N("UNDEF203 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*204*/ {N("IASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*205*/ {N("LASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*206*/ {N("FASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*207*/ {N("DASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*208*/ {N("AASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*209*/ {N("BASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*210*/ {N("CASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*211*/ {N("SASTORECONST ") DF_2_TO_0 , CF_NORMAL, PEI /* S+ (AI--) */},
+/*212*/ {N("PUTSTATICCONST ") DF_0_TO_0 , CF_NORMAL, PEI /* S+ (--) */},
+/*213*/ {N("PUTFIELDCONST ") DF_1_TO_0 , CF_NORMAL, PEI /* S+ (A--) */},
+/*214*/ {N("IMULPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (I--I) */},
+/*215*/ {N("LMULPOW2 ") DF_1_TO_1 , CF_NORMAL, 0 /* S+ (L--L) */},
+/*216*/ {N("IF_FCMPEQ ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*217*/ {N("IF_FCMPNE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*218*/ {N("IF_FCMPL_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*219*/ {N("IF_FCMPL_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*220*/ {N("IF_FCMPL_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*221*/ {N("IF_FCMPL_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*222*/ {N("IF_FCMPG_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*223*/ {N("IF_FCMPG_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*224*/ {N("IF_FCMPG_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*225*/ {N("IF_FCMPG_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*226*/ {N("IF_DCMPEQ ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*227*/ {N("IF_DCMPNE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*228*/ {N("IF_DCMPL_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*229*/ {N("IF_DCMPL_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*230*/ {N("IF_DCMPL_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*231*/ {N("IF_DCMPL_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*232*/ {N("IF_DCMPG_LT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*233*/ {N("IF_DCMPG_GE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*234*/ {N("IF_DCMPG_GT ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*235*/ {N("IF_DCMPG_LE ") DF_0_TO_0 , CF_IF , 0 /* -- () */},
+/*236*/ {N("UNDEF236 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*237*/ {N("UNDEF237 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*238*/ {N("UNDEF238 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*239*/ {N("UNDEF239 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*240*/ {N("UNDEF240 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*241*/ {N("UNDEF241 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*242*/ {N("UNDEF242 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*243*/ {N("UNDEF243 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*244*/ {N("UNDEF244 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*245*/ {N("UNDEF245 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*246*/ {N("UNDEF246 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*247*/ {N("UNDEF247 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*248*/ {N("UNDEF248 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*249*/ {N("GETEXCEPTION ") DF_0_TO_1 , CF_NORMAL, 0 /* -- () */},
+/*250*/ {N("PHI ") DF_N_TO_1 , CF_NORMAL, 0 /* -- () */},
+/*251*/ {N("INLINE_START ") DF_0_TO_0 , CF_NORMAL, 0 /* S+ (--) */},
+/*252*/ {N("INLINE_END ") DF_0_TO_0 , CF_NORMAL, 0 /* S+ (--) */},
+/*253*/ {N("INLINE_BODY ") DF_0_TO_0 , CF_NORMAL, 0 /* S+ (--) */},
+/*254*/ {N("UNDEF254 ") DF_0_TO_0 , CF_NORMAL, 0 /* -- () */},
+/*255*/ {N("BUILTIN ") DF_BUILTIN, CF_NORMAL, PEI|CALLS /* (.--1|.--2|.--) */}
+
--- /dev/null
+/* src/vm/jit/ir/instruction.cpp - IR instruction
+
+ 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/descriptor.h"
+
+#include "vm/jit/ir/instruction.hpp"
+
+
+// REMOVEME
+extern "C" {
+
+methoddesc* instruction_call_site(const instruction* iptr)
+{
+ if (iptr->opc == ICMD_BUILTIN) {
+ return iptr->sx.s23.s3.bte->md;
+ }
+ else if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ return iptr->sx.s23.s3.um->methodref->parseddesc.md;
+ }
+ else {
+ return iptr->sx.s23.s3.fmiref->p.method->parseddesc;
+ }
+}
+
+}
+
+
+/*
+ * These 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/ir/instruction.hpp - IR instruction
+
+ 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 _INSTRUCTION_HPP
+#define _INSTRUCTION_HPP
+
+// Forward typedefs.
+typedef struct instruction instruction;
+typedef struct insinfo_inline insinfo_inline;
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/descriptor.h"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/replace.hpp"
+
+#include "vm/jit/ir/icmd.hpp"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Instruction structure.
+
+/* branch_target_t: used in TABLESWITCH tables */
+
+typedef union {
+ int32_t insindex; /* used in parse */
+ basicblock *block; /* valid after parse */
+} branch_target_t;
+
+/* lookup_target_t: used in LOOKUPSWITCH tables */
+
+typedef struct {
+ int32_t value; /* case value */
+ branch_target_t target; /* branch target, see above */
+} lookup_target_t;
+
+/*** s1 operand ***/
+
+typedef union {
+ int32_t varindex;
+ int32_t argcount;
+} s1_operand_t;
+
+/*** s2 operand ***/
+
+typedef union {
+ int32_t varindex;
+ int32_t *args;
+ classref_or_classinfo c;
+ unresolved_class *uc;
+ uintptr_t constval; /* for PUT*CONST */
+ int32_t tablelow; /* for TABLESWITCH */
+ uint32_t lookupcount; /* for LOOKUPSWITCH */
+ int32_t retaddrnr; /* for ASTORE */
+ instruction **iargs; /* for PHI */
+} s2_operand_t;
+
+/*** s3 operand ***/
+
+typedef union {
+ int32_t varindex;
+ uintptr_t constval;
+ classref_or_classinfo c;
+ constant_FMIref *fmiref;
+ unresolved_method *um;
+ unresolved_field *uf;
+ insinfo_inline *inlineinfo; /* for INLINE_START/END */
+ int32_t tablehigh; /* for TABLESWITCH */
+ branch_target_t lookupdefault; /* for LOOKUPSWITCH */
+ branch_target_t jsrtarget; /* for JSR */
+ int32_t javaindex; /* for *STORE */
+ struct builtintable_entry *bte;
+} s3_operand_t;
+
+/*** val operand ***/
+
+typedef union {
+ int32_t i;
+ int64_t l;
+ float f;
+ double d;
+ void *anyptr;
+ java_handle_t *stringconst; /* for ACONST with string */
+ classref_or_classinfo c; /* for ACONST with class */
+} val_operand_t;
+
+/*** dst operand ***/
+
+typedef union {
+ int32_t varindex;
+ basicblock *block; /* valid after parse */
+ branch_target_t *table; /* for TABLESWITCH */
+ lookup_target_t *lookup; /* for LOOKUPSWITCH */
+ int32_t insindex; /* used in parse */
+} dst_operand_t;
+
+/*** flags (32 bits) ***/
+
+#define INS_FLAG_BASICBLOCK 0x01 /* marks a basic block start */
+#define INS_FLAG_UNRESOLVED 0x02 /* contains unresolved field/meth/class*/
+#define INS_FLAG_CLASS 0x04 /* for ACONST, PUT*CONST with class */
+#define INS_FLAG_ARRAY 0x08 /* for CHECKCAST/INSTANCEOF with array */
+#define INS_FLAG_CHECK 0x10 /* for *ALOAD|*ASTORE: check index */
+ /* for BUILTIN: check exception */
+#define INS_FLAG_KILL_PREV 0x04 /* for *STORE, invalidate prev local */
+#define INS_FLAG_KILL_NEXT 0x08 /* for *STORE, invalidate next local */
+#define INS_FLAG_RETADDR 0x10 /* for ASTORE: op is a returnAddress */
+
+#define INS_FLAG_ID_SHIFT 5
+#define INS_FLAG_ID_MASK (~0 << INS_FLAG_ID_SHIFT)
+
+typedef union {
+ u4 bits;
+} flags_operand_t;
+
+
+// Instruction.
+
+/* The instruction format for the intermediate representation: */
+
+struct instruction {
+ u2 opc; /* opcode */
+ u2 line; /* line number */
+#if SIZEOF_VOID_P == 8
+ flags_operand_t flags; /* 4 bytes */
+#endif
+ s1_operand_t s1; /* pointer-size */
+ union {
+ struct {
+ s2_operand_t s2; /* pointer-size */
+ s3_operand_t s3; /* pointer-size */
+ } s23; /* XOR */
+ val_operand_t val; /* long-size */
+ } sx;
+ dst_operand_t dst; /* pointer-size */
+#if SIZEOF_VOID_P == 4
+ flags_operand_t flags; /* 4 bytes */
+#endif
+#if defined(ENABLE_ESCAPE_REASON)
+ void *escape_reasons;
+#endif
+};
+
+
+#define INSTRUCTION_STARTS_BASICBLOCK(iptr) \
+ ((iptr)->flags.bits & INS_FLAG_BASICBLOCK)
+
+#define INSTRUCTION_IS_RESOLVED(iptr) \
+ (!((iptr)->flags.bits & INS_FLAG_UNRESOLVED))
+
+#define INSTRUCTION_IS_UNRESOLVED(iptr) \
+ ((iptr)->flags.bits & INS_FLAG_UNRESOLVED)
+
+#define INSTRUCTION_MUST_CHECK(iptr) \
+ ((iptr)->flags.bits & INS_FLAG_CHECK)
+
+#define INSTRUCTION_GET_FIELDREF(iptr,fref) \
+ do { \
+ if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
+ fref = iptr->sx.s23.s3.uf->fieldref; \
+ else \
+ fref = iptr->sx.s23.s3.fmiref; \
+ } while (0)
+
+#define INSTRUCTION_GET_METHODREF(iptr,mref) \
+ do { \
+ if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
+ mref = iptr->sx.s23.s3.um->methodref; \
+ else \
+ mref = iptr->sx.s23.s3.fmiref; \
+ } while (0)
+
+#define INSTRUCTION_GET_METHODDESC(iptr, md) \
+ do { \
+ if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
+ md = iptr->sx.s23.s3.um->methodref->parseddesc.md; \
+ else \
+ md = iptr->sx.s23.s3.fmiref->parseddesc.md; \
+ } while (0)
+
+
+/* additional info structs for special instructions ***************************/
+
+/* for ICMD_INLINE_START and ICMD_INLINE_END */
+
+struct insinfo_inline {
+ /* fields copied from the inlining tree ----------------------------------*/
+ insinfo_inline *parent; /* insinfo of the surrounding inlining, if any*/
+ methodinfo *method; /* the inlined method starting/ending here */
+ methodinfo *outer; /* the outer method suspended/resumed here */
+ int32_t synclocal; /* local index used for synchronization */
+ bool synchronize; /* true if synchronization is needed */
+ int32_t throughcount; /* total # of pass-through variables */
+ int32_t paramcount; /* number of parameters of original call */
+ int32_t stackvarscount; /* source stackdepth at INLINE_START */
+ int32_t *stackvars; /* stack vars at INLINE_START */
+
+ /* fields set by inlining ------------------------------------------------*/
+ int32_t *javalocals_start; /* javalocals at start of inlined body */
+ int32_t *javalocals_end; /* javalocals after inlined body */
+
+ /* fields set by replacement point creation ------------------------------*/
+#if defined(ENABLE_REPLACEMENT)
+ rplpoint *rp; /* replacement point at INLINE_START */
+#endif
+
+ /* fields set by the codegen ---------------------------------------------*/
+ int32_t startmpc; /* machine code offset of start of inlining */
+};
+
+
+/* Additional instruction accessors */
+
+methoddesc* instruction_call_site(const instruction* iptr);
+
+static inline bool instruction_has_dst(const instruction* iptr)
+{
+ if (
+ (icmd_table[iptr->opc].dataflow == DF_INVOKE) ||
+ (icmd_table[iptr->opc].dataflow == DF_BUILTIN)
+ ) {
+ return instruction_call_site(iptr)->returntype.type != TYPE_VOID;
+ }
+ else {
+ return icmd_table[iptr->opc].dataflow >= DF_DST_BASE;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _INSTRUCTION_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/jit.c - calls the code generation 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 "md.h"
-
-#include "mm/memory.h"
-
-#include "native/native.h"
-
-#include "toolbox/logging.h"
-
-#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/cfg.h"
-
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/disass.h"
-#include "vm/jit/dseg.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/parse.h"
-#include "vm/jit/reg.h"
-
-#include "vm/jit/show.h"
-#include "vm/jit/stack.h"
-
-#if defined(ENABLE_JITCACHE)
-# include "vm/jit/jitcache.hpp"
-#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"
-#endif
-
-#if defined(ENABLE_SSA)
-# include "vm/jit/optimizing/lsra.h"
-# include "vm/jit/optimizing/ssa.h"
-#endif
-
-#if defined(ENABLE_INLINING)
-# include "vm/jit/inline/inline.h"
-#endif
-
-#include "vm/jit/ir/bytecode.h"
-
-#include "vm/jit/loop/analyze.h"
-#include "vm/jit/loop/graph.h"
-#include "vm/jit/loop/loop.h"
-
-#if defined(ENABLE_IFCONV)
-# include "vm/jit/optimizing/ifconv.h"
-#endif
-
-#include "vm/jit/optimizing/reorder.h"
-
-#if defined(ENABLE_PYTHON)
-# include "vm/jit/python.h"
-#endif
-
-#include "vm/jit/verify/typecheck.h"
-
-
-/* debug macros ***************************************************************/
-
-#if !defined(NDEBUG)
-#define DEBUG_JIT_COMPILEVERBOSE(x) \
- do { \
- if (compileverbose) { \
- log_message_method(x, m); \
- } \
- } while (0)
-#else
-#define DEBUG_JIT_COMPILEVERBOSE(x) /* nothing */
-#endif
-
-#if !defined(NDEBUG)
-# define TRACECOMPILERCALLS() \
- do { \
- if (opt_TraceCompilerCalls) { \
- log_start(); \
- log_print("[JIT compiler started: method="); \
- method_print(m); \
- log_print("]"); \
- log_finish(); \
- } \
- } while (0)
-#else
-# define TRACECOMPILERCALLS()
-#endif
-
-
-/* the ICMD table ************************************************************/
-
-#if !defined(NDEBUG)
-#define N(name) name,
-#else
-#define N(name)
-#endif
-
-/* abbreviations for flags */
-
-#define PEI ICMDTABLE_PEI
-#define CALLS ICMDTABLE_CALLS
-
-/* some machine dependent values */
-
-#if SUPPORT_DIVISION
-#define IDIV_CALLS 0
-#else
-#define IDIV_CALLS ICMDTABLE_CALLS
-#endif
-
-#if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
-#define LDIV_CALLS 0
-#else
-#define LDIV_CALLS ICMDTABLE_CALLS
-#endif
-
-/* include the actual table */
-
-icmdtable_entry_t icmd_table[256] = {
-#include <vm/jit/icmdtable.inc>
-};
-
-#undef N
-#undef PEI
-#undef CALLS
-
-/* XXX hack until the old "PEI" definition is removed */
-#define PEI 1
-
-
-/* jit_init ********************************************************************
-
- Initializes the JIT subsystem.
-
-*******************************************************************************/
-
-void jit_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("jit_init");
-
-#if defined(ENABLE_JIT)
- /* initialize stack analysis subsystem */
-
- (void) stack_init();
-#endif
-
- /* initialize show subsystem */
-
-#if !defined(NDEBUG)
- (void) show_init();
-#endif
-
- /* initialize codegen subsystem */
-
- codegen_init();
-
- /* initialize code subsystem */
-
- (void) code_init();
-
- /* Machine dependent initialization. */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- intrp_md_init();
- else
-# endif
- md_init();
-#else
- intrp_md_init();
-#endif
-
-#if defined(ENABLE_OPAGENT)
- if (opt_EnableOpagent)
- OprofileAgent_initialize();
-#endif
-}
-
-
-/* jit_close *******************************************************************
-
- Close the JIT subsystem.
-
-*******************************************************************************/
-
-void jit_close(void)
-{
-#if defined(ENABLE_OPAGENT)
- if (opt_EnableOpagent)
- OprofileAgent_close();
-#endif
-}
-
-
-/* dummy function, used when there is no JavaVM code available */
-
-static u1 *do_nothing_function(void)
-{
- return NULL;
-}
-
-
-/* jit_jitdata_new *************************************************************
-
- Allocates and initalizes a new jitdata structure.
-
-*******************************************************************************/
-
-jitdata *jit_jitdata_new(methodinfo *m)
-{
- jitdata *jd;
- codeinfo *code;
-
- /* allocate jitdata structure and fill it */
-
- jd = DNEW(jitdata);
-
- jd->m = m;
- jd->cd = DNEW(codegendata);
- jd->rd = DNEW(registerdata);
-#if defined(ENABLE_LOOP)
- jd->ld = DNEW(loopdata);
-#endif
-
- /* Allocate codeinfo memory from the heap as we need to keep them. */
-
- code = code_codeinfo_new(m);
-
- /* Set codeinfo flags. */
-
-#if defined(ENABLE_THREADS)
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- code_flag_synchronized(code);
-
- if (checksync && (m->flags & ACC_SYNCHRONIZED))
- code_unflag_leafmethod(code);
- else
-#endif
- code_flag_leafmethod(code);
-
- /* initialize variables */
-
- jd->code = code;
- jd->flags = 0;
- jd->exceptiontable = NULL;
- jd->exceptiontablelength = 0;
- jd->returncount = 0;
- jd->branchtoentry = false;
- jd->branchtoend = false;
- jd->returncount = 0;
- jd->returnblock = NULL;
- jd->maxlocals = m->maxlocals;
-
- return jd;
-}
-
-
-/* jit_compile *****************************************************************
-
- Translates one method to machine code.
-
-*******************************************************************************/
-
-static u1 *jit_compile_intern(jitdata *jd);
-
-u1 *jit_compile(methodinfo *m)
-{
- u1 *r;
- jitdata *jd;
- int32_t dumpmarker;
-
- STATISTICS(count_jit_calls++);
-
- /* Initialize the static function's class. */
-
- /* ATTENTION: This MUST be done before the method lock is aquired,
- otherwise we could run into a deadlock with <clinit>'s that
- call static methods of it's own class. */
-
- if ((m->flags & ACC_STATIC) && !(m->clazz->state & CLASS_INITIALIZED)) {
-#if !defined(NDEBUG)
- if (initverbose)
- log_message_class("Initialize class ", m->clazz);
-#endif
-
- if (!initialize_class(m->clazz))
- return NULL;
-
- /* check if the method has been compiled during initialization */
-
- if ((m->code != NULL) && (m->code->entrypoint != NULL))
- return m->code->entrypoint;
- }
-
- /* enter a monitor on the method */
-
- LOCK_MONITOR_ENTER(m);
-
- /* if method has been already compiled return immediately */
-
- if (m->code != NULL) {
- LOCK_MONITOR_EXIT(m);
-
- assert(m->code->entrypoint);
- return m->code->entrypoint;
- }
-
- TRACECOMPILERCALLS();
-
- STATISTICS(count_methods++);
-
-#if defined (ENABLE_JITCACHE)
-
- if (jitcache_load (m))
- {
- LOCK_MONITOR_EXIT(m);
-
- return m->code->entrypoint;
- }
-
-#endif
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- compilingtime_start();
-#endif
-
- /* mark start of dump memory area */
-
- DMARKER;
-
- /* create jitdata structure */
-
- jd = jit_jitdata_new(m);
-
- /* set the flags for the current JIT run */
-
- jd->flags = JITDATA_FLAG_PARSE;
-
-#if defined(ENABLE_VERIFIER)
- if (opt_verify)
- jd->flags |= JITDATA_FLAG_VERIFY;
-#endif
-
-#if defined(ENABLE_PROFILING)
- if (opt_prof)
- jd->flags |= JITDATA_FLAG_INSTRUMENT;
-#endif
-
-#if defined(ENABLE_IFCONV)
- if (opt_ifconv)
- jd->flags |= JITDATA_FLAG_IFCONV;
-#endif
-
-#if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
- if (opt_Inline && opt_InlineAll)
- jd->flags |= JITDATA_FLAG_INLINE;
-#endif
-
- if (opt_showintermediate)
- jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
-
- if (opt_showdisassemble)
- jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
-
- if (opt_verbosecall)
- jd->flags |= JITDATA_FLAG_VERBOSECALL;
-
-#if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
- if (opt_Inline && (jd->m->hitcountdown > 0) && (jd->code->optlevel == 0)) {
- jd->flags |= JITDATA_FLAG_COUNTDOWN;
- }
-#endif
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- /* initialize the register allocator */
- {
- reg_setup(jd);
- }
-#endif
-
- /* setup the codegendata memory */
-
- codegen_setup(jd);
-
- /* now call internal compile function */
-
- r = jit_compile_intern(jd);
-
- if (r == NULL) {
- /* We had an exception! Finish stuff here if necessary. */
-
- /* release codeinfo */
-
- code_codeinfo_free(jd->code);
-
-#if defined(ENABLE_PROFILING)
- /* Release memory for basic block profiling information. */
-
- if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
- if (jd->code->bbfrequency != NULL)
- MFREE(jd->code->bbfrequency, u4, jd->code->basicblockcount);
-#endif
- }
- else {
- DEBUG_JIT_COMPILEVERBOSE("Running: ");
- }
-
-#if defined (ENABLE_JITCACHE)
- jitcache_store(m);
-#endif
-
- /* release dump area */
-
- DRELEASE;
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- compilingtime_stop();
-#endif
-
-#if defined(ENABLE_OPAGENT)
- if (opt_EnableOpagent)
- OprofileAgent_newmethod(m);
-#endif
-
- /* leave the monitor */
-
- LOCK_MONITOR_EXIT(m);
-
- /* return pointer to the methods entry point */
-
- return r;
-}
-
-
-/* jit_recompile ***************************************************************
-
- Recompiles a Java method.
-
-*******************************************************************************/
-
-u1 *jit_recompile(methodinfo *m)
-{
- u1 *r;
- jitdata *jd;
- u1 optlevel;
- int32_t dumpmarker;
-
- /* check for max. optimization level */
-
- optlevel = (m->code) ? m->code->optlevel : 0;
-
-#if 0
- if (optlevel == 1) {
-/* log_message_method("not recompiling: ", m); */
- return NULL;
- }
-#endif
-
- DEBUG_JIT_COMPILEVERBOSE("Recompiling start: ");
-
- STATISTICS(count_jit_calls++);
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- compilingtime_start();
-#endif
-
- /* mark start of dump memory area */
-
- DMARKER;
-
- /* create jitdata structure */
-
- jd = jit_jitdata_new(m);
-
- /* set the current optimization level to the previous one plus 1 */
-
- jd->code->optlevel = optlevel + 1;
-
- /* get the optimization flags for the current JIT run */
-
-#if defined(ENABLE_VERIFIER)
- jd->flags |= JITDATA_FLAG_VERIFY;
-#endif
-
- /* jd->flags |= JITDATA_FLAG_REORDER; */
- if (opt_showintermediate)
- jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
- if (opt_showdisassemble)
- jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
- if (opt_verbosecall)
- jd->flags |= JITDATA_FLAG_VERBOSECALL;
-
-#if defined(ENABLE_INLINING)
- if (opt_Inline)
- jd->flags |= JITDATA_FLAG_INLINE;
-#endif
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- /* initialize the register allocator */
-
- reg_setup(jd);
-#endif
-
- /* setup the codegendata memory */
-
- codegen_setup(jd);
-
- /* now call internal compile function */
-
- r = jit_compile_intern(jd);
-
- if (r == NULL) {
- /* We had an exception! Finish stuff here if necessary. */
-
- /* release codeinfo */
-
- code_codeinfo_free(jd->code);
- }
-
- /* release dump area */
-
- DRELEASE;
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- 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 */
-
- return r;
-}
-
-#if defined(ENABLE_PM_HACKS)
-#include "vm/jit/jit_pm_1.inc"
-#endif
-
-/* jit_compile_intern **********************************************************
-
- Static internal function which does the actual compilation.
-
-*******************************************************************************/
-
-static u1 *jit_compile_intern(jitdata *jd)
-{
- methodinfo *m;
- codegendata *cd;
- codeinfo *code;
-
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start,time_checks,time_parse,time_stack,
- time_typecheck,time_loop,time_ifconv,time_alloc,
- time_codegen;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- /* get required compiler data */
-
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
- jd->ls = NULL;
-#endif
- m = jd->m;
- code = jd->code;
- cd = jd->cd;
-
-#if defined(ENABLE_DEBUG_FILTER)
- show_filters_apply(jd->m);
-#endif
-
- /* Handle native methods and create a native stub. */
-
- if (m->flags & ACC_NATIVE) {
- functionptr f;
-
- f = native_method_resolve(m);
-
- if (f == NULL)
- return NULL;
-
- code = codegen_generate_stub_native(m, f);
-
- /* Native methods are never recompiled. */
-
- assert(!m->code);
-
- m->code = code;
-
- return code->entrypoint;
- }
-
- /* if there is no javacode, print error message and return empty method */
-
- if (m->jcode == NULL) {
- DEBUG_JIT_COMPILEVERBOSE("No code given for: ");
-
- code->entrypoint = (u1 *) (ptrint) do_nothing_function;
- m->code = code;
-
- return code->entrypoint; /* return empty method */
- }
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- count_javacodesize += m->jcodelength + 18;
- count_tryblocks += jd->exceptiontablelength;
- count_javaexcsize += jd->exceptiontablelength * SIZEOF_VOID_P;
- }
-#endif
-
- RT_TIMING_GET_TIME(time_checks);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* Code for Sun's OpenJDK (see
- hotspot/src/share/vm/classfile/verifier.cpp
- (Verifier::is_eligible_for_verification)): Don't verify
- dynamically-generated bytecodes. */
-
-# if defined(ENABLE_VERIFIER)
- if (class_issubclass(m->clazz, class_sun_reflect_MagicAccessorImpl))
- jd->flags &= ~JITDATA_FLAG_VERIFY;
-# endif
-#endif
-
- /* call the compiler passes ***********************************************/
-
- DEBUG_JIT_COMPILEVERBOSE("Parsing: ");
-
- /* call parse pass */
-
- if (!parse(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while parsing: ");
-
- return NULL;
- }
- RT_TIMING_GET_TIME(time_parse);
-
- DEBUG_JIT_COMPILEVERBOSE("Parsing done: ");
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
-
- /* call stack analysis pass */
-
- if (!stack_analyse(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
-
- return NULL;
- }
- RT_TIMING_GET_TIME(time_stack);
-
- DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
-
-#ifdef ENABLE_VERIFIER
- if (JITDATA_HAS_FLAG_VERIFY(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
-
- /* call typecheck pass */
- if (!typecheck(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
-
- return NULL;
- }
-
- DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
- }
-#endif
- RT_TIMING_GET_TIME(time_typecheck);
-
-#if defined(ENABLE_LOOP)
- if (opt_loops) {
- depthFirst(jd);
- analyseGraph(jd);
- optimize_loops(jd);
- jit_renumber_basicblocks(jd);
- }
-#endif
- RT_TIMING_GET_TIME(time_loop);
-
-#if defined(ENABLE_IFCONV)
- if (JITDATA_HAS_FLAG_IFCONV(jd)) {
- if (!ifconv_static(jd))
- return NULL;
- jit_renumber_basicblocks(jd);
- }
-#endif
- RT_TIMING_GET_TIME(time_ifconv);
-
- /* 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-conversion. */
-
- if (JITDATA_HAS_FLAG_REORDER(jd)) {
- if (!reorder(jd))
- return NULL;
- jit_renumber_basicblocks(jd);
- }
-#endif
-
-#if defined(ENABLE_PM_HACKS)
-#include "vm/jit/jit_pm_2.inc"
-#endif
- DEBUG_JIT_COMPILEVERBOSE("Allocating registers: ");
-
-#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
- /* allocate registers */
- if (opt_lsra) {
- if (!lsra(jd))
- return NULL;
-
- STATISTICS(count_methods_allocated_by_lsra++);
-
- } else
-# endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
-#if defined(ENABLE_SSA)
- /* allocate registers */
- if (
- (opt_lsra &&
- jd->code->optlevel > 0)
- /* strncmp(jd->m->name->text, "hottie", 6) == 0*/
- /*&& jd->exceptiontablelength == 0*/
- ) {
- /*printf("=== %s ===\n", jd->m->name->text);*/
- jd->ls = DNEW(lsradata);
- jd->ls = NULL;
- ssa(jd);
- /*lsra(jd);*/ regalloc(jd);
- /*eliminate_subbasicblocks(jd);*/
- STATISTICS(count_methods_allocated_by_lsra++);
-
- } else
-# endif /* defined(ENABLE_SSA) */
- {
- STATISTICS(count_locals_conflicts += (jd->maxlocals - 1) * (jd->maxlocals));
-
- regalloc(jd);
- }
-
- STATISTICS(simplereg_make_statistics(jd));
-
- DEBUG_JIT_COMPILEVERBOSE("Allocating registers done: ");
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif /* defined(ENABLE_JIT) */
- RT_TIMING_GET_TIME(time_alloc);
-
-#if defined(ENABLE_PROFILING)
- /* Allocate memory for basic block profiling information. This
- _must_ be done after loop optimization and register allocation,
- since they can change the basic block count. */
-
- if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
- code->bbfrequency = MNEW(u4, jd->basicblockcount);
-#endif
-
- DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
-
- /* now generate the machine code */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp) {
-#if defined(ENABLE_VERIFIER)
- if (opt_verify) {
- DEBUG_JIT_COMPILEVERBOSE("Typechecking (stackbased): ");
-
- if (!typecheck_stackbased(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking (stackbased): ");
- return NULL;
- }
- }
-#endif
- if (!intrp_codegen(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
-
- return NULL;
- }
- } else
-# endif
- {
- if (!codegen_generate(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
-
- return NULL;
- }
- }
-#else
- if (!intrp_codegen(jd)) {
- DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
-
- return NULL;
- }
-#endif
- RT_TIMING_GET_TIME(time_codegen);
-
- DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
-
-#if !defined(NDEBUG) && defined(ENABLE_REPLACEMENT)
- /* activate replacement points inside newly created code */
-
- if (opt_TestReplacement)
- replace_activate_replacement_points(code, false);
-#endif
-
-#if !defined(NDEBUG)
-#if defined(ENABLE_DEBUG_FILTER)
- if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
-#endif
- {
- /* intermediate and assembly code listings */
-
- if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
- show_method(jd, SHOW_CODE);
- }
- else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
-# if defined(ENABLE_DISASSEMBLER)
- DISASSEMBLE(code->entrypoint,
- code->entrypoint + (code->mcodelength - cd->dseglen));
-# endif
- }
-
- if (opt_showddatasegment)
- dseg_display(jd);
- }
-#endif
-
- /* switch to the newly generated code */
-
- assert(code);
- assert(code->entrypoint);
-
- /* add the current compile version to the methodinfo */
-
- code->prev = m->code;
- m->code = code;
-
- RT_TIMING_TIME_DIFF(time_start,time_checks,RT_TIMING_JIT_CHECKS);
- RT_TIMING_TIME_DIFF(time_checks,time_parse,RT_TIMING_JIT_PARSE);
- RT_TIMING_TIME_DIFF(time_parse,time_stack,RT_TIMING_JIT_STACK);
- RT_TIMING_TIME_DIFF(time_stack,time_typecheck,RT_TIMING_JIT_TYPECHECK);
- RT_TIMING_TIME_DIFF(time_typecheck,time_loop,RT_TIMING_JIT_LOOP);
- RT_TIMING_TIME_DIFF(time_loop,time_alloc,RT_TIMING_JIT_ALLOC);
- RT_TIMING_TIME_DIFF(time_alloc,time_codegen,RT_TIMING_JIT_CODEGEN);
- RT_TIMING_TIME_DIFF(time_start,time_codegen,RT_TIMING_JIT_TOTAL);
-
- /* return pointer to the methods entry point */
-
- return code->entrypoint;
-}
-
-
-/* jit_invalidate_code *********************************************************
-
- Mark the compiled code of the given method as invalid and take care that
- it is replaced if necessary.
-
- XXX Not fully implemented, yet.
-
-*******************************************************************************/
-
-void jit_invalidate_code(methodinfo *m)
-{
- codeinfo *code;
-
- code = m->code;
-
- if (code == NULL || code_is_invalid(code))
- return;
-
- code_flag_invalid(code);
-
- /* activate mappable replacement points */
-
-#if defined(ENABLE_REPLACEMENT)
- replace_activate_replacement_points(code, true);
-#else
- vm_abort("invalidating code only works with ENABLE_REPLACEMENT");
-#endif
-}
-
-
-/* jit_request_optimization ****************************************************
-
- Request optimization of the given method. If the code of the method is
- unoptimized, it will be invalidated, so the next jit_get_current_code(m)
- triggers an optimized recompilation.
- If the method is already optimized, this function does nothing.
-
- IN:
- m................the method
-
-*******************************************************************************/
-
-void jit_request_optimization(methodinfo *m)
-{
- codeinfo *code;
-
- code = m->code;
-
- if (code && code->optlevel == 0)
- jit_invalidate_code(m);
-}
-
-
-/* jit_get_current_code ********************************************************
-
- Get the currently valid code for the given method. If there is no valid
- code, (re)compile the method.
-
- IN:
- m................the method
-
- RETURN VALUE:
- the codeinfo* for the current code, or
- NULL if an exception has been thrown during recompilation.
-
-*******************************************************************************/
-
-codeinfo *jit_get_current_code(methodinfo *m)
-{
- assert(m);
-
- /* if we have valid code, return it */
-
- if (m->code && !code_is_invalid(m->code))
- return m->code;
-
- /* otherwise: recompile */
-
- if (!jit_recompile(m))
- return NULL;
-
- assert(m->code);
-
- return m->code;
-}
-
-
-/* jit_asm_compile *************************************************************
-
- This method is called from asm_vm_call_method and does:
-
- - create stackframe info for exceptions
- - compile the method
- - patch the entrypoint of the method into the calculated address in
- the JIT code
- - flushes the instruction cache.
-
-*******************************************************************************/
-
-#if defined(ENABLE_JIT)
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
-u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra)
-{
- stackframeinfo_t sfi;
- u1 *entrypoint;
- u1 *pa;
- ptrint *p;
-
- /* create the stackframeinfo (subtract 1 from RA as it points to the */
- /* instruction after the call) */
-
- stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ra-1);
-
- /* actually compile the method */
-
- entrypoint = jit_compile(m);
-
- /* remove the stackframeinfo */
-
- stacktrace_stackframeinfo_remove(&sfi);
-
- /* there was a problem during compilation */
-
- if (entrypoint == NULL)
- return NULL;
-
- /* get the method patch address */
-
- pa = md_jit_method_patch_address(sfi.pv, (void *) ra, mptr);
-
- /* patch the method entry point */
-
- p = (ptrint *) pa;
-
- *p = (ptrint) entrypoint;
-
- /* flush the instruction cache */
-
- md_icacheflush(pa, SIZEOF_VOID_P);
-
- return entrypoint;
-}
-#endif
-
-/* jit_compile_handle **********************************************************
-
- This method is called from the appropriate signal handler which
- handles compiler-traps and does the following:
-
- - compile the method
- - patch the entrypoint of the method into the calculated address in
- the JIT code
- - flush the instruction cache
-
-*******************************************************************************/
-
-void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
-{
- void *newpv; /* new compiled method PV */
- void *pa; /* patch address */
- uintptr_t *p; /* convenience pointer */
-
- /* Compile the method. */
-
- newpv = jit_compile(m);
-
- /* There was a problem during compilation. */
-
- if (newpv == NULL)
- return NULL;
-
- /* Get the method patch address. */
-
- pa = md_jit_method_patch_address(pv, ra, mptr);
-
- /* Patch the method entry point. */
-
- p = (uintptr_t *) pa;
-
- *p = (uintptr_t) newpv;
-
- /* Flush both caches. */
-
- md_cacheflush(pa, SIZEOF_VOID_P);
-
- return newpv;
-}
-#endif /* defined(ENABLE_JIT) */
-
-
-/* jit_complement_condition ****************************************************
-
- Returns the complement of the passed conditional instruction.
-
- We use the order of the different conditions, e.g.:
-
- ICMD_IFEQ 153
- ICMD_IFNE 154
-
- If the passed opcode is odd, we simply add 1 to get the complement.
- If the opcode is even, we subtract 1.
-
- Exception:
-
- ICMD_IFNULL 198
- ICMD_IFNONNULL 199
-
-*******************************************************************************/
-
-s4 jit_complement_condition(s4 opcode)
-{
- switch (opcode) {
- case ICMD_IFNULL:
- return ICMD_IFNONNULL;
-
- case ICMD_IFNONNULL:
- return ICMD_IFNULL;
-
- default:
- /* check if opcode is odd */
-
- if (opcode & 0x1)
- return opcode + 1;
- else
- return opcode - 1;
- }
-}
-
-
-/* jit_renumber_basicblocks ****************************************************
-
- Set the ->nr of all blocks so it increases when traversing ->next.
-
- IN:
- jitdata..........the current jitdata
-
-*******************************************************************************/
-
-void jit_renumber_basicblocks(jitdata *jd)
-{
- s4 nr;
- basicblock *bptr;
-
- nr = 0;
- for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
- bptr->nr = nr++;
- }
-
- /* we have one block more than jd->basicblockcount (the end marker) */
-
- assert(nr == jd->basicblockcount + 1);
-}
-
-
-/* jit_check_basicblock_numbers ************************************************
-
- Assert that the ->nr of the first block is zero and increases by 1 each
- time ->next is traversed.
- This function should be called before any analysis that relies on
- the basicblock numbers.
-
- IN:
- jitdata..........the current jitdata
-
- NOTE: Aborts with an assertion if the condition is not met!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void jit_check_basicblock_numbers(jitdata *jd)
-{
- s4 nr;
- basicblock *bptr;
-
- nr = 0;
- for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
- assert(bptr->nr == nr);
- nr++;
- }
-
- /* we have one block more than jd->basicblockcount (the end marker) */
-
- assert(nr == jd->basicblockcount + 1);
-}
-#endif /* !defined(NDEBUG) */
-
-methoddesc *instruction_call_site(const instruction *iptr) {
- if (iptr->opc == ICMD_BUILTIN) {
- return iptr->sx.s23.s3.bte->md;
- } else if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- return iptr->sx.s23.s3.um->methodref->parseddesc.md;
- } else {
- return iptr->sx.s23.s3.fmiref->p.method->parseddesc;
- }
-}
-
-/*
- * These 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/jit.cpp - Just-In-Time compiler
+
+ 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 "md.h"
+
+#include "mm/memory.h"
+
+#include "native/native.hpp"
+
+#include "toolbox/logging.h"
+
+#include "threads/mutex.hpp"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/loader.hpp"
+#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/cfg.h"
+
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/dseg.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/parse.h"
+#include "vm/jit/reg.h"
+
+#include "vm/jit/show.hpp"
+#include "vm/jit/stack.h"
+#include "vm/jit/stubs.hpp"
+
+#if defined(ENABLE_JITCACHE)
+# include "vm/jit/jitcache.hpp"
+#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"
+#endif
+
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#endif
+
+#if defined(ENABLE_INLINING)
+# include "vm/jit/inline/inline.h"
+#endif
+
+#include "vm/jit/ir/bytecode.h"
+
+#include "vm/jit/loop/analyze.h"
+#include "vm/jit/loop/graph.h"
+#include "vm/jit/loop/loop.h"
+
+#if defined(ENABLE_IFCONV)
+# include "vm/jit/optimizing/ifconv.h"
+#endif
+
+#include "vm/jit/optimizing/reorder.h"
+
+#if defined(ENABLE_PYTHON)
+# include "vm/jit/python.h"
+#endif
+
+#include "vm/jit/verify/typecheck.h"
+
+
+/* debug macros ***************************************************************/
+
+#if !defined(NDEBUG)
+#define DEBUG_JIT_COMPILEVERBOSE(x) \
+ do { \
+ if (compileverbose) { \
+ log_message_method(x, m); \
+ } \
+ } while (0)
+#else
+#define DEBUG_JIT_COMPILEVERBOSE(x) /* nothing */
+#endif
+
+#if !defined(NDEBUG)
+# define TRACECOMPILERCALLS() \
+ do { \
+ if (opt_TraceCompilerCalls) { \
+ log_start(); \
+ log_print("[JIT compiler started: method="); \
+ method_print(m); \
+ log_print("]"); \
+ log_finish(); \
+ } \
+ } while (0)
+#else
+# define TRACECOMPILERCALLS()
+#endif
+
+
+/* jit_init ********************************************************************
+
+ Initializes the JIT subsystem.
+
+*******************************************************************************/
+
+void jit_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("jit_init");
+
+#if defined(ENABLE_JIT)
+ /* initialize stack analysis subsystem */
+
+ (void) stack_init();
+#endif
+
+ /* initialize show subsystem */
+
+#if !defined(NDEBUG)
+ (void) show_init();
+#endif
+
+ /* initialize codegen subsystem */
+
+ codegen_init();
+
+ /* initialize code subsystem */
+
+ (void) code_init();
+
+ /* Machine dependent initialization. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ intrp_md_init();
+ else
+# endif
+ md_init();
+#else
+ intrp_md_init();
+#endif
+
+#if defined(ENABLE_OPAGENT)
+ if (opt_EnableOpagent)
+ OprofileAgent::initialize();
+#endif
+}
+
+
+/* jit_close *******************************************************************
+
+ Close the JIT subsystem.
+
+*******************************************************************************/
+
+void jit_close(void)
+{
+#if defined(ENABLE_OPAGENT)
+ if (opt_EnableOpagent)
+ OprofileAgent::close();
+#endif
+}
+
+
+/* dummy function, used when there is no JavaVM code available */
+
+static u1 *do_nothing_function(void)
+{
+ return NULL;
+}
+
+
+/* jit_jitdata_new *************************************************************
+
+ Allocates and initalizes a new jitdata structure.
+
+*******************************************************************************/
+
+jitdata *jit_jitdata_new(methodinfo *m)
+{
+ jitdata *jd;
+ codeinfo *code;
+
+ /* allocate jitdata structure and fill it */
+
+ jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
+
+ jd->m = m;
+ jd->cd = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
+ jd->rd = (registerdata*) DumpMemory::allocate(sizeof(registerdata));
+#if defined(ENABLE_LOOP)
+ jd->ld = (loopdata*) DumpMemory::allocate(sizeof(loopdata));
+#endif
+
+ /* Allocate codeinfo memory from the heap as we need to keep them. */
+
+ code = code_codeinfo_new(m);
+
+ /* Set codeinfo flags. */
+
+#if defined(ENABLE_THREADS)
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ code_flag_synchronized(code);
+
+ if (checksync && (m->flags & ACC_SYNCHRONIZED))
+ code_unflag_leafmethod(code);
+ else
+#endif
+ code_flag_leafmethod(code);
+
+ /* initialize variables */
+
+ jd->code = code;
+ jd->flags = 0;
+ jd->exceptiontable = NULL;
+ jd->exceptiontablelength = 0;
+ jd->returncount = 0;
+ jd->branchtoentry = false;
+ jd->branchtoend = false;
+ jd->returncount = 0;
+ jd->returnblock = NULL;
+ jd->maxlocals = m->maxlocals;
+
+ return jd;
+}
+
+
+/* jit_compile *****************************************************************
+
+ Translates one method to machine code.
+
+*******************************************************************************/
+
+static u1 *jit_compile_intern(jitdata *jd);
+
+u1 *jit_compile(methodinfo *m)
+{
+ u1 *r;
+ jitdata *jd;
+
+ STATISTICS(count_jit_calls++);
+
+ /* Initialize the static function's class. */
+
+ /* ATTENTION: This MUST be done before the method lock is aquired,
+ otherwise we could run into a deadlock with <clinit>'s that
+ call static methods of it's own class. */
+
+ if ((m->flags & ACC_STATIC) && !(m->clazz->state & CLASS_INITIALIZED)) {
+#if !defined(NDEBUG)
+ if (initverbose)
+ log_message_class("Initialize class ", m->clazz);
+#endif
+
+ if (!initialize_class(m->clazz))
+ return NULL;
+
+ /* check if the method has been compiled during initialization */
+
+ if ((m->code != NULL) && (m->code->entrypoint != NULL))
+ return m->code->entrypoint;
+ }
+
+ /* enter a monitor on the method */
+
+ m->mutex->lock();
+
+ /* if method has been already compiled return immediately */
+
+ if (m->code != NULL) {
+ m->mutex->unlock();
+
+ assert(m->code->entrypoint);
+ return m->code->entrypoint;
+ }
+
+ TRACECOMPILERCALLS();
+
+ STATISTICS(count_methods++);
+
+#if defined (ENABLE_JITCACHE)
+
+ if (jitcache_load (m))
+ {
+ m->mutex->unlock();
+
+ return m->code->entrypoint;
+ }
+
+#endif
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ compilingtime_start();
+#endif
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* create jitdata structure */
+
+ jd = jit_jitdata_new(m);
+
+ /* set the flags for the current JIT run */
+
+ jd->flags = JITDATA_FLAG_PARSE;
+
+#if defined(ENABLE_VERIFIER)
+ if (opt_verify)
+ jd->flags |= JITDATA_FLAG_VERIFY;
+#endif
+
+#if defined(ENABLE_PROFILING)
+ if (opt_prof)
+ jd->flags |= JITDATA_FLAG_INSTRUMENT;
+#endif
+
+#if defined(ENABLE_IFCONV)
+ if (opt_ifconv)
+ jd->flags |= JITDATA_FLAG_IFCONV;
+#endif
+
+#if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
+ if (opt_Inline && opt_InlineAll)
+ jd->flags |= JITDATA_FLAG_INLINE;
+#endif
+
+ if (opt_showintermediate)
+ jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+
+ if (opt_showdisassemble)
+ jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+
+ if (opt_verbosecall)
+ jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+#if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
+ if (opt_Inline && (jd->m->hitcountdown > 0) && (jd->code->optlevel == 0)) {
+ jd->flags |= JITDATA_FLAG_COUNTDOWN;
+ }
+#endif
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ /* initialize the register allocator */
+ {
+ reg_setup(jd);
+ }
+#endif
+
+ /* setup the codegendata memory */
+
+ codegen_setup(jd);
+
+ /* now call internal compile function */
+
+ r = jit_compile_intern(jd);
+
+ if (r == NULL) {
+ /* We had an exception! Finish stuff here if necessary. */
+
+ /* release codeinfo */
+
+ code_codeinfo_free(jd->code);
+
+#if defined(ENABLE_PROFILING)
+ /* Release memory for basic block profiling information. */
+
+ if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
+ if (jd->code->bbfrequency != NULL)
+ MFREE(jd->code->bbfrequency, u4, jd->code->basicblockcount);
+#endif
+ }
+ else {
+ DEBUG_JIT_COMPILEVERBOSE("Running: ");
+ }
+
+#if defined (ENABLE_JITCACHE)
+ jitcache_store(m);
+#endif
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ compilingtime_stop();
+#endif
+
+#if defined(ENABLE_OPAGENT)
+ if (opt_EnableOpagent)
+ OprofileAgent::newmethod(m);
+#endif
+
+ /* leave the monitor */
+
+ m->mutex->unlock();
+
+ /* return pointer to the methods entry point */
+
+ return r;
+}
+
+
+/* jit_recompile ***************************************************************
+
+ Recompiles a Java method.
+
+*******************************************************************************/
+
+u1 *jit_recompile(methodinfo *m)
+{
+ u1 *r;
+ jitdata *jd;
+ u1 optlevel;
+
+ /* check for max. optimization level */
+
+ optlevel = (m->code) ? m->code->optlevel : 0;
+
+#if 0
+ if (optlevel == 1) {
+/* log_message_method("not recompiling: ", m); */
+ return NULL;
+ }
+#endif
+
+ DEBUG_JIT_COMPILEVERBOSE("Recompiling start: ");
+
+ STATISTICS(count_jit_calls++);
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ compilingtime_start();
+#endif
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* create jitdata structure */
+
+ jd = jit_jitdata_new(m);
+
+ /* set the current optimization level to the previous one plus 1 */
+
+ jd->code->optlevel = optlevel + 1;
+
+ /* get the optimization flags for the current JIT run */
+
+#if defined(ENABLE_VERIFIER)
+ jd->flags |= JITDATA_FLAG_VERIFY;
+#endif
+
+ /* jd->flags |= JITDATA_FLAG_REORDER; */
+ if (opt_showintermediate)
+ jd->flags |= JITDATA_FLAG_SHOWINTERMEDIATE;
+ if (opt_showdisassemble)
+ jd->flags |= JITDATA_FLAG_SHOWDISASSEMBLE;
+ if (opt_verbosecall)
+ jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+#if defined(ENABLE_INLINING)
+ if (opt_Inline)
+ jd->flags |= JITDATA_FLAG_INLINE;
+#endif
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ /* initialize the register allocator */
+
+ reg_setup(jd);
+#endif
+
+ /* setup the codegendata memory */
+
+ codegen_setup(jd);
+
+ /* now call internal compile function */
+
+ r = jit_compile_intern(jd);
+
+ if (r == NULL) {
+ /* We had an exception! Finish stuff here if necessary. */
+
+ /* release codeinfo */
+
+ code_codeinfo_free(jd->code);
+ }
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ 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 */
+
+ return r;
+}
+
+#if defined(ENABLE_PM_HACKS)
+#include "vm/jit/jit_pm_1.inc"
+#endif
+
+/* jit_compile_intern **********************************************************
+
+ Static internal function which does the actual compilation.
+
+*******************************************************************************/
+
+static u1 *jit_compile_intern(jitdata *jd)
+{
+ methodinfo *m;
+ codegendata *cd;
+ codeinfo *code;
+
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start,time_checks,time_parse,time_stack,
+ time_typecheck,time_loop,time_ifconv,time_alloc,
+ time_codegen;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ /* get required compiler data */
+
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+ jd->ls = NULL;
+#endif
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+
+#if defined(ENABLE_DEBUG_FILTER)
+ show_filters_apply(jd->m);
+#endif
+
+ // Handle native methods and create a native stub.
+ if (m->flags & ACC_NATIVE) {
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ void* f = nm.resolve_method(m);
+
+ if (f == NULL)
+ return NULL;
+
+ code = NativeStub::generate(m, (functionptr) f);
+
+ /* Native methods are never recompiled. */
+
+ assert(!m->code);
+
+ m->code = code;
+
+ return code->entrypoint;
+ }
+
+ /* if there is no javacode, print error message and return empty method */
+
+ if (m->jcode == NULL) {
+ DEBUG_JIT_COMPILEVERBOSE("No code given for: ");
+
+ code->entrypoint = (u1 *) (ptrint) do_nothing_function;
+ m->code = code;
+
+ return code->entrypoint; /* return empty method */
+ }
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ count_javacodesize += m->jcodelength + 18;
+ count_tryblocks += jd->exceptiontablelength;
+ count_javaexcsize += jd->exceptiontablelength * SIZEOF_VOID_P;
+ }
+#endif
+
+ RT_TIMING_GET_TIME(time_checks);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* Code for Sun's OpenJDK (see
+ hotspot/src/share/vm/classfile/verifier.cpp
+ (Verifier::is_eligible_for_verification)): Don't verify
+ dynamically-generated bytecodes. */
+
+# if defined(ENABLE_VERIFIER)
+ if (class_issubclass(m->clazz, class_sun_reflect_MagicAccessorImpl))
+ jd->flags &= ~JITDATA_FLAG_VERIFY;
+# endif
+#endif
+
+ /* call the compiler passes ***********************************************/
+
+ DEBUG_JIT_COMPILEVERBOSE("Parsing: ");
+
+ /* call parse pass */
+
+ if (!parse(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while parsing: ");
+
+ return NULL;
+ }
+ RT_TIMING_GET_TIME(time_parse);
+
+ DEBUG_JIT_COMPILEVERBOSE("Parsing done: ");
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp) {
+# endif
+ DEBUG_JIT_COMPILEVERBOSE("Analysing: ");
+
+ /* call stack analysis pass */
+
+ if (!stack_analyse(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while analysing: ");
+
+ return NULL;
+ }
+ RT_TIMING_GET_TIME(time_stack);
+
+ DEBUG_JIT_COMPILEVERBOSE("Analysing done: ");
+
+#ifdef ENABLE_VERIFIER
+ if (JITDATA_HAS_FLAG_VERIFY(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Typechecking: ");
+
+ /* call typecheck pass */
+ if (!typecheck(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking: ");
+
+ return NULL;
+ }
+
+ DEBUG_JIT_COMPILEVERBOSE("Typechecking done: ");
+ }
+#endif
+ RT_TIMING_GET_TIME(time_typecheck);
+
+#if defined(ENABLE_LOOP)
+ if (opt_loops) {
+ depthFirst(jd);
+ analyseGraph(jd);
+ optimize_loops(jd);
+ jit_renumber_basicblocks(jd);
+ }
+#endif
+ RT_TIMING_GET_TIME(time_loop);
+
+#if defined(ENABLE_IFCONV)
+ if (JITDATA_HAS_FLAG_IFCONV(jd)) {
+ if (!ifconv_static(jd))
+ return NULL;
+ jit_renumber_basicblocks(jd);
+ }
+#endif
+ RT_TIMING_GET_TIME(time_ifconv);
+
+ /* 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-conversion. */
+
+ if (JITDATA_HAS_FLAG_REORDER(jd)) {
+ if (!reorder(jd))
+ return NULL;
+ jit_renumber_basicblocks(jd);
+ }
+#endif
+
+#if defined(ENABLE_PM_HACKS)
+#include "vm/jit/jit_pm_2.inc"
+#endif
+ DEBUG_JIT_COMPILEVERBOSE("Allocating registers: ");
+
+#if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
+ /* allocate registers */
+ if (opt_lsra) {
+ if (!lsra(jd))
+ return NULL;
+
+ STATISTICS(count_methods_allocated_by_lsra++);
+
+ } else
+# endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
+#if defined(ENABLE_SSA)
+ /* allocate registers */
+ if (
+ (opt_lsra &&
+ jd->code->optlevel > 0)
+ /* strncmp(jd->m->name->text, "hottie", 6) == 0*/
+ /*&& jd->exceptiontablelength == 0*/
+ ) {
+ /*printf("=== %s ===\n", jd->m->name->text);*/
+ jd->ls = (lsradata*) DumpMemory::allocate(sizeof(lsradata));
+ jd->ls = NULL;
+ ssa(jd);
+ /*lsra(jd);*/ regalloc(jd);
+ /*eliminate_subbasicblocks(jd);*/
+ STATISTICS(count_methods_allocated_by_lsra++);
+
+ } else
+# endif /* defined(ENABLE_SSA) */
+ {
+ STATISTICS(count_locals_conflicts += (jd->maxlocals - 1) * (jd->maxlocals));
+
+ regalloc(jd);
+ }
+
+ STATISTICS(simplereg_make_statistics(jd));
+
+ DEBUG_JIT_COMPILEVERBOSE("Allocating registers done: ");
+# if defined(ENABLE_INTRP)
+ }
+# endif
+#endif /* defined(ENABLE_JIT) */
+ RT_TIMING_GET_TIME(time_alloc);
+
+#if defined(ENABLE_PROFILING)
+ /* Allocate memory for basic block profiling information. This
+ _must_ be done after loop optimization and register allocation,
+ since they can change the basic block count. */
+
+ if (JITDATA_HAS_FLAG_INSTRUMENT(jd))
+ code->bbfrequency = MNEW(u4, jd->basicblockcount);
+#endif
+
+ DEBUG_JIT_COMPILEVERBOSE("Generating code: ");
+
+ /* now generate the machine code */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp) {
+#if defined(ENABLE_VERIFIER)
+ if (opt_verify) {
+ DEBUG_JIT_COMPILEVERBOSE("Typechecking (stackbased): ");
+
+ if (!typecheck_stackbased(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while typechecking (stackbased): ");
+ return NULL;
+ }
+ }
+#endif
+ if (!intrp_codegen(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+
+ return NULL;
+ }
+ } else
+# endif
+ {
+ if (!codegen_generate(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+
+ return NULL;
+ }
+ }
+#else
+ if (!intrp_codegen(jd)) {
+ DEBUG_JIT_COMPILEVERBOSE("Exception while generating code: ");
+
+ return NULL;
+ }
+#endif
+ RT_TIMING_GET_TIME(time_codegen);
+
+ DEBUG_JIT_COMPILEVERBOSE("Generating code done: ");
+
+#if !defined(NDEBUG) && defined(ENABLE_REPLACEMENT)
+ /* activate replacement points inside newly created code */
+
+ if (opt_TestReplacement)
+ replace_activate_replacement_points(code, false);
+#endif
+
+#if !defined(NDEBUG)
+#if defined(ENABLE_DEBUG_FILTER)
+ if (jd->m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
+#endif
+ {
+ /* intermediate and assembly code listings */
+
+ if (JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd)) {
+ show_method(jd, SHOW_CODE);
+ }
+ else if (JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
+# if defined(ENABLE_DISASSEMBLER)
+ DISASSEMBLE(code->entrypoint,
+ code->entrypoint + (code->mcodelength - cd->dseglen));
+# endif
+ }
+
+ if (opt_showddatasegment)
+ dseg_display(jd);
+ }
+#endif
+
+ /* switch to the newly generated code */
+
+ assert(code);
+ assert(code->entrypoint);
+
+ /* add the current compile version to the methodinfo */
+
+ code->prev = m->code;
+ m->code = code;
+
+ RT_TIMING_TIME_DIFF(time_start,time_checks,RT_TIMING_JIT_CHECKS);
+ RT_TIMING_TIME_DIFF(time_checks,time_parse,RT_TIMING_JIT_PARSE);
+ RT_TIMING_TIME_DIFF(time_parse,time_stack,RT_TIMING_JIT_STACK);
+ RT_TIMING_TIME_DIFF(time_stack,time_typecheck,RT_TIMING_JIT_TYPECHECK);
+ RT_TIMING_TIME_DIFF(time_typecheck,time_loop,RT_TIMING_JIT_LOOP);
+ RT_TIMING_TIME_DIFF(time_loop,time_alloc,RT_TIMING_JIT_ALLOC);
+ RT_TIMING_TIME_DIFF(time_alloc,time_codegen,RT_TIMING_JIT_CODEGEN);
+ RT_TIMING_TIME_DIFF(time_start,time_codegen,RT_TIMING_JIT_TOTAL);
+
+ /* return pointer to the methods entry point */
+
+ return code->entrypoint;
+}
+
+
+/* jit_invalidate_code *********************************************************
+
+ Mark the compiled code of the given method as invalid and take care that
+ it is replaced if necessary.
+
+ XXX Not fully implemented, yet.
+
+*******************************************************************************/
+
+void jit_invalidate_code(methodinfo *m)
+{
+ codeinfo *code;
+
+ code = m->code;
+
+ if (code == NULL || code_is_invalid(code))
+ return;
+
+ code_flag_invalid(code);
+
+ /* activate mappable replacement points */
+
+#if defined(ENABLE_REPLACEMENT)
+ replace_activate_replacement_points(code, true);
+#else
+ vm_abort("invalidating code only works with ENABLE_REPLACEMENT");
+#endif
+}
+
+
+/* jit_request_optimization ****************************************************
+
+ Request optimization of the given method. If the code of the method is
+ unoptimized, it will be invalidated, so the next jit_get_current_code(m)
+ triggers an optimized recompilation.
+ If the method is already optimized, this function does nothing.
+
+ IN:
+ m................the method
+
+*******************************************************************************/
+
+void jit_request_optimization(methodinfo *m)
+{
+ codeinfo *code;
+
+ code = m->code;
+
+ if (code && code->optlevel == 0)
+ jit_invalidate_code(m);
+}
+
+
+/* jit_get_current_code ********************************************************
+
+ Get the currently valid code for the given method. If there is no valid
+ code, (re)compile the method.
+
+ IN:
+ m................the method
+
+ RETURN VALUE:
+ the codeinfo* for the current code, or
+ NULL if an exception has been thrown during recompilation.
+
+*******************************************************************************/
+
+codeinfo *jit_get_current_code(methodinfo *m)
+{
+ assert(m);
+
+ /* if we have valid code, return it */
+
+ if (m->code && !code_is_invalid(m->code))
+ return m->code;
+
+ /* otherwise: recompile */
+
+ if (!jit_recompile(m))
+ return NULL;
+
+ assert(m->code);
+
+ return m->code;
+}
+
+
+/* jit_asm_compile *************************************************************
+
+ This method is called from asm_vm_call_method and does:
+
+ - create stackframe info for exceptions
+ - compile the method
+ - patch the entrypoint of the method into the calculated address in
+ the JIT code
+ - flushes the instruction cache.
+
+*******************************************************************************/
+
+#if defined(ENABLE_JIT)
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
+extern "C" {
+void* jit_asm_compile(methodinfo *m, void* mptr, void* sp, void* ra)
+{
+ stackframeinfo_t sfi;
+ void *entrypoint;
+ void *pa;
+ uintptr_t *p;
+
+ /* create the stackframeinfo (subtract 1 from RA as it points to the */
+ /* instruction after the call) */
+
+ stacktrace_stackframeinfo_add(&sfi, NULL, sp, ra, ((uint8_t*) ra) - 1);
+
+ /* actually compile the method */
+
+ entrypoint = jit_compile(m);
+
+ /* remove the stackframeinfo */
+
+ stacktrace_stackframeinfo_remove(&sfi);
+
+ /* there was a problem during compilation */
+
+ if (entrypoint == NULL)
+ return NULL;
+
+ /* get the method patch address */
+
+ pa = md_jit_method_patch_address(sfi.pv, (void *) ra, mptr);
+
+ /* patch the method entry point */
+
+ p = (uintptr_t*) pa;
+
+ *p = (uintptr_t) entrypoint;
+
+ /* flush the instruction cache */
+
+ md_icacheflush(pa, SIZEOF_VOID_P);
+
+ return entrypoint;
+}
+}
+#endif
+
+/* jit_compile_handle **********************************************************
+
+ This method is called from the appropriate signal handler which
+ handles compiler-traps and does the following:
+
+ - compile the method
+ - patch the entrypoint of the method into the calculated address in
+ the JIT code
+ - flush the instruction cache
+
+*******************************************************************************/
+
+void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr)
+{
+ void *newpv; /* new compiled method PV */
+ void *pa; /* patch address */
+ uintptr_t *p; /* convenience pointer */
+
+ /* Compile the method. */
+
+ newpv = jit_compile(m);
+
+ /* There was a problem during compilation. */
+
+ if (newpv == NULL)
+ return NULL;
+
+ /* Get the method patch address. */
+
+ pa = md_jit_method_patch_address(pv, ra, mptr);
+
+ /* Patch the method entry point. */
+
+ p = (uintptr_t *) pa;
+
+ *p = (uintptr_t) newpv;
+
+ /* Flush both caches. */
+
+ md_cacheflush(pa, SIZEOF_VOID_P);
+
+ return newpv;
+}
+#endif /* defined(ENABLE_JIT) */
+
+
+/* jit_complement_condition ****************************************************
+
+ Returns the complement of the passed conditional instruction.
+
+ We use the order of the different conditions, e.g.:
+
+ ICMD_IFEQ 153
+ ICMD_IFNE 154
+
+ If the passed opcode is odd, we simply add 1 to get the complement.
+ If the opcode is even, we subtract 1.
+
+ Exception:
+
+ ICMD_IFNULL 198
+ ICMD_IFNONNULL 199
+
+*******************************************************************************/
+
+s4 jit_complement_condition(s4 opcode)
+{
+ switch (opcode) {
+ case ICMD_IFNULL:
+ return ICMD_IFNONNULL;
+
+ case ICMD_IFNONNULL:
+ return ICMD_IFNULL;
+
+ default:
+ /* check if opcode is odd */
+
+ if (opcode & 0x1)
+ return opcode + 1;
+ else
+ return opcode - 1;
+ }
+}
+
+
+/* jit_renumber_basicblocks ****************************************************
+
+ Set the ->nr of all blocks so it increases when traversing ->next.
+
+ IN:
+ jitdata..........the current jitdata
+
+*******************************************************************************/
+
+void jit_renumber_basicblocks(jitdata *jd)
+{
+ s4 nr;
+ basicblock *bptr;
+
+ nr = 0;
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+ bptr->nr = nr++;
+ }
+
+ /* we have one block more than jd->basicblockcount (the end marker) */
+
+ assert(nr == jd->basicblockcount + 1);
+}
+
+
+/* jit_check_basicblock_numbers ************************************************
+
+ Assert that the ->nr of the first block is zero and increases by 1 each
+ time ->next is traversed.
+ This function should be called before any analysis that relies on
+ the basicblock numbers.
+
+ IN:
+ jitdata..........the current jitdata
+
+ NOTE: Aborts with an assertion if the condition is not met!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void jit_check_basicblock_numbers(jitdata *jd)
+{
+ s4 nr;
+ basicblock *bptr;
+
+ nr = 0;
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+ assert(bptr->nr == nr);
+ nr++;
+ }
+
+ /* we have one block more than jd->basicblockcount (the end marker) */
+
+ assert(nr == jd->basicblockcount + 1);
+}
+#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/jit.h - code generation 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 _JIT_H
-#define _JIT_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct jitdata jitdata;
-typedef struct basicblock basicblock;
-typedef struct instruction instruction;
-typedef struct insinfo_inline insinfo_inline;
-typedef struct exception_entry exception_entry;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#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.hpp"
-
-#if defined(ENABLE_INLINING)
-# include "vm/jit/inline/inline.h"
-#endif
-
-#include "vm/jit/ir/bytecode.h"
-
-#if defined(ENABLE_LOOP)
-# include "vm/jit/loop/loop.h"
-#endif
-#if defined(ENABLE_SSA)
-# include "vm/jit/optimizing/lsra.h"
-#endif
-#if defined(ENABLE_LSRA)
-# include "vm/jit/allocator/lsra.h"
-#endif
-
-#include "vm/jit/verify/typeinfo.h"
-
-
-/* common jit/codegen macros **************************************************/
-
-#if defined(ENABLE_STATISTICS)
-# define COUNT(x) (x)++
-# define COUNT_SPILLS /* use COUNT_(READ|WRITE)_SPILLS instead */
-# define COUNT_READ_SPILLS(var) \
- switch(var->type) { \
- case TYPE_FLT: count_spills_read_flt++; break; \
- case TYPE_DBL: count_spills_read_dbl++; break; \
- default: count_spills_read_ila++; break; \
- }
-
-# define COUNT_WRITE_SPILLS(var) \
- switch(var->type) { \
- case TYPE_FLT: count_spills_write_flt++; break; \
- case TYPE_DBL: count_spills_write_dbl++; break; \
- default: count_spills_write_ila++; break; \
- }
-
-#else
-# define COUNT(x) /* nothing */
-# define COUNT_SPILLS /* nothing */
-# define COUNT_READ_SPILLS(x) /* nothing */
-# define COUNT_WRITE_SPILLS(x) /* nothing */
-#endif
-
-typedef struct interface_info interface_info;
-
-struct interface_info {
- s4 flags;
- s4 regoff;
-};
-
-
-/* jitdata ********************************************************************/
-
-struct jitdata {
- methodinfo *m; /* methodinfo of the method compiled */
- codeinfo *code;
- codegendata *cd;
- registerdata *rd;
-#if defined(ENABLE_LOOP)
- loopdata *ld;
-#endif
-#if defined(ENABLE_SSA) || defined(ENABLE_LSRA)
- lsradata *ls;
-#endif
-
- u4 flags; /* contains JIT compiler flags */
-
- instruction *instructions; /* ICMDs, valid between parse and stack */
- basicblock *basicblocks; /* start of basic block list */
- stackelement_t *stack; /* XXX should become stack.c internal */
- s4 instructioncount;/* XXX remove this? */
- s4 basicblockcount; /* number of basic blocks */
- s4 stackcount; /* number of stackelements to allocate */
- /* (passed from parse to stack) */
-
- varinfo *var; /* array of variables */
- s4 vartop; /* next free index in var array */
-
- s4 varcount; /* number of variables in var array */
- s4 localcount; /* number of locals at start of var ar. */
- s4 *local_map; /* map for renaming (de-coallescing) */
- /* locals and keeping the coalescing info for simplereg. */
- /* local_map[javaindex * 5 + type] = */
- /* >= 0......index into jd->var, or */
- /* UNUSED....this (javaindex,type) pair is not used */
-
- s4 *reverselocalmap; /* map from CACAO varindex to javaindex */
- /* (varindex must be < localcount) */
-
- s4 maxlocals; /* max. number of javalocals */
-
- interface_info *interface_map; /* interface variables (for simplereg) */
- s4 maxinterfaces; /* max. number of interface variables */
-
- s4 exceptiontablelength; /* exceptiontable length */
- exception_entry *exceptiontable; /* the exceptiontable */
-
- basicblock *returnblock; /* block containing the *RETURN */
- /* (only use if returncount==1) */
- s4 returncount; /* number of return instructions */
- bool branchtoentry; /* true if first block is a target */
- bool branchtoend; /* true if end dummy is a target */
-};
-
-#define FOR_EACH_BASICBLOCK(jd, it) \
- for ((it) = (jd)->basicblocks; (it) != NULL; (it) = (it)->next)
-
-#define UNUSED -1
-
-#define JITDATA_FLAG_PARSE 0x00000001
-#define JITDATA_FLAG_VERIFY 0x00000002
-
-#define JITDATA_FLAG_INSTRUMENT 0x00000004
-
-#define JITDATA_FLAG_IFCONV 0x00000008
-#define JITDATA_FLAG_REORDER 0x00000010
-#define JITDATA_FLAG_INLINE 0x00000020
-
-#define JITDATA_FLAG_COUNTDOWN 0x00000100
-
-#define JITDATA_FLAG_SHOWINTERMEDIATE 0x20000000
-#define JITDATA_FLAG_SHOWDISASSEMBLE 0x40000000
-#define JITDATA_FLAG_VERBOSECALL 0x80000000
-
-
-#define JITDATA_HAS_FLAG_PARSE(jd) \
- ((jd)->flags & JITDATA_FLAG_PARSE)
-
-#define JITDATA_HAS_FLAG_VERIFY(jd) \
- ((jd)->flags & JITDATA_FLAG_VERIFY)
-
-#define JITDATA_HAS_FLAG_INSTRUMENT(jd) \
- ((jd)->flags & JITDATA_FLAG_INSTRUMENT)
-
-#define JITDATA_HAS_FLAG_IFCONV(jd) \
- ((jd)->flags & JITDATA_FLAG_IFCONV)
-
-#define JITDATA_HAS_FLAG_REORDER(jd) \
- ((jd)->flags & JITDATA_FLAG_REORDER)
-
-#define JITDATA_HAS_FLAG_INLINE(jd) \
- ((jd)->flags & JITDATA_FLAG_INLINE)
-
-#define JITDATA_HAS_FLAG_COUNTDOWN(jd) \
- ((jd)->flags & JITDATA_FLAG_COUNTDOWN)
-
-#define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd) \
- ((jd)->flags & JITDATA_FLAG_SHOWINTERMEDIATE)
-
-#define JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) \
- ((jd)->flags & JITDATA_FLAG_SHOWDISASSEMBLE)
-
-#define JITDATA_HAS_FLAG_VERBOSECALL(jd) \
- ((jd)->flags & JITDATA_FLAG_VERBOSECALL)
-
-
-/* exception_entry ************************************************************/
-
-struct exception_entry {
- basicblock *start;
- basicblock *end;
- basicblock *handler;
- classref_or_classinfo catchtype; /* catchtype of exc. (NULL == catchall) */
- exception_entry *next; /* next in list of exceptions when */
- /* loops are copied */
- exception_entry *down; /* next exception_entry */
-};
-
-
-/* macros for accessing variables *********************************************
-
- Use VAROP for s1, s2, s3 and dst operands (eg. VAROP(iptr->s1)),
- use VAR if you have the variable index (eg. VAR(iptr->sx.s23.s2.args[0])).
-
-******************************************************************************/
-
-#define VAROP(v) (jd->var + (v).varindex)
-#define VAR(i) (jd->var + (i))
-
-static inline bool var_is_local(const jitdata *jd, s4 i) {
- return (i < jd->localcount);
-}
-
-static inline bool var_is_prealloc(const jitdata *jd, s4 i) {
- return ((i >= jd->localcount) && (jd->var[i].flags & PREALLOC));
-}
-
-static inline bool var_is_inout(const jitdata *jd, s4 i) {
- const varinfo *v = jd->var + i;
- return (
- (i >= jd->localcount) && (
- (!(v->flags & PREALLOC) && (v->flags & INOUT)) ||
- /* special case of TYPE_RET, used with JSR */
- ((v->flags & PREALLOC) && (v->flags & INOUT) && (v->type == TYPE_RET))
- )
- );
-}
-
-static inline bool var_is_temp(const jitdata *jd, s4 i) {
- const varinfo *v = jd->var + i;
- return ((i >= jd->localcount) && !(v->flags & PREALLOC) && !(v->flags & INOUT));
-}
-
-static inline bool var_is_saved(const jitdata *jd, s4 i) {
- return (jd->var[i].flags & SAVEDVAR);
-}
-
-
-/**************************** instruction structure ***************************/
-
-/* branch_target_t: used in TABLESWITCH tables */
-
-typedef union {
- s4 insindex; /* used in parse */
- basicblock *block; /* valid after parse */
-} branch_target_t;
-
-/* lookup_target_t: used in LOOKUPSWITCH tables */
-
-typedef struct {
- s4 value; /* case value */
- branch_target_t target; /* branch target, see above */
-} lookup_target_t;
-
-/*** s1 operand ***/
-
-typedef union {
- s4 varindex;
- s4 argcount;
-} s1_operand_t;
-
-/*** s2 operand ***/
-
-typedef union {
- s4 varindex;
- s4 *args;
- classref_or_classinfo c;
- unresolved_class *uc;
- ptrint constval; /* for PUT*CONST */
- s4 tablelow; /* for TABLESWITCH */
- u4 lookupcount; /* for LOOKUPSWITCH */
- s4 retaddrnr; /* for ASTORE */
- instruction **iargs; /* for PHI */
-} s2_operand_t;
-
-/*** s3 operand ***/
-
-typedef union {
- s4 varindex;
- ptrint constval;
- classref_or_classinfo c;
- constant_FMIref *fmiref;
- unresolved_method *um;
- unresolved_field *uf;
- insinfo_inline *inlineinfo; /* for INLINE_START/END */
- s4 tablehigh; /* for TABLESWITCH */
- branch_target_t lookupdefault; /* for LOOKUPSWITCH */
- branch_target_t jsrtarget; /* for JSR */
- s4 javaindex; /* for *STORE */
- struct builtintable_entry *bte;
-} s3_operand_t;
-
-/*** val operand ***/
-
-typedef union {
- s4 i;
- s8 l;
- float f;
- double d;
- void *anyptr;
- java_handle_t *stringconst; /* for ACONST with string */
- classref_or_classinfo c; /* for ACONST with class */
-} val_operand_t;
-
-/*** dst operand ***/
-
-typedef union {
- s4 varindex;
- basicblock *block; /* valid after parse */
- branch_target_t *table; /* for TABLESWITCH */
- lookup_target_t *lookup; /* for LOOKUPSWITCH */
- s4 insindex; /* used in parse */
-} dst_operand_t;
-
-/*** flags (32 bits) ***/
-
-#define INS_FLAG_BASICBLOCK 0x01 /* marks a basic block start */
-#define INS_FLAG_UNRESOLVED 0x02 /* contains unresolved field/meth/class*/
-#define INS_FLAG_CLASS 0x04 /* for ACONST, PUT*CONST with class */
-#define INS_FLAG_ARRAY 0x08 /* for CHECKCAST/INSTANCEOF with array */
-#define INS_FLAG_CHECK 0x10 /* for *ALOAD|*ASTORE: check index */
- /* for BUILTIN: check exception */
-#define INS_FLAG_KILL_PREV 0x04 /* for *STORE, invalidate prev local */
-#define INS_FLAG_KILL_NEXT 0x08 /* for *STORE, invalidate next local */
-#define INS_FLAG_RETADDR 0x10 /* for ASTORE: op is a returnAddress */
-
-#define INS_FLAG_ID_SHIFT 5
-#define INS_FLAG_ID_MASK (~0 << INS_FLAG_ID_SHIFT)
-
-typedef union {
- u4 bits;
-} flags_operand_t;
-
-/*** instruction ***/
-
-/* The instruction format for the intermediate representation: */
-
-struct instruction {
- u2 opc; /* opcode */
- u2 line; /* line number */
-#if SIZEOF_VOID_P == 8
- flags_operand_t flags; /* 4 bytes */
-#endif
- s1_operand_t s1; /* pointer-size */
- union {
- struct {
- s2_operand_t s2; /* pointer-size */
- s3_operand_t s3; /* pointer-size */
- } s23; /* XOR */
- val_operand_t val; /* long-size */
- } sx;
- dst_operand_t dst; /* pointer-size */
-#if SIZEOF_VOID_P == 4
- flags_operand_t flags; /* 4 bytes */
-#endif
-#if defined(ENABLE_ESCAPE_REASON)
- void *escape_reasons;
-#endif
-};
-
-
-#define INSTRUCTION_STARTS_BASICBLOCK(iptr) \
- ((iptr)->flags.bits & INS_FLAG_BASICBLOCK)
-
-#define INSTRUCTION_IS_RESOLVED(iptr) \
- (!((iptr)->flags.bits & INS_FLAG_UNRESOLVED))
-
-#define INSTRUCTION_IS_UNRESOLVED(iptr) \
- ((iptr)->flags.bits & INS_FLAG_UNRESOLVED)
-
-#define INSTRUCTION_MUST_CHECK(iptr) \
- ((iptr)->flags.bits & INS_FLAG_CHECK)
-
-#define INSTRUCTION_GET_FIELDREF(iptr,fref) \
- do { \
- if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
- fref = iptr->sx.s23.s3.uf->fieldref; \
- else \
- fref = iptr->sx.s23.s3.fmiref; \
- } while (0)
-
-#define INSTRUCTION_GET_METHODREF(iptr,mref) \
- do { \
- if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
- mref = iptr->sx.s23.s3.um->methodref; \
- else \
- mref = iptr->sx.s23.s3.fmiref; \
- } while (0)
-
-#define INSTRUCTION_GET_METHODDESC(iptr, md) \
- do { \
- if (iptr->flags.bits & INS_FLAG_UNRESOLVED) \
- md = iptr->sx.s23.s3.um->methodref->parseddesc.md; \
- else \
- md = iptr->sx.s23.s3.fmiref->parseddesc.md; \
- } while (0)
-
-/* additional info structs for special instructions ***************************/
-
-/* for ICMD_INLINE_START and ICMD_INLINE_END */
-
-struct insinfo_inline {
- /* fields copied from the inlining tree ----------------------------------*/
- insinfo_inline *parent; /* insinfo of the surrounding inlining, if any*/
- methodinfo *method; /* the inlined method starting/ending here */
- methodinfo *outer; /* the outer method suspended/resumed here */
- s4 synclocal; /* local index used for synchronization */
- bool synchronize; /* true if synchronization is needed */
- s4 throughcount; /* total # of pass-through variables */
- s4 paramcount; /* number of parameters of original call */
- s4 stackvarscount; /* source stackdepth at INLINE_START */
- s4 *stackvars; /* stack vars at INLINE_START */
-
- /* fields set by inlining ------------------------------------------------*/
- s4 *javalocals_start; /* javalocals at start of inlined body */
- s4 *javalocals_end; /* javalocals after inlined body */
-
- /* fields set by replacement point creation ------------------------------*/
-#if defined(ENABLE_REPLACEMENT)
- rplpoint *rp; /* replacement point at INLINE_START */
-#endif
-
- /* fields set by the codegen ---------------------------------------------*/
- s4 startmpc; /* machine code offset of start of inlining */
-};
-
-
-/* basicblock *****************************************************************/
-
-/* flags */
-
-#define BBDELETED -2
-#define BBUNDEF -1
-#define BBREACHED 0
-#define BBFINISHED 1
-
-#define BBTYPECHECK_UNDEF 2
-#define BBTYPECHECK_REACHED 3
-
-#define BBTYPE_STD 0 /* standard basic block type */
-#define BBTYPE_EXH 1 /* exception handler basic block type */
-#define BBTYPE_SBR 2 /* subroutine basic block type */
-
-#define BBFLAG_REPLACEMENT 0x01 /* put a replacement point at the start */
-
-/* XXX basicblock wastes quite a lot of memory by having four flag fields */
-/* (flags, bitflags, type and lflags). Probably the last three could be */
-/* combined without loss of efficiency. The first one could be combined with */
-/* the others by using bitfields. */
-
-/* XXX "flags" should probably be called "state", as it is an integer state */
-
-struct basicblock {
- s4 nr; /* basic block number */
- s4 flags; /* used during stack analysis, init with -1 */
- s4 bitflags; /* OR of BBFLAG_... constants, init with 0 */
- s4 type; /* basic block type (std, xhandler, subroutine*/
- s4 lflags; /* used during loop copying, init with 0 */
-
- s4 icount; /* number of intermediate code instructions */
- instruction *iinstr; /* pointer to intermediate code instructions */
-
- varinfo *inlocals; /* copy of locals on block entry */
- s4 *javalocals; /* map from java locals to cacao variables[+] */
- s4 *invars; /* array of in-variables at begin of block */
- s4 *outvars; /* array of out-variables at end of block */
- s4 indepth; /* stack depth at begin of basic block */
- s4 outdepth; /* stack depth end of basic block */
- s4 varstart; /* index of first non-invar block variable */
- s4 varcount; /* number of non-invar block variables */
-
- s4 predecessorcount;
- s4 successorcount;
- basicblock **predecessors; /* array of predecessor basic blocks */
- basicblock **successors; /* array of successor basic blocks */
-
- branchref *branchrefs; /* list of branches to be patched */
-
- basicblock *next; /* used to build a BB list (instead of array) */
- basicblock *copied_to; /* points to the copy of this basic block */
- /* when loop nodes are copied */
- basicblock *original; /* block of which this block is a clone */
- /* NULL for the original block itself */
- methodinfo *method; /* method this block belongs to */
- insinfo_inline *inlineinfo; /* inlineinfo for the start of this block */
-
- s4 mpc; /* machine code pc at start of block */
-
- /* TODO: those fields are probably usefull for other passes as well. */
-
-#if defined(ENABLE_SSA)
- basicblock *idom; /* Immediate dominator, parent in dominator tree */
- basicblock **domsuccessors;/* Children in dominator tree */
- s4 domsuccessorcount;
-
- basicblock **domfrontier; /* Dominance frontier */
- s4 domfrontiercount;
-
- basicblock **exhandlers; /* Exception handlers for this block */
- s4 exhandlercount;
- basicblock **expredecessors; /* Blocks this block is exception handler for */
- s4 expredecessorcount;
- s4 exouts; /* Number of exceptional exits */
-
- instruction *phis; /* Phi functions */
- s4 phicount; /* Number of phi functions */
-
- void *vp; /* Freely used by different passes */
-#endif
-};
-
-#define FOR_EACH_SUCCESSOR(bptr, it) \
- for ((it) = (bptr)->successors; (it) != (bptr)->successors + (bptr)->successorcount; ++(it))
-
-#define FOR_EACH_PREDECESSOR(bptr, it) \
- for ( \
- (it) = (bptr)->predecessors; \
- (it) != (bptr)->predecessors + ((bptr)->predecessorcount < 0 ? 0 : (bptr)->predecessorcount); \
- ++(it) \
- )
-
-#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) \
- for ((it) = (bptr)->exhandlers; (it) != (bptr)->exhandlers + (bptr)->exhandlercount; ++(it))
-
-#define FOR_EACH_EXPREDECESSOR(bptr, it) \
- for ((it) = (bptr)->expredecessors; (it) != (bptr)->expredecessors + (bptr)->expredecessorcount; ++(it))
-
-#endif
-
-/* [+]...the javalocals array: This array is indexed by the javaindex (the */
-/* local variable index ocurring in the original bytecode). An element */
-/* javalocals[javaindex] encodes where to find the contents of the */
-/* original variable at this point in the program. */
-/* There are three cases for javalocals[javaindex]: */
-/* >= 0.......it's an index into the jd->var array, where the */
-/* CACAO variable corresponding to the original local */
-/* can be found. */
-/* UNUSED.....the original variable is not live at this point */
-/* < UNUSED...the original variable contains a returnAddress at */
-/* this point. The number of the block to return to can */
-/* be calculated using RETADDR_FROM_JAVALOCAL: */
-/* */
-/* javalocals[javaindex] == JAVALOCAL_FROM_RETADDR(nr) */
-/* RETADDR_FROM_JAVALOCAL(javalocals[javaindex]) == nr */
-
-#define JAVALOCAL_FROM_RETADDR(nr) (UNUSED - (1 + (nr)))
-#define RETADDR_FROM_JAVALOCAL(jl) (UNUSED - (1 + (jl)))
-
-
-/* Macro for initializing newly allocated basic block's. It does not
- need to zero fields, as we zero out the whole basic block array. */
-
-#define BASICBLOCK_INIT(bptr,m) \
- do { \
- bptr->mpc = -1; \
- bptr->flags = -1; \
- bptr->type = BBTYPE_STD; \
- bptr->method = (m); \
- } while (0)
-
-static inline bool basicblock_reached(const basicblock *bptr) {
- return (bptr->flags >= BBREACHED);
-}
-
-/* data-flow constants for the ICMD table ************************************/
-
-#define DF_0_TO_0 0
-#define DF_1_TO_0 1
-#define DF_2_TO_0 2
-#define DF_3_TO_0 3
-
-#define DF_DST_BASE 4 /* from this value on, iptr->dst is a variable */
-
-#define DF_0_TO_1 (DF_DST_BASE + 0)
-#define DF_1_TO_1 (DF_DST_BASE + 1)
-#define DF_2_TO_1 (DF_DST_BASE + 2)
-#define DF_3_TO_1 (DF_DST_BASE + 3)
-#define DF_N_TO_1 (DF_DST_BASE + 4)
-
-#define DF_INVOKE (DF_DST_BASE + 5)
-#define DF_BUILTIN (DF_DST_BASE + 6)
-
-#define DF_COPY (DF_DST_BASE + 7)
-#define DF_MOVE (DF_DST_BASE + 8)
-
-#define DF_DUP -1
-#define DF_DUP_X1 -1
-#define DF_DUP_X2 -1
-#define DF_DUP2 -1
-#define DF_DUP2_X1 -1
-#define DF_DUP2_X2 -1
-#define DF_SWAP -1
-
-/* special data-flow recognized by verify/generate.pl: */
-#define DF_LOAD DF_COPY
-#define DF_STORE DF_MOVE
-#define DF_IINC DF_1_TO_1
-#define DF_POP DF_1_TO_0
-#define DF_POP2 DF_2_TO_0
-
-
-/* control-flow constants for the ICMD table *********************************/
-
-#define CF_NORMAL 0
-#define CF_IF 1
-
-#define CF_END_BASE 2 /* from here on, they mark the end of a superblock */
-
-#define CF_END (CF_END_BASE + 0)
-#define CF_GOTO (CF_END_BASE + 1)
-#define CF_TABLE (CF_END_BASE + 2)
-#define CF_LOOKUP (CF_END_BASE + 3)
-#define CF_JSR (CF_END_BASE + 4)
-#define CF_RET (CF_END_BASE + 5)
-
-
-/* flag constants for the ICMD table *****************************************/
-
-#define ICMDTABLE_PEI 0x0001 /* ICMD may throw an exception */
-#define ICMDTABLE_CALLS 0x0002 /* needs registers to be saved, may call */
-
-
-/* ICMD table entry **********************************************************/
-
-typedef struct icmdtable_entry_t icmdtable_entry_t;
-
-struct icmdtable_entry_t {
-#if !defined(NDEBUG)
- char *name; /* name, without ICMD_ prefix */
-#endif
- s4 dataflow; /* a DF_ constant, see above */
- s4 controlflow; /* a CF_ constant, see above */
- s4 flags; /* a combination of ICMDTABLE_ flags */
-};
-
-
-/* the ICMD table ************************************************************/
-
-extern icmdtable_entry_t icmd_table[256];
-
-
-/********** JavaVM operation codes (sorted) and instruction lengths ***********/
-
-enum {
- ICMD_NOP = BC_nop,
-
- ICMD_ACONST = BC_aconst_null,
-
- ICMD_CHECKNULL = 2,
-
- ICMD_ICONST = BC_iconst_0,
-
- /* 3 */
- /* 4 */
-
- ICMD_IDIVPOW2 = 5,
- ICMD_LDIVPOW2 = 6,
-
- /* 7 */
- /* 8 */
-
- ICMD_LCONST = BC_lconst_0,
-
- ICMD_LCMPCONST = 10,
-
- ICMD_FCONST = BC_fconst_0,
-
- /* 12 */
- /* 13 */
-
- ICMD_DCONST = BC_dconst_0,
-
- ICMD_COPY = 15,
- ICMD_MOVE = 16,
-
- /* 17 */
- /* 18 */
- /* 19 */
- /* 20 */
-
- /* Order of LOAD instructions must be equal to order of TYPE_*
- defines. */
-
- ICMD_ILOAD = BC_iload,
- ICMD_LLOAD = BC_lload,
- ICMD_FLOAD = BC_fload,
- ICMD_DLOAD = BC_dload,
- ICMD_ALOAD = BC_aload,
-
- ICMD_IADDCONST = 26,
- ICMD_ISUBCONST = 27,
- ICMD_IMULCONST = 28,
- ICMD_IANDCONST = 29,
- ICMD_IORCONST = 30,
- ICMD_IXORCONST = 31,
-
- ICMD_ISHLCONST = 32,
- ICMD_ISHRCONST = 33,
- ICMD_IUSHRCONST = 34,
-
- ICMD_IREMPOW2 = 35,
-
- ICMD_LADDCONST = 36,
- ICMD_LSUBCONST = 37,
- ICMD_LMULCONST = 38,
- ICMD_LANDCONST = 39,
- ICMD_LORCONST = 40,
- ICMD_LXORCONST = 41,
-
- ICMD_LSHLCONST = 42,
- ICMD_LSHRCONST = 43,
- ICMD_LUSHRCONST = 44,
-
- ICMD_LREMPOW2 = 45,
-
- ICMD_IALOAD = BC_iaload,
- ICMD_LALOAD = BC_laload,
- ICMD_FALOAD = BC_faload,
- ICMD_DALOAD = BC_daload,
- ICMD_AALOAD = BC_aaload,
- ICMD_BALOAD = BC_baload,
- ICMD_CALOAD = BC_caload,
- ICMD_SALOAD = BC_saload,
-
- /* Order of STORE instructions must be equal to order of TYPE_*
- defines. */
-
- ICMD_ISTORE = BC_istore,
- ICMD_LSTORE = BC_lstore,
- ICMD_FSTORE = BC_fstore,
- ICMD_DSTORE = BC_dstore,
- ICMD_ASTORE = BC_astore,
-
- ICMD_IF_LEQ = 59,
- ICMD_IF_LNE = 60,
- ICMD_IF_LLT = 61,
- ICMD_IF_LGE = 62,
- ICMD_IF_LGT = 63,
- ICMD_IF_LLE = 64,
-
- ICMD_IF_LCMPEQ = 65,
- ICMD_IF_LCMPNE = 66,
- ICMD_IF_LCMPLT = 67,
- ICMD_IF_LCMPGE = 68,
- ICMD_IF_LCMPGT = 69,
- ICMD_IF_LCMPLE = 70,
-
- /* 71 */
- /* 72 */
- /* 73 */
- /* 74 */
- /* 75 */
- /* 76 */
- /* 77 */
- /* 78 */
-
- ICMD_IASTORE = BC_iastore,
- ICMD_LASTORE = BC_lastore,
- ICMD_FASTORE = BC_fastore,
- ICMD_DASTORE = BC_dastore,
- ICMD_AASTORE = BC_aastore,
- ICMD_BASTORE = BC_bastore,
- ICMD_CASTORE = BC_castore,
- ICMD_SASTORE = BC_sastore,
-
- ICMD_POP = BC_pop,
- ICMD_POP2 = BC_pop2,
- ICMD_DUP = BC_dup,
- ICMD_DUP_X1 = BC_dup_x1,
- ICMD_DUP_X2 = BC_dup_x2,
- ICMD_DUP2 = BC_dup2,
- ICMD_DUP2_X1 = BC_dup2_x1,
- ICMD_DUP2_X2 = BC_dup2_x2,
- ICMD_SWAP = BC_swap,
-
- ICMD_IADD = BC_iadd,
- ICMD_LADD = BC_ladd,
- ICMD_FADD = BC_fadd,
- ICMD_DADD = BC_dadd,
-
- ICMD_ISUB = BC_isub,
- ICMD_LSUB = BC_lsub,
- ICMD_FSUB = BC_fsub,
- ICMD_DSUB = BC_dsub,
-
- ICMD_IMUL = BC_imul,
- ICMD_LMUL = BC_lmul,
- ICMD_FMUL = BC_fmul,
- ICMD_DMUL = BC_dmul,
-
- ICMD_IDIV = BC_idiv,
- ICMD_LDIV = BC_ldiv,
- ICMD_FDIV = BC_fdiv,
- ICMD_DDIV = BC_ddiv,
-
- ICMD_IREM = BC_irem,
- ICMD_LREM = BC_lrem,
- ICMD_FREM = BC_frem,
- ICMD_DREM = BC_drem,
-
- ICMD_INEG = BC_ineg,
- ICMD_LNEG = BC_lneg,
- ICMD_FNEG = BC_fneg,
- ICMD_DNEG = BC_dneg,
-
- ICMD_ISHL = BC_ishl,
- ICMD_LSHL = BC_lshl,
- ICMD_ISHR = BC_ishr,
- ICMD_LSHR = BC_lshr,
- ICMD_IUSHR = BC_iushr,
- ICMD_LUSHR = BC_lushr,
-
- ICMD_IAND = BC_iand,
- ICMD_LAND = BC_land,
- ICMD_IOR = BC_ior,
- ICMD_LOR = BC_lor,
- ICMD_IXOR = BC_ixor,
- ICMD_LXOR = BC_lxor,
-
- ICMD_IINC = BC_iinc,
-
- ICMD_I2L = BC_i2l,
- ICMD_I2F = BC_i2f,
- ICMD_I2D = BC_i2d,
- ICMD_L2I = BC_l2i,
- ICMD_L2F = BC_l2f,
- ICMD_L2D = BC_l2d,
- ICMD_F2I = BC_f2i,
- ICMD_F2L = BC_f2l,
- ICMD_F2D = BC_f2d,
- ICMD_D2I = BC_d2i,
- ICMD_D2L = BC_d2l,
- ICMD_D2F = BC_d2f,
-
- ICMD_INT2BYTE = BC_int2byte,
- ICMD_INT2CHAR = BC_int2char,
- ICMD_INT2SHORT = BC_int2short,
-
- ICMD_LCMP = BC_lcmp,
- ICMD_FCMPL = BC_fcmpl,
- ICMD_FCMPG = BC_fcmpg,
- ICMD_DCMPL = BC_dcmpl,
- ICMD_DCMPG = BC_dcmpg,
-
- ICMD_IFEQ = BC_ifeq,
- ICMD_IFNE = BC_ifne,
- ICMD_IFLT = BC_iflt,
- ICMD_IFGE = BC_ifge,
- ICMD_IFGT = BC_ifgt,
- ICMD_IFLE = BC_ifle,
-
- ICMD_IF_ICMPEQ = BC_if_icmpeq,
- ICMD_IF_ICMPNE = BC_if_icmpne,
- ICMD_IF_ICMPLT = BC_if_icmplt,
- ICMD_IF_ICMPGE = BC_if_icmpge,
- ICMD_IF_ICMPGT = BC_if_icmpgt,
- ICMD_IF_ICMPLE = BC_if_icmple,
- ICMD_IF_ACMPEQ = BC_if_acmpeq,
- ICMD_IF_ACMPNE = BC_if_acmpne,
-
- ICMD_GOTO = BC_goto,
- ICMD_JSR = BC_jsr,
- ICMD_RET = BC_ret,
-
- ICMD_TABLESWITCH = BC_tableswitch,
- ICMD_LOOKUPSWITCH = BC_lookupswitch,
-
- ICMD_IRETURN = BC_ireturn,
- ICMD_LRETURN = BC_lreturn,
- ICMD_FRETURN = BC_freturn,
- ICMD_DRETURN = BC_dreturn,
- ICMD_ARETURN = BC_areturn,
- ICMD_RETURN = BC_return,
-
- ICMD_GETSTATIC = BC_getstatic,
- ICMD_PUTSTATIC = BC_putstatic,
- ICMD_GETFIELD = BC_getfield,
- ICMD_PUTFIELD = BC_putfield,
-
- ICMD_INVOKEVIRTUAL = BC_invokevirtual,
- ICMD_INVOKESPECIAL = BC_invokespecial,
- ICMD_INVOKESTATIC = BC_invokestatic,
- ICMD_INVOKEINTERFACE = BC_invokeinterface,
-
- /* 186 */
-
- ICMD_NEW = BC_new,
- ICMD_NEWARRAY = BC_newarray,
- ICMD_ANEWARRAY = BC_anewarray,
-
- ICMD_ARRAYLENGTH = BC_arraylength,
-
- ICMD_ATHROW = BC_athrow,
-
- ICMD_CHECKCAST = BC_checkcast,
- ICMD_INSTANCEOF = BC_instanceof,
-
- ICMD_MONITORENTER = BC_monitorenter,
- ICMD_MONITOREXIT = BC_monitorexit,
-
- /* 196 */
-
- ICMD_MULTIANEWARRAY = BC_multianewarray,
-
- ICMD_IFNULL = BC_ifnull,
- ICMD_IFNONNULL = BC_ifnonnull,
-
- /* 200 */
- /* 201 */
- /* 202 */
-
- ICMD_IASTORECONST = 204,
- ICMD_LASTORECONST = 205,
- ICMD_FASTORECONST = 206,
- ICMD_DASTORECONST = 207,
- ICMD_AASTORECONST = 208,
- ICMD_BASTORECONST = 209,
- ICMD_CASTORECONST = 210,
- ICMD_SASTORECONST = 211,
-
- ICMD_PUTSTATICCONST = 212,
- ICMD_PUTFIELDCONST = 213,
-
- ICMD_IMULPOW2 = 214,
- ICMD_LMULPOW2 = 215,
-
- ICMD_GETEXCEPTION = 249,
- ICMD_PHI = 250,
-
- ICMD_INLINE_START = 251, /* instruction before inlined method */
- ICMD_INLINE_END = 252, /* instruction after inlined method */
- ICMD_INLINE_BODY = 253, /* start of inlined body */
-
- ICMD_BUILTIN = 255 /* internal opcode */
-};
-
-/* Additional instruction accessors */
-
-methoddesc *instruction_call_site(const instruction *iptr);
-
-static inline bool instruction_has_dst(const instruction *iptr) {
- if (
- (icmd_table[iptr->opc].dataflow == DF_INVOKE) ||
- (icmd_table[iptr->opc].dataflow == DF_BUILTIN)
- ) {
- return instruction_call_site(iptr)->returntype.type != TYPE_VOID;
- } else {
- return icmd_table[iptr->opc].dataflow >= DF_DST_BASE;
- }
-}
-
-/***************************** register types *********************************/
-
-#define REG_RES 0 /* reserved register for OS or code generator */
-#define REG_RET 1 /* return value register */
-#define REG_EXC 2 /* exception value register */
-#define REG_SAV 3 /* (callee) saved register */
-#define REG_TMP 4 /* scratch temporary register (caller saved) */
-#define REG_ARG 5 /* argument register (caller saved) */
-
-#define REG_END -1 /* last entry in tables */
-
-#define PARAMMODE_NUMBERED 0
-#define PARAMMODE_STUFFED 1
-
-
-/* function prototypes ********************************************************/
-
-/* compiler initialisation */
-void jit_init(void);
-
-/* compiler finalisation */
-void jit_close(void);
-
-/* create a new jitdata */
-jitdata *jit_jitdata_new(methodinfo *m);
-
-/* compile a method with jit compiler */
-u1 *jit_compile(methodinfo *m);
-u1 *jit_recompile(methodinfo *m);
-
-void jit_invalidate_code(methodinfo *m);
-codeinfo *jit_get_current_code(methodinfo *m);
-void jit_request_optimization(methodinfo *m);
-
-/* patch the method entrypoint */
-#if !defined(JIT_COMPILER_VIA_SIGNAL)
-u1 *jit_asm_compile(methodinfo *m, u1 *mptr, u1 *sp, u1 *ra);
-#endif
-void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr);
-
-s4 jit_complement_condition(s4 opcode);
-
-void jit_renumber_basicblocks(jitdata *jd);
-#if !defined(NDEBUG)
-void jit_check_basicblock_numbers(jitdata *jd);
-#endif
-
-
-/* machine dependent functions ************************************************/
-
-#if defined(ENABLE_JIT)
-void md_init(void);
-#endif
-
-#if defined(ENABLE_INTRP)
-void intrp_md_init(void);
-#endif
-
-void *md_jit_method_patch_address(void *pv, void *ra, void *mptr);
-
-#endif /* _JIT_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/jit.hpp - Just-In-Time compiler
+
+ 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_HPP
+#define _JIT_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct jitdata jitdata;
+typedef struct basicblock basicblock;
+typedef struct exception_entry exception_entry;
+
+
+#include "config.h"
+#include "vm/types.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.hpp"
+#include "vm/jit/reg.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stack.h"
+#include "vm/jit/stacktrace.hpp"
+
+#if defined(ENABLE_INLINING)
+# include "vm/jit/inline/inline.h"
+#endif
+
+#include "vm/jit/ir/bytecode.h"
+#include "vm/jit/ir/instruction.hpp"
+
+#if defined(ENABLE_LOOP)
+# include "vm/jit/loop/loop.h"
+#endif
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+#endif
+#if defined(ENABLE_LSRA)
+# include "vm/jit/allocator/lsra.h"
+#endif
+
+#include "vm/jit/verify/typeinfo.h"
+
+
+/* common jit/codegen macros **************************************************/
+
+#if defined(ENABLE_STATISTICS)
+# define COUNT(x) (x)++
+# define COUNT_SPILLS /* use COUNT_(READ|WRITE)_SPILLS instead */
+# define COUNT_READ_SPILLS(var) \
+ switch(var->type) { \
+ case TYPE_FLT: count_spills_read_flt++; break; \
+ case TYPE_DBL: count_spills_read_dbl++; break; \
+ default: count_spills_read_ila++; break; \
+ }
+
+# define COUNT_WRITE_SPILLS(var) \
+ switch(var->type) { \
+ case TYPE_FLT: count_spills_write_flt++; break; \
+ case TYPE_DBL: count_spills_write_dbl++; break; \
+ default: count_spills_write_ila++; break; \
+ }
+
+#else
+# define COUNT(x) /* nothing */
+# define COUNT_SPILLS /* nothing */
+# define COUNT_READ_SPILLS(x) /* nothing */
+# define COUNT_WRITE_SPILLS(x) /* nothing */
+#endif
+
+typedef struct interface_info interface_info;
+
+struct interface_info {
+ s4 flags;
+ s4 regoff;
+};
+
+
+/* jitdata ********************************************************************/
+
+struct jitdata {
+ methodinfo *m; /* methodinfo of the method compiled */
+ codeinfo *code;
+ codegendata *cd;
+ registerdata *rd;
+#if defined(ENABLE_LOOP)
+ loopdata *ld;
+#endif
+#if defined(ENABLE_SSA) || defined(ENABLE_LSRA)
+ lsradata *ls;
+#endif
+
+ u4 flags; /* contains JIT compiler flags */
+
+ instruction *instructions; /* ICMDs, valid between parse and stack */
+ basicblock *basicblocks; /* start of basic block list */
+ stackelement_t *stack; /* XXX should become stack.c internal */
+ s4 instructioncount;/* XXX remove this? */
+ s4 basicblockcount; /* number of basic blocks */
+ s4 stackcount; /* number of stackelements to allocate */
+ /* (passed from parse to stack) */
+
+ varinfo *var; /* array of variables */
+ s4 vartop; /* next free index in var array */
+
+ s4 varcount; /* number of variables in var array */
+ s4 localcount; /* number of locals at start of var ar. */
+ s4 *local_map; /* map for renaming (de-coallescing) */
+ /* locals and keeping the coalescing info for simplereg. */
+ /* local_map[javaindex * 5 + type] = */
+ /* >= 0......index into jd->var, or */
+ /* UNUSED....this (javaindex,type) pair is not used */
+
+ s4 *reverselocalmap; /* map from CACAO varindex to javaindex */
+ /* (varindex must be < localcount) */
+
+ s4 maxlocals; /* max. number of javalocals */
+
+ interface_info *interface_map; /* interface variables (for simplereg) */
+ s4 maxinterfaces; /* max. number of interface variables */
+
+ s4 exceptiontablelength; /* exceptiontable length */
+ exception_entry *exceptiontable; /* the exceptiontable */
+
+ basicblock *returnblock; /* block containing the *RETURN */
+ /* (only use if returncount==1) */
+ s4 returncount; /* number of return instructions */
+ bool branchtoentry; /* true if first block is a target */
+ bool branchtoend; /* true if end dummy is a target */
+};
+
+#define FOR_EACH_BASICBLOCK(jd, it) \
+ for ((it) = (jd)->basicblocks; (it) != NULL; (it) = (it)->next)
+
+#define UNUSED -1
+
+#define JITDATA_FLAG_PARSE 0x00000001
+#define JITDATA_FLAG_VERIFY 0x00000002
+
+#define JITDATA_FLAG_INSTRUMENT 0x00000004
+
+#define JITDATA_FLAG_IFCONV 0x00000008
+#define JITDATA_FLAG_REORDER 0x00000010
+#define JITDATA_FLAG_INLINE 0x00000020
+
+#define JITDATA_FLAG_COUNTDOWN 0x00000100
+
+#define JITDATA_FLAG_SHOWINTERMEDIATE 0x20000000
+#define JITDATA_FLAG_SHOWDISASSEMBLE 0x40000000
+#define JITDATA_FLAG_VERBOSECALL 0x80000000
+
+
+#define JITDATA_HAS_FLAG_PARSE(jd) \
+ ((jd)->flags & JITDATA_FLAG_PARSE)
+
+#define JITDATA_HAS_FLAG_VERIFY(jd) \
+ ((jd)->flags & JITDATA_FLAG_VERIFY)
+
+#define JITDATA_HAS_FLAG_INSTRUMENT(jd) \
+ ((jd)->flags & JITDATA_FLAG_INSTRUMENT)
+
+#define JITDATA_HAS_FLAG_IFCONV(jd) \
+ ((jd)->flags & JITDATA_FLAG_IFCONV)
+
+#define JITDATA_HAS_FLAG_REORDER(jd) \
+ ((jd)->flags & JITDATA_FLAG_REORDER)
+
+#define JITDATA_HAS_FLAG_INLINE(jd) \
+ ((jd)->flags & JITDATA_FLAG_INLINE)
+
+#define JITDATA_HAS_FLAG_COUNTDOWN(jd) \
+ ((jd)->flags & JITDATA_FLAG_COUNTDOWN)
+
+#define JITDATA_HAS_FLAG_SHOWINTERMEDIATE(jd) \
+ ((jd)->flags & JITDATA_FLAG_SHOWINTERMEDIATE)
+
+#define JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) \
+ ((jd)->flags & JITDATA_FLAG_SHOWDISASSEMBLE)
+
+#define JITDATA_HAS_FLAG_VERBOSECALL(jd) \
+ ((jd)->flags & JITDATA_FLAG_VERBOSECALL)
+
+
+/* exception_entry ************************************************************/
+
+struct exception_entry {
+ basicblock *start;
+ basicblock *end;
+ basicblock *handler;
+ classref_or_classinfo catchtype; /* catchtype of exc. (NULL == catchall) */
+ exception_entry *next; /* next in list of exceptions when */
+ /* loops are copied */
+ exception_entry *down; /* next exception_entry */
+};
+
+
+/* macros for accessing variables *********************************************
+
+ Use VAROP for s1, s2, s3 and dst operands (eg. VAROP(iptr->s1)),
+ use VAR if you have the variable index (eg. VAR(iptr->sx.s23.s2.args[0])).
+
+******************************************************************************/
+
+#define VAROP(v) (jd->var + (v).varindex)
+#define VAR(i) (jd->var + (i))
+
+static inline bool var_is_local(const jitdata *jd, s4 i) {
+ return (i < jd->localcount);
+}
+
+static inline bool var_is_prealloc(const jitdata *jd, s4 i) {
+ return ((i >= jd->localcount) && (jd->var[i].flags & PREALLOC));
+}
+
+static inline bool var_is_inout(const jitdata *jd, s4 i) {
+ const varinfo *v = jd->var + i;
+ return (
+ (i >= jd->localcount) && (
+ (!(v->flags & PREALLOC) && (v->flags & INOUT)) ||
+ /* special case of TYPE_RET, used with JSR */
+ ((v->flags & PREALLOC) && (v->flags & INOUT) && (v->type == TYPE_RET))
+ )
+ );
+}
+
+static inline bool var_is_temp(const jitdata *jd, s4 i) {
+ const varinfo *v = jd->var + i;
+ return ((i >= jd->localcount) && !(v->flags & PREALLOC) && !(v->flags & INOUT));
+}
+
+static inline bool var_is_saved(const jitdata *jd, s4 i) {
+ return (jd->var[i].flags & SAVEDVAR);
+}
+
+
+/* basicblock *****************************************************************/
+
+/* flags */
+
+#define BBDELETED -2
+#define BBUNDEF -1
+#define BBREACHED 0
+#define BBFINISHED 1
+
+#define BBTYPECHECK_UNDEF 2
+#define BBTYPECHECK_REACHED 3
+
+#define BBTYPE_STD 0 /* standard basic block type */
+#define BBTYPE_EXH 1 /* exception handler basic block type */
+#define BBTYPE_SBR 2 /* subroutine basic block type */
+
+#define BBFLAG_REPLACEMENT 0x01 /* put a replacement point at the start */
+
+/* XXX basicblock wastes quite a lot of memory by having four flag fields */
+/* (flags, bitflags, type and lflags). Probably the last three could be */
+/* combined without loss of efficiency. The first one could be combined with */
+/* the others by using bitfields. */
+
+/* XXX "flags" should probably be called "state", as it is an integer state */
+
+struct basicblock {
+ s4 nr; /* basic block number */
+ s4 flags; /* used during stack analysis, init with -1 */
+ s4 bitflags; /* OR of BBFLAG_... constants, init with 0 */
+ s4 type; /* basic block type (std, xhandler, subroutine*/
+ s4 lflags; /* used during loop copying, init with 0 */
+
+ s4 icount; /* number of intermediate code instructions */
+ instruction *iinstr; /* pointer to intermediate code instructions */
+
+ varinfo *inlocals; /* copy of locals on block entry */
+ s4 *javalocals; /* map from java locals to cacao variables[+] */
+ s4 *invars; /* array of in-variables at begin of block */
+ s4 *outvars; /* array of out-variables at end of block */
+ s4 indepth; /* stack depth at begin of basic block */
+ s4 outdepth; /* stack depth end of basic block */
+ s4 varstart; /* index of first non-invar block variable */
+ s4 varcount; /* number of non-invar block variables */
+
+ s4 predecessorcount;
+ s4 successorcount;
+ basicblock **predecessors; /* array of predecessor basic blocks */
+ basicblock **successors; /* array of successor basic blocks */
+
+ branchref *branchrefs; /* list of branches to be patched */
+
+ basicblock *next; /* used to build a BB list (instead of array) */
+ basicblock *copied_to; /* points to the copy of this basic block */
+ /* when loop nodes are copied */
+ basicblock *original; /* block of which this block is a clone */
+ /* NULL for the original block itself */
+ methodinfo *method; /* method this block belongs to */
+ insinfo_inline *inlineinfo; /* inlineinfo for the start of this block */
+
+ s4 mpc; /* machine code pc at start of block */
+
+ /* TODO: those fields are probably usefull for other passes as well. */
+
+#if defined(ENABLE_SSA)
+ basicblock *idom; /* Immediate dominator, parent in dominator tree */
+ basicblock **domsuccessors;/* Children in dominator tree */
+ s4 domsuccessorcount;
+
+ basicblock **domfrontier; /* Dominance frontier */
+ s4 domfrontiercount;
+
+ basicblock **exhandlers; /* Exception handlers for this block */
+ s4 exhandlercount;
+ basicblock **expredecessors; /* Blocks this block is exception handler for */
+ s4 expredecessorcount;
+ s4 exouts; /* Number of exceptional exits */
+
+ instruction *phis; /* Phi functions */
+ s4 phicount; /* Number of phi functions */
+
+ void *vp; /* Freely used by different passes */
+#endif
+};
+
+#define FOR_EACH_SUCCESSOR(bptr, it) \
+ for ((it) = (bptr)->successors; (it) != (bptr)->successors + (bptr)->successorcount; ++(it))
+
+#define FOR_EACH_PREDECESSOR(bptr, it) \
+ for ( \
+ (it) = (bptr)->predecessors; \
+ (it) != (bptr)->predecessors + ((bptr)->predecessorcount < 0 ? 0 : (bptr)->predecessorcount); \
+ ++(it) \
+ )
+
+#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) \
+ for ((it) = (bptr)->exhandlers; (it) != (bptr)->exhandlers + (bptr)->exhandlercount; ++(it))
+
+#define FOR_EACH_EXPREDECESSOR(bptr, it) \
+ for ((it) = (bptr)->expredecessors; (it) != (bptr)->expredecessors + (bptr)->expredecessorcount; ++(it))
+
+#endif
+
+/* [+]...the javalocals array: This array is indexed by the javaindex (the */
+/* local variable index ocurring in the original bytecode). An element */
+/* javalocals[javaindex] encodes where to find the contents of the */
+/* original variable at this point in the program. */
+/* There are three cases for javalocals[javaindex]: */
+/* >= 0.......it's an index into the jd->var array, where the */
+/* CACAO variable corresponding to the original local */
+/* can be found. */
+/* UNUSED.....the original variable is not live at this point */
+/* < UNUSED...the original variable contains a returnAddress at */
+/* this point. The number of the block to return to can */
+/* be calculated using RETADDR_FROM_JAVALOCAL: */
+/* */
+/* javalocals[javaindex] == JAVALOCAL_FROM_RETADDR(nr) */
+/* RETADDR_FROM_JAVALOCAL(javalocals[javaindex]) == nr */
+
+#define JAVALOCAL_FROM_RETADDR(nr) (UNUSED - (1 + (nr)))
+#define RETADDR_FROM_JAVALOCAL(jl) (UNUSED - (1 + (jl)))
+
+
+/* Macro for initializing newly allocated basic block's. It does not
+ need to zero fields, as we zero out the whole basic block array. */
+
+#define BASICBLOCK_INIT(bptr,m) \
+ do { \
+ bptr->mpc = -1; \
+ bptr->flags = -1; \
+ bptr->type = BBTYPE_STD; \
+ bptr->method = (m); \
+ } while (0)
+
+static inline bool basicblock_reached(const basicblock *bptr) {
+ return (bptr->flags >= BBREACHED);
+}
+
+
+
+/***************************** register types *********************************/
+
+#define REG_RES 0 /* reserved register for OS or code generator */
+#define REG_RET 1 /* return value register */
+#define REG_EXC 2 /* exception value register */
+#define REG_SAV 3 /* (callee) saved register */
+#define REG_TMP 4 /* scratch temporary register (caller saved) */
+#define REG_ARG 5 /* argument register (caller saved) */
+
+#define REG_END -1 /* last entry in tables */
+
+#define PARAMMODE_NUMBERED 0
+#define PARAMMODE_STUFFED 1
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* compiler initialisation */
+void jit_init(void);
+
+/* compiler finalisation */
+void jit_close(void);
+
+/* create a new jitdata */
+jitdata *jit_jitdata_new(methodinfo *m);
+
+/* compile a method with jit compiler */
+u1 *jit_compile(methodinfo *m);
+u1 *jit_recompile(methodinfo *m);
+
+void jit_invalidate_code(methodinfo *m);
+codeinfo *jit_get_current_code(methodinfo *m);
+void jit_request_optimization(methodinfo *m);
+
+/* patch the method entrypoint */
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
+void *jit_asm_compile(methodinfo *m, void* mptr, void* sp, void* ra);
+#endif
+void *jit_compile_handle(methodinfo *m, void *pv, void *ra, void *mptr);
+
+s4 jit_complement_condition(s4 opcode);
+
+void jit_renumber_basicblocks(jitdata *jd);
+#if !defined(NDEBUG)
+void jit_check_basicblock_numbers(jitdata *jd);
+#endif
+
+
+/* machine dependent functions ************************************************/
+
+#if defined(ENABLE_JIT)
+void md_init(void);
+#endif
+
+#if defined(ENABLE_INTRP)
+void intrp_md_init(void);
+#endif
+
+void *md_jit_method_patch_address(void *pv, void *ra, void *mptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _JIT_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:
+ */
#if defined(ENABLE_JITCACHE)
-/* for mkdir() */
+#include "threads/thread.hpp"
+
+#include "toolbox/list.hpp"
+
+#include "vm/field.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/jitcache.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/patcher-common.hpp"
+
+#include "vm/os.hpp"
+#include "vm/string.hpp"
extern "C" {
+/* for mkdir() */
#include <sys/stat.h>
#include <assert.h>
#include "md.h"
-#include "toolbox/list.h"
#include "toolbox/logging.h"
#include "mm/memory.h"
#include "mm/codememory.h"
-#include "vm/builtin.h"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/resolve.h"
#include "vm/types.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/code.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/linenumbertable.h"
#include "vm/jit/exceptiontable.h"
#include "vm/jit/methodtree.h"
#include "vm/references.h"
-#include "vm/field.h"
#include "vm/utf8.h"
}
-#include "vm/string.hpp"
-#include "vm/os.hpp"
-#include "vm/jit/jitcache.hpp"
-#include "threads/thread.hpp"
/* TODO: Wrap this in vm/system.h" */
#include "unistd.h"
void jitcache_list_create(codeinfo *code)
{
- code->cachedrefs = list_create(OFFSET(cachedref_t, linkage));
+ code->cachedrefs = new List<cachedref_t>();
}
void jitcache_list_reset(codeinfo *code)
{
- cachedref_t *pr;
-
- /* free all elements of the list */
-
- while((pr = (cachedref_t *) list_first(code->cachedrefs)) != NULL) {
- list_remove(code->cachedrefs, pr);
-
- FREE(pr, cachedref_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_cachedref -= sizeof(cachedref_t);
-#endif
- }
+ code->cachedrefs->clear();
}
/* free the list itself */
- FREE(code->cachedrefs, list_t);
+ delete code->cachedrefs;
+ code->cachedrefs = 0;
}
static cachedref_t *jitcache_list_find(codeinfo *code, s4 disp)
{
- cachedref_t *cr;
-
/* walk through all cached references for the given codeinfo */
- cr = (cachedref_t *) list_first(code->cachedrefs);
- while (cr) {
-
- if (cr->disp == disp)
- return cr;
+ for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
+ it != code->cachedrefs->end(); it++)
+ {
- cr = (cachedref_t *) list_next(code->cachedrefs, cr);
+ if (it->disp == disp)
+ return &(*it);
}
return NULL;
*******************************************************************************/
-cachedref_t *jitcache_new_cached_ref(cachedreftype type, s4 md_patch, void* ref, s4 disp)
+cachedref_t jitcache_new_cached_ref(cachedreftype type, s4 md_patch, void* ref, s4 disp)
{
- cachedref_t *cr;
-
- /* allocate cachedref on heap (at least freed together with codeinfo) */
-
- cr = NEW(cachedref_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_cachedref += sizeof(cachedref_t);
-#endif
+ cachedref_t cr;
/* set reference information */
- cr->type = type;
- cr->md_patch= md_patch;
- cr->disp = disp;
- cr->ref = ref;
+ cr.type = type;
+ cr.md_patch= md_patch;
+ cr.disp = disp;
+ cr.ref = ref;
return cr;
}
-/* jitcache_add_cachedref_jd ***************************************************
+/* jitcache_add_cachedref_intern ***********************************************
- Creates a new cached ref appends it to the list in the codeinfo structure
- *or* attaches it to the *last* patchref_t if it overlaps with the address
- of the cached reference.
+ Creates a new cached ref appends it to the list in the codeinfo structure.
*******************************************************************************/
-void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t *cachedref)
+void jitcache_add_cached_ref_intern(codeinfo *code, cachedref_t cachedref)
{
- cachedref_t *list_cr;
-
- list_cr = (cachedref_t *) list_first(code->cachedrefs);
+ List<cachedref_t>::iterator it = code->cachedrefs->begin();
- while (list_cr)
+ while (it != code->cachedrefs->end())
{
- if (list_cr->disp == cachedref->disp)
+ if (it->disp == cachedref.disp)
{
- assert(list_cr->type == cachedref->type);
- assert(list_cr->ref == cachedref->ref);
+ assert(it->type == cachedref.type);
+ assert(it->ref == cachedref.ref);
/* Cachedref for already existing object found. No need to store
* it.
return;
}
- list_cr = (cachedref_t *) list_next(code->cachedrefs, list_cr);
+ it++;
}
- list_add_first(code->cachedrefs, cachedref);
+ code->cachedrefs->push_front(cachedref);
}
/* jitcache_add_cachedref_jd ***************************************************
void jitcache_add_cached_ref_md_jd(jitdata *jd, cachedreftype type, s4 md_patch, void* ref)
{
- patchref_t *patchref;
+ patchref_t patchref;
codegendata *cd;
ptrint disp;
- cachedref_t *cachedref;
+ cachedref_t cachedref;
if (type >= CRT_OBJECT_HEADER && !ref)
return;
disp = (ptrint) (cd->mcodeptr - cd->mcodebase) - SIZEOF_VOID_P;
cachedref = jitcache_new_cached_ref(type, md_patch, ref, disp);
- patchref = (patchref_t *) list_first(jd->code->patchers);
+ patchref = jd->code->patchers->front();
- if (patchref
- && (patchref->mpc) <= disp
- && (patchref->mpc + sizeof(patchref->mcode)) >= disp)
+ if ((patchref.mpc) <= disp
+ && (patchref.mpc + sizeof(patchref.mcode)) >= disp)
{
/* patchers and cachedref overlap: cached ref must
* be handled after the patcher.
- */
+ */
if (opt_DebugJitCache)
{
}
/* There can be only one cached ref per patcher currently.
- * If the need arises to handle more cached refs a list can
- * be used.
- */
- assert(!patchref->attached_ref);
+ * If the need arises to handle more cached refs a list can
+ * be used.
+ */
+ assert(!patchref.attached_ref);
- patchref->attached_ref = cachedref;
+ patchref.attached_ref = &cachedref;
}
else
jitcache_add_cached_ref_intern(jd->code, cachedref);
void jitcache_add_cached_ref(codeinfo *code, cachedreftype type, void* ref, s4 disp)
{
- cachedref_t *cr;
+ cachedref_t cr;
/* allocate cachedref on heap (at least freed together with codeinfo) */
cr = jitcache_new_cached_ref(type, 0, ref,disp);
location = (u1 **) (code->entrypoint + cr->disp);
/* Write the restored reference into the code. */
+#if defined (__ARM__)
if (cr->md_patch)
patch_md(cr->md_patch, (ptrint) location, cr->ref);
else
+#endif
*location = (u1 *) cr->ref;
md_cacheflush(location, SIZEOF_VOID_P);
if (opt_DebugJitCache)
log_message_method("[jitcache] no cache file found for ", m);
+ perror("get_cache_file_writable: ");
+
os::free(dest_file);
return 0;
{
if (mkdir_hier(dest_dir, S_IRWXU | S_IRWXG) != 0)
{
+ perror("get_cache_file_writable: ");
+
if (opt_DebugJitCache)
log_println("[jitcache] unable to create cache directory: %s", dest_dir);
os::free(dest_file);
if (fd <= 0)
+ {
+ perror("get_cache_file_writable2: ");
return 0;
+ }
}
os::free(dest_file);
}
}
- return mkdir(path, mode);
+ if (!mkdir(path, mode) || errno == EEXIST)
+ return 0;
}
/* get_dest_file ****************************************************************
{
int temp = 0;
void *temp_ptr;
- patchref_t *pr;
int j;
- list_t *patchers = code->patchers;
+ int size = code->patchers->size();
/* serialize patchers list */
- system_write(fd, (const void *) &patchers->size, sizeof(patchers->size));
+ system_write(fd, (const void *) &size, sizeof(size));
if (opt_DebugJitCache)
- log_println("store_to_file_patchers - patchers size %d", patchers->size);
+ log_println("store_to_file_patchers - patchers size %d", size);
- for (pr = (patchref_t *) list_first(patchers); pr != NULL; pr = (patchref_t *) list_next(patchers, pr))
+ for (List<patchref_t>::iterator it = code->patchers->begin();
+ it != code->patchers->end(); it++)
{
- temp_ptr = to_offset(code->mcode, (u1 *) pr->mpc);
+ temp_ptr = to_offset(code->mcode, (u1 *) it->mpc);
system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
- temp_ptr = to_offset(code->mcode, (u1 *) pr->datap);
+ temp_ptr = to_offset(code->mcode, (u1 *) it->datap);
system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
- system_write(fd, (const void *) &pr->disp, sizeof(pr->disp));
+ system_write(fd, (const void *) &it->disp, sizeof(it->disp));
temp = -1;
j = 0;
while (patcher_functions[j].patcher)
{
- if (patcher_functions[j].patcher == pr->patcher)
+ if (patcher_functions[j].patcher == it->patcher)
{
temp = j;
system_write(fd, (const void *) &j, sizeof(j));
- (*patcher_functions[j].serializer)(fd, pr, code->m);
+ (*patcher_functions[j].serializer)(fd, &(*it), code->m);
if (patcher_functions[j].serializer == s_dummy)
log_println("store_to_file_patchers: unhandled patcher function for %d", j);
system_write(fd, (const void *) &temp, sizeof(temp));
}
- system_write(fd, (const void *) &pr->attached_ref, sizeof(pr->attached_ref));
+ if (it->attached_ref)
+ temp = 1;
+
+ system_write(fd, (const void *) &temp, sizeof(temp));
- if (pr->attached_ref)
+ if (it->attached_ref)
{
- store_cachedref(fd, pr->attached_ref);
+ store_cachedref(fd, it->attached_ref);
/* Release the cached reference now because it should not be used
* in the current Cacao process.
*/
- FREE(pr->attached_ref, cachedref_t);
- pr->attached_ref = NULL;
+ FREE(it->attached_ref, cachedref_t);
+ it->attached_ref = NULL;
}
- system_write(fd, (const void *) &pr->mcode, sizeof(pr->mcode));
+ system_write(fd, (const void *) &it->mcode, sizeof(it->mcode));
}
}
*******************************************************************************/
void store_to_file_cachedrefs(int fd, codeinfo *code)
{
- cachedref_t *cr;
-
- list_t *cachedrefs = code->cachedrefs;
+ int size = code->cachedrefs->size();
if (opt_DebugJitCache)
- log_println("store_to_file_cachedrefs - cachedrefs size %d", cachedrefs->size);
+ log_println("store_to_file_cachedrefs - cachedrefs size %d", size);
/* serialize cachedrefs list */
- system_write(fd, (const void *) &cachedrefs->size, sizeof(cachedrefs->size));
+ system_write(fd, (const void *) &size, sizeof(size));
- for (cr = (cachedref_t *) list_first(cachedrefs);
- cr != NULL;
- cr = (cachedref_t *) list_next(cachedrefs, cr))
- store_cachedref(fd, cr);
+ for (List<cachedref_t>::iterator it = code->cachedrefs->begin();
+ it != code->cachedrefs->end(); it++)
+ store_cachedref(fd, &(*it));
}
/* store_cachedref *************************************************************
void store_to_file_linenumbertable(int fd, codeinfo *code)
{
void *temp_ptr;
- linenumbertable_entry_t *lte;
int count = 0;
- int i;
- linenumbertable_t *linenumbertable;
-
- linenumbertable = code->linenumbertable;
if (code->linenumbertable)
- count = code->linenumbertable->length;
+ count = code->linenumbertable->_linenumbers.size();
/* serialize patchers list */
system_write(fd, (const void *) &count, sizeof(count));
if (count)
{
- lte = linenumbertable->entries;
- for (i = 0; i < count; i++)
+ for (std::vector<Linenumber>::iterator it = code->linenumbertable->_linenumbers.begin();
+ it != code->linenumbertable->_linenumbers.end(); it++)
{
- system_write(fd, (const void *) <e->linenumber, sizeof(lte->linenumber));
+ int temp = it->get_linenumber();
+ system_write(fd, (const void *) &temp, sizeof(temp));
- temp_ptr = to_offset(code->entrypoint, lte->pc);
+ temp_ptr = to_offset(code->entrypoint, it->get_pc());
system_write(fd, (const void *) &temp_ptr, sizeof(temp_ptr));
-
- lte++;
}
}
for (i = 0;i < count; i++)
{
- patchref_t *pr = NEW(patchref_t);
+ patchref_t pr;
system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
- pr->mpc = (ptrint) to_abs(code->mcode, temp_ptr);
+ pr.mpc = (ptrint) to_abs(code->mcode, temp_ptr);
system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
- pr->datap = (ptrint) to_abs(code->mcode, temp_ptr);
+ pr.datap = (ptrint) to_abs(code->mcode, temp_ptr);
- system_read(fd, (void *) &pr->disp, sizeof(pr->disp));
+ system_read(fd, (void *) &pr.disp, sizeof(pr.disp));
system_read(fd, (void *) &temp, sizeof(temp));
if (temp == -1)
vm_abort("Invalid patcher function index loaded!");
temp = 0;
}
- pr->patcher = patcher_functions[temp].patcher;
+ pr.patcher = patcher_functions[temp].patcher;
- (*patcher_functions[temp].deserializer)(pr, fd, code->m);
+ (*patcher_functions[temp].deserializer)(&pr, fd, code->m);
/* Load the pointer value to decide whether a cached reference must
* be loaded or not. */
- system_read(fd, (void *) &pr->attached_ref, sizeof(pr->attached_ref));
+ system_read(fd, (void *) &temp, sizeof(temp));
- if (pr->attached_ref)
+ if (temp)
{
- pr->attached_ref = NULL;
- load_cachedref(&pr->attached_ref, fd, code);
+ pr.attached_ref = 0;
+ load_cachedref(&pr.attached_ref, fd, code);
}
- system_read(fd, (void *) &pr->mcode, sizeof(pr->mcode));
+ system_read(fd, (void *) &pr.mcode, sizeof(pr.mcode));
- pr->done = false;
+ pr.done = false;
- list_add_first(code->patchers, pr);
+ code->patchers->push_front(pr);
}
}
load_cachedref(&cr, fd, code);
/* Write the restored reference into the code. */
+#if defined (__ARM__)
if (cr->md_patch)
patch_md(cr->md_patch, ((ptrint) code->entrypoint) + cr->disp, cr->ref);
else
+#endif
{
*((u1 **) (code->entrypoint + cr->disp)) = (u1 *) cr->ref;
}
*******************************************************************************/
void load_from_file_linenumbertable(codeinfo *code, int fd)
{
- linenumbertable_entry_t *lte;
void *temp_ptr;
int i;
- code->linenumbertable = NEW(linenumbertable_t);
+ code->linenumbertable = new LinenumberTable();
- system_read(fd, (void *) &code->linenumbertable->length, sizeof(code->linenumbertable->length));
+ int size;
+ system_read(fd, (void *) &size, sizeof(size));
if (opt_DebugJitCache)
- log_println("load_linenumbertable - linenumbertable size %d", code->linenumbertable->length);
-
- lte = MNEW(linenumbertable_entry_t, code->linenumbertable->length);
- code->linenumbertable->entries = lte;
+ log_println("load_linenumbertable - linenumbertable size %d", size);
- for (i = 0;i < code->linenumbertable->length; i++)
+ for (i = 0;i < size; i++)
{
- system_read(fd, (void *) <e->linenumber, sizeof(lte->linenumber));
+ int linenumber;
+ system_read(fd, (void *) &linenumber, sizeof(linenumber));
system_read(fd, (void *) &temp_ptr, sizeof(temp_ptr));
- lte->pc = to_abs(code->entrypoint, temp_ptr);
- lte++;
+ code->linenumbertable->_linenumbers.push_back(
+ Linenumber(linenumber, to_abs(code->entrypoint, temp_ptr)));
}
}
#ifndef _JITCACHE_H
#define _JITCACHE_H
+#include "vm/jit/patcher-common.hpp"
+
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
-#include "vm/jit/patcher-common.h"
-
#include "vm/class.h"
#include "vm/method.h"
*******************************************************************************/
-typedef struct cachedref_t {
+struct cachedref_t {
cachedreftype type; /* type of the cached reference */
s4 md_patch; /* machine dependent back patching */
s4 disp; /* displacement of ref in the data segment */
void* ref; /* reference passed */
- listnode_t linkage;
-} cachedref_t;
+};
/*
typedef struct mru_entry_t {
/* jitcache_patcher_function_list_t typedef ***********************************/
-typedef struct jitcache_patcher_function_list_t {
+struct jitcache_patcher_function_list_t {
functionptr patcher;
serializerfptr serializer;
deserializerfptr deserializer;
-} jitcache_patcher_function_list_t;
+};
/* function prototypes ********************************************************/
+++ /dev/null
-/* src/vm/jit/linenumbertable.c - linenumber handling stuff
-
- 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"
-
-#include <assert.h>
-#include <stdint.h>
-
-#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(__S390__)
-# define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
-#else
-# define ADDR_MASK(type, x) (x)
-#endif
-
-/* linenumbertable_create ******************************************************
-
- Creates the linenumber table. We allocate an array and store the
- linenumber entry in reverse-order, so we can search the correct
- linenumber more easily.
-
-*******************************************************************************/
-
-void linenumbertable_create(jitdata *jd)
-{
- codeinfo *code;
- codegendata *cd;
- linenumbertable_t *lnt;
- linenumbertable_entry_t *lnte;
- list_t *l;
- linenumbertable_list_entry_t *le;
- uint8_t *pv;
- void *pc;
-
- /* Get required compiler data. */
-
- code = jd->code;
- cd = jd->cd;
-
- /* Don't allocate a linenumber table if we don't need one. */
-
- l = cd->linenumbers;
-
- if (l->size == 0)
- return;
-
- /* Allocate the linenumber table and the entries array. */
-
- lnt = NEW(linenumbertable_t);
- lnte = MNEW(linenumbertable_entry_t, l->size);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- count_linenumbertable++;
-
- size_linenumbertable +=
- sizeof(linenumbertable_t) +
- sizeof(linenumbertable_entry_t) * l->size;
- }
-#endif
-
- /* Fill the linenumber table. */
-
- lnt->length = l->size;
- lnt->entries = lnte;
-
- /* Fill the linenumber table entries in reverse order, so the
- search can be forward. */
-
- /* FIXME I only made this change to prevent a problem when moving
- to C++. This should be changed back when this file has
- converted to C++. */
-
- pv = ADDR_MASK(uint8_t *, code->entrypoint);
-
- for (le = list_first(l); le != NULL; le = list_next(l, le), lnte++) {
- /* If the entry contains an mcode pointer (normal case),
- resolve it (see doc/inlining_stacktrace.txt for
- details). */
-
- if (le->linenumber >= -2)
- pc = pv + le->mpc;
- else
- pc = (void *) le->mpc;
-
- /* Fill the linenumber table entry. */
-
- lnte->linenumber = le->linenumber;
- lnte->pc = pc;
- }
-
- /* Store the linenumber table in the codeinfo. */
-
- code->linenumbertable = lnt;
-}
-
-
-/* linenumbertable_list_entry_add **********************************************
-
- Add a line number reference.
-
- IN:
- cd.............current codegen data
- linenumber.....number of line that starts with the given mcodeptr
-
-*******************************************************************************/
-
-void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
-{
- linenumbertable_list_entry_t *le;
-
- le = DNEW(linenumbertable_list_entry_t);
-
- le->linenumber = linenumber;
- le->mpc = cd->mcodeptr - cd->mcodebase;
-
- list_add_first(cd->linenumbers, le);
-}
-
-
-/* linenumbertable_list_entry_add_inline_start *********************************
-
- Add a marker to the line number table indicating the start of an
- inlined method body. (see doc/inlining_stacktrace.txt)
-
- IN:
- cd ..... current codegen data
- iptr ... the ICMD_INLINE_BODY instruction
-
-*******************************************************************************/
-
-void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr)
-{
- linenumbertable_list_entry_t *le;
- insinfo_inline *insinfo;
- uintptr_t mpc;
-
- le = DNEW(linenumbertable_list_entry_t);
-
- le->linenumber = (-2); /* marks start of inlined method */
- le->mpc = (mpc = cd->mcodeptr - cd->mcodebase);
-
- list_add_first(cd->linenumbers, le);
-
- insinfo = iptr->sx.s23.s3.inlineinfo;
-
- insinfo->startmpc = mpc; /* store for corresponding INLINE_END */
-}
-
-
-/* linenumbertable_list_entry_add_inline_end ***********************************
-
- Add a marker to the line number table indicating the end of an
- inlined method body. (see doc/inlining_stacktrace.txt)
-
- IN:
- cd ..... current codegen data
- iptr ... the ICMD_INLINE_END instruction
-
- Note:
- iptr->method must point to the inlined callee.
-
-*******************************************************************************/
-
-void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr)
-{
- linenumbertable_list_entry_t *le;
- insinfo_inline *insinfo;
-
- insinfo = iptr->sx.s23.s3.inlineinfo;
-
- assert(insinfo);
-
- le = DNEW(linenumbertable_list_entry_t);
-
- /* special entry containing the methodinfo * */
- le->linenumber = (-3) - iptr->line;
- le->mpc = (uintptr_t) insinfo->method;
-
- list_add_first(cd->linenumbers, le);
-
- le = DNEW(linenumbertable_list_entry_t);
-
- /* end marker with PC of start of body */
- le->linenumber = (-1);
- le->mpc = insinfo->startmpc;
-
- list_add_first(cd->linenumbers, le);
-}
-
-
-/* linenumbertable_linenumber_for_pc_intern ************************************
-
- This function search the line number table for the line
- corresponding to a given pc. The function recurses for inlined
- methods.
-
-*******************************************************************************/
-
-static s4 linenumbertable_linenumber_for_pc_intern(methodinfo **pm, linenumbertable_entry_t *lnte, int32_t lntsize, void *pc)
-{
- linenumbertable_entry_t *lntinline; /* special entry for inlined method */
-
- pc = ADDR_MASK(void *, pc);
-
- for (; lntsize > 0; lntsize--, lnte++) {
- /* Note: In case of inlining this may actually compare the pc
- against a methodinfo *, yielding a non-sensical
- result. This is no problem, however, as we ignore such
- entries in the switch below. This way we optimize for the
- common case (ie. a real pc in lntentry->pc). */
-
- if (pc >= lnte->pc) {
- /* did we reach the current line? */
-
- if (lnte->linenumber >= 0)
- return lnte->linenumber;
-
- /* we found a special inline entry (see
- doc/inlining_stacktrace.txt for details */
-
- switch (lnte->linenumber) {
- case -1:
- /* begin of inlined method (ie. INLINE_END
- instruction) */
-
- lntinline = --lnte; /* get entry with methodinfo * */
- lnte--; /* skip the special entry */
- lntsize -= 2;
-
- /* search inside the inlined method */
-
- if (linenumbertable_linenumber_for_pc_intern(pm, lnte, lntsize, pc)) {
- /* the inlined method contained the pc */
-
- *pm = (methodinfo *) lntinline->pc;
-
- assert(lntinline->linenumber <= -3);
-
- return (-3) - lntinline->linenumber;
- }
-
- /* pc was not in inlined method, continue search.
- Entries inside the inlined method will be skipped
- because their lntentry->pc is higher than pc. */
- break;
-
- case -2:
- /* end of inlined method */
-
- return 0;
-
- /* default: is only reached for an -3-line entry after
- a skipped -2 entry. We can safely ignore it and
- continue searching. */
- }
- }
- }
-
- /* PC not found. */
-
- return 0;
-}
-
-
-/* linenumbertable_linenumber_for_pc *******************************************
-
- A wrapper for linenumbertable_linenumber_for_pc_intern.
-
- NOTE: We have a intern version because the function is called
- recursively for inlined methods.
-
-*******************************************************************************/
-
-int32_t linenumbertable_linenumber_for_pc(methodinfo **pm, codeinfo *code, void *pc)
-{
- linenumbertable_t *lnt;
- int32_t linenumber;
-
- /* Get line number table. */
-
- lnt = code->linenumbertable;
-
- if (lnt == NULL)
- return 0;
-
- /* Get the line number. */
-
- linenumber = linenumbertable_linenumber_for_pc_intern(pm, lnt->entries, lnt->length, pc);
-
- return linenumber;
-}
-
-
-/*
- * These 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/linenumbertable.cpp - linenumber handling stuff
+
+ 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 <algorithm>
+
+#include "mm/memory.h"
+
+#include "toolbox/list.hpp"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/options.h"
+# include "vm/statistics.h"
+#endif
+
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/linenumbertable.hpp"
+
+
+#if defined(__S390__)
+# define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
+#else
+# define ADDR_MASK(type, x) (x)
+#endif
+
+
+/**
+ * Resolve the linenumber.
+ *
+ * If the entry contains an mcode pointer (normal case), resolve it
+ * (see doc/inlining_stacktrace.txt for details).
+ *
+ * @param code Code structure.
+ */
+void Linenumber::resolve(const codeinfo* code)
+{
+ void* pv = ADDR_MASK(void*, code->entrypoint);
+
+ // TODO Use constant.
+ if (_linenumber >= -2)
+ _pc = (void*) ((uintptr_t) pv + (uintptr_t) _pc);
+}
+
+
+/**
+ * Creates a linenumber table.
+ *
+ * We allocate an array and store the linenumber entry in
+ * reverse-order, so we can search the correct linenumber more easily.
+ *
+ * @param jd JIT data.
+ */
+LinenumberTable::LinenumberTable(jitdata* jd) : _linenumbers(jd->cd->linenumbers->begin(), jd->cd->linenumbers->end())
+{
+ // Get required compiler data.
+ codeinfo* code = jd->code;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ count_linenumbertable++;
+
+ size_linenumbertable +=
+ sizeof(LinenumberTable) +
+ sizeof(Linenumber) * _linenumbers.size();
+ }
+#endif
+
+ // Resolve all linenumbers in the vector.
+ (void) for_each(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(LinenumberResolver(), code));
+}
+
+
+/**
+ * Search the the line number table for the line corresponding to a
+ * given program counter.
+ *
+ * @param pc Program counter.
+ *
+ * @return Line number.
+ */
+int32_t LinenumberTable::find(methodinfo **pm, void* pc)
+{
+ void* maskpc = ADDR_MASK(void*, pc);
+
+ std::vector<Linenumber>::iterator it = find_if(_linenumbers.begin(), _linenumbers.end(), std::bind2nd(comparator(), maskpc));
+
+ // No matching entry found.
+ if (it == _linenumbers.end())
+ return 0;
+
+ Linenumber& ln = *it;
+ int32_t linenumber = ln.get_linenumber();
+
+ // Check for linenumber entry type.
+ if (linenumber < 0) {
+ os::abort("FIX ME!");
+
+#if 0
+ // We found a special inline entry (see
+ // doc/inlining_stacktrace.txt for details).
+ switch (linenumber) {
+ case -1:
+ // Begin of an inlined method (ie. INLINE_END instruction.
+ lntinline = --lnte; /* get entry with methodinfo * */
+ lnte--; /* skip the special entry */
+
+ /* search inside the inlined method */
+
+ if (linenumbertable_linenumber_for_pc_intern(pm, lnte, lntsize, pc)) {
+ /* the inlined method contained the pc */
+
+ *pm = (methodinfo *) lntinline->pc;
+
+ assert(lntinline->linenumber <= -3);
+
+ return (-3) - lntinline->linenumber;
+ }
+
+ /* pc was not in inlined method, continue search.
+ Entries inside the inlined method will be skipped
+ because their lntentry->pc is higher than pc. */
+ break;
+
+ case -2:
+ /* end of inlined method */
+
+ return 0;
+
+ /* default: is only reached for an -3-line entry after
+ a skipped -2 entry. We can safely ignore it and
+ continue searching. */
+ }
+#endif
+ }
+
+ // Normal linenumber entry, return it.
+ return linenumber;
+}
+
+
+/* linenumbertable_list_entry_add **********************************************
+
+ Add a line number reference.
+
+ IN:
+ cd.............current codegen data
+ linenumber.....number of line that starts with the given mcodeptr
+
+*******************************************************************************/
+
+void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber)
+{
+ void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
+ Linenumber ln(linenumber, pc);
+
+ cd->linenumbers->push_front(ln);
+}
+
+
+/* linenumbertable_list_entry_add_inline_start *********************************
+
+ Add a marker to the line number table indicating the start of an
+ inlined method body. (see doc/inlining_stacktrace.txt)
+
+ IN:
+ cd ..... current codegen data
+ iptr ... the ICMD_INLINE_BODY instruction
+
+*******************************************************************************/
+
+void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr)
+{
+ void* pc = (void*) (cd->mcodeptr - cd->mcodebase);
+
+ Linenumber ln(-2 /* marks start of inlined method */, pc);
+
+ cd->linenumbers->push_front(ln);
+
+ insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
+ insinfo->startmpc = (int32_t) (uintptr_t) pc; /* store for corresponding INLINE_END */
+}
+
+
+/* linenumbertable_list_entry_add_inline_end ***********************************
+
+ Add a marker to the line number table indicating the end of an
+ inlined method body. (see doc/inlining_stacktrace.txt)
+
+ IN:
+ cd ..... current codegen data
+ iptr ... the ICMD_INLINE_END instruction
+
+ Note:
+ iptr->method must point to the inlined callee.
+
+*******************************************************************************/
+
+void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr)
+{
+ insinfo_inline* insinfo = iptr->sx.s23.s3.inlineinfo;
+
+ // Sanity check.
+ assert(insinfo);
+
+ // Special entry containing the methodinfo.
+ Linenumber ln((-3) - iptr->line, insinfo->method);
+
+ cd->linenumbers->push_front(ln);
+
+ // End marker with PC of start of body.
+ Linenumber lne(-1, (void*) insinfo->startmpc);
+
+ cd->linenumbers->push_front(lne);
+}
+
+
+/*
+ * These 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/linenumbertable.h - linenumber table
-
- 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 _LINENUMBERTABLE_H
-#define _LINENUMBERTABLE_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct linenumbertable_t linenumbertable_t;
-typedef struct linenumbertable_entry_t linenumbertable_entry_t;
-typedef struct linenumbertable_list_entry_t linenumbertable_list_entry_t;
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "toolbox/list.h"
-
-#include "vm/method.h"
-
-#include "vm/jit/jit.h"
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
-
-
-/* linenumbertable_t **********************************************************/
-
-struct linenumbertable_t {
- int32_t length; /* length of the entries array */
- linenumbertable_entry_t *entries; /* actual linenumber entries */
-};
-
-
-/* linenumbertable_entry_t *****************************************************
-
- NOTE: See doc/inlining_stacktrace.txt for special meanings of line
- and pc.
-
-*******************************************************************************/
-
-struct linenumbertable_entry_t {
- int32_t linenumber; /* linenumber of this entry */
- void *pc; /* PC where this linenumber starts */
-};
-
-
-/* linenumbertable_list_entry_t ***********************************************/
-
-struct linenumbertable_list_entry_t {
- int32_t linenumber; /* line number, used for inserting into the */
- /* table and for validity checking */
- /* -1......start of inlined body */
- /* -2......end of inlined body */
- /* <= -3...special entry with methodinfo * */
- /* (see doc/inlining_stacktrace.txt) */
- ptrint mpc; /* machine code program counter of first */
- /* instruction for given line */
- /* NOTE: for linenumber <= -3 this is a the */
- /* (methodinfo *) of the inlined method */
- listnode_t linkage;
-};
-
-
-/* function prototypes ********************************************************/
-
-void linenumbertable_create(jitdata *jd);
-
-void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber);
-void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr);
-void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr);
-
-int32_t linenumbertable_linenumber_for_pc(methodinfo **pm, codeinfo *code, void *pc);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _LINENUMBERTABLE_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/linenumbertable.hpp - linenumber table
+
+ 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 _LINENUMBERTABLE_HPP
+#define _LINENUMBERTABLE_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <functional>
+#include <vector>
+#endif
+
+#include "toolbox/list.hpp"
+
+#include "vm/method.h"
+
+#include "vm/jit/jit.hpp"
+#include "vm/jit/code.hpp"
+
+#include "vm/jit/ir/instruction.hpp"
+
+
+#ifdef __cplusplus
+
+/**
+ * Represents a Java line number.
+ */
+class Linenumber {
+private:
+ // TODO Add constants.
+ /* -1......start of inlined body */
+ /* -2......end of inlined body */
+ /* <= -3...special entry with methodinfo * */
+ /* (see doc/inlining_stacktrace.txt) */
+
+ int32_t _linenumber;
+ void* _pc;
+
+public:
+ Linenumber(int32_t linenumber, void* pc) : _linenumber(linenumber), _pc(pc) {}
+
+ inline int32_t get_linenumber() const { return _linenumber; }
+ inline void* get_pc () const { return _pc; }
+
+ void resolve(const codeinfo* code);
+};
+
+
+/**
+ * Unary function to resolve Linenumber objects.
+ */
+class LinenumberResolver : public std::binary_function<Linenumber, codeinfo*, void> {
+public:
+ // Unary resolve function.
+ void operator() (Linenumber& ln, const codeinfo* code) const
+ {
+ ln.resolve(code);
+ }
+};
+
+
+/**
+ * Linenumber table of a Java method.
+ */
+class LinenumberTable {
+public:
+ std::vector<Linenumber> _linenumbers;
+private:
+
+ // Comparator class.
+ class comparator : public std::binary_function<Linenumber, void*, bool> {
+ public:
+ bool operator() (const Linenumber& ln, const void* pc) const
+ {
+ return (pc >= ln.get_pc());
+ }
+ };
+
+public:
+ LinenumberTable(jitdata* jd);
+ LinenumberTable() { }
+ ~LinenumberTable();
+
+ int32_t find(methodinfo **pm, void* pc);
+};
+
+#else
+
+typedef struct LinenumberTable LinenumberTable;
+
+#endif
+
+#include "vm/jit/codegen-common.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void linenumbertable_list_entry_add(codegendata *cd, int32_t linenumber);
+void linenumbertable_list_entry_add_inline_start(codegendata *cd, instruction *iptr);
+void linenumbertable_list_entry_add_inline_end(codegendata *cd, instruction *iptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _LINENUMBERTABLE_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 "toolbox/logging.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/stack.h"
#include "vm/jit/loop/analyze.h"
#include "config.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* function prototypes ********************************************************/
#include "mm/memory.h"
#include "toolbox/logging.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/loop/graph.h"
#include "vm/jit/loop/loop.h"
#include "mm/memory.h"
#include "toolbox/logging.h"
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/loop/loop.h"
#include "vm/jit/loop/graph.h"
#include "vm/jit/loop/tracing.h"
#include "vm/global.h"
#include "vm/method.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* Different types for struct Trace */
#include "mm/memory.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/resolve.h"
#include "vm/jit/loop/loop.h"
#include "vm/jit/loop/tracing.h"
#ifndef _TRACING_H
#define _TRACING_H
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
typedef struct Trace Trace;
emit.c \
patcher.c \
\
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 1
#define SUPPORT_LONG 1
#include "vm/jit/m68k/emit.h"
#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
-#include "threads/lock-common.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "threads/lock.hpp"
+
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#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/patcher-common.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/parse.h"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
/* src/vm/jit/m68k/codegen.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
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#define PATCHER_NOPS \
do { M_TPFL; M_TPF; M_TPF } while (0);
-#define PATCHER_CALL_SIZE (3*2)
-
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE (2+2)
+#define PATCHER_CALL_SIZE 2
/* coldfire instruction format:
#include "mm/memory.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/emit-common.h"
+#include "vm/jit/emit-common.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
#include "vm/types.h"
#include "vm/vm.hpp"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
void emit_mov_imm_reg (codegendata *cd, s4 imm, s4 dreg);
void emit_mov_imm_areg(codegendata *cd, s4 imm, s4 dreg);
--- /dev/null
+/* src/vm/jit/m68k/md-stubs.hpp - m68k JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a m68k architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 2 + 2;
+}
+
+#endif // _MD_STUBS_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 <assert.h>
#include <stdint.h>
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/methodtree.h"
#include "vm/jit/m68k/md.h"
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#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/patcher-common.hpp"
#include "codegen.h"
/* patch back original code */
PATCH_BACK_ORIGINAL_MCODE;
- /* if we show NOPs, we have to skip them */
- if (opt_shownops) ra += PATCHER_CALL_SIZE;
-
assert( *((u2*)(ra+8)) == 0x286b);
/* patch vftbl index */
/* patch back original code */
PATCH_BACK_ORIGINAL_MCODE;
- /* patch stubroutine */
- if (opt_shownops) disp += PATCHER_CALL_SIZE;
-
*((ptrint *) (disp+2)) = (ptrint) m->stubroutine;
/* synchronize inst cache */
PATCH_BACK_ORIGINAL_MCODE;
/* patch the classinfo pointer */
- if (opt_shownops) disp += PATCHER_CALL_SIZE;
*((ptrint *) (disp+2)) = (ptrint) c;
/* synchronize inst cache */
md_icacheflush(pr->mpc, 2);
/* patch the field value's address */
- if (opt_shownops) disp += PATCHER_CALL_SIZE;
assert(*((uint16_t*)(disp)) == 0x247c);
*((intptr_t *) (disp+2)) = (intptr_t) fi->value;
PATCH_BACK_ORIGINAL_MCODE;
md_icacheflush(pr->mpc, 2);
- /* if we show NOPs, we have to skip them */
- if (opt_shownops) ra += PATCHER_CALL_SIZE;
-
/* patch the field's offset */
if (IS_LNG_TYPE(fi->type)) {
/*
md_icacheflush(pr->mpc, 2);
/* patch class flags */
- if (opt_shownops) disp += PATCHER_CALL_SIZE;
assert( (*((u2*)(disp)) == 0x263c) || (*((u2*)(disp)) == 0x283c) );
*((s4 *) (disp + 2)) = (s4) c->flags;
md_icacheflush(pr->mpc, 2);
/* patch super class' vftbl */
- if (opt_shownops) disp += PATCHER_CALL_SIZE;
assert( (*((u2*)disp) == 0x287c) || (*((u2*)disp)== 0x267c) );
*((s4 *) (disp+2)) = (s4) c->vftbl;
PATCH_BACK_ORIGINAL_MCODE;
md_icacheflush(pr->mpc, 2);
- /* if we show NOPs, we have to skip them */
- if (opt_shownops) ra += PATCHER_CALL_SIZE;
-
/* patch super class index */
disp = -(c->index);
assert( *((u2*)(ra + 8)) == 0xd8bc );
PATCH_BACK_ORIGINAL_MCODE;
md_icacheflush(pr->mpc, 2);
- /* if we show NOPs, we have to skip them */
- if (opt_shownops) ra += PATCHER_CALL_SIZE;
-
/* patch super class index */
disp = -(c->index);
assert ( *((u2 *)(ra + 8)) == 0xd8bc );
md_icacheflush(pr->mpc, 2);
/* patch native function pointer */
- if (opt_shownops) disp += PATCHER_CALL_SIZE;
*((ptrint *) (disp + 2)) = (ptrint) f;
/* synchronize data cache */
md_icacheflush(pr->mpc, 2);
/* if we show NOPs, we have to skip them */
- if (opt_shownops) ra += PATCHER_CALL_SIZE;
assert( *((uint32_t*)ra) == 0x246f0000 );
/* patch interfacetable index (first #0) */
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
\
md-abi.c \
md-abi.h \
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#if SIZEOF_VOID_P == 8
#define SUPPORT_DIVISION 1
#include "mm/memory.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trap.h"
#if defined(ENABLE_LSRA)
/* src/vm/jit/mips/codegen.h - code generation macros and definitions for MIPS
- 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"
#include "vm/types.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* additional functions and macros to generate code ***************************/
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 1 * 4
-
-
/* macros to create code ******************************************************/
/* code generation macros operands:
/* macros for all used commands (see a MIPS-manual for description) ***********/
+#define M_RESERVED M_RTYPE(0x3b, 0, 0, 0, 0, 0)
+
/* load/store macros use the form OPERATION(source/dest, base, offset) */
#define M_LDA(a,b,disp) \
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.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/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trap.h"
uint32_t emit_trap(codegendata *cd)
{
- uint32_t mcode;
+ // Get machine code which is patched back in later. The trap is 1
+ // instruction word long.
+ uint32_t mcode = *((uint32_t*) cd->mcodeptr);
- /* Get machine code which is patched back in later. The
- trap is 1 instruction word long. */
-
- mcode = *((uint32_t *) cd->mcodeptr);
-
- M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
+ M_RESERVED;
return mcode;
}
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
/* md_init *********************************************************************
/* fall-through */
- case TRAP_PATCHER:
- if (p == NULL) {
- /* We set the PC again because the cause may have changed
- the XPC. */
+ default:
+ _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
+ _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
+#if defined(__UCLIBC__)
+ _gregs[CTX_EPC] = (uintptr_t) asm_handle_exception;
+#else
+ _mc->pc = (uintptr_t) asm_handle_exception;
+#endif
+ }
+}
+
+
+/**
+ * Signal handler for patcher calls.
+ */
+void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
+{
+ ucontext_t* _uc = (struct ucontext *) _p;
+ mcontext_t* _mc = &_uc->uc_mcontext;
+ greg_t* _gregs;
#if defined(__UCLIBC__)
- _gregs[CTX_EPC] = (uintptr_t) xpc;
+ _gregs = _mc->gpregs;
+#else
+ _gregs = _mc->gregs;
+#endif
+
+ // In glibc's ucontext.h the registers are defined as long long
+ // int, even for MIPS32, so we cast them. This is not the case
+ // for uClibc.
+ void* pv = (void*) (uintptr_t) _gregs[REG_PV];
+ void* sp = (void*) (uintptr_t) _gregs[REG_SP];
+ void* ra = (void*) (uintptr_t) _gregs[REG_RA]; // The RA is correct for leaf methods.
+
+#if defined(__UCLIBC__)
+ void* xpc = (void*) (uintptr_t) _gregs[CTX_EPC];
#else
- _mc->pc = (uintptr_t) xpc;
+ void* xpc = (void*) (uintptr_t) _mc->pc;
#endif
- break;
- }
- /* fall-through */
-
- default:
+ // This signal is always a patcher.
+ int type = TRAP_PATCHER;
+ intptr_t val = 0;
+
+ // Handle the trap.
+ void* p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ // Set registers if we have an exception, continue execution
+ // otherwise.
+ if (p != NULL) {
_gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
_gregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
#if defined(__UCLIBC__)
_gregs[CTX_EPC] = (uintptr_t) asm_handle_exception;
#else
_mc->pc = (uintptr_t) asm_handle_exception;
+#endif
+ }
+ else {
+ // We set the PC again because the cause may have changed the
+ // XPC.
+#if defined(__UCLIBC__)
+ _gregs[CTX_EPC] = (uintptr_t) xpc;
+#else
+ _mc->pc = (uintptr_t) xpc;
#endif
}
}
--- /dev/null
+/* src/vm/jit/mips/md-stubs.hpp - MIPS JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a MIPS architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 1 * 4;
+}
+
+#endif // _MD_STUBS_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 = 7,
/* Don't use 8 (could be a normal load offset). */
- TRAP_COMPILER = 9,
- TRAP_COUNTDOWN = 10,
- TRAP_END
+ TRAP_COUNTDOWN = 9,
+ TRAP_END,
+
+ // This is handled via SIGILL.
+ TRAP_PATCHER = 99 // A large number.
};
#endif /* _MD_TRAP_H */
#include "vm/global.h"
#include "vm/vm.hpp"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* md_jit_method_patch_address *************************************************
#include <assert.h>
#include <stdint.h>
-#include "vm/types.h"
-
#include "vm/jit/mips/codegen.h"
#include "vm/jit/mips/md.h"
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#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"
-
-
-#define PATCH_BACK_ORIGINAL_MCODE \
- *((u4 *) pr->mpc) = (u4) pr->mcode; \
- md_icacheflush((u1 *) pr->mpc, PATCHER_CALL_SIZE);
+#include "vm/jit/patcher-common.hpp"
/* patcher_patch_code **********************************************************
void patcher_patch_code(patchref_t *pr)
{
- PATCH_BACK_ORIGINAL_MCODE;
+ *((uint32_t*) pr->mpc) = (uint32_t) pr->mcode;
+ md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
}
bool patcher_get_putstatic(patchref_t *pr)
{
- unresolved_field *uf;
- u1 *datap;
- fieldinfo *fi;
-
- /* get stuff from the stack */
-
- uf = (unresolved_field *) pr->ref;
- datap = (u1 *) pr->datap;
+ unresolved_field* uf = (unresolved_field *) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- /* get the fieldinfo */
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- /* check if the field's class is initialized */
-
+ // Check if the field's class is initialized.
if (!(fi->clazz->state & CLASS_INITIALIZED))
if (!initialize_class(fi->clazz))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch the field value's address */
-
- *((intptr_t *) datap) = (intptr_t) fi->value;
-
- /* synchronize data cache */
+ // Patch the field value's address.
+ *datap = (uintptr_t) fi->value;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_get_putfield(patchref_t *pr)
{
- u1 *ra;
- unresolved_field *uf;
- fieldinfo *fi;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
- ra = (u1 *) pr->mpc;
- uf = (unresolved_field *) pr->ref;
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- /* get the fieldinfo */
-
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
#if SIZEOF_VOID_P == 4
if (IS_LNG_TYPE(fi->type)) {
# if WORDS_BIGENDIAN == 1
- /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
- *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
- *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+ // ATTENTION: order of these instructions depend on M_LLD_INTERN.
+ // The first instruction is patched back later.
+ pr->mcode |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
+ pc[1] |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
# else
- /* ATTENTION: order of these instructions depend on M_LLD_INTERN */
- *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
- *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+ // ATTENTION: order of these instructions depend on M_LLD_INTERN.
+ // The first instruction is patched back later.
+ pr->mcode |= (int16_t) ((fi->offset + 4) & 0x0000ffff);
+ pc[1] |= (int16_t) ((fi->offset + 0) & 0x0000ffff);
# endif
}
else
#endif
- *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
+ {
+ // The instruction is patched back later.
+ pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
+ }
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc, 2 * 4);
- md_icacheflush(ra, 2 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
-
- /* get stuff from the stack */
+ constant_classref* cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the classinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch the classinfo pointer */
-
- *((intptr_t *) datap) = (intptr_t) c;
-
- /* synchronize data cache */
+ // Patch the class.
+ *datap = (uintptr_t) c;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
-
- /* get stuff from the stack */
+ constant_classref* cr = (constant_classref *) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the field.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch super class' vftbl */
-
- *((intptr_t *) datap) = (intptr_t) c->vftbl;
-
- /* synchronize data cache */
+ // Patch super class' vftbl.
+ *datap = (uintptr_t) c->vftbl;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_resolve_classref_to_flags(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
-
- /* get stuff from the stack */
+ constant_classref* cr = (constant_classref*) pr->ref;
+ int32_t* datap = (int32_t*) pr->datap;
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch class flags */
-
- *((int32_t *) datap) = (int32_t) c->flags;
-
- /* synchronize data cache */
+ // Patch class flags.
+ *datap = (int32_t) c->flags;
+ // Synchronize data cache.
md_dcacheflush(datap, sizeof(int32_t));
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_invokestatic_special(patchref_t *pr)
{
- unresolved_method *um;
- u1 *datap;
- methodinfo *m;
-
- /* get stuff from the stack */
+ unresolved_method* um = (unresolved_method*) pr->ref;
+ void** datap = (void*) pr->datap;
- um = (unresolved_method *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch stubroutine */
-
- *((ptrint *) datap) = (ptrint) m->stubroutine;
-
- /* synchronize data cache */
+ // Patch stubroutine.
+ *datap = (void*) m->stubroutine;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_invokevirtual(patchref_t *pr)
{
- u1 *ra;
- unresolved_method *um;
- methodinfo *m;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- ra = (u1 *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
- /* patch vftbl index */
+ // Patch vftbl index.
+ pc[1] |= (int32_t) ((OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
- *((s4 *) (ra + 1 * 4)) |=
- (s4) ((OFFSET(vftbl_t, table[0]) +
- sizeof(methodptr) * m->vftblindex) & 0x0000ffff);
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 1 * 4);
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 1 * 4, 1 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokeinterface(patchref_t *pr)
{
- u1 *ra;
- unresolved_method *um;
- methodinfo *m;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- ra = (u1 *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ // Resovlve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
+ // Patch interfacetable index.
+ pc[1] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
+ // Patch method offset.
+ pc[2] |= (int32_t) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
- /* patch interfacetable index */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 2 * 4);
- *((s4 *) (ra + 1 * 4)) |=
- (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
-
- /* patch method offset */
-
- *((s4 *) (ra + 2 * 4)) |=
- (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 1 * 4, 2 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_checkcast_interface(patchref_t *pr)
{
- u1 *ra;
- constant_classref *cr;
- classinfo *c;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- /* get stuff from the stack */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- ra = (u1 *) pr->mpc;
- cr = (constant_classref *) pr->ref;
-
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
+ // Patch super class index.
+ pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
+ pc[6] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
- /* patch super class index */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 2, 5 * 4);
- *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
- /* *((s4 *) (ra + 5 * 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) - */
- /* c->index * sizeof(methodptr*)) & 0x0000ffff); */
- *((s4 *) (ra + 6 * 4)) |=
- (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- c->index * sizeof(methodptr*)) & 0x0000ffff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 2 * 4, 5 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_instanceof_interface(patchref_t *pr)
{
- u1 *ra;
- constant_classref *cr;
- classinfo *c;
-
- /* get stuff from the stack */
-
- ra = (u1 *) pr->mpc;
- cr = (constant_classref *) pr->ref;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the method.
+ classinfo* c = resolve_classref_eager(cr);
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
- /* patch super class index */
-
- *((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x0000ffff);
- *((s4 *) (ra + 5 * 4)) |=
- (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- c->index * sizeof(methodptr*)) & 0x0000ffff);
+ // Patch super class index.
+ pc[2] |= (int32_t) (-(c->index) & 0x0000ffff);
+ pc[5] |= (int32_t) ((OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*)) & 0x0000ffff);
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 2, 4 * 4);
- md_icacheflush(ra + 2 * 4, 4 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
*/
-
#include "config.h"
#include "mm/memory.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
#include "vm/jit/oprofile-agent.hpp"
#include <string.h>
_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.
#include "config.h"
-#ifdef __cplusplus
extern "C" {
-#endif
#include "vm/method.h"
-
#include <opagent.h>
-#ifdef __cplusplus
}
-#endif
-
-#ifdef __cplusplus
class OprofileAgent
{
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 */
## src/vm/jit/optimizing/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.
##
endif
if ENABLE_THREADS
-RECOMPILE_SOURCES = \
- recompile.c \
- recompile.h
+RECOMPILER_SOURCES = \
+ recompiler.cpp \
+ recompiler.hpp
endif
if ENABLE_SSA
ssa_rename.h \
graph.c \
graph.h \
- dominators.c \
- dominators.h \
+ dominators.cpp \
+ dominators.hpp \
lifetimes.c \
lifetimes.h \
ssa2.c \
liboptimizing_la_SOURCES = \
$(IFCONV_SOURCES) \
$(PROFILE_SOURCES) \
- $(RECOMPILE_SOURCES) \
+ $(RECOMPILER_SOURCES) \
$(REORDER_SOURCES) \
$(SSA_SOURCES) \
$(ESCAPE_SOURCES)
#include "config.h"
-#include "mm/dumpmemory.h"
+#include <stdint.h>
+
+#include "mm/dumpmemory.hpp"
#include "mm/memory.h"
#include "toolbox/bitvector.h"
+++ /dev/null
-/* src/vm/jit/optimizing/dominators.c - dominators and dominance frontier
-
- Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-
-*/
-
-
-#include "mm/memory.h"
-
-#include "toolbox/bitvector.h"
-
-#include "vm/jit/jit.h"
-
-#include "vm/jit/optimizing/graph.h"
-#include "vm/jit/optimizing/dominators.h"
-
-/* function prototypes */
-void dom_Dominators_init(dominatordata *dd, int basicblockcount);
-#ifdef DOM_DEBUG_CHECK
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount);
-void dom_Link(dominatordata *dd, int p, int n, int basicblockcount);
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
- int basicblockcount);
-#else
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v);
-void dom_Link(dominatordata *dd, int p, int n);
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N);
-#endif
-
-/*************************************
-Calculate Dominators
-*************************************/
-dominatordata *compute_Dominators(graphdata *gd, int basicblockcount) {
- int i,j,n,N,p,s,s_,v,y;
- graphiterator iter;
- dominatordata *dd;
-
- dd = DNEW(dominatordata);
-
- dom_Dominators_init(dd, basicblockcount);
-
- N=0;
-
- /* 1 ist the root node of the method */
- /* 0 is the artificial parent, where locals are set to their parameters */
- dom_DFS(gd, dd, -1, 0, &N
-#ifdef DOM_DEBUG_CHECK
- ,basicblockcount
-#endif
- );
-
- for(i = N-1; i > 0; i--) {
- _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
- n = dd->vertex[i];
- _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
- p = dd->parent[n];
- s = p;
- j = graph_get_first_predecessor(gd, n, &iter);
- for (; j != -1; j = graph_get_next(&iter)) {
- _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
- if (dd->dfnum[j] <= dd->dfnum[n])
- s_ = j;
- else
- s_ = dd->semi[dom_AncestorWithLowestSemi(dd, j
-#ifdef DOM_DEBUG_CHECK
- ,basicblockcount
-#endif
- )];
- _DOM_CHECK_BOUNDS(s_, 0, basicblockcount);
- _DOM_CHECK_BOUNDS(s, 0, basicblockcount);
- if (dd->dfnum[s_] < dd->dfnum[s])
- s = s_;
- }
- dd->semi[n] = s;
- _DOM_CHECK_BOUNDS(dd->num_bucket[s], 0, basicblockcount);
- dd->bucket[s][dd->num_bucket[s]] = n;
- dd->num_bucket[s]++;
- dom_Link(dd, p, n
-#ifdef DOM_DEBUG_CHECK
- , basicblockcount
-#endif
- );
- _DOM_CHECK_BOUNDS(p, 0, basicblockcount);
- for(j = 0; j < dd->num_bucket[p]; j++) {
- _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
- v = dd->bucket[p][j];
- y = dom_AncestorWithLowestSemi(dd, v
-#ifdef DOM_DEBUG_CHECK
- , basicblockcount
-#endif
- );
- _DOM_CHECK_BOUNDS(y, 0, basicblockcount);
- _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
- if (dd->semi[y] == dd->semi[v])
- dd->idom[v] = p;
- else
- dd->samedom[v] = y;
- }
- dd->num_bucket[p] = 0;
- }
- for(i = 1; i < N; i++) {
- n = dd->vertex[i];
- _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
- if (dd->samedom[n] != -1) {
- _DOM_CHECK_BOUNDS(dd->samedom[n], 0, basicblockcount);
- dd->idom[n] = dd->idom[dd->samedom[n]];
- }
- }
- return dd;
-}
-
-/********************************************
-compute Dominace Frontier
-********************************************/
-void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n) {
- int c,i,j;
- bool *_S;
- graphiterator iter;
-
- _S = DMNEW(bool, basicblockcount);
- for(i = 0; i < basicblockcount; i++)
- _S[i] = false;
- i = graph_get_first_successor(gd, n, &iter);
- for (; i != -1; i = graph_get_next(&iter)) {
- _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
- if (dd->idom[i] != n)
- _S[i] = true;
- }
- for(c=0; c < basicblockcount; c++) {
- if (dd->idom[c] == n) {
- computeDF(gd, dd, basicblockcount, c);
- for(j=0; j < dd->num_DF[c]; j++) {
- _DOM_CHECK_BOUNDS(dd->DF[c][j], 0, basicblockcount);
- if (n != dd->idom[dd->DF[c][j]])
- /* n does not dominate DF[c][j] -> traverse idom list? */
- _S[dd->DF[c][j]] = true;
- }
- }
- }
- for(i = 0; i < basicblockcount; i++)
- if (_S[i]) {
- _DOM_CHECK_BOUNDS(dd->num_DF[n], 0, basicblockcount);
- dd->DF[n][dd->num_DF[n]] = i;
- dd->num_DF[n]++;
- }
-}
-
-
-void dom_Dominators_init(dominatordata *dd, int basicblockcount) {
- int i;
-
- dd->dfnum = DMNEW(int, basicblockcount);
- dd->vertex = DMNEW(int, basicblockcount);
- dd->parent = DMNEW(int, basicblockcount);
- dd->semi = DMNEW(int, basicblockcount);
- dd->ancestor = DMNEW(int, basicblockcount);
- dd->idom = DMNEW(int, basicblockcount);
- dd->samedom = DMNEW(int, basicblockcount);
- dd->bucket = DMNEW(int*, basicblockcount);
- dd->num_bucket = DMNEW(int, basicblockcount);
- dd->DF = DMNEW(int*, basicblockcount);
- dd->num_DF = DMNEW(int, basicblockcount);
- dd->best = DMNEW(int, basicblockcount);
- for (i=0; i < basicblockcount; i++) {
- dd->dfnum[i] = -1;
- dd->semi[i] = dd->ancestor[i] = dd->idom[i] = dd->samedom[i] = -1;
- dd->num_bucket[i] = 0;
- dd->bucket[i] = DMNEW(int, basicblockcount);
- dd->num_DF[i] = 0;
- dd->DF[i] = DMNEW(int, basicblockcount);
- }
-}
-
-/**************************************
-Create Depth First Spanning Tree
-**************************************/
-#ifdef DOM_DEBUG_CHECK
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
- int basicblockcount) {
-#else
-void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N) {
-#endif
- int i;
- graphiterator iter;
-
- _DOM_CHECK_BOUNDS(n,0,basicblockcount);
- if (dd->dfnum[n] == -1) { /* not visited till now? */
- dd->dfnum[n] = *N;
- _DOM_CHECK_BOUNDS(*N,0,basicblockcount);
- dd->vertex[*N] = n;
- dd->parent[n] = p;
- (*N)++;
- i = graph_get_first_successor(gd, n, &iter);
- for (; i != -1; i = graph_get_next(&iter)) {
- dom_DFS(gd, dd, n, i, N
-#ifdef DOM_DEBUG_CHECK
- , basicblockcount
-#endif
- );
- }
- }
-}
-
-#ifdef DOM_DEBUG_CHECK
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount) {
-#else
-int dom_AncestorWithLowestSemi(dominatordata *dd, int v) {
-#endif
- int a,b;
-
- _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
- a = dd->ancestor[v];
- _DOM_CHECK_BOUNDS(a,0,basicblockcount);
- if (dd->ancestor[a] != -1) {
- b = dom_AncestorWithLowestSemi(dd, a
-#ifdef DOM_DEBUG_CHECK
- , basicblockcount
-#endif
- );
- dd->ancestor[v] = dd->ancestor[a];
- _DOM_CHECK_BOUNDS(b,0,basicblockcount);
- _DOM_CHECK_BOUNDS(dd->best[v],0,basicblockcount);
- _DOM_CHECK_BOUNDS(dd->semi[dd->best[v]],0,basicblockcount);
- if (dd->dfnum[dd->semi[b]] < dd->dfnum[dd->semi[dd->best[v]]])
- dd->best[v] = b;
- }
- return dd->best[v];
-}
-
-#ifdef DOM_DEBUG_CHECK
-void dom_Link(dominatordata *dd, int p, int n, int basicblockcount) {
-#else
-void dom_Link(dominatordata *dd, int p, int n) {
-#endif
- _DOM_CHECK_BOUNDS(n,0,basicblockcount);
- dd->ancestor[n] = p;
- dd->best[n] = n;
-}
-
-/*********************************************************/
-
-typedef struct basicblock_info basicblock_info;
-
-struct basicblock_info {
- basicblock *bb;
- int dfnum;
- basicblock_info *parent;
- basicblock_info *semi;
- basicblock_info *ancestor;
- basicblock_info *best;
- basicblock_info *idom;
- basicblock_info *samedom;
- basicblock_info **bucket;
- unsigned bucketcount;
-};
-
-typedef struct dominator_tree_info dominator_tree_info;
-
-struct dominator_tree_info {
- jitdata *jd;
- basicblock_info *basicblocks;
- basicblock_info **df_map;
- unsigned df_counter;
-};
-
-static dominator_tree_info *dominator_tree_init(jitdata *jd) {
- dominator_tree_info *di;
- basicblock *itb;
- basicblock_info *iti;
-
- di = DNEW(dominator_tree_info);
-
- di->jd = jd;
-
- di->basicblocks = DMNEW(basicblock_info, jd->basicblockcount);
- MZERO(di->basicblocks, basicblock_info, jd->basicblockcount);
-
- for (iti = di->basicblocks; iti != di->basicblocks + jd->basicblockcount; ++iti) {
- iti->dfnum = -1;
- iti->bucket = DMNEW(basicblock_info *, jd->basicblockcount);
- iti->bucketcount = 0;
- }
-
- for (itb = jd->basicblocks; itb; itb = itb->next) {
- di->basicblocks[itb->nr].bb = itb;
- }
-
- di->df_map = DMNEW(basicblock_info *, jd->basicblockcount);
- MZERO(di->df_map, basicblock_info *, jd->basicblockcount);
-
- di->df_counter = 0;
-
- return di;
-}
-
-inline basicblock_info *dominator_tree_get_basicblock(dominator_tree_info *di, basicblock *bb) {
- return di->basicblocks + bb->nr;
-}
-
-static void dominator_tree_depth_first_search(
- dominator_tree_info *di, basicblock_info *parent, basicblock_info *node
-) {
- basicblock **it;
-
- if (node->dfnum == -1) {
-
- node->dfnum = di->df_counter;
- node->parent = parent;
- di->df_map[di->df_counter] = node;
- di->df_counter += 1;
-
- for (it = node->bb->successors; it != node->bb->successors + node->bb->successorcount; ++it) {
- dominator_tree_depth_first_search(
- di, node,
- dominator_tree_get_basicblock(di, *it)
- );
- }
- }
-}
-
-void dominator_tree_link(dominator_tree_info *di, basicblock_info *parent, basicblock_info *node) {
- node->ancestor = parent;
- node->best = node;
-}
-
-basicblock_info *dominator_tree_ancestor_with_lowest_semi(
- dominator_tree_info *di, basicblock_info *node
-) {
- basicblock_info *a, *b;
-
- a = node->ancestor;
-
- if (a->ancestor != NULL) {
- b = dominator_tree_ancestor_with_lowest_semi(di, a);
- node->ancestor = a->ancestor;
- if (b->semi->dfnum < node->best->semi->dfnum) {
- node->best = b;
- }
- }
-
- return node->best;
-}
-
-void dominator_tree_build_intern(jitdata *jd) {
-
- dominator_tree_info *di;
- basicblock_info *node;
- basicblock_info *semicand;
- basicblock_info *pred;
- basicblock **itb;
- basicblock_info **itii;
- basicblock_info *v, *y;
- int i;
-
- di = dominator_tree_init(jd);
-
- dominator_tree_depth_first_search(di, NULL, dominator_tree_get_basicblock(di, jd->basicblocks));
-
- for (i = di->df_counter - 1; i >= 1; --i) {
- node = di->df_map[i];
-
- node->semi = node->parent;
-
- for (
- itb = node->bb->predecessors;
- itb != node->bb->predecessors + node->bb->predecessorcount;
- ++itb
- ) {
-
- pred = dominator_tree_get_basicblock(di, *itb);
-
- if (pred->dfnum <= node->dfnum) {
- semicand = pred;
- } else {
- semicand = dominator_tree_ancestor_with_lowest_semi(di, pred)->semi;
- }
-
- if (semicand->dfnum < node->semi->dfnum) {
- node->semi = semicand;
- }
- }
-
- node->semi->bucket[node->semi->bucketcount] = node;
- node->semi->bucketcount += 1;
-
- dominator_tree_link(di, node->parent, node);
-
- for (itii = node->parent->bucket; itii != node->parent->bucket + node->parent->bucketcount; ++itii) {
- v = *itii;
- y = dominator_tree_ancestor_with_lowest_semi(di, v);
- if (y->semi == v->semi) {
- v->idom = node->parent;
- } else {
- v->samedom = y;
- }
- }
-
- node->parent->bucketcount = 0;
- }
-
- for (i = 1; i < di->df_counter; ++i) {
- node = di->df_map[i];
- if (node->samedom) {
- node->idom = node->samedom->idom;
- }
-
- node->bb->idom = node->idom->bb;
- node->idom->bb->domsuccessorcount += 1;
- }
-}
-
-void dominator_tree_link_children(jitdata *jd) {
- basicblock *bb;
- int32_t ds;
- /* basicblock number => current number of successors */
- unsigned *numsuccessors;
-
- /* Allocate memory for successors */
-
- for (bb = jd->basicblocks; bb; bb = bb->next) {
- if (bb->domsuccessorcount > 0) {
- bb->domsuccessors = DMNEW(basicblock *, bb->domsuccessorcount);
- }
- }
-
- /* Allocate memory for per basic block counter of successors */
-
- ds = dumpmemory_marker();
- numsuccessors = DMNEW(unsigned, jd->basicblockcount);
- MZERO(numsuccessors, unsigned, jd->basicblockcount);
-
- /* Link immediate dominators with successors */
-
- for (bb = jd->basicblocks; bb; bb = bb->next) {
- if (bb->idom) {
- bb->idom->domsuccessors[numsuccessors[bb->idom->nr]] = bb;
- numsuccessors[bb->idom->nr] += 1;
- }
- }
-
- /* Free memory */
-
- dumpmemory_release(ds);
-}
-
-bool dominator_tree_build(jitdata *jd) {
- int32_t ds;
-
- ds = dumpmemory_marker();
- dominator_tree_build_intern(jd);
- dumpmemory_release(ds);
-
- dominator_tree_link_children(jd);
-
- return true;
-}
-
-typedef struct dominance_frontier_item dominance_frontier_item;
-
-struct dominance_frontier_item {
- basicblock *bb;
- dominance_frontier_item *next;
-};
-
-typedef struct dominance_frontier_list dominance_frontier_list;
-
-struct dominance_frontier_list {
- dominance_frontier_item *first;
- unsigned count;
-};
-
-void dominance_frontier_list_add(dominance_frontier_list *list, basicblock *bb) {
- dominance_frontier_item *item;
-
- for (item = list->first; item; item = item->next) {
- if (item->bb == bb) return;
- }
-
- item = DNEW(dominance_frontier_item);
- item->bb = bb;
- item->next = list->first;
- list->first = item;
- list->count += 1;
-}
-
-typedef struct dominance_frontier_info dominance_frontier_info;
-
-struct dominance_frontier_info {
- jitdata *jd;
- dominance_frontier_list *map;
-};
-
-dominance_frontier_info *dominance_frontier_init(jitdata *jd) {
- dominance_frontier_info *dfi = DNEW(dominance_frontier_info);
-
- dfi->jd = jd;
-
- dfi->map = DMNEW(dominance_frontier_list, jd->basicblockcount);
- MZERO(dfi->map, dominance_frontier_list, jd->basicblockcount);
-
- return dfi;
-}
-
-bool dominance_frontier_dominates(basicblock *d, basicblock *x) {
- x = x->idom;
-
- while (x != NULL) {
- if (x == d) {
- return true;
- }
- x = x->idom;
- }
-
- return false;
-}
-
-void dominance_frontier_for_block(dominance_frontier_info *dfi, basicblock *b) {
- basicblock **it;
- dominance_frontier_item *itdf;
- dominance_frontier_list s = { NULL, 0 };
-
- for (it = b->successors; it != b->successors + b->successorcount; ++it) {
- if ((*it)->idom != b) {
- dominance_frontier_list_add(&s, *it);
- }
- }
-
- for (it = b->domsuccessors; it != b->domsuccessors + b->domsuccessorcount; ++it) {
- dominance_frontier_for_block(dfi, *it);
- for (itdf = dfi->map[(*it)->nr].first; itdf; itdf = itdf->next) {
- if (! dominance_frontier_dominates(b, itdf->bb)) {
- dominance_frontier_list_add(&s, itdf->bb);
- }
- }
- }
-
- dfi->map[b->nr] = s;
-}
-
-void dominance_frontier_store(dominance_frontier_info *dfi) {
- basicblock *bb;
- dominance_frontier_item *itdf;
- basicblock **itout;
-
- for (bb = dfi->jd->basicblocks; bb; bb = bb->next) {
- if (bb->nr < dfi->jd->basicblockcount) {
- if (dfi->map[bb->nr].count > 0) {
- bb->domfrontiercount = dfi->map[bb->nr].count;
- itout = bb->domfrontier = DMNEW(basicblock *, bb->domfrontiercount);
- for (itdf = dfi->map[bb->nr].first; itdf; itdf = itdf->next) {
- *itout = itdf->bb;
- itout += 1;
- }
- }
- }
- }
-}
-
-bool dominance_frontier_build(jitdata *jd) {
- int32_t ds = dumpmemory_marker();
-
- dominance_frontier_info *dfi = dominance_frontier_init(jd);
- dominance_frontier_for_block(dfi, jd->basicblocks);
- dominance_frontier_store(dfi);
-}
-
-#include "vm/jit/show.h"
-#include "vm/jit/python.h"
-
-extern void graph_add_edge( graphdata *gd, int from, int to );
-
-void dominator_tree_validate(jitdata *jd, dominatordata *_dd) {
- int32_t ds = dumpmemory_marker();
- graphdata *gd;
- int i, j;
- basicblock *bptr, **it;
- dominatordata *dd;
- int *itnr;
- bool found;
-
- fprintf(stderr, "%s/%s: \n", jd->m->clazz->name->text, jd->m->name->text);
- gd = graph_init(jd->basicblockcount);
-
- for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
- for (it = bptr->successors; it != bptr->successors + bptr->successorcount; ++it) {
- graph_add_edge(gd, bptr->nr, (*it)->nr);
- }
- }
-
- dd = compute_Dominators(gd, jd->basicblockcount);
-
- for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
- if (bptr->flags >= BBREACHED) {
- if (bptr->idom == NULL) {
- if (!(dd->idom[bptr->nr] == -1)) {
- printf("-- %d %d\n", dd->idom[bptr->nr], bptr->nr);
- assert(0);
- }
- } else {
- assert(dd->idom[bptr->nr] == bptr->idom->nr);
- }
- }
- }
-
- computeDF(gd, dd, jd->basicblockcount, 0);
-
- for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
- if (bptr->flags >= BBREACHED) {
- assert(bptr->domfrontiercount == dd->num_DF[bptr->nr]);
- for (itnr = dd->DF[bptr->nr]; itnr != dd->DF[bptr->nr] + dd->num_DF[bptr->nr]; ++itnr) {
- found = false;
- for (it = bptr->domfrontier; it != bptr->domfrontier + bptr->domfrontiercount; ++it) {
- if ((*it)->nr == *itnr) {
- found =true; break;
- }
- }
- assert(found);
- }
- }
- }
-
- dumpmemory_release(ds);
-}
-
-/*
- * These 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/optimizing/dominators.cpp - dominators and dominance frontier
+
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+*/
+
+
+#include "config.h"
+
+#include "config.h"
+
+#include "mm/memory.h"
+
+#include "toolbox/bitvector.h"
+
+#include "vm/jit/jit.hpp"
+
+#include "vm/jit/optimizing/graph.h"
+#include "vm/jit/optimizing/dominators.hpp"
+
+
+/* function prototypes */
+void dom_Dominators_init(dominatordata *dd, int basicblockcount);
+#ifdef DOM_DEBUG_CHECK
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount);
+void dom_Link(dominatordata *dd, int p, int n, int basicblockcount);
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
+ int basicblockcount);
+#else
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v);
+void dom_Link(dominatordata *dd, int p, int n);
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N);
+#endif
+
+/*************************************
+Calculate Dominators
+*************************************/
+dominatordata *compute_Dominators(graphdata *gd, int basicblockcount) {
+ int i,j,n,N,p,s,s_,v,y;
+ graphiterator iter;
+ dominatordata *dd;
+
+ dd = (dominatordata*) DumpMemory::allocate(sizeof(dominatordata));
+
+ dom_Dominators_init(dd, basicblockcount);
+
+ N=0;
+
+ /* 1 ist the root node of the method */
+ /* 0 is the artificial parent, where locals are set to their parameters */
+ dom_DFS(gd, dd, -1, 0, &N
+#ifdef DOM_DEBUG_CHECK
+ ,basicblockcount
+#endif
+ );
+
+ for(i = N-1; i > 0; i--) {
+ _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
+ n = dd->vertex[i];
+ _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
+ p = dd->parent[n];
+ s = p;
+ j = graph_get_first_predecessor(gd, n, &iter);
+ for (; j != -1; j = graph_get_next(&iter)) {
+ _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
+ if (dd->dfnum[j] <= dd->dfnum[n])
+ s_ = j;
+ else
+ s_ = dd->semi[dom_AncestorWithLowestSemi(dd, j
+#ifdef DOM_DEBUG_CHECK
+ ,basicblockcount
+#endif
+ )];
+ _DOM_CHECK_BOUNDS(s_, 0, basicblockcount);
+ _DOM_CHECK_BOUNDS(s, 0, basicblockcount);
+ if (dd->dfnum[s_] < dd->dfnum[s])
+ s = s_;
+ }
+ dd->semi[n] = s;
+ _DOM_CHECK_BOUNDS(dd->num_bucket[s], 0, basicblockcount);
+ dd->bucket[s][dd->num_bucket[s]] = n;
+ dd->num_bucket[s]++;
+ dom_Link(dd, p, n
+#ifdef DOM_DEBUG_CHECK
+ , basicblockcount
+#endif
+ );
+ _DOM_CHECK_BOUNDS(p, 0, basicblockcount);
+ for(j = 0; j < dd->num_bucket[p]; j++) {
+ _DOM_CHECK_BOUNDS(j, 0, basicblockcount);
+ v = dd->bucket[p][j];
+ y = dom_AncestorWithLowestSemi(dd, v
+#ifdef DOM_DEBUG_CHECK
+ , basicblockcount
+#endif
+ );
+ _DOM_CHECK_BOUNDS(y, 0, basicblockcount);
+ _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
+ if (dd->semi[y] == dd->semi[v])
+ dd->idom[v] = p;
+ else
+ dd->samedom[v] = y;
+ }
+ dd->num_bucket[p] = 0;
+ }
+ for(i = 1; i < N; i++) {
+ n = dd->vertex[i];
+ _DOM_CHECK_BOUNDS(n, 0, basicblockcount);
+ if (dd->samedom[n] != -1) {
+ _DOM_CHECK_BOUNDS(dd->samedom[n], 0, basicblockcount);
+ dd->idom[n] = dd->idom[dd->samedom[n]];
+ }
+ }
+ return dd;
+}
+
+/********************************************
+compute Dominace Frontier
+********************************************/
+void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n) {
+ int c,i,j;
+ bool *_S;
+ graphiterator iter;
+
+ _S = (bool*) DumpMemory::allocate(sizeof(bool) * basicblockcount);
+ for(i = 0; i < basicblockcount; i++)
+ _S[i] = false;
+ i = graph_get_first_successor(gd, n, &iter);
+ for (; i != -1; i = graph_get_next(&iter)) {
+ _DOM_CHECK_BOUNDS(i, 0, basicblockcount);
+ if (dd->idom[i] != n)
+ _S[i] = true;
+ }
+ for(c=0; c < basicblockcount; c++) {
+ if (dd->idom[c] == n) {
+ computeDF(gd, dd, basicblockcount, c);
+ for(j=0; j < dd->num_DF[c]; j++) {
+ _DOM_CHECK_BOUNDS(dd->DF[c][j], 0, basicblockcount);
+ if (n != dd->idom[dd->DF[c][j]])
+ /* n does not dominate DF[c][j] -> traverse idom list? */
+ _S[dd->DF[c][j]] = true;
+ }
+ }
+ }
+ for(i = 0; i < basicblockcount; i++)
+ if (_S[i]) {
+ _DOM_CHECK_BOUNDS(dd->num_DF[n], 0, basicblockcount);
+ dd->DF[n][dd->num_DF[n]] = i;
+ dd->num_DF[n]++;
+ }
+}
+
+
+void dom_Dominators_init(dominatordata *dd, int basicblockcount) {
+ int i;
+
+ dd->dfnum = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->vertex = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->parent = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->semi = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->ancestor = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->idom = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->samedom = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->bucket = (int**) DumpMemory::allocate(sizeof(int*) * basicblockcount);
+ dd->num_bucket = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->DF = (int**) DumpMemory::allocate(sizeof(int*) * basicblockcount);
+ dd->num_DF = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->best = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ for (i=0; i < basicblockcount; i++) {
+ dd->dfnum[i] = -1;
+ dd->semi[i] = dd->ancestor[i] = dd->idom[i] = dd->samedom[i] = -1;
+ dd->num_bucket[i] = 0;
+ dd->bucket[i] = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ dd->num_DF[i] = 0;
+ dd->DF[i] = (int*) DumpMemory::allocate(sizeof(int) * basicblockcount);
+ }
+}
+
+/**************************************
+Create Depth First Spanning Tree
+**************************************/
+#ifdef DOM_DEBUG_CHECK
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N,
+ int basicblockcount) {
+#else
+void dom_DFS(graphdata *gd, dominatordata *dd, int p, int n, int *N) {
+#endif
+ int i;
+ graphiterator iter;
+
+ _DOM_CHECK_BOUNDS(n,0,basicblockcount);
+ if (dd->dfnum[n] == -1) { /* not visited till now? */
+ dd->dfnum[n] = *N;
+ _DOM_CHECK_BOUNDS(*N,0,basicblockcount);
+ dd->vertex[*N] = n;
+ dd->parent[n] = p;
+ (*N)++;
+ i = graph_get_first_successor(gd, n, &iter);
+ for (; i != -1; i = graph_get_next(&iter)) {
+ dom_DFS(gd, dd, n, i, N
+#ifdef DOM_DEBUG_CHECK
+ , basicblockcount
+#endif
+ );
+ }
+ }
+}
+
+#ifdef DOM_DEBUG_CHECK
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v, int basicblockcount) {
+#else
+int dom_AncestorWithLowestSemi(dominatordata *dd, int v) {
+#endif
+ int a,b;
+
+ _DOM_CHECK_BOUNDS(v, 0, basicblockcount);
+ a = dd->ancestor[v];
+ _DOM_CHECK_BOUNDS(a,0,basicblockcount);
+ if (dd->ancestor[a] != -1) {
+ b = dom_AncestorWithLowestSemi(dd, a
+#ifdef DOM_DEBUG_CHECK
+ , basicblockcount
+#endif
+ );
+ dd->ancestor[v] = dd->ancestor[a];
+ _DOM_CHECK_BOUNDS(b,0,basicblockcount);
+ _DOM_CHECK_BOUNDS(dd->best[v],0,basicblockcount);
+ _DOM_CHECK_BOUNDS(dd->semi[dd->best[v]],0,basicblockcount);
+ if (dd->dfnum[dd->semi[b]] < dd->dfnum[dd->semi[dd->best[v]]])
+ dd->best[v] = b;
+ }
+ return dd->best[v];
+}
+
+#ifdef DOM_DEBUG_CHECK
+void dom_Link(dominatordata *dd, int p, int n, int basicblockcount) {
+#else
+void dom_Link(dominatordata *dd, int p, int n) {
+#endif
+ _DOM_CHECK_BOUNDS(n,0,basicblockcount);
+ dd->ancestor[n] = p;
+ dd->best[n] = n;
+}
+
+/*********************************************************/
+
+typedef struct basicblock_info basicblock_info;
+
+struct basicblock_info {
+ basicblock *bb;
+ int dfnum;
+ basicblock_info *parent;
+ basicblock_info *semi;
+ basicblock_info *ancestor;
+ basicblock_info *best;
+ basicblock_info *idom;
+ basicblock_info *samedom;
+ basicblock_info **bucket;
+ unsigned bucketcount;
+};
+
+typedef struct dominator_tree_info dominator_tree_info;
+
+struct dominator_tree_info {
+ jitdata *jd;
+ basicblock_info *basicblocks;
+ basicblock_info **df_map;
+ unsigned df_counter;
+};
+
+static dominator_tree_info *dominator_tree_init(jitdata *jd) {
+ dominator_tree_info *di;
+ basicblock *itb;
+ basicblock_info *iti;
+
+ di = (dominator_tree_info*) DumpMemory::allocate(sizeof(dominator_tree_info));
+
+ di->jd = jd;
+
+ di->basicblocks = (basicblock_info*) DumpMemory::allocate(sizeof(basicblock_info) * jd->basicblockcount);
+ MZERO(di->basicblocks, basicblock_info, jd->basicblockcount);
+
+ for (iti = di->basicblocks; iti != di->basicblocks + jd->basicblockcount; ++iti) {
+ iti->dfnum = -1;
+ iti->bucket = (basicblock_info**) DumpMemory::allocate(sizeof(basicblock_info*) * jd->basicblockcount);
+ iti->bucketcount = 0;
+ }
+
+ for (itb = jd->basicblocks; itb; itb = itb->next) {
+ di->basicblocks[itb->nr].bb = itb;
+ }
+
+ di->df_map = (basicblock_info**) DumpMemory::allocate(sizeof(basicblock_info*) * jd->basicblockcount);
+ MZERO(di->df_map, basicblock_info *, jd->basicblockcount);
+
+ di->df_counter = 0;
+
+ return di;
+}
+
+static inline basicblock_info *dominator_tree_get_basicblock(dominator_tree_info *di, basicblock *bb) {
+ return di->basicblocks + bb->nr;
+}
+
+static void dominator_tree_depth_first_search(
+ dominator_tree_info *di, basicblock_info *parent, basicblock_info *node
+) {
+ basicblock **it;
+
+ if (node->dfnum == -1) {
+
+ node->dfnum = di->df_counter;
+ node->parent = parent;
+ di->df_map[di->df_counter] = node;
+ di->df_counter += 1;
+
+ for (it = node->bb->successors; it != node->bb->successors + node->bb->successorcount; ++it) {
+ dominator_tree_depth_first_search(
+ di, node,
+ dominator_tree_get_basicblock(di, *it)
+ );
+ }
+ }
+}
+
+void dominator_tree_link(dominator_tree_info *di, basicblock_info *parent, basicblock_info *node) {
+ node->ancestor = parent;
+ node->best = node;
+}
+
+basicblock_info *dominator_tree_ancestor_with_lowest_semi(
+ dominator_tree_info *di, basicblock_info *node
+) {
+ basicblock_info *a, *b;
+
+ a = node->ancestor;
+
+ if (a->ancestor != NULL) {
+ b = dominator_tree_ancestor_with_lowest_semi(di, a);
+ node->ancestor = a->ancestor;
+ if (b->semi->dfnum < node->best->semi->dfnum) {
+ node->best = b;
+ }
+ }
+
+ return node->best;
+}
+
+void dominator_tree_build_intern(jitdata *jd) {
+
+ dominator_tree_info *di;
+ basicblock_info *node;
+ basicblock_info *semicand;
+ basicblock_info *pred;
+ basicblock **itb;
+ basicblock_info **itii;
+ basicblock_info *v, *y;
+ int i;
+
+ di = dominator_tree_init(jd);
+
+ dominator_tree_depth_first_search(di, NULL, dominator_tree_get_basicblock(di, jd->basicblocks));
+
+ for (i = di->df_counter - 1; i >= 1; --i) {
+ node = di->df_map[i];
+
+ node->semi = node->parent;
+
+ for (
+ itb = node->bb->predecessors;
+ itb != node->bb->predecessors + node->bb->predecessorcount;
+ ++itb
+ ) {
+
+ pred = dominator_tree_get_basicblock(di, *itb);
+
+ if (pred->dfnum <= node->dfnum) {
+ semicand = pred;
+ } else {
+ semicand = dominator_tree_ancestor_with_lowest_semi(di, pred)->semi;
+ }
+
+ if (semicand->dfnum < node->semi->dfnum) {
+ node->semi = semicand;
+ }
+ }
+
+ node->semi->bucket[node->semi->bucketcount] = node;
+ node->semi->bucketcount += 1;
+
+ dominator_tree_link(di, node->parent, node);
+
+ for (itii = node->parent->bucket; itii != node->parent->bucket + node->parent->bucketcount; ++itii) {
+ v = *itii;
+ y = dominator_tree_ancestor_with_lowest_semi(di, v);
+ if (y->semi == v->semi) {
+ v->idom = node->parent;
+ } else {
+ v->samedom = y;
+ }
+ }
+
+ node->parent->bucketcount = 0;
+ }
+
+ for (i = 1; i < di->df_counter; ++i) {
+ node = di->df_map[i];
+ if (node->samedom) {
+ node->idom = node->samedom->idom;
+ }
+
+ node->bb->idom = node->idom->bb;
+ node->idom->bb->domsuccessorcount += 1;
+ }
+}
+
+void dominator_tree_link_children(jitdata *jd) {
+ basicblock *bb;
+ /* basicblock number => current number of successors */
+ unsigned *numsuccessors;
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* Allocate memory for successors */
+
+ for (bb = jd->basicblocks; bb; bb = bb->next) {
+ if (bb->domsuccessorcount > 0) {
+ bb->domsuccessors = (basicblock**) DumpMemory::allocate(sizeof(basicblock*) * bb->domsuccessorcount);
+ }
+ }
+
+ /* Allocate memory for per basic block counter of successors */
+
+ numsuccessors = (unsigned*) DumpMemory::allocate(sizeof(unsigned) * jd->basicblockcount);
+ MZERO(numsuccessors, unsigned, jd->basicblockcount);
+
+ /* Link immediate dominators with successors */
+
+ for (bb = jd->basicblocks; bb; bb = bb->next) {
+ if (bb->idom) {
+ bb->idom->domsuccessors[numsuccessors[bb->idom->nr]] = bb;
+ numsuccessors[bb->idom->nr] += 1;
+ }
+ }
+}
+
+bool dominator_tree_build(jitdata *jd) {
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ dominator_tree_build_intern(jd);
+
+ dominator_tree_link_children(jd);
+
+ return true;
+}
+
+typedef struct dominance_frontier_item dominance_frontier_item;
+
+struct dominance_frontier_item {
+ basicblock *bb;
+ dominance_frontier_item *next;
+};
+
+typedef struct dominance_frontier_list dominance_frontier_list;
+
+struct dominance_frontier_list {
+ dominance_frontier_item *first;
+ unsigned count;
+};
+
+void dominance_frontier_list_add(dominance_frontier_list *list, basicblock *bb) {
+ dominance_frontier_item *item;
+
+ for (item = list->first; item; item = item->next) {
+ if (item->bb == bb) return;
+ }
+
+ item = (dominance_frontier_item*) DumpMemory::allocate(sizeof(dominance_frontier_item));
+ item->bb = bb;
+ item->next = list->first;
+ list->first = item;
+ list->count += 1;
+}
+
+typedef struct dominance_frontier_info dominance_frontier_info;
+
+struct dominance_frontier_info {
+ jitdata *jd;
+ dominance_frontier_list *map;
+};
+
+dominance_frontier_info *dominance_frontier_init(jitdata *jd) {
+ dominance_frontier_info *dfi = (dominance_frontier_info*) DumpMemory::allocate(sizeof(dominance_frontier_info));
+
+ dfi->jd = jd;
+
+ dfi->map = (dominance_frontier_list*) DumpMemory::allocate(sizeof(dominance_frontier_list) * jd->basicblockcount);
+ MZERO(dfi->map, dominance_frontier_list, jd->basicblockcount);
+
+ return dfi;
+}
+
+bool dominance_frontier_dominates(basicblock *d, basicblock *x) {
+ x = x->idom;
+
+ while (x != NULL) {
+ if (x == d) {
+ return true;
+ }
+ x = x->idom;
+ }
+
+ return false;
+}
+
+void dominance_frontier_for_block(dominance_frontier_info *dfi, basicblock *b) {
+ basicblock **it;
+ dominance_frontier_item *itdf;
+ dominance_frontier_list s = { NULL, 0 };
+
+ for (it = b->successors; it != b->successors + b->successorcount; ++it) {
+ if ((*it)->idom != b) {
+ dominance_frontier_list_add(&s, *it);
+ }
+ }
+
+ for (it = b->domsuccessors; it != b->domsuccessors + b->domsuccessorcount; ++it) {
+ dominance_frontier_for_block(dfi, *it);
+ for (itdf = dfi->map[(*it)->nr].first; itdf; itdf = itdf->next) {
+ if (! dominance_frontier_dominates(b, itdf->bb)) {
+ dominance_frontier_list_add(&s, itdf->bb);
+ }
+ }
+ }
+
+ dfi->map[b->nr] = s;
+}
+
+void dominance_frontier_store(dominance_frontier_info *dfi) {
+ basicblock *bb;
+ dominance_frontier_item *itdf;
+ basicblock **itout;
+
+ for (bb = dfi->jd->basicblocks; bb; bb = bb->next) {
+ if (bb->nr < dfi->jd->basicblockcount) {
+ if (dfi->map[bb->nr].count > 0) {
+ bb->domfrontiercount = dfi->map[bb->nr].count;
+ itout = bb->domfrontier = (basicblock**) DumpMemory::allocate(sizeof(basicblock*) * bb->domfrontiercount);
+ for (itdf = dfi->map[bb->nr].first; itdf; itdf = itdf->next) {
+ *itout = itdf->bb;
+ itout += 1;
+ }
+ }
+ }
+ }
+}
+
+bool dominance_frontier_build(jitdata *jd) {
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ dominance_frontier_info *dfi = dominance_frontier_init(jd);
+ dominance_frontier_for_block(dfi, jd->basicblocks);
+ dominance_frontier_store(dfi);
+}
+
+#include "vm/jit/show.hpp"
+#include "vm/jit/python.h"
+
+extern "C" void graph_add_edge( graphdata *gd, int from, int to );
+
+void dominator_tree_validate(jitdata *jd, dominatordata *_dd) {
+ graphdata *gd;
+ int i, j;
+ basicblock *bptr, **it;
+ dominatordata *dd;
+ int *itnr;
+ bool found;
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ fprintf(stderr, "%s/%s: \n", jd->m->clazz->name->text, jd->m->name->text);
+ gd = graph_init(jd->basicblockcount);
+
+ for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+ for (it = bptr->successors; it != bptr->successors + bptr->successorcount; ++it) {
+ graph_add_edge(gd, bptr->nr, (*it)->nr);
+ }
+ }
+
+ dd = compute_Dominators(gd, jd->basicblockcount);
+
+ for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+ if (bptr->flags >= BBREACHED) {
+ if (bptr->idom == NULL) {
+ if (!(dd->idom[bptr->nr] == -1)) {
+ printf("-- %d %d\n", dd->idom[bptr->nr], bptr->nr);
+ assert(0);
+ }
+ } else {
+ assert(dd->idom[bptr->nr] == bptr->idom->nr);
+ }
+ }
+ }
+
+ computeDF(gd, dd, jd->basicblockcount, 0);
+
+ for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+ if (bptr->flags >= BBREACHED) {
+ assert(bptr->domfrontiercount == dd->num_DF[bptr->nr]);
+ for (itnr = dd->DF[bptr->nr]; itnr != dd->DF[bptr->nr] + dd->num_DF[bptr->nr]; ++itnr) {
+ found = false;
+ for (it = bptr->domfrontier; it != bptr->domfrontier + bptr->domfrontiercount; ++it) {
+ if ((*it)->nr == *itnr) {
+ found =true; break;
+ }
+ }
+ assert(found);
+ }
+ }
+ }
+}
+
+
+/*
+ * These 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/optimizing/dominators.h - Dominators and Dominance Frontier header
-
- 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
-
- 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., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Christian Ullrich
-
-
-*/
-
-
-#ifndef _DOMINATORS_H
-#define _DOMINATORS_H
-
-#include "vm/jit/optimizing/graph.h"
-
-#if !defined(NDEBUG)
-# include <assert.h>
-/* # define DOM_DEBUG_CHECK */
-# define DOM_DEBUG_VERBOSE
-#endif
-
-#ifdef DOM_DEBUG_CHECK
-# define _DOM_CHECK_BOUNDS(i,l,h) assert( ((i) >= (l)) && ((i) < (h)));
-# define _DOM_ASSERT(a) assert((a));
-#else
-# define _DOM_CHECK_BOUNDS(i,l,h)
-# define _DOM_ASSERT(a)
-#endif
-
-struct dominatordata {
- int *dfnum; /* [0..ls->basicblockcount[ */
- int *vertex; /* [0..ls->basicblockcount[ */
- int *parent; /* [0..ls->basicblockcount[ */
- int *semi; /* [0..ls->basicblockcount[ */
- int *ancestor; /* [0..ls->basicblockcount[ */
- int *idom; /* [0..ls->basicblockcount[ */
- int *samedom; /* [0..ls->basicblockcount[ */
- int **bucket; /* [0..ls->basicblockcount[[0..ls->bbc[ */
- int *num_bucket; /* [0..ls->basicblockcount[ */
- int *best; /* [0..ls->basicblockcount[ */
- int **DF; /* [0..ls->basicblockcount[[0..ls->bbc[ */
- int *num_DF; /* [0..ls->basicblockcount[ */
-};
-
-typedef struct dominatordata dominatordata;
-
-/* function prototypes */
-dominatordata *compute_Dominators(graphdata *gd, int basicblockcount);
-void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n);
-
-/* ............................... */
-
-bool dominator_tree_build(jitdata *jd);
-
-bool dominance_frontier_build(jitdata *jd);
-
-void dominator_tree_validate(jitdata *jd, dominatordata *dd);
-
-#endif /* _DOMINATORS_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/optimizing/dominators.hpp - Dominators and Dominance Frontier header
+
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+*/
+
+
+#ifndef _DOMINATORS_HPP
+#define _DOMINATORS_HPP
+
+#include "config.h"
+
+#include "vm/jit/optimizing/graph.h"
+
+#if !defined(NDEBUG)
+# include <assert.h>
+/* # define DOM_DEBUG_CHECK */
+# define DOM_DEBUG_VERBOSE
+#endif
+
+#ifdef DOM_DEBUG_CHECK
+# define _DOM_CHECK_BOUNDS(i,l,h) assert( ((i) >= (l)) && ((i) < (h)));
+# define _DOM_ASSERT(a) assert((a));
+#else
+# define _DOM_CHECK_BOUNDS(i,l,h)
+# define _DOM_ASSERT(a)
+#endif
+
+struct dominatordata {
+ int *dfnum; /* [0..ls->basicblockcount[ */
+ int *vertex; /* [0..ls->basicblockcount[ */
+ int *parent; /* [0..ls->basicblockcount[ */
+ int *semi; /* [0..ls->basicblockcount[ */
+ int *ancestor; /* [0..ls->basicblockcount[ */
+ int *idom; /* [0..ls->basicblockcount[ */
+ int *samedom; /* [0..ls->basicblockcount[ */
+ int **bucket; /* [0..ls->basicblockcount[[0..ls->bbc[ */
+ int *num_bucket; /* [0..ls->basicblockcount[ */
+ int *best; /* [0..ls->basicblockcount[ */
+ int **DF; /* [0..ls->basicblockcount[[0..ls->bbc[ */
+ int *num_DF; /* [0..ls->basicblockcount[ */
+};
+
+typedef struct dominatordata dominatordata;
+
+/* function prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+dominatordata *compute_Dominators(graphdata *gd, int basicblockcount);
+void computeDF(graphdata *gd, dominatordata *dd, int basicblockcount, int n);
+
+/* ............................... */
+
+bool dominator_tree_build(jitdata *jd);
+
+bool dominance_frontier_build(jitdata *jd);
+
+void dominator_tree_validate(jitdata *jd, dominatordata *dd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _DOMINATORS_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 "vm/class.h"
#include "vm/classcache.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/optimizing/escape.h"
#include <stdarg.h>
#ifndef _VM_JIT_OPTIMIZING_ESCAPE_H
#define _VM_JIT_OPTIMIZING_ESCAPE_H
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/method.h"
typedef enum {
#include "toolbox/bitvector.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/optimizing/lsra.h"
#include "vm/jit/optimizing/ssa.h"
/* src/vm/jit/optimizing/graph.h - control flow graph header
- 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
-
-
*/
#ifndef _LSRA_GRAPH_H
#define _LSRA_GRAPH_H
+#include "config.h"
+
#include "vm/jit/optimizing/lsra.h"
#if !defined(NDEBUG)
typedef graph_element *graphiterator;
/* function prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void transform_BB(jitdata *, graphdata *gd);
graphdata *graph_init(int basicblockcount);
/* Generate the CFG */
bool graph_has_multiple_successors( graphdata *gd, int b_index);
bool graph_has_multiple_predecessors( graphdata *gd, int b_index);
+#ifdef __cplusplus
+}
+#endif
#endif /* _LSRA_GRAPH_H */
#include "vm/method.h"
#include "vm/vm.hpp"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
/* patterns for a total number of 3 instructions ******************************/
#define _IFCONV_H
#include "config.h"
-#include "vm/types.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/reg.h"
+#include <stdbool.h>
+
+#include "vm/jit/jit.hpp"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool ifconv_static(jitdata *jd);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _IFCONV_H */
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/resolve.h"
#include "vm/exceptions.hpp"
#include "vm/string.hpp"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/optimizing/graph.h"
#include "vm/jit/optimizing/lsra.h"
#ifndef _LIFETIMES_H
#define _LIFETIMES_H
-#include "vm/jit/optimizing/dominators.h"
+#include "config.h"
+
+#include "vm/jit/optimizing/dominators.hpp"
#if !defined(NDEBUG)
# include <assert.h>
#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/optimizing/graph.h"
#include "vm/jit/optimizing/lifetimes.h"
struct lifetime *lt;
struct freemem *fmem;
int lt_index;
-#ifdef HAS_4BYTE_STACKSLOT
- struct freemem *fmem_2;
-#endif
methodinfo *m;
registerdata *rd;
lsradata *ls;
fmem=DNEW(struct freemem);
fmem->off=-1;
fmem->next=NULL;
-#ifdef HAS_4BYTE_STACKSLOT
- fmem_2=DNEW(struct freemem);
- fmem_2->off=-1;
- fmem_2->next=NULL;
-#endif
for (lt_index = 0; lt_index < lifetimecount; lt_index ++) {
lt = ls->lifetime + lifet[lt_index];
#endif
if (lt->regoff == -1) {
flags = INMEMORY;
-#ifdef HAS_4BYTE_STACKSLOT
- if (IS_2_WORD_TYPE(lt->type))
- regoff = lsra_getmem(lt, fmem_2, mem_use);
- else
-#endif
regoff = lsra_getmem(lt, fmem, mem_use);
} else {
flags = lt->savedvar;
/* no memmory allocated till now, or all other are still live */
if ((fmem->next == NULL) || (fmem->next->end > lt->i_start)) {
/* if (1) { */
-#ifdef HAS_4BYTE_STACKSLOT
- if (IS_2_WORD_TYPE(lt->type))
- if ( (*mem_use)&1 ) /* align memory location for 2 Word Types */
- (*mem_use)++;
fm=lsra_getnewmem(mem_use);
- if (IS_2_WORD_TYPE(lt->type))
- /* allocate a second following Slot for 2 Word Types */
- (*mem_use)++;
-#else
- fm=lsra_getnewmem(mem_use);
-#endif
} else {
/* Speicherstelle frei */
fm=fmem->next;
switch (lt->type) {
case TYPE_LNG:
-#if (defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)) || defined (__I386__)
+#if defined (__I386__)
flags = 0;
#else
flags = 1;
#include "mm/memory.h"
-#include "threads/threadlist.h"
+#include "threads/threadlist.hpp"
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#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/jit.hpp"
#include "vm/jit/methodheader.h"
#include "vm/jit/methodtree.h"
-#include "vm/jit/optimizing/recompile.h"
+#include "vm/jit/optimizing/recompiler.hpp"
/* profile_init ****************************************************************
threads_sleep(0, nanos);
runs++;
- /* lock the threads lists */
-
- threadlist_lock();
+ // Lock the thread lists.
+ ThreadList_lock();
/* iterate over all started threads */
- for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ for (t = ThreadList_first(); t != NULL; t = ThreadList_next(t)) {
/* is this a Java thread? */
if (!(t->flags & THREAD_FLAG_JAVA))
/* add this method to the method list and
start recompilation */
- recompile_queue_method(m);
+ Recompiler_queue_method(m);
}
}
}
}
}
- /* unlock the threads lists */
-
- threadlist_unlock();
+ // Unlock the thread lists.
+ ThreadList_unlock();
}
}
#endif
#if !defined(NDEBUG)
void profile_printstats(void)
{
- list_t *l;
- list_method_entry *lme;
- list_method_entry *tlme;
classinfo *c;
methodinfo *m;
codeinfo *code;
cycles = 0;
/* create new method list */
-
- l = list_create(OFFSET(list_method_entry, linkage));
+ // TODO Use a sorted container.
+ List* l = List_new();
/* iterate through all classes and methods */
frequency += code->frequency;
cycles += code->cycles;
- /* create new list entry */
-
- lme = NEW(list_method_entry);
- lme->m = m;
-
/* sort the new entry into the list */
- if ((tlme = list_first(l)) == NULL) {
- list_add_first(l, lme);
+ if (List_empty(l) == NULL) {
+ List_push_back(l, m);
}
else {
for (; tlme != NULL; tlme = list_next(l, tlme)) {
+++ /dev/null
-/* src/vm/jit/optimizing/recompile.c - recompilation 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 <stdlib.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-#include "threads/thread.hpp"
-
-#include "toolbox/list.h"
-
-#include "vm/builtin.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"
-
-
-/* global variables ***********************************************************/
-
-static java_object_t *lock_thread_recompile;
-static list_t *list_recompile_methods;
-
-
-/* recompile_init **************************************************************
-
- Initializes the recompilation system.
-
-*******************************************************************************/
-
-bool recompile_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("recompile_init");
-
- /* initialize the recompile lock object */
-
- lock_thread_recompile = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(lock_thread_recompile);
-
- /* create method list */
-
- list_recompile_methods = list_create(OFFSET(list_method_entry, linkage));
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* recompile_replace_vftbl *****************************************************
-
- XXX
-
-*******************************************************************************/
-
-static void recompile_replace_vftbl(methodinfo *m)
-{
- codeinfo *code;
- codeinfo *pcode;
- u4 slot;
- classcache_name_entry *nmen;
- classcache_class_entry *clsen;
- classinfo *c;
- vftbl_t *vftbl;
- s4 i;
-
- /* get current and previous codeinfo structure */
-
- code = m->code;
- pcode = code->prev;
-
- assert(pcode);
-
- /* iterate over 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;
-
- /* Search for entrypoint of the previous codeinfo in
- the vftbl and replace it with the current one. */
-
- vftbl = c->vftbl;
-
- /* Is the class linked? Means, is the vftbl finished? */
-
- if (!(c->state & CLASS_LINKED))
- continue;
-
- /* Does the class have a vftbl? Some internal classes
- (e.g. $NEW$) are linked, but do not have a
- vftbl. */
-
- if (vftbl == NULL)
- continue;
-
- for (i = 0; i < vftbl->vftbllength; i++) {
- if (vftbl->table[i] == pcode->entrypoint) {
-#if !defined(NDEBUG)
- printf("replacing vftbl in: ");
- class_println(c);
-#endif
- vftbl->table[i] = code->entrypoint;
- }
- }
- }
- }
- }
-}
-
-
-/* recompile_thread ************************************************************
-
- XXX
-
-*******************************************************************************/
-
-static void recompile_thread(void)
-{
- list_method_entry *lme;
-
- while (true) {
- /* get the lock on the recompile lock object, so we can call wait */
-
- LOCK_MONITOR_ENTER(lock_thread_recompile);
-
- /* wait forever on that object till we are signaled */
-
- LOCK_WAIT_FOREVER(lock_thread_recompile);
-
- /* leave the lock */
-
- LOCK_MONITOR_EXIT(lock_thread_recompile);
-
- /* get the next method and recompile it */
-
- while ((lme = list_first(list_recompile_methods)) != NULL) {
- /* recompile this method */
-
- if (jit_recompile(lme->m) != NULL) {
- /* replace in vftbl's */
-
- recompile_replace_vftbl(lme->m);
- }
- else {
- /* XXX what is the right-thing(tm) to do here? */
-
- exceptions_print_current_exception();
- }
-
- /* remove the compiled method */
-
- list_remove(list_recompile_methods, lme);
-
- /* free the entry */
-
- FREE(lme, list_method_entry);
- }
- }
-}
-
-
-/* recompile_start_thread ******************************************************
-
- Starts the recompilation thread.
-
-*******************************************************************************/
-
-bool recompile_start_thread(void)
-{
- utf *name;
-
- name = utf_new_char("Recompiler");
-
- if (!threads_thread_start_internal(name, recompile_thread))
- return false;
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* recompile_queue_method ******************************************************
-
- Adds a method to the recompilation list and signal the
- recompilation thread that there is some work to do.
-
-*******************************************************************************/
-
-void recompile_queue_method(methodinfo *m)
-{
- list_method_entry *lme;
-
- /* create a method entry */
-
- lme = NEW(list_method_entry);
- lme->m = m;
-
- /* and add it to the list */
-
- list_add_last(list_recompile_methods, lme);
-
- /* get the lock on the recompile lock object, so we can call notify */
-
- LOCK_MONITOR_ENTER(lock_thread_recompile);
-
- /* signal the recompiler thread */
-
- LOCK_NOTIFY(lock_thread_recompile);
-
- /* leave the lock */
-
- LOCK_MONITOR_EXIT(lock_thread_recompile);
-}
-
-
-/*
- * These 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/optimizing/recompile.h - recompilation 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.
-
-*/
-
-
-#ifndef _RECOMPILE_H
-#define _RECOMPILE_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* list_method_entry **********************************************************/
-
-typedef struct list_method_entry list_method_entry;
-
-struct list_method_entry {
- methodinfo *m;
- listnode_t linkage;
-};
-
-
-/* function prototypes ********************************************************/
-
-bool recompile_init(void);
-bool recompile_start_thread(void);
-
-void recompile_queue_method(methodinfo *m);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RECOMPILE_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/optimizing/recompiler.cpp - recompilation 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 "mm/memory.h"
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+#include "threads/thread.hpp"
+
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/jit/code.hpp"
+#include "vm/jit/jit.hpp"
+
+#include "vm/jit/optimizing/recompiler.hpp"
+
+
+/**
+ * Stop the worker thread.
+ */
+Recompiler::~Recompiler()
+{
+ // Set the running flag to false.
+ _run = false;
+
+ // Now signal the worker thread.
+ _cond.signal();
+
+ // TODO We should wait here until the thread exits.
+}
+
+
+/* recompile_replace_vftbl *****************************************************
+
+ XXX
+
+*******************************************************************************/
+
+static void recompile_replace_vftbl(methodinfo *m)
+{
+ codeinfo *code;
+ codeinfo *pcode;
+ u4 slot;
+ classcache_name_entry *nmen;
+ classcache_class_entry *clsen;
+ classinfo *c;
+ vftbl_t *vftbl;
+ s4 i;
+
+ /* get current and previous codeinfo structure */
+
+ code = m->code;
+ pcode = code->prev;
+
+ assert(pcode);
+
+ /* iterate over 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;
+
+ /* Search for entrypoint of the previous codeinfo in
+ the vftbl and replace it with the current one. */
+
+ vftbl = c->vftbl;
+
+ /* Is the class linked? Means, is the vftbl finished? */
+
+ if (!(c->state & CLASS_LINKED))
+ continue;
+
+ /* Does the class have a vftbl? Some internal classes
+ (e.g. $NEW$) are linked, but do not have a
+ vftbl. */
+
+ if (vftbl == NULL)
+ continue;
+
+ for (i = 0; i < vftbl->vftbllength; i++) {
+ if (vftbl->table[i] == pcode->entrypoint) {
+#if !defined(NDEBUG)
+ printf("replacing vftbl in: ");
+ class_println(c);
+#endif
+ vftbl->table[i] = code->entrypoint;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/**
+ * The actual recompilation thread.
+ */
+void Recompiler::thread()
+{
+ // FIXME This just works for one recompiler.
+ Recompiler& r = VM::get_current()->get_recompiler();
+
+ while (r._run == true) {
+ // Enter the recompile mutex, so we can call wait.
+ r._mutex.lock();
+
+ // Wait forever on that condition until we are signaled.
+ r._cond.wait(r._mutex);
+
+ // Leave the mutex.
+ r._mutex.unlock();
+
+ // FIXME Move this into the for loop.
+ if (r._run == false)
+ break;
+
+ // Sanity check.
+ assert(r._methods.empty() == false);
+
+ // Get the next method form the queue and recompile it.
+ while (r._methods.empty() == false) {
+ methodinfo* m = r._methods.front();
+
+ // Recompile this method.
+ if (jit_recompile(m) != NULL) {
+ // Replace in vftbl's.
+ recompile_replace_vftbl(m);
+ }
+ else {
+ // XXX What is the right-thing(tm) to do here?
+ exceptions_print_current_exception();
+ }
+
+ // Remove the method from the queue.
+ r._methods.pop();
+ }
+ }
+}
+
+
+/**
+ * Start the recompilation thread.
+ *
+ * @return true on success, false otherwise.
+ */
+bool Recompiler::start()
+{
+ utf *name = utf_new_char("Recompiler");
+
+ if (!threads_thread_start_internal(name, (functionptr) &Recompiler::thread))
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Add a method to the recompilation queue and signal the
+ * recompilation thread that there is some work to do.
+ *
+ * @param m Method to recompile.
+ */
+void Recompiler::queue_method(methodinfo *m)
+{
+ // Add the method to the queue.
+ _methods.push(m);
+
+ // Enter the recompile mutex, so we can call notify.
+ _mutex.lock();
+
+ // Signal the recompiler thread.
+ _cond.signal();
+
+ // Leave the mutex.
+ _mutex.unlock();
+}
+
+
+
+// Legacy C interface.
+extern "C" {
+ void Recompiler_queue_method(methodinfo* m) { VM::get_current()->get_recompiler().queue_method(m); }
+}
+
+/*
+ * These 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/optimizing/recompiler.hpp - recompilation 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.
+
+*/
+
+
+#ifndef _RECOMPILER_HPP
+#define _RECOMPILER_HPP
+
+#include "config.h"
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+#include <queue>
+#endif
+
+#include "threads/condition.hpp"
+#include "threads/mutex.hpp"
+
+#include "vm/method.h"
+
+
+#ifdef __cplusplus
+
+/**
+ * Thread for JIT recompilations.
+ */
+class Recompiler {
+private:
+ Mutex _mutex;
+ Condition _cond;
+ std::queue<methodinfo*> _methods;
+ bool _run; ///< Flag to stop worker thread.
+
+ static void thread(); ///< Worker thread.
+
+public:
+ Recompiler() : _run(true) {}
+ ~Recompiler();
+
+ bool start(); ///< Start the worker thread.
+ void queue_method(methodinfo* m); ///< Queue a method for recompilation.
+};
+
+#endif
+
+/* list_method_entry **********************************************************/
+
+typedef struct list_method_entry list_method_entry;
+
+struct list_method_entry {
+ methodinfo *m;
+/* listnode_t linkage; */
+};
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void Recompiler_queue_method(methodinfo *m);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _RECOMPILER_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 "vm/types.h"
#include "mm/memory.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* reorder_place_next_unplaced_block *******************************************
-/* src/vm/reorder.h - basic block reordering
+/* src/vm/optimizing/reorder.h - basic block reordering
- 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,
- 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.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#define _REORDER_H
#include "config.h"
-#include "vm/types.h"
-#include "vm/jit/jit.h"
+#include <stdbool.h>
+
+#include "vm/jit/jit.hpp"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool reorder(jitdata *jd);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _REORDER_H */
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
-#include "vm/jit/jit.h" /* icmd_table */
+#include "vm/jit/jit.hpp" /* icmd_table */
#include "vm/jit/ir/bytecode.h"
-#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/dominators.hpp"
#include "vm/jit/optimizing/graph.h"
#include "vm/jit/optimizing/lifetimes.h"
#include "vm/jit/optimizing/lsra.h"
/* src/vm/jit/optimizing/ssa.h - static single assignment form header
- 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, 2006, 2007, 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
This file is part of CACAO.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Christian Ullrich
-
- $Id: ssa.h$
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
*/
#ifndef _SSA_H
#define _SSA_H
+#include "config.h"
+
#include "vm/jit/optimizing/graph.h"
#if !defined(NDEBUG)
#endif
/* function prototypes */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void ssa_init(jitdata *);
void ssa(jitdata */* , graphdata **/);
+void fix_exception_handlers(jitdata *jd);
+
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _SSA_H */
/*
#include "toolbox/worklist.h"
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#if 1
#define printf(...) do { if (getenv("VERB")) printf(__VA_ARGS__); } while (0)
* Unify access to phi args.
*/
-#include "vm/jit/jit.h"
+
+#include "config.h"
+
+#include "vm/jit/jit.hpp"
#include "vm/global.h"
#include "mm/memory.h"
-#include "mm/dumpmemory.h"
-#include "toolbox/list.h"
+#include "mm/dumpmemory.hpp"
+#include "toolbox/list.hpp"
#include <limits.h>
#include <stdio.h>
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
-#include "vm/jit/jit.h" /* icmd_table */
+#include "vm/jit/jit.hpp" /* icmd_table */
-#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/dominators.hpp"
#include "vm/jit/optimizing/graph.h"
#include "vm/jit/optimizing/lifetimes.h"
#include "vm/jit/optimizing/lsra.h"
#include "toolbox/bitvector.h"
#include "toolbox/worklist.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
-#include "vm/jit/jit.h" /* icmd_table */
+#include "vm/jit/jit.hpp" /* icmd_table */
-#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/dominators.hpp"
#include "vm/jit/optimizing/graph.h"
#include "vm/jit/optimizing/lifetimes.h"
#include "vm/jit/optimizing/lsra.h"
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
/* #define USEBUILTINTABLE */
#define SUPPORT_DIVISION 0
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/resolve.h"
#endif
#include "vm/string.hpp"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/loop/loop.h"
case BC_f2i:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_f2i);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_f2i);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
case BC_f2l:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_f2l);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_f2l);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
case BC_d2i:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_d2i);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_d2i);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
case BC_d2l:
#if defined(__ALPHA__)
- if (!opt_noieee) {
- bte = builtintable_get_internal(BUILTIN_d2l);
- OP_BUILTIN_NO_EXCEPTION(bte);
- }
- else
+ bte = builtintable_get_internal(BUILTIN_d2l);
+ OP_BUILTIN_NO_EXCEPTION(bte);
+#else
+ OP(opcode);
#endif
- {
- OP(opcode);
- }
break;
/* src/vm/jit/parse.h - parser 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
-
- Author: Christian Thalinger
- Edwin Steiner
-
*/
#include "vm/types.h"
#include "vm/global.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
/* macros for verifier checks during parsing **********************************/
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool parse(jitdata *jd);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _PARSE_H */
+++ /dev/null
-/* src/vm/jit/patcher-common.c - architecture independent code patching stuff
-
- 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 "codegen.h" /* for PATCHER_NOPS */
-#include "md.h"
-
-#include "mm/memory.h"
-
-#include "native/native.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/list.h"
-#include "toolbox/logging.h" /* XXX remove me! */
-
-#include "vm/exceptions.hpp"
-#include "vm/initialize.h"
-#include "vm/options.h"
-#include "vm/resolve.h"
-#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"
-
-
-/* patcher_function_list *******************************************************
-
- This is a list which maps patcher function pointers to the according
- names of the patcher functions. It is only usefull for debugging
- purposes.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-typedef struct patcher_function_list_t {
- functionptr patcher;
- char *name;
-} patcher_function_list_t;
-
-static patcher_function_list_t patcher_function_list[] = {
- { PATCHER_initialize_class, "initialize_class" },
- { PATCHER_resolve_class, "resolve_class" },
- { PATCHER_resolve_native_function, "resolve_native_function" },
- { PATCHER_invokestatic_special, "invokestatic_special" },
- { PATCHER_invokevirtual, "invokevirtual" },
- { PATCHER_invokeinterface, "invokeinterface" },
- { NULL, "-UNKNOWN PATCHER FUNCTION-" }
-};
-#endif
-
-
-/* patcher_list_create *********************************************************
-
- Creates an empty patcher list for the given codeinfo.
-
-*******************************************************************************/
-
-void patcher_list_create(codeinfo *code)
-{
- code->patchers = list_create(OFFSET(patchref_t, linkage));
-}
-
-
-/* patcher_list_reset **********************************************************
-
- Resets the patcher list inside a codeinfo. This is usefull when
- resetting a codeinfo for recompiling.
-
-*******************************************************************************/
-
-void patcher_list_reset(codeinfo *code)
-{
- patchref_t *pr;
-
- /* free all elements of the list */
-
- while((pr = list_first(code->patchers)) != NULL) {
- list_remove(code->patchers, pr);
-
- FREE(pr, patchref_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_patchref -= sizeof(patchref_t);
-#endif
- }
-}
-
-/* patcher_list_free ***********************************************************
-
- Frees the patcher list and all its entries for the given codeinfo.
-
-*******************************************************************************/
-
-void patcher_list_free(codeinfo *code)
-{
- /* free all elements of the list */
-
- patcher_list_reset(code);
-
- /* free the list itself */
-
- FREE(code->patchers, list_t);
-}
-
-
-/* patcher_list_find ***********************************************************
-
- Find an entry inside the patcher list for the given codeinfo
- by specifying the program counter of the patcher position.
-
- NOTE: Caller should hold the patcher list lock or maintain
- exclusive access otherwise.
-
-*******************************************************************************/
-
-static patchref_t *patcher_list_find(codeinfo *code, u1 *pc)
-{
- patchref_t *pr;
-
- /* walk through all patcher references for the given codeinfo */
-
- pr = list_first(code->patchers);
-
- while (pr) {
-
-/*#define TRACE_PATCHER_FIND*/
-#ifdef TRACE_PATCHER_FIND
- log_println("patcher_list_find: %p == %p", pr->mpc, pc);
-#endif
-
- if (pr->mpc == (ptrint) pc)
- return pr;
-
- pr = list_next(code->patchers, pr);
- }
-
- return NULL;
-}
-
-
-/* patcher_add_patch_ref *******************************************************
-
- Appends a new patcher reference to the list of patching positions.
-
-*******************************************************************************/
-
-void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
-{
- codegendata *cd;
- codeinfo *code;
- patchref_t *pr;
- s4 patchmpc;
-
- cd = jd->cd;
- code = jd->code;
- patchmpc = cd->mcodeptr - cd->mcodebase;
-
-#if !defined(NDEBUG)
- if (patcher_list_find(code, (u1 *) (intptr_t) patchmpc) != NULL)
- vm_abort("patcher_add_patch_ref: different patchers at same position.");
-#endif
-
- /* allocate patchref on heap (at least freed together with codeinfo) */
-
- pr = NEW(patchref_t);
- list_add_first(code->patchers, pr);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_patchref += sizeof(patchref_t);
-#endif
-
- /* set patcher information (mpc is resolved later) */
-
- pr->mpc = patchmpc;
- pr->disp = disp;
- pr->patcher = patcher;
- pr->ref = ref;
- pr->mcode = 0;
- pr->done = false;
-
-#if defined(ENABLE_JITCACHE)
- pr->attached_ref = NULL;
-#endif
-
- /* Generate NOPs for opt_shownops. */
-
- if (opt_shownops)
- PATCHER_NOPS;
-
-#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
-
- /* XXX We can remove that when we don't use UD2 anymore on i386
- and x86_64. */
-
- /* On some architectures the patcher stub call instruction might
- be longer than the actual instruction generated. On this
- architectures we store the last patcher call position and after
- the basic block code generation is completed, we check the
- range and maybe generate some nop's. */
- /* The nops are generated in codegen_emit in each codegen */
-
- cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
-#endif
-}
-
-
-/**
- * Resolve all patchers in the current JIT run.
- *
- * @param jd JIT data-structure
- */
-void patcher_resolve(jitdata* jd)
-{
- codeinfo* code;
- patchref_t* pr;
-
- /* Get required compiler data. */
-
- code = jd->code;
-
- for (pr = list_first(code->patchers); pr != NULL; pr = list_next(code->patchers, pr)) {
- pr->mpc += (intptr_t) code->entrypoint;
- pr->datap = (intptr_t) (pr->disp + code->entrypoint);
- }
-}
-
-
-/* patcher_handler *************************************************************
-
- Handles the request to patch JIT code at the given patching
- position. This function is normally called by the signal
- handler.
-
- NOTE: The patcher list lock is used to maintain exclusive
- access of the patched position (in fact of the whole code).
- After patching has suceeded, the patcher reference should be
- removed from the patcher list to avoid double patching.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-/* XXX this indent is not thread safe! */
-/* XXX if you want it thread safe, place patcher_depth in threadobject! */
-static int patcher_depth = 0;
-#define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
-#endif /* !defined(NDEBUG) */
-
-java_handle_t *patcher_handler(u1 *pc)
-{
- codeinfo *code;
- patchref_t *pr;
- bool result;
- java_handle_t *e;
-#if !defined(NDEBUG)
- patcher_function_list_t *l;
- int i;
-#endif
-
- /* define the patcher function */
-
- bool (*patcher_function)(patchref_t *);
-
- /* search the codeinfo for the given PC */
-
- code = code_find_codeinfo_for_pc(pc);
- assert(code);
-
- /* enter a monitor on the patcher list */
-
- LOCK_MONITOR_ENTER(code->patchers);
-
- /* search the patcher information for the given PC */
-
- pr = patcher_list_find(code, pc);
-
- if (pr == NULL)
- vm_abort("patcher_handler: Unable to find patcher reference.");
-
- if (pr->done) {
-#if !defined(NDEBUG)
- if (opt_DebugPatcher) {
- log_println("patcher_handler: double-patching detected!");
- }
-#endif
- LOCK_MONITOR_EXIT(code->patchers);
- return NULL;
- }
-
-#if !defined(NDEBUG)
- if (opt_DebugPatcher) {
- for (l = patcher_function_list; l->patcher != NULL; l++)
- if (l->patcher == pr->patcher)
- break;
-
- TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
- TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
-
- TRACE_PATCHER_INDENT;
- printf("\tmachine code before = ");
-
-# if defined(ENABLE_DISASSEMBLER)
- disassinstr((void *) pr->mpc);
-# else
- printf("disassembler disabled\n");
-# endif
-
- patcher_depth++;
- assert(patcher_depth > 0);
- }
-#endif
-
- /* cast the passed function to a patcher function */
-
- patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
-
- /* call the proper patcher function */
-
- result = (patcher_function)(pr);
-
-#if !defined(NDEBUG)
- if (opt_DebugPatcher) {
- assert(patcher_depth > 0);
- patcher_depth--;
-
- TRACE_PATCHER_INDENT;
- printf("\tmachine code after = ");
-
-# if defined(ENABLE_DISASSEMBLER)
- disassinstr((void *) pr->mpc);
-# else
- printf("disassembler disabled\n");
-# endif
-
- if (result == false) {
- TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
- }
- }
-#endif
-
-#if defined(ENABLE_JITCACHE)
- /* Put cached reference into the code and remove it from the patcher */
- if (pr->attached_ref)
- {
- jitcache_handle_cached_ref(pr->attached_ref, code);
- pr->attached_ref = NULL;
- }
-#endif
-
- /* check for return value and exit accordingly */
-
- if (result == false) {
- e = exceptions_get_and_clear_exception();
-
- LOCK_MONITOR_EXIT(code->patchers);
-
- return e;
- }
-
- pr->done = true; /* XXX this is only preliminary to prevent double-patching */
-
- LOCK_MONITOR_EXIT(code->patchers);
-
- return NULL;
-}
-
-
-/* patcher_initialize_class ****************************************************
-
- Initalizes a given classinfo pointer.
- This function does not patch any data.
-
-*******************************************************************************/
-
-bool patcher_initialize_class(patchref_t *pr)
-{
- classinfo *c;
-
- /* get stuff from the patcher reference */
-
- c = (classinfo *) pr->ref;
-
- /* check if the class is initialized */
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return false;
-
- /* patch back original code */
-
- patcher_patch_code(pr);
-
- return true;
-}
-
-
-/* patcher_resolve_class *******************************************************
-
- Resolves a given unresolved class reference.
- This function does not patch any data.
-
-*******************************************************************************/
-
-#ifdef ENABLE_VERIFIER
-bool patcher_resolve_class(patchref_t *pr)
-{
- unresolved_class *uc;
-
- /* get stuff from the patcher reference */
-
- uc = (unresolved_class *) pr->ref;
-
- /* resolve the class and check subtype constraints */
-
- if (!resolve_class_eager_no_access_check(uc))
- return false;
-
- /* patch back original code */
-
- patcher_patch_code(pr);
-
- return true;
-}
-#endif /* ENABLE_VERIFIER */
-
-
-/* patcher_resolve_native_function *********************************************
-
- Resolves the native function for a given methodinfo.
- This function patches one data segment word.
-
-*******************************************************************************/
-
-bool patcher_resolve_native_function(patchref_t *pr)
-{
- methodinfo *m;
- uint8_t *datap;
- functionptr f;
-
- /* get stuff from the patcher reference */
-
- m = (methodinfo *) pr->ref;
- datap = (uint8_t *) pr->datap;
-
- /* resolve native function */
-
- if (!(f = native_method_resolve(m)))
- return false;
-
- /* patch native function pointer */
-
- *((intptr_t *) datap) = (intptr_t) f;
-
- /* synchronize data cache */
-
- md_dcacheflush(datap, SIZEOF_VOID_P);
-
- /* patch back original code */
-
- patcher_patch_code(pr);
-
- return true;
-}
-
-/** Placeholder functions to calm down linker */
-#if defined(__I386__)
-bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
-{
- return true;
-}
-
-bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
-{
- return true;
-}
-
-bool patcher_resolve_classref_to_index(patchref_t *pr)
-{
- return true;
-}
-
-bool patcher_resolve_classref_to_flags(patchref_t *pr)
-{
- return true;
-}
-#endif
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * 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/patcher-common.cpp - architecture independent code patching stuff
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ 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 <assert.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <functional>
+
+#include "codegen.h" /* for PATCHER_NOPS */
+#include "md.h"
+
+#include "mm/memory.h"
+
+#include "native/native.hpp"
+
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h" /* XXX remove me! */
+
+#include "vm/exceptions.hpp"
+#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
+#include "vm/vm.hpp" /* for vm_abort */
+
+#include "vm/jit/code.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+
+
+/* patcher_function_list *******************************************************
+
+ This is a list which maps patcher function pointers to the according
+ names of the patcher functions. It is only usefull for debugging
+ purposes.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+typedef struct patcher_function_list_t {
+ functionptr patcher;
+ const char* name;
+} patcher_function_list_t;
+
+static patcher_function_list_t patcher_function_list[] = {
+ { PATCHER_initialize_class, "initialize_class" },
+ { PATCHER_resolve_class, "resolve_class" },
+ { PATCHER_resolve_native_function, "resolve_native_function" },
+ { PATCHER_invokestatic_special, "invokestatic_special" },
+ { PATCHER_invokevirtual, "invokevirtual" },
+ { PATCHER_invokeinterface, "invokeinterface" },
+ { NULL, "-UNKNOWN PATCHER FUNCTION-" }
+};
+#endif
+
+
+/* patcher_list_create *********************************************************
+
+ Creates an empty patcher list for the given codeinfo.
+
+*******************************************************************************/
+
+void patcher_list_create(codeinfo *code)
+{
+ code->patchers = new List<patchref_t>();
+}
+
+
+/* patcher_list_reset **********************************************************
+
+ Resets the patcher list inside a codeinfo. This is usefull when
+ resetting a codeinfo for recompiling.
+
+*******************************************************************************/
+
+void patcher_list_reset(codeinfo *code)
+{
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_patchref -= sizeof(patchref_t) * code->patchers->size();
+#endif
+
+ // Free all elements of the list.
+ code->patchers->clear();
+}
+
+/* patcher_list_free ***********************************************************
+
+ Frees the patcher list and all its entries for the given codeinfo.
+
+*******************************************************************************/
+
+void patcher_list_free(codeinfo *code)
+{
+ // Free all elements of the list.
+ patcher_list_reset(code);
+
+ // Free the list itself.
+ delete code->patchers;
+}
+
+
+/**
+ * Find an entry inside the patcher list for the given codeinfo by
+ * specifying the program counter of the patcher position.
+ *
+ * NOTE: Caller should hold the patcher list lock or maintain
+ * exclusive access otherwise.
+ *
+ * @param pc Program counter to find.
+ *
+ * @return Pointer to patcher.
+ */
+
+struct foo : public std::binary_function<patchref_t, void*, bool> {
+ bool operator() (const patchref_t& pr, const void* pc) const
+ {
+ return (pr.mpc == (uintptr_t) pc);
+ }
+};
+
+static patchref_t* patcher_list_find(codeinfo* code, void* pc)
+{
+ // Search for a patcher with the given PC.
+ List<patchref_t>::iterator it = std::find_if(code->patchers->begin(), code->patchers->end(), std::bind2nd(foo(), pc));
+
+ if (it == code->patchers->end())
+ return NULL;
+
+ return &(*it);
+}
+
+
+/* patcher_add_patch_ref *******************************************************
+
+ Appends a new patcher reference to the list of patching positions.
+
+*******************************************************************************/
+
+void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp)
+{
+ codegendata *cd;
+ codeinfo *code;
+ s4 patchmpc;
+
+ cd = jd->cd;
+ code = jd->code;
+ patchmpc = cd->mcodeptr - cd->mcodebase;
+
+#if !defined(NDEBUG)
+ if (patcher_list_find(code, (void*) (intptr_t) patchmpc) != NULL)
+ vm_abort("patcher_add_patch_ref: different patchers at same position.");
+#endif
+
+ // Set patcher information (mpc is resolved later).
+ patchref_t pr;
+
+ pr.mpc = patchmpc;
+ pr.datap = 0;
+ pr.disp = disp;
+ pr.patcher = patcher;
+ pr.ref = ref;
+ pr.mcode = 0;
+ pr.done = false;
+
+#if defined(ENABLE_JITCACHE)
+ pr.attached_ref = NULL;
+#endif
+
+ // Store patcher in the list (NOTE: structure is copied).
+ code->patchers->push_back(pr);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_patchref += sizeof(patchref_t);
+#endif
+
+#if defined(ENABLE_JIT) && (defined(__I386__) || defined(__M68K__) || defined(__SPARC_64__) || defined(__X86_64__))
+
+ /* XXX We can remove that when we don't use UD2 anymore on i386
+ and x86_64. */
+
+ /* On some architectures the patcher stub call instruction might
+ be longer than the actual instruction generated. On this
+ architectures we store the last patcher call position and after
+ the basic block code generation is completed, we check the
+ range and maybe generate some nop's. */
+ /* The nops are generated in codegen_emit in each codegen */
+
+ cd->lastmcodeptr = cd->mcodeptr + PATCHER_CALL_SIZE;
+#endif
+}
+
+
+/**
+ * Resolve all patchers in the current JIT run.
+ *
+ * @param jd JIT data-structure
+ */
+void patcher_resolve(jitdata* jd)
+{
+ // Get required compiler data.
+ codeinfo* code = jd->code;
+
+ for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
+ patchref_t& pr = *it;
+
+ pr.mpc += (intptr_t) code->entrypoint;
+ pr.datap = (intptr_t) (pr.disp + code->entrypoint);
+ }
+}
+
+
+/**
+ * Check if the patcher is already patched. This is done by comparing
+ * the machine instruction.
+ *
+ * @param pr Patcher structure.
+ *
+ * @return true if patched, false otherwise.
+ */
+bool patcher_is_patched(patchref_t* pr)
+{
+ // Validate the instruction at the patching position is the same
+ // instruction as the patcher structure contains.
+ uint32_t mcode = *((uint32_t*) pr->mpc);
+
+ if (mcode != pr->mcode) {
+ // The code differs.
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ *
+ */
+bool patcher_is_patched_at(void* pc)
+{
+ codeinfo* code = code_find_codeinfo_for_pc(pc);
+
+ // Get the patcher for the given PC.
+ patchref_t* pr = patcher_list_find(code, pc);
+
+ if (pr == NULL) {
+ // The given PC is not a patcher position.
+ return false;
+ }
+
+ // Validate the instruction.
+ return patcher_is_patched(pr);
+}
+
+
+/* patcher_handler *************************************************************
+
+ Handles the request to patch JIT code at the given patching
+ position. This function is normally called by the signal
+ handler.
+
+ NOTE: The patcher list lock is used to maintain exclusive
+ access of the patched position (in fact of the whole code).
+ After patching has suceeded, the patcher reference should be
+ removed from the patcher list to avoid double patching.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+/* XXX this indent is not thread safe! */
+/* XXX if you want it thread safe, place patcher_depth in threadobject! */
+static int patcher_depth = 0;
+#define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
+#endif /* !defined(NDEBUG) */
+
+java_handle_t *patcher_handler(u1 *pc)
+{
+ codeinfo *code;
+ patchref_t *pr;
+ bool result;
+ java_handle_t *e;
+#if !defined(NDEBUG)
+ patcher_function_list_t *l;
+ int i;
+#endif
+
+ /* define the patcher function */
+
+ bool (*patcher_function)(patchref_t *);
+
+ /* search the codeinfo for the given PC */
+
+ code = code_find_codeinfo_for_pc(pc);
+ assert(code);
+
+ // Enter a mutex on the patcher list.
+ code->patchers->lock();
+
+ /* search the patcher information for the given PC */
+
+ pr = patcher_list_find(code, pc);
+
+ if (pr == NULL)
+ vm_abort("patcher_handler: Unable to find patcher reference.");
+
+ if (pr->done) {
+#if !defined(NDEBUG)
+ if (opt_DebugPatcher) {
+ log_println("patcher_handler: double-patching detected!");
+ }
+#endif
+ code->patchers->unlock();
+ return NULL;
+ }
+
+#if !defined(NDEBUG)
+ if (opt_DebugPatcher) {
+ for (l = patcher_function_list; l->patcher != NULL; l++)
+ if (l->patcher == pr->patcher)
+ break;
+
+ TRACE_PATCHER_INDENT; printf("patching in "); method_print(code->m); printf(" at %p\n", (void *) pr->mpc);
+ TRACE_PATCHER_INDENT; printf("\tpatcher function = %s <%p>\n", l->name, (void *) (intptr_t) pr->patcher);
+
+ TRACE_PATCHER_INDENT;
+ printf("\tmachine code before = ");
+
+# if defined(ENABLE_DISASSEMBLER)
+ disassinstr((u1*) (void*) pr->mpc);
+# else
+ printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
+# endif
+
+ patcher_depth++;
+ assert(patcher_depth > 0);
+ }
+#endif
+
+ /* cast the passed function to a patcher function */
+
+ patcher_function = (bool (*)(patchref_t *)) (ptrint) pr->patcher;
+
+ /* call the proper patcher function */
+
+ result = (patcher_function)(pr);
+
+#if !defined(NDEBUG)
+ if (opt_DebugPatcher) {
+ assert(patcher_depth > 0);
+ patcher_depth--;
+
+ TRACE_PATCHER_INDENT;
+ printf("\tmachine code after = ");
+
+# if defined(ENABLE_DISASSEMBLER)
+ disassinstr((u1*) (void*) pr->mpc);
+# else
+ printf("%x at %p (disassembler disabled)\n", *((uint32_t*) pr->mpc), (void*) pr->mpc);
+# endif
+
+ if (result == false) {
+ TRACE_PATCHER_INDENT; printf("\tPATCHER EXCEPTION!\n");
+ }
+ }
+#endif
+
+#if defined(ENABLE_JITCACHE)
+ /* Put cached reference into the code and remove it from the patcher */
+ if (pr->attached_ref)
+ {
+ jitcache_handle_cached_ref(pr->attached_ref, code);
+ pr->attached_ref = NULL;
+ }
+#endif
+
+ /* check for return value and exit accordingly */
+
+ if (result == false) {
+ e = exceptions_get_and_clear_exception();
+
+ code->patchers->unlock();
+
+ return e;
+ }
+
+ pr->done = true; /* XXX this is only preliminary to prevent double-patching */
+
+ code->patchers->unlock();
+
+ return NULL;
+}
+
+
+/* patcher_initialize_class ****************************************************
+
+ Initalizes a given classinfo pointer.
+ This function does not patch any data.
+
+*******************************************************************************/
+
+bool patcher_initialize_class(patchref_t *pr)
+{
+ classinfo *c;
+
+ /* get stuff from the patcher reference */
+
+ c = (classinfo *) pr->ref;
+
+ /* check if the class is initialized */
+
+ if (!(c->state & CLASS_INITIALIZED))
+ if (!initialize_class(c))
+ return false;
+
+ /* patch back original code */
+
+ patcher_patch_code(pr);
+
+ return true;
+}
+
+
+/* patcher_resolve_class *******************************************************
+
+ Resolves a given unresolved class reference.
+ This function does not patch any data.
+
+*******************************************************************************/
+
+#ifdef ENABLE_VERIFIER
+bool patcher_resolve_class(patchref_t *pr)
+{
+ unresolved_class *uc;
+
+ /* get stuff from the patcher reference */
+
+ uc = (unresolved_class *) pr->ref;
+
+ /* resolve the class and check subtype constraints */
+
+ if (!resolve_class_eager_no_access_check(uc))
+ return false;
+
+ /* patch back original code */
+
+ patcher_patch_code(pr);
+
+ return true;
+}
+#endif /* ENABLE_VERIFIER */
+
+
+/* patcher_resolve_native_function *********************************************
+
+ Resolves the native function for a given methodinfo.
+ This function patches one data segment word.
+
+*******************************************************************************/
+
+bool patcher_resolve_native_function(patchref_t *pr)
+{
+ methodinfo *m;
+ uint8_t *datap;
+
+ /* get stuff from the patcher reference */
+
+ m = (methodinfo *) pr->ref;
+ datap = (uint8_t *) pr->datap;
+
+ /* resolve native function */
+
+ NativeMethods& nm = VM::get_current()->get_nativemethods();
+ void* f = nm.resolve_method(m);
+
+ if (f == NULL)
+ return false;
+
+ /* patch native function pointer */
+
+ *((intptr_t*) datap) = (intptr_t) f;
+
+ /* synchronize data cache */
+
+ md_dcacheflush(datap, SIZEOF_VOID_P);
+
+ /* patch back original code */
+
+ patcher_patch_code(pr);
+
+ return true;
+}
+
+/** Placeholder functions to calm down linker */
+#if defined(__I386__)
+bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
+{
+ return true;
+}
+
+bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
+{
+ return true;
+}
+
+bool patcher_resolve_classref_to_index(patchref_t *pr)
+{
+ return true;
+}
+
+bool patcher_resolve_classref_to_flags(patchref_t *pr)
+{
+ return true;
+}
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * 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/patcher-common.h - architecture independent code patching stuff
-
- 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 _PATCHER_COMMON_H
-#define _PATCHER_COMMON_H
-
-/* forward typedefs ***********************************************************/
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-
-#include "vm/jit/jit.h"
-
-#if defined (ENABLE_JITCACHE)
-struct cached_ref_t;
-#endif
-
-/* patchref_t ******************************************************************
-
- A patcher reference contains information about a code position
- which needs additional code patching during runtime.
-
-*******************************************************************************/
-
-typedef struct patchref_t {
- ptrint mpc; /* absolute position in code segment */
- ptrint datap; /* absolute position in data segment */
- s4 disp; /* displacement of ref in the data segment */
- functionptr patcher; /* patcher function to call */
- void* ref; /* reference passed */
- u8 mcode; /* machine code to be patched back in */
- bool done; /* XXX preliminary: patch already applied? */
-#if defined (ENABLE_JITCACHE)
- struct cachedref_t *attached_ref;
- /* cached reference which must be resolved *
- * patcher has been run. */
-#endif
- listnode_t linkage;
-} patchref_t;
-
-
-/* macros *********************************************************************/
-
-
-/* function prototypes ********************************************************/
-
-void patcher_list_create(codeinfo *code);
-void patcher_list_reset(codeinfo *code);
-void patcher_list_free(codeinfo *code);
-
-void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
-
-void patcher_resolve(jitdata* jd);
-
-java_handle_t *patcher_handler(u1 *pc);
-
-
-/* empty patcher (just patches back original mcode) ***************************/
-
-void patcher_patch_code(patchref_t *pr);
-
-
-/* patcher prototypes and macros **********************************************/
-
-/* new patcher functions */
-
-bool patcher_resolve_class(patchref_t *pr);
-#define PATCHER_resolve_class (functionptr) patcher_resolve_class
-
-bool patcher_initialize_class(patchref_t *pr);
-#define PATCHER_initialize_class (functionptr) patcher_initialize_class
-
-bool patcher_resolve_classref_to_classinfo(patchref_t *pr);
-#define PATCHER_resolve_classref_to_classinfo (functionptr) patcher_resolve_classref_to_classinfo
-
-bool patcher_resolve_classref_to_vftbl(patchref_t *pr);
-#define PATCHER_resolve_classref_to_vftbl (functionptr) patcher_resolve_classref_to_vftbl
-
-bool patcher_resolve_classref_to_index(patchref_t *pr);
-#define PATCHER_resolve_classref_to_index (functionptr) patcher_resolve_classref_to_index
-
-bool patcher_resolve_classref_to_flags(patchref_t *pr);
-#define PATCHER_resolve_classref_to_flags (functionptr) patcher_resolve_classref_to_flags
-
-bool patcher_resolve_native_function(patchref_t *pr);
-#define PATCHER_resolve_native_function (functionptr) patcher_resolve_native_function
-
-/* old patcher functions */
-
-bool patcher_get_putstatic(patchref_t *pr);
-#define PATCHER_get_putstatic (functionptr) patcher_get_putstatic
-
-#if defined(__I386__)
-
-bool patcher_getfield(patchref_t *pr);
-#define PATCHER_getfield (functionptr) patcher_getfield
-
-bool patcher_putfield(patchref_t *pr);
-#define PATCHER_putfield (functionptr) patcher_putfield
-
-#else
-
-bool patcher_get_putfield(patchref_t *pr);
-#define PATCHER_get_putfield (functionptr) patcher_get_putfield
-
-#endif /* defined(__I386__) */
-
-#if defined(__I386__) || defined(__X86_64__)
-
-bool patcher_putfieldconst(patchref_t *pr);
-#define PATCHER_putfieldconst (functionptr) patcher_putfieldconst
-
-#endif /* defined(__I386__) || defined(__X86_64__) */
-
-bool patcher_invokestatic_special(patchref_t *pr);
-#define PATCHER_invokestatic_special (functionptr) patcher_invokestatic_special
-
-bool patcher_invokevirtual(patchref_t *pr);
-#define PATCHER_invokevirtual (functionptr) patcher_invokevirtual
-
-bool patcher_invokeinterface(patchref_t *pr);
-#define PATCHER_invokeinterface (functionptr) patcher_invokeinterface
-
-#if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
-
-bool patcher_checkcast_interface(patchref_t *pr);
-#define PATCHER_checkcast_interface (functionptr) patcher_checkcast_interface
-
-bool patcher_instanceof_interface(patchref_t *pr);
-#define PATCHER_instanceof_interface (functionptr) patcher_instanceof_interface
-
-#endif /* defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) */
-
-#if defined(__S390__)
-
-bool patcher_checkcast_instanceof_interface(patchref_t *pr);
-#define PATCHER_checkcast_instanceof_interface (functionptr) patcher_checkcast_instanceof_interface
-
-#endif /* defined(__S390__) */
-
-#if defined(__I386__)
-
-bool patcher_aconst(patchref_t *pr);
-#define PATCHER_aconst (functionptr) patcher_aconst
-
-bool patcher_builtin_multianewarray(patchref_t *pr);
-#define PATCHER_builtin_multianewarray (functionptr) patcher_builtin_multianewarray
-
-bool patcher_builtin_arraycheckcast(patchref_t *pr);
-#define PATCHER_builtin_arraycheckcast (functionptr) patcher_builtin_arraycheckcast
-
-bool patcher_checkcast_instanceof_flags(patchref_t *pr);
-#define PATCHER_checkcast_instanceof_flags (functionptr) patcher_checkcast_instanceof_flags
-
-bool patcher_checkcast_class(patchref_t *pr);
-#define PATCHER_checkcast_class (functionptr) patcher_checkcast_class
-
-bool patcher_instanceof_class(patchref_t *pr);
-#define PATCHER_instanceof_class (functionptr) patcher_instanceof_class
-
-#endif /* defined(__I386__) */
-
-void patch_md(s4 md_patch, ptrint dest, void* ref);
-
-#endif /* _PATCHER_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:
- * vim:noexpandtab:sw=4:ts=4:
- */
--- /dev/null
+/* src/vm/jit/patcher-common.hpp - architecture independent code patching stuff
+
+ 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 _PATCHER_COMMON_HPP
+#define _PATCHER_COMMON_HPP
+
+/* forward typedefs ***********************************************************/
+
+typedef struct cachedref_t cachedref_t;
+typedef struct patchref_t patchref_t;
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "toolbox/list.hpp"
+
+#include "vm/global.h"
+
+#include "vm/jit/jit.hpp"
+
+#if defined (ENABLE_JITCACHE)
+struct cached_ref_t;
+#endif
+
+/* patchref_t ******************************************************************
+
+ A patcher reference contains information about a code position
+ which needs additional code patching during runtime.
+
+*******************************************************************************/
+
+struct patchref_t {
+ ptrint mpc; /* absolute position in code segment */
+ ptrint datap; /* absolute position in data segment */
+ s4 disp; /* displacement of ref in the data segment */
+ functionptr patcher; /* patcher function to call */
+ void* ref; /* reference passed */
+ uint32_t mcode; /* machine code to be patched back in */
+ bool done; /* XXX preliminary: patch already applied? */
+#if defined (ENABLE_JITCACHE)
+ cachedref_t *attached_ref;
+ /* cached reference which must be resolved *
+ * patcher has been run. */
+#endif
+};
+
+
+/* macros *********************************************************************/
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void patcher_list_create(codeinfo *code);
+void patcher_list_reset(codeinfo *code);
+void patcher_list_free(codeinfo *code);
+
+void patcher_add_patch_ref(jitdata *jd, functionptr patcher, void* ref, s4 disp);
+
+void patcher_resolve(jitdata* jd);
+
+bool patcher_is_patched(patchref_t* pr);
+bool patcher_is_patched_at(void* pc);
+
+// MD function.
+bool patcher_is_valid_trap_instruction_at(void* pc);
+
+java_handle_t *patcher_handler(u1 *pc);
+
+
+/* empty patcher (just patches back original mcode) ***************************/
+
+void patcher_patch_code(patchref_t *pr);
+
+
+/* patcher prototypes and macros **********************************************/
+
+/* new patcher functions */
+
+bool patcher_resolve_class(patchref_t *pr);
+#define PATCHER_resolve_class (functionptr) patcher_resolve_class
+
+bool patcher_initialize_class(patchref_t *pr);
+#define PATCHER_initialize_class (functionptr) patcher_initialize_class
+
+bool patcher_resolve_classref_to_classinfo(patchref_t *pr);
+#define PATCHER_resolve_classref_to_classinfo (functionptr) patcher_resolve_classref_to_classinfo
+
+bool patcher_resolve_classref_to_vftbl(patchref_t *pr);
+#define PATCHER_resolve_classref_to_vftbl (functionptr) patcher_resolve_classref_to_vftbl
+
+bool patcher_resolve_classref_to_index(patchref_t *pr);
+#define PATCHER_resolve_classref_to_index (functionptr) patcher_resolve_classref_to_index
+
+bool patcher_resolve_classref_to_flags(patchref_t *pr);
+#define PATCHER_resolve_classref_to_flags (functionptr) patcher_resolve_classref_to_flags
+
+bool patcher_resolve_native_function(patchref_t *pr);
+#define PATCHER_resolve_native_function (functionptr) patcher_resolve_native_function
+
+/* old patcher functions */
+
+bool patcher_get_putstatic(patchref_t *pr);
+#define PATCHER_get_putstatic (functionptr) patcher_get_putstatic
+
+#if defined(__I386__)
+
+bool patcher_getfield(patchref_t *pr);
+#define PATCHER_getfield (functionptr) patcher_getfield
+
+bool patcher_putfield(patchref_t *pr);
+#define PATCHER_putfield (functionptr) patcher_putfield
+
+#else
+
+bool patcher_get_putfield(patchref_t *pr);
+#define PATCHER_get_putfield (functionptr) patcher_get_putfield
+
+#endif /* defined(__I386__) */
+
+#if defined(__I386__) || defined(__X86_64__)
+
+bool patcher_putfieldconst(patchref_t *pr);
+#define PATCHER_putfieldconst (functionptr) patcher_putfieldconst
+
+#endif /* defined(__I386__) || defined(__X86_64__) */
+
+bool patcher_invokestatic_special(patchref_t *pr);
+#define PATCHER_invokestatic_special (functionptr) patcher_invokestatic_special
+
+bool patcher_invokevirtual(patchref_t *pr);
+#define PATCHER_invokevirtual (functionptr) patcher_invokevirtual
+
+bool patcher_invokeinterface(patchref_t *pr);
+#define PATCHER_invokeinterface (functionptr) patcher_invokeinterface
+
+#if defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+
+bool patcher_checkcast_interface(patchref_t *pr);
+#define PATCHER_checkcast_interface (functionptr) patcher_checkcast_interface
+
+bool patcher_instanceof_interface(patchref_t *pr);
+#define PATCHER_instanceof_interface (functionptr) patcher_instanceof_interface
+
+#endif /* defined(__ALPHA__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__) */
+
+#if defined(__S390__)
+
+bool patcher_checkcast_instanceof_interface(patchref_t *pr);
+#define PATCHER_checkcast_instanceof_interface (functionptr) patcher_checkcast_instanceof_interface
+
+#endif /* defined(__S390__) */
+
+#if defined(__I386__)
+
+bool patcher_aconst(patchref_t *pr);
+#define PATCHER_aconst (functionptr) patcher_aconst
+
+bool patcher_builtin_multianewarray(patchref_t *pr);
+#define PATCHER_builtin_multianewarray (functionptr) patcher_builtin_multianewarray
+
+bool patcher_builtin_arraycheckcast(patchref_t *pr);
+#define PATCHER_builtin_arraycheckcast (functionptr) patcher_builtin_arraycheckcast
+
+bool patcher_checkcast_instanceof_flags(patchref_t *pr);
+#define PATCHER_checkcast_instanceof_flags (functionptr) patcher_checkcast_instanceof_flags
+
+bool patcher_checkcast_class(patchref_t *pr);
+#define PATCHER_checkcast_class (functionptr) patcher_checkcast_class
+
+bool patcher_instanceof_class(patchref_t *pr);
+#define PATCHER_instanceof_class (functionptr) patcher_instanceof_class
+
+#endif /* defined(__I386__) */
+
+#if defined (__ARM__)
+void patch_md(s4 md_patch, ptrint dest, void* ref);
+#endif /* defined(__ARM__) */
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _PATCHER_COMMON_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:
+ */
emit.c \
patcher.c \
\
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 1
#define SUPPORT_LONG 1
#include "mm/memory.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/methodheader.h"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
#include "md-abi.h"
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/reg.h"
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 1 * 4
-
-
/* macros to create code ******************************************************/
#define M_OP3(opcode,y,oe,rc,d,a,b) \
#define MI_and(rA,rS,rB) M_OP3(31, 28, 0, 0, rS, rA, rB)
#define MI_anddot(rA,rS,rB) M_OP3(31, 28, 0, 1, rS, rA, rB)
#define MI_andi(rA,rS,UIMM) M_OP2_IMM(28, rS, rA, UIMM)
+#define MI_illegal M_OP3( 0, 0, 0, 0, 0, 0, 0)
#define MI_lwarx(rD,rA,rB) M_OP3(31, 20, 0, 0, rD, rA, rB)
#define MI_or(rA,rS,rB) M_OP3(31, 444, 0, 0, rS, rA, rB)
#define MI_ordot(rA,rS,rB) M_OP3(31, 444, 0, 1, rS, rA, rB)
#define M_IAND(a,b,d) MI_and(d, a, b)
#define M_IAND_IMM(a,b,d) MI_andi(d, a, b)
+#define M_ILLEGAL MI_illegal
#define M_IOR(a,b,d) MI_or(d, a, b)
#define M_IOR_IMM(a,b,d) MI_ori(d, a, b)
#define M_IOR_TST(a,b,d) MI_ordot(d, a, b)
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/global.h"
#include "vm/signallocal.h"
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
CODEGENDATA_FLAG_LONGBRANCHES);
}
- switch (condition) {
- case BRANCH_EQ:
- M_BNE(1);
- M_BR(branchdisp);
- break;
- case BRANCH_NE:
- M_BEQ(1);
- M_BR(branchdisp);
- break;
- case BRANCH_LT:
- M_BGE(1);
- M_BR(branchdisp);
- break;
- case BRANCH_GE:
- M_BLT(1);
- M_BR(branchdisp);
- break;
- case BRANCH_GT:
- M_BLE(1);
- M_BR(branchdisp);
- break;
- case BRANCH_LE:
- M_BGT(1);
- M_BR(branchdisp);
- break;
- case BRANCH_NAN:
- vm_abort("emit_branch: long BRANCH_NAN");
- break;
- default:
- vm_abort("emit_branch: unknown condition %d", condition);
+ // Subtract 1 instruction from the displacement as the
+ // actual branch is the second instruction.
+ checkdisp = checkdisp - 4;
+ branchdisp = branchdisp - 1;
+
+ if ((checkdisp < (int32_t) 0xfe000000) || (checkdisp > (int32_t) 0x01fffffc)) {
+ vm_abort("emit_branch: emit conditional long-branch code");
+ }
+ else {
+ switch (condition) {
+ case BRANCH_EQ:
+ M_BNE(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_NE:
+ M_BEQ(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_LT:
+ M_BGE(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_GE:
+ M_BLT(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_GT:
+ M_BLE(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_LE:
+ M_BGT(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_NAN:
+ vm_abort("emit_branch: long BRANCH_NAN");
+ break;
+ default:
+ vm_abort("emit_branch: unknown condition %d", condition);
+ }
}
}
else {
uint32_t emit_trap(codegendata *cd)
{
- uint32_t mcode;
-
- /* Get machine code which is patched back in later. The
- trap is 1 instruction word long. */
-
- mcode = *((uint32_t *) cd->mcodeptr);
+ // Get machine code which is patched back in later. The rap is 1
+ // instruction word long.
+ uint32_t mcode = *((uint32_t*) cd->mcodeptr);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
+ M_ILLEGAL;
return mcode;
}
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/signallocal.h"
#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
+#include "vm/jit/disass.h"
#include "vm/jit/executionstate.h"
#if defined(ENABLE_PROFILING)
# include "vm/jit/optimizing/profile.h"
#endif
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/trap.h"
intptr_t addr;
intptr_t val;
int type;
- void *p;
_uc = (ucontext_t *) _p;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
- switch (type) {
- case TRAP_COMPILER:
- if (p != NULL) {
- _gregs[REG_PV] = (uintptr_t) p;
- _gregs[PT_NIP] = (uintptr_t) p;
- break;
- }
- /* Get and set the PV from the parent Java method. */
+/**
+ * Signal handler for patcher calls.
+ */
+void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
+{
+ ucontext_t* _uc = (ucontext_t*) _p;
+ mcontext_t* _mc;
+ unsigned long* _gregs;
- pv = md_codegen_get_pv_from_pc(ra);
+#if defined(__UCLIBC__)
+ _mc = &(_uc->uc_mcontext);
+ _gregs = _mc->regs->gpr;
+#else
+ _mc = _uc->uc_mcontext.uc_regs;
+ _gregs = _mc->gregs;
+#endif
- _gregs[REG_PV] = (uintptr_t) pv;
+ /* get register values */
- /* Get the exception object. */
+ void* pv = (void*) _gregs[REG_PV];
+ void* sp = (void*) _gregs[REG_SP];
+ void* ra = (void*) _gregs[PT_LNK]; // The RA is correct for leag methods.
+ void* xpc =(void*) _gregs[PT_NIP];
- p = builtin_retrieve_exception();
+ // Get the illegal-instruction.
+ uint32_t mcode = *((uint32_t*) xpc);
- assert(p != NULL);
+ // Check if the trap instruction is valid.
+ // TODO Move this into patcher_handler.
+ if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+ // Check if the PC has been patched during our way to this
+ // signal handler (see PR85).
+ if (patcher_is_patched_at(xpc) == true)
+ return;
- /* fall-through */
+ // We have a problem...
+ log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%lx", mcode, xpc);
+#if defined(ENABLE_DISASSEMBLER)
+ (void) disassinstr(xpc);
+#endif
+ vm_abort("Aborting...");
+ }
- case TRAP_PATCHER:
- if (p == NULL)
- break;
+ // This signal is always a patcher.
+ int type = TRAP_PATCHER;
+ intptr_t val = 0;
- /* fall-through */
-
- default:
- _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
- _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
- _gregs[PT_NIP] = (uintptr_t) asm_handle_exception;
- }
+ // Handle the trap.
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
int s1;
intptr_t val;
int type;
- void *p;
_uc = (ucontext_t *) _p;
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
-
- _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
- _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
- _gregs[PT_NIP] = (uintptr_t) asm_handle_exception;
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
--- /dev/null
+/* src/vm/jit/powerpc/md-stubs.hpp - PowerPC JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a PowerPC architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 1 * 4;
+}
+
+#endif // _MD_STUBS_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 "vm/global.h"
#include "vm/vm.hpp"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* md_init *********************************************************************
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
/* md_stacktrace_get_returnaddress *********************************************
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/initialize.h"
#include "vm/options.h"
#include "vm/references.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
-#include "vm/jit/patcher-common.h"
-
-
-#define PATCH_BACK_ORIGINAL_MCODE \
- *((u4 *) pr->mpc) = (u4) pr->mcode; \
- md_icacheflush((u1 *) pr->mpc, 4);
+#include "vm/jit/patcher-common.hpp"
/* patcher_patch_code **********************************************************
void patcher_patch_code(patchref_t *pr)
{
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch back original code.
+ *((uint32_t*) pr->mpc) = pr->mcode;
+
+ // Synchronize instruction cache.
+ md_icacheflush((void*) pr->mpc, 1 * 4);
+}
+
+
+/**
+ * Check if the trap instruction at the given PC is valid.
+ *
+ * @param pc Program counter.
+ *
+ * @return true if valid, false otherwise.
+ */
+bool patcher_is_valid_trap_instruction_at(void* pc)
+{
+ uint32_t mcode = *((uint32_t*) pc);
+
+ // Check for the undefined instruction we use.
+ return (mcode == 0x00000000);
}
bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
-
- /* get stuff from the stack */
+ constant_classref * cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the classinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch the classinfo pointer */
-
- *((ptrint *) datap) = (ptrint) c;
-
- /* synchronize data cache */
+ // Patch the class pointer.
+ *datap = (uintptr_t) c;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- /* get stuff from the stack */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
-
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch super class' vftbl */
-
- *((ptrint *) datap) = (ptrint) c->vftbl;
-
- /* synchronize data cache */
+ // Patch super class' vftbl.
+ *datap = (uintptr_t) c->vftbl;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_resolve_classref_to_flags(patchref_t *pr)
{
- constant_classref *cr;
- u1 *datap;
- classinfo *c;
-
- /* get stuff from the stack */
-
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ int32_t* datap = (int32_t*) pr->datap;
- /* get the fieldinfo */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch class flags */
-
- *((s4 *) datap) = (s4) c->flags;
-
- /* synchronize data cache */
+ // Patch class flags.
+ *datap = c->flags;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_get_putstatic(patchref_t *pr)
{
- u1 *ra;
- unresolved_field *uf;
- u1 *datap;
- fieldinfo *fi;
-
- /* get stuff from the stack */
+ unresolved_field* uf = (unresolved_field*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- ra = (u1 *) pr->mpc;
- uf = (unresolved_field *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- /* get the fieldinfo */
-
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- /* check if the field's class is initialized */
-
+ // Check if the field's class is initialized.
if (!(fi->clazz->state & CLASS_INITIALIZED))
if (!initialize_class(fi->clazz))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch the field value's address */
-
- *((intptr_t *) datap) = (intptr_t) fi->value;
-
- /* synchronize data cache */
+ // Patch the field value's address.
+ *datap = (uintptr_t) fi->value;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_get_putfield(patchref_t *pr)
{
- u1 *ra;
- unresolved_field *uf;
- fieldinfo *fi;
- s2 disp;
-
- ra = (u1 *) pr->mpc;
- uf = (unresolved_field *) pr->ref;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show NOPs, we have to skip them */
-
- if (opt_shownops)
- ra = ra + 1 * 4;
-
- /* patch the field's offset */
-
+ // Patch the field's offset.
if (IS_LNG_TYPE(fi->type)) {
/* If the field has type long, we have to patch two
instructions. But we have to check which instruction
is first. We do that with the offset of the first
instruction. */
- disp = *((u4 *) (ra + 0 * 4));
+ uint32_t disp = (pr->mcode & 0x0000ffff);
if (disp == 4) {
- *((u4 *) (ra + 0 * 4)) &= 0xffff0000;
- *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
- *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
+ pr->mcode &= 0xffff0000;
+ pr->mcode |= ((fi->offset + 4) & 0x0000ffff);
+ pc[1] |= ((fi->offset + 0) & 0x0000ffff);
}
else {
- *((u4 *) (ra + 0 * 4)) |= (s2) ((fi->offset + 0) & 0x0000ffff);
- *((u4 *) (ra + 1 * 4)) &= 0xffff0000;
- *((u4 *) (ra + 1 * 4)) |= (s2) ((fi->offset + 4) & 0x0000ffff);
+ pr->mcode |= ((fi->offset + 0) & 0x0000ffff);
+ pc[1] &= 0xffff0000;
+ pc[1] |= ((fi->offset + 4) & 0x0000ffff);
}
- }
- else
- *((u4 *) (ra + 0 * 4)) |= (s2) (fi->offset & 0x0000ffff);
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 1 * 4);
+ }
+ else {
+ pr->mcode |= (fi->offset & 0x0000ffff);
+ }
- md_icacheflush(ra + 0 * 4, 2 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokestatic_special(patchref_t *pr)
{
- unresolved_method *um;
- u1 *datap;
- methodinfo *m;
-
- /* get stuff from the stack */
+ unresolved_method* um = (unresolved_method*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- um = (unresolved_method *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* patch stubroutine */
-
- *((ptrint *) datap) = (ptrint) m->stubroutine;
-
- /* synchronize data cache */
+ // Patch stubroutine.
+ *datap = (uintptr_t) m->stubroutine;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_invokevirtual(patchref_t *pr)
{
- u1 *ra;
- unresolved_method *um;
- methodinfo *m;
- s4 disp;
-
- /* get stuff from the stack */
-
- ra = (u1 *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch vftbl index.
+ int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
- /* if we show NOPs, we have to skip them */
+ pc[1] |= (disp & 0x0000ffff);
- if (opt_shownops)
- ra = ra + 1 * 4;
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 1 * 4);
- /* patch vftbl index */
-
- disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
-
- *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 1 * 4, 1 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokeinterface(patchref_t *pr)
{
- u1 *ra;
- unresolved_method *um;
- methodinfo *m;
- s4 disp;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- ra = (u1 *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show NOPs, we have to skip them */
-
- if (opt_shownops)
- ra = ra + 1 * 4;
-
- /* patch interfacetable index */
-
- disp = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->clazz->index;
+ // Patch interfacetable index.
+ int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
/* XXX TWISTI: check displacement */
+ pc[1] |= (disp & 0x0000ffff);
- *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
-
- /* patch method offset */
-
+ // Patch method offset.
disp = sizeof(methodptr) * (m - m->clazz->methods);
/* XXX TWISTI: check displacement */
+ pc[2] |= (disp & 0x0000ffff);
- *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
-
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 2 * 4);
- md_icacheflush(ra + 1 * 4, 2 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_checkcast_interface(patchref_t *pr)
{
- u1 *ra;
- constant_classref *cr;
- classinfo *c;
- s4 disp;
-
- /* get stuff from the stack */
-
- ra = (u1 *) pr->mpc;
- cr = (constant_classref *) pr->ref;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show NOPs, we have to skip them */
-
- if (opt_shownops)
- ra = ra + 1 * 4;
-
- /* patch super class index */
-
- disp = -(c->index);
-
- *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+ // Patch super class index.
+ int32_t disp = -(c->index);
+ pc[2] |= (disp & 0x0000ffff);
disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+ pc[5] |= (disp & 0x0000ffff);
- *((s4 *) (ra + 5 * 4)) |= (disp & 0x0000ffff);
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 2, 4 * 4);
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 2 * 4, 4 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_instanceof_interface(patchref_t *pr)
{
- u1 *ra;
- constant_classref *cr;
- classinfo *c;
- s4 disp;
-
- /* get stuff from the stack */
-
- ra = (u1 *) pr->mpc;
- cr = (constant_classref *) pr->ref;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show NOPs, we have to skip them */
-
- if (opt_shownops)
- ra = ra + 1 * 4;
-
- /* patch super class index */
-
- disp = -(c->index);
-
- *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+ // Patch super class index.
+ int32_t disp = -(c->index);
+ pc[2] |= (disp & 0x0000ffff);
disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+ pc[4] |= (disp & 0x0000ffff);
- *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
-
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 2, 3 * 4);
- md_icacheflush(ra + 2 * 4, 3 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
emit.c \
patcher.c \
\
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 1
#define SUPPORT_LONG 1
#include "mm/memory.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
-/* src/vm/jit/powerpc64/codegen.h - code generation macros and definitions for
- 64-bit PowerPC
+/* src/vm/jit/powerpc64/codegen.h - code generation macros and
+ definitions for PowerPC64
- 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.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Stefan Ring
- Christian Thalinger
- Christian Ullrich
-
-
*/
#include "md-abi.h"
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/reg.h"
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 1 * 4
-
-
/* macros to create code ******************************************************/
#define M_OP3(opcode,y,oe,rc,d,a,b) \
/* instruction macros *********************************************************/
-#define M_IADD(a,b,c) M_LADD(a,b,c)
+#define M_ILLEGAL M_OP3(0, 0, 0, 0, 0, 0, 0)
+#define M_IADD(a,b,c) M_LADD(a,b,c)
#define M_LADD(a,b,c) M_OP3(31, 266, 0, 0, c, a, b)
#define M_IADD_IMM(a,b,c) M_OP2_IMM(14, c, a, b) /* XXX */
#define M_LADD_IMM(a,b,c) M_OP2_IMM(14, c, a, b)
#include "md-abi.h"
#include "vm/jit/powerpc64/codegen.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#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/emit-common.hpp"
+#include "vm/jit/jit.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
CODEGENDATA_FLAG_LONGBRANCHES);
}
- branchdisp --; /* we jump from the second instruction */
- switch (condition) {
- case BRANCH_EQ:
- M_BNE(1);
- M_BR(branchdisp);
- break;
- case BRANCH_NE:
- M_BEQ(1);
- M_BR(branchdisp);
- break;
- case BRANCH_LT:
- M_BGE(1);
- M_BR(branchdisp);
- break;
- case BRANCH_GE:
- M_BLT(1);
- M_BR(branchdisp);
- break;
- case BRANCH_GT:
- M_BLE(1);
- M_BR(branchdisp);
- break;
- case BRANCH_LE:
- M_BGT(1);
- M_BR(branchdisp);
- break;
- case BRANCH_NAN:
- vm_abort("emit_branch: long BRANCH_NAN");
- break;
- default:
- vm_abort("emit_branch: unknown condition %d", condition);
- }
+ // Subtract 1 instruction from the displacement as the
+ // actual branch is the second instruction.
+ checkdisp = checkdisp - 4;
+ branchdisp = branchdisp - 1;
+ if ((checkdisp < (int32_t) 0xfe000000) || (checkdisp > (int32_t) 0x01fffffc)) {
+ vm_abort("emit_branch: emit conditional long-branch code");
+ }
+ else {
+ switch (condition) {
+ case BRANCH_EQ:
+ M_BNE(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_NE:
+ M_BEQ(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_LT:
+ M_BGE(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_GE:
+ M_BLT(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_GT:
+ M_BLE(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_LE:
+ M_BGT(1);
+ M_BR(branchdisp);
+ break;
+ case BRANCH_NAN:
+ vm_abort("emit_branch: long BRANCH_NAN");
+ break;
+ default:
+ vm_abort("emit_branch: unknown condition %d", condition);
+ }
+ }
}
else {
switch (condition) {
uint32_t emit_trap(codegendata *cd)
{
- uint32_t mcode;
-
- /* Get machine code which is patched back in later. The
- trap is 1 instruction word long. */
-
- mcode = *((uint32_t *) cd->mcodeptr);
+ // Get machine code which is patched back in later. The trap is 1
+ // instruction word long.
+ uint32_t mcode = *((uint32_t*) cd->mcodeptr);
- /* ALD is 4 byte aligned, ILD 2, only LWZ is byte aligned */
- M_LWZ(REG_ZERO, REG_ZERO, TRAP_PATCHER);
+ M_ILLEGAL;
return mcode;
}
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/signallocal.h"
#include "vm/os.hpp"
# include "vm/jit/optimizing/profile.h"
#endif
+#include "vm/jit/disass.h"
#include "vm/jit/trap.h"
int type;
intptr_t addr;
intptr_t val;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &(_uc->uc_mcontext);
/* Handle the trap. */
- p = trap_handle(type, val, pv, sp, ra, xpc, _p);
-
- /* Set registers. */
-
- switch (type) {
- case TRAP_COMPILER:
- if (p != NULL) {
- _mc->gp_regs[REG_PV] = (uintptr_t) p;
- _mc->gp_regs[PT_NIP] = (uintptr_t) p;
- break;
- }
-
- /* Get and set the PV from the parent Java method. */
-
- pv = md_codegen_get_pv_from_pc(ra);
-
- _mc->gp_regs[REG_PV] = (uintptr_t) pv;
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
+}
- /* Get the exception object. */
- p = builtin_retrieve_exception();
+/**
+ * Signal handler for patcher calls.
+ */
+void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
+{
+ ucontext_t* _uc = (ucontext_t*) _p;
+ mcontext_t* _mc = &(_uc->uc_mcontext);
- assert(p != NULL);
+ /* get register values */
- /* fall-through */
+ void* pv = (void*) _mc->gp_regs[REG_PV];
+ void* sp = (void*) _mc->gp_regs[REG_SP];
+ void* ra = (void*) _mc->gp_regs[PT_LNK]; // The RA is correct for leag methods.
+ void* xpc =(void*) _mc->gp_regs[PT_NIP];
+
+ // Get the illegal-instruction.
+ uint32_t mcode = *((uint32_t*) xpc);
+
+ // Check if the trap instruction is valid.
+ // TODO Move this into patcher_handler.
+ if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+ // Check if the PC has been patched during our way to this
+ // signal handler (see PR85).
+ if (patcher_is_patched_at(xpc) == true)
+ return;
+
+ // We have a problem...
+ log_println("md_signal_handler_sigill: Unknown illegal instruction 0x%x at 0x%lx", mcode, xpc);
+#if defined(ENABLE_DISASSEMBLER)
+ (void) disassinstr(xpc);
+#endif
+ vm_abort("Aborting...");
+ }
- case TRAP_PATCHER:
- if (p == NULL)
- break;
+ // This signal is always a patcher.
+ int type = TRAP_PATCHER;
+ intptr_t val = 0;
- /* fall-through */
-
- default:
- _mc->gp_regs[REG_ITMP1_XPTR] = (uintptr_t) p;
- _mc->gp_regs[REG_ITMP2_XPC] = (uintptr_t) xpc;
- _mc->gp_regs[PT_NIP] = (uintptr_t) asm_handle_exception;
- }
+ // Handle the trap.
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
void md_executionstate_read(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;
+ _mc = &(_uc->uc_mcontext);
/* 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];
+ es->pc = (u1 *) _mc->gp_regs[PT_NIP];
+ es->sp = (u1 *) _mc->gp_regs[REG_SP];
+ es->pv = (u1 *) _mc->gp_regs[REG_PV];
+ es->ra = (u1 *) _mc->gp_regs[PT_LNK];
/* read integer registers */
for (i = 0; i < INT_REG_CNT; i++)
- es->intregs[i] = _gregs[i];
+ es->intregs[i] = _mc->gp_regs[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
-
- vm_abort("md_executionstate_read: IMPLEMENT ME!");
+ // The assertion below will fail because _mc->fp_regs[] also
+ // contains the "fpscr" register.
+ //assert(sizeof(_mc->fp_regs) == sizeof(es->fltregs));
+ os_memcpy(&es->fltregs, &_mc->fp_regs, sizeof(es->fltregs));
}
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;
+ _mc = &(_uc->uc_mcontext);
/* write integer registers */
for (i = 0; i < INT_REG_CNT; i++)
- _gregs[i] = es->intregs[i];
+ _mc->gp_regs[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));
+ // The assertion below will fail because _mc->fp_regs[] also
+ // contains the "fpscr" register.
+ //assert(sizeof(_mc->fp_regs) == sizeof(es->fltregs));
+ os_memcpy(&_mc->fp_regs, &es->fltregs, sizeof(es->fltregs));
/* 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!");
+ _mc->gp_regs[PT_NIP] = (ptrint) es->pc;
+ _mc->gp_regs[REG_SP] = (ptrint) es->sp;
+ _mc->gp_regs[REG_PV] = (ptrint) es->pv;
+ _mc->gp_regs[PT_LNK] = (ptrint) es->ra;
}
--- /dev/null
+/* src/vm/jit/powerpc64/md-stubs.hpp - PowerPC64 JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a PowerPC64 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 1 * 4;
+}
+
+#endif // _MD_STUBS_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 = 7,
/* Don't use 8 (could be a normal load offset). */
- TRAP_COMPILER = 9,
- TRAP_COUNTDOWN = 10,
- TRAP_END
+ TRAP_COUNTDOWN = 9,
+ TRAP_END,
+
+ // This handled via SIGILL.
+ TRAP_PATCHER = 99 // A large number.
};
#endif /* _MD_TRAP_H */
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/trap.h"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* md_stacktrace_get_returnaddress *********************************************
Copyright (C) 1996-2005, 2006, 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/initialize.h"
#include "vm/options.h"
#include "vm/references.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
/* patcher_patch_code **********************************************************
void patcher_patch_code(patchref_t *pr)
{
- /* patch back original code */
+ // Patch back original code.
+ *((uint32_t*) pr->mpc) = pr->mcode;
+
+ // Synchronize instruction cache.
+ md_icacheflush((void*) pr->mpc, 1 * 4);
+}
- *((u4 *) pr->mpc) = pr->mcode;
- /* synchronize instruction cache */
+/**
+ * Check if the trap instruction at the given PC is valid.
+ *
+ * @param pc Program counter.
+ *
+ * @return true if valid, false otherwise.
+ */
+bool patcher_is_valid_trap_instruction_at(void* pc)
+{
+ uint32_t mcode = *((uint32_t*) pc);
- md_icacheflush(pr->mpc, 4);
+ // Check for the undefined instruction we use.
+ return (mcode == 0x00000000);
}
*******************************************************************************/
-bool patcher_get_putstatic(patchref_t *pr)
+bool patcher_get_putstatic(patchref_t* pr)
{
- u1 *ra;
- u4 mcode;
- unresolved_field *uf;
- u1 *datap;
- fieldinfo *fi;
-
- /* get stuff from the stack */
-
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- uf = (unresolved_field *) pr->ref;
- datap = (u1 *) pr->datap;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- /* get the fieldinfo */
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- /* check if the field's class is initialized */
-
+ // Check if the field's class is initialized.
if (!(fi->clazz->state & CLASS_INITIALIZED))
if (!initialize_class(fi->clazz))
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* patch the field value's address */
-
- *((intptr_t *) datap) = (intptr_t) fi->value;
-
- /* synchronize data cache */
+ // Patch the field value's address.
+ *datap = (uintptr_t) fi->value;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
*******************************************************************************/
-bool patcher_get_putfield(patchref_t *pr)
+bool patcher_get_putfield(patchref_t* pr)
{
- u1 *ra;
- u4 mcode;
- unresolved_field *uf;
- fieldinfo *fi;
-
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- uf = (unresolved_field *) pr->ref;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
+ // Patch the field offset in the patcher. We also need this to
+ // validate patchers.
+ pr->mcode |= (int16_t) (fi->offset & 0x0000ffff);
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
-
- /* patch the field's offset */
-
- *((u4 *) ra) |= (s2) (fi->offset & 0x0000ffff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 8);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
******************************************************************************/
-bool patcher_invokestatic_special(patchref_t *pr)
+bool patcher_invokestatic_special(patchref_t* pr)
{
- u1 *ra;
- u4 mcode;
- unresolved_method *um;
- u1 *datap;
- methodinfo *m;
-
- /* get stuff from the stack */
+ unresolved_method* um = (unresolved_method*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- um = (unresolved_method *) pr->ref;
- datap = (u1 *) pr->datap;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* patch stubroutine */
-
- *((ptrint *) datap) = (ptrint) m->stubroutine;
-
- /* synchronize data cache */
+ // Patch stubroutine.
+ *datap = (uintptr_t) m->stubroutine;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
*******************************************************************************/
-bool patcher_invokevirtual(patchref_t *pr)
+bool patcher_invokevirtual(patchref_t* pr)
{
- u1 *ra;
- u4 mcode;
- unresolved_method *um;
- methodinfo *m;
- s4 disp;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- um = (unresolved_method *) pr->ref;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
+ // Patch vftbl index.
+ int32_t disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
- md_icacheflush(ra, 4);
+ pc[1] |= (disp & 0x0000ffff);
- /* if we show disassembly, we have to skip the nop */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 1 * 4);
- if (opt_shownops)
- ra = ra + 4;
-
- /* patch vftbl index */
-
- disp = (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
-
- *((s4 *) (ra + 4)) |= (disp & 0x0000ffff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 2 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
*******************************************************************************/
-bool patcher_invokeinterface(patchref_t *pr)
+bool patcher_invokeinterface(patchref_t* pr)
{
- u1 *ra;
- u4 mcode;
- unresolved_method *um;
- methodinfo *m;
- s4 disp;
-
- /* get stuff from the stack */
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- um = (unresolved_method *) pr->ref;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
+ // Patch interfacetable index.
+ int32_t disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
- /* patch interfacetable index */
-
- disp = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->clazz->index;
-
- /* XXX TWISTI: check displacement */
-
- *((s4 *) (ra + 1 * 4)) |= (disp & 0x0000ffff);
-
- /* patch method offset */
+ // XXX TWISTI: check displacement
+ pc[1] |= (disp & 0x0000ffff);
+ // Patch method offset.
disp = sizeof(methodptr) * (m - m->clazz->methods);
- /* XXX TWISTI: check displacement */
-
- *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+ // XXX TWISTI: check displacement
+ pc[2] |= (disp & 0x0000ffff);
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 1, 2 * 4);
- md_icacheflush(ra, 3 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
*******************************************************************************/
-bool patcher_checkcast_interface(patchref_t *pr)
+bool patcher_checkcast_interface(patchref_t* pr)
{
- u1 *ra;
- constant_classref *cr;
- classinfo *c;
- s4 disp;
- u4 mcode;
-
- /* get stuff from stack */
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- cr = (constant_classref *) pr->ref;
-
- /* get the fieldinfo */
- if (!(c = resolve_classref_eager(cr))) {
- return false;
- }
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- /* patch back original code */
- *((u4 *) ra) = mcode;
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* if we show NOPs, we have to skip them */
- if (opt_shownops)
- ra = ra +4;
-
- /* patch super class index */
- disp = -(c->index);
+ if (c == NULL)
+ return false;
- *((s4*)(ra + 2*4)) |= (disp & 0x0000ffff);
+ // Patch super class index.
+ int32_t disp = -(c->index);
+ pc[2] |= (disp & 0x0000ffff);
disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+ pc[5] |= (disp & 0x0000ffff);
- *((s4 *)(ra + 5*4)) |= (disp & 0x0000ffff);
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 2, 4 * 4);
- /* sync instruction cache */
- md_icacheflush(ra, 6*4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
*******************************************************************************/
-bool patcher_instanceof_interface(patchref_t *pr)
+bool patcher_instanceof_interface(patchref_t* pr)
{
- u1 *ra;
- u4 mcode;
- constant_classref *cr;
- classinfo *c;
- s4 disp;
-
- /* get stuff from the stack */
-
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- cr = (constant_classref *) pr->ref;
+ uint32_t* pc = (uint32_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* if we show disassembly, we have to skip the nop */
-
- if (opt_shownops)
- ra = ra + 4;
-
- /* patch super class index */
-
- disp = -(c->index);
-
- *((s4 *) (ra + 2 * 4)) |= (disp & 0x0000ffff);
+ // Patch super class index.
+ int32_t disp = -(c->index);
+ pc[2] |= (disp & 0x0000ffff);
disp = OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*);
+ pc[4] |= (disp & 0x0000ffff);
- *((s4 *) (ra + 4 * 4)) |= (disp & 0x0000ffff);
-
- /* synchronize instruction cache */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 2, 3 * 4);
- md_icacheflush(ra, 5 * 4);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
*******************************************************************************/
-bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
+bool patcher_resolve_classref_to_classinfo(patchref_t* pr)
{
- constant_classref *cr;
- u1 *datap, *ra;
- u4 mcode;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- /* get stuff from the stack */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
-
- /* get the classinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* patch the classinfo pointer */
-
- *((ptrint *) datap) = (ptrint) c;
-
- /* synchronize data cache */
+ // Patch the classinfo pointer.
+ *datap = (uintptr_t) c;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
*******************************************************************************/
-bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
+bool patcher_resolve_classref_to_vftbl(patchref_t* pr)
{
- constant_classref *cr;
- u1 *datap, *ra;
- u4 mcode;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- /* get stuff from the stack */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
-
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* patch super class' vftbl */
-
- *((ptrint *) datap) = (ptrint) c->vftbl;
-
- /* synchronize data cache */
+ // Patch super class' vftbl.
+ *datap = (uintptr_t) c->vftbl;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
*******************************************************************************/
-bool patcher_resolve_classref_to_flags(patchref_t *pr)
+bool patcher_resolve_classref_to_flags(patchref_t* pr)
{
- constant_classref *cr;
- u1 *datap, *ra;
- u4 mcode;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ int32_t* datap = (int32_t*) pr->datap;
- /* get stuff from the stack */
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- ra = (u1 *) pr->mpc;
- mcode = pr->mcode;
- cr = (constant_classref *) pr->ref;
- datap = (u1 *) pr->datap;
-
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- /* patch back original code */
-
- *((u4 *) ra) = mcode;
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra, 4);
-
- /* patch class flags */
-
- *((s4 *) datap) = (s4) c->flags;
-
- /* synchronize data cache */
+ // Patch class flags.
+ *datap = (int32_t) c->flags;
+ // Synchronize data cache.
md_dcacheflush(datap, SIZEOF_VOID_P);
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
#include "vm/global.h"
#include "vm/jit/python.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#if defined(ENABLE_THREADS)
-# include "threads/lock-common.h"
+# include "threads/mutex.hpp"
#endif
#if defined(ENABLE_THREADS)
-static java_object_t *python_global_lock;
+static Mutex *python_global_mutex;
#endif
/*
}
#if defined(ENABLE_THREADS)
- python_global_lock = NEW(java_object_t);
- LOCK_INIT_OBJECT_LOCK(python_global_lock);
+ python_global_mutex = Mutex_new();
#endif
}
int success = 0;
root_state root;
- LOCK_MONITOR_ENTER(python_global_lock);
+ Mutex_lock(python_global_mutex);
pymodname = PyString_FromString(module);
pymod = PyImport_Import(pymodname);
Py_XDECREF(pyret);
Py_XDECREF(objcache);
- LOCK_MONITOR_EXIT(python_global_lock);
+ Mutex_unlock(python_global_mutex);
return (success == 1 ? 1 : 0);
}
#define _VM_JIT_PYTHON_H
#if defined(ENABLE_PYTHON)
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
void pythonpass_init();
void pythonpass_cleanup();
assert(rd->tmpadrreguse == ADR_TMP_CNT);
assert(rd->argadrreguse == ADR_ARG_CNT);
#endif
-
+
/* setup the float register table */
rd->tmpfltregs = DMNEW(s4, FLT_TMP_CNT);
assert(rd->savfltreguse == FLT_SAV_CNT);
assert(rd->tmpfltreguse == FLT_TMP_CNT);
-
rd->freemem = DMNEW(s4, m->maxstack);
-#if defined(HAS_4BYTE_STACKSLOT)
- rd->freemem_2 = DMNEW(s4, m->maxstack);
-#endif
#if defined(SPECIALMEMUSE)
# if defined(__DARWIN__)
#include "arch.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/verify/typeinfo.h"
int freeargadrtop; /* free argument address register count */
#endif
-#if defined(HAS_4BYTE_STACKSLOT)
- int *freemem_2;
- int freememtop_2;
-#endif
int *freemem; /* free scratch memory */
int freememtop; /* free memory count */
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void reg_setup(jitdata *jd);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _REG_H */
+++ /dev/null
-/* src/vm/jit/replace.c - on-stack replacement of 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.
-
-*/
-
-#include "config.h"
-#include "vm/types.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "arch.h"
-#include "md.h"
-
-#if defined(ENABLE_GC_CACAO)
-# include "mm/cacao-gc/gc.h"
-#endif
-
-#include "mm/memory.h"
-
-#include "threads/thread.hpp"
-
-#include "toolbox/logging.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/disass.h"
-#include "vm/jit/executionstate.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/methodheader.h"
-#include "vm/jit/replace.h"
-#include "vm/jit/show.h"
-#include "vm/jit/stack.h"
-
-
-#define REPLACE_PATCH_DYNAMIC_CALL
-/*#define REPLACE_PATCH_ALL*/
-
-#if defined(ENABLE_VMLOG)
-#include <vmlog_cacao.h>
-#endif
-
-/*** architecture-dependent configuration *************************************/
-
-/* first unset the macros (default) */
-#undef REPLACE_RA_BETWEEN_FRAMES
-#undef REPLACE_RA_TOP_OF_FRAME
-#undef REPLACE_RA_LINKAGE_AREA
-#undef REPLACE_LEAFMETHODS_RA_REGISTER
-
-/* i386, x86_64 and m68k */
-#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
-#define REPLACE_RA_BETWEEN_FRAMES
-/* alpha */
-#elif defined(__ALPHA__)
-#define REPLACE_RA_TOP_OF_FRAME
-#define REPLACE_LEAFMETHODS_RA_REGISTER
-/* powerpc */
-#elif defined(__POWERPC__)
-#define REPLACE_RA_LINKAGE_AREA
-#define REPLACE_LEAFMETHODS_RA_REGISTER
-/* s390 */
-#elif defined(__S390__)
-#define REPLACE_RA_TOP_OF_FRAME
-#endif
-
-
-/*** configuration of native stack slot size **********************************/
-
-/* XXX this should be in md-abi.h files, probably */
-
-#if defined(HAS_4BYTE_STACKSLOT)
-#define SIZE_OF_STACKSLOT 4
-#define STACK_SLOTS_PER_FLOAT 2
-typedef u4 stackslot_t;
-#else
-#define SIZE_OF_STACKSLOT 8
-#define STACK_SLOTS_PER_FLOAT 1
-typedef u8 stackslot_t;
-#endif
-
-
-/*** debugging ****************************************************************/
-
-#if !defined(NDEBUG)
-static void java_value_print(s4 type, replace_val_t value);
-static void replace_stackframeinfo_println(stackframeinfo_t *sfi);
-#endif
-
-#if !defined(NDEBUG)
-#define DOLOG(code) do{ if (opt_TraceReplacement > 1) { code; } } while(0)
-#define DOLOG_SHORT(code) do{ if (opt_TraceReplacement > 0) { code; } } while(0)
-#else
-#define DOLOG(code)
-#define DOLOG_SHORT(code)
-#endif
-
-
-/*** statistics ***************************************************************/
-
-#define REPLACE_STATISTICS
-
-#if defined(REPLACE_STATISTICS)
-
-static int stat_replacements = 0;
-static int stat_frames = 0;
-static int stat_recompile = 0;
-static int stat_staticpatch = 0;
-static int stat_unroll_inline = 0;
-static int stat_unroll_call = 0;
-static int stat_dist_frames[20] = { 0 };
-static int stat_dist_locals[20] = { 0 };
-static int stat_dist_locals_adr[10] = { 0 };
-static int stat_dist_locals_prim[10] = { 0 };
-static int stat_dist_locals_ret[10] = { 0 };
-static int stat_dist_locals_void[10] = { 0 };
-static int stat_dist_stack[10] = { 0 };
-static int stat_dist_stack_adr[10] = { 0 };
-static int stat_dist_stack_prim[10] = { 0 };
-static int stat_dist_stack_ret[10] = { 0 };
-static int stat_methods = 0;
-static int stat_rploints = 0;
-static int stat_regallocs = 0;
-static int stat_dist_method_rplpoints[20] = { 0 };
-
-#define REPLACE_COUNT(cnt) (cnt)++
-#define REPLACE_COUNT_IF(cnt, cond) do{ if(cond) (cnt)++; } while(0)
-#define REPLACE_COUNT_INC(cnt, inc) ((cnt) += (inc))
-
-#define REPLACE_COUNT_DIST(array, val) \
- do { \
- int limit = (sizeof(array) / sizeof(int)) - 1; \
- if ((val) < (limit)) (array)[val]++; \
- else (array)[limit]++; \
- } while (0)
-
-static void replace_statistics_source_frame(sourceframe_t *frame);
-
-#else
-
-#define REPLACE_COUNT(cnt)
-#define REPLACE_COUNT_IF(cnt, cond)
-#define REPLACE_COUNT_INC(cnt, inc)
-#define REPLACE_COUNT_DIST(array, val)
-
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-/*** constants used internally ************************************************/
-
-#define TOP_IS_NORMAL 0
-#define TOP_IS_ON_STACK 1
-#define TOP_IS_IN_ITMP1 2
-#define TOP_IS_VOID 3
-
-
-/******************************************************************************/
-/* PART I: Creating / freeing replacement points */
-/******************************************************************************/
-
-
-/* replace_create_replacement_point ********************************************
-
- Create a replacement point.
-
- IN:
- jd...............current jitdata
- iinfo............inlining info for the current position
- rp...............pre-allocated (uninitialized) rplpoint
- type.............RPLPOINT_TYPE constant
- iptr.............current instruction
- *pra.............current rplalloc pointer
- javalocals.......the javalocals at the current point
- stackvars........the stack variables at the current point
- stackdepth.......the stack depth at the current point
- paramcount.......number of parameters at the start of stackvars
-
- OUT:
- *rpa.............points to the next free rplalloc
-
-*******************************************************************************/
-
-static void replace_create_replacement_point(jitdata *jd,
- insinfo_inline *iinfo,
- rplpoint *rp,
- s4 type,
- instruction *iptr,
- rplalloc **pra,
- s4 *javalocals,
- s4 *stackvars,
- s4 stackdepth,
- s4 paramcount)
-{
- rplalloc *ra;
- s4 i;
- varinfo *v;
- s4 index;
-
- ra = *pra;
-
- REPLACE_COUNT(stat_rploints);
-
- rp->method = (iinfo) ? iinfo->method : jd->m;
- rp->pc = NULL; /* set by codegen */
- rp->callsize = 0; /* set by codegen */
- rp->regalloc = ra;
- rp->flags = 0;
- rp->type = type;
- rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
-
- /* XXX unify these two fields */
- rp->parent = (iinfo) ? iinfo->rp : NULL;
-
- /* store local allocation info of javalocals */
-
- if (javalocals) {
- for (i = 0; i < rp->method->maxlocals; ++i) {
- index = javalocals[i];
- if (index == UNUSED)
- continue;
-
- ra->index = i;
- if (index >= 0) {
- v = VAR(index);
- ra->flags = v->flags & (INMEMORY);
- ra->regoff = v->vv.regoff;
- ra->type = v->type;
- }
- else {
- ra->regoff = RETADDR_FROM_JAVALOCAL(index);
- ra->type = TYPE_RET;
- ra->flags = 0;
- }
- ra++;
- }
- }
-
- /* store allocation info of java stack vars */
-
- for (i = 0; i < stackdepth; ++i) {
- v = VAR(stackvars[i]);
- ra->flags = v->flags & (INMEMORY);
- ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
- ra->type = v->type;
- /* XXX how to handle locals on the stack containing returnAddresses? */
- if (v->type == TYPE_RET) {
- assert(stackvars[i] >= jd->localcount);
- ra->regoff = v->vv.retaddr->nr;
- }
- else
- ra->regoff = v->vv.regoff;
- ra++;
- }
-
- /* total number of allocations */
-
- rp->regalloccount = ra - rp->regalloc;
-
- *pra = ra;
-}
-
-
-/* replace_create_inline_start_replacement_point *******************************
-
- Create an INLINE_START replacement point.
-
- IN:
- jd...............current jitdata
- rp...............pre-allocated (uninitialized) rplpoint
- iptr.............current instruction
- *pra.............current rplalloc pointer
- javalocals.......the javalocals at the current point
-
- OUT:
- *rpa.............points to the next free rplalloc
-
- RETURN VALUE:
- the insinfo_inline * for the following inlined body
-
-*******************************************************************************/
-
-static insinfo_inline * replace_create_inline_start_replacement_point(
- jitdata *jd,
- rplpoint *rp,
- instruction *iptr,
- rplalloc **pra,
- s4 *javalocals)
-{
- insinfo_inline *calleeinfo;
- rplalloc *ra;
-
- calleeinfo = iptr->sx.s23.s3.inlineinfo;
-
- calleeinfo->rp = rp;
-
- replace_create_replacement_point(jd, calleeinfo->parent, rp,
- RPLPOINT_TYPE_INLINE, iptr, pra,
- javalocals,
- calleeinfo->stackvars, calleeinfo->stackvarscount,
- calleeinfo->paramcount);
-
- if (calleeinfo->synclocal != UNUSED) {
- ra = (*pra)++;
- ra->index = RPLALLOC_SYNC;
- ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
- ra->flags = jd->var[calleeinfo->synclocal].flags & INMEMORY;
- ra->type = TYPE_ADR;
-
- rp->regalloccount++;
- }
-
- return calleeinfo;
-}
-
-
-/* replace_create_replacement_points *******************************************
-
- Create the replacement points for the given code.
-
- IN:
- jd...............current jitdata, must not have any replacement points
-
- OUT:
- code->rplpoints.......set to the list of replacement points
- code->rplpointcount...number of replacement points
- code->regalloc........list of allocation info
- code->regalloccount...total length of allocation info list
- code->globalcount.....number of global allocations at the
- start of code->regalloc
-
- RETURN VALUE:
- true.............everything ok
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#define CLEAR_javalocals(array, method) \
- do { \
- for (i=0; i<(method)->maxlocals; ++i) \
- (array)[i] = UNUSED; \
- } while (0)
-
-#define COPY_OR_CLEAR_javalocals(dest, array, method) \
- do { \
- if ((array) != NULL) \
- MCOPY((dest), (array), s4, (method)->maxlocals); \
- else \
- CLEAR_javalocals((dest), (method)); \
- } while (0)
-
-#define COUNT_javalocals(array, method, counter) \
- do { \
- for (i=0; i<(method)->maxlocals; ++i) \
- if ((array)[i] != UNUSED) \
- (counter)++; \
- } while (0)
-
-bool replace_create_replacement_points(jitdata *jd)
-{
- codeinfo *code;
- registerdata *rd;
- basicblock *bptr;
- int count;
- methodinfo *m;
- rplpoint *rplpoints;
- rplpoint *rp;
- int alloccount;
- rplalloc *regalloc;
- rplalloc *ra;
- int i;
- instruction *iptr;
- instruction *iend;
- s4 *javalocals;
- s4 *jl;
- methoddesc *md;
- insinfo_inline *iinfo;
- s4 startcount;
- s4 firstcount;
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
- bool needentry;
-#endif
-
- REPLACE_COUNT(stat_methods);
-
- /* get required compiler data */
-
- code = jd->code;
- rd = jd->rd;
-
- /* assert that we wont overwrite already allocated data */
-
- assert(code);
- assert(code->m);
- assert(code->rplpoints == NULL);
- assert(code->rplpointcount == 0);
- assert(code->regalloc == NULL);
- assert(code->regalloccount == 0);
- assert(code->globalcount == 0);
-
- m = code->m;
-
- /* in instance methods, we may need a rplpoint at the method entry */
-
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
- if (!(m->flags & ACC_STATIC)) {
- jd->basicblocks[0].bitflags |= BBFLAG_REPLACEMENT;
- needentry = true;
- }
- else {
- needentry = false;
- }
-#endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
-
- /* iterate over the basic block list to find replacement points */
-
- count = 0;
- alloccount = 0;
-
- javalocals = DMNEW(s4, jd->maxlocals);
-
- for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
-
- /* skip dead code */
-
- if (bptr->flags < BBFINISHED)
- continue;
-
- /* get info about this block */
-
- m = bptr->method;
- iinfo = bptr->inlineinfo;
-
- /* initialize javalocals at the start of this block */
-
- COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
-
- /* iterate over the instructions */
-
- iptr = bptr->iinstr;
- iend = iptr + bptr->icount;
- startcount = count;
- firstcount = count;
-
- for (; iptr != iend; ++iptr) {
- switch (iptr->opc) {
-#if defined(ENABLE_GC_CACAO)
- case ICMD_BUILTIN:
- md = iptr->sx.s23.s3.bte->md;
- count++;
- COUNT_javalocals(javalocals, m, alloccount);
- alloccount += iptr->s1.argcount;
- if (iinfo)
- alloccount -= iinfo->throughcount;
- break;
-#endif
-
- case ICMD_INVOKESTATIC:
- case ICMD_INVOKESPECIAL:
- case ICMD_INVOKEVIRTUAL:
- case ICMD_INVOKEINTERFACE:
- INSTRUCTION_GET_METHODDESC(iptr, md);
- count++;
- COUNT_javalocals(javalocals, m, alloccount);
- alloccount += iptr->s1.argcount;
- if (iinfo)
- alloccount -= iinfo->throughcount;
- break;
-
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_ASTORE:
- stack_javalocals_store(iptr, javalocals);
- break;
-
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- alloccount += 1;
- /* FALLTHROUGH! */
- case ICMD_RETURN:
- count++;
- break;
-
- case ICMD_INLINE_START:
- iinfo = iptr->sx.s23.s3.inlineinfo;
-
- count++;
- COUNT_javalocals(javalocals, m, alloccount);
- alloccount += iinfo->stackvarscount;
- if (iinfo->synclocal != UNUSED)
- alloccount++;
-
- m = iinfo->method;
- /* javalocals may be set at next block start, or now */
- COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
- break;
-
- case ICMD_INLINE_BODY:
- assert(iinfo == iptr->sx.s23.s3.inlineinfo);
-
- jl = iinfo->javalocals_start;
- if (jl == NULL) {
- /* get the javalocals from the following block start */
- assert(bptr->next);
- jl = bptr->next->javalocals;
- }
- count++;
- COUNT_javalocals(jl, m, alloccount);
- break;
-
- case ICMD_INLINE_END:
- assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
- iinfo == iptr->sx.s23.s3.inlineinfo->parent);
- iinfo = iptr->sx.s23.s3.inlineinfo;
- m = iinfo->outer;
- if (iinfo->javalocals_end)
- MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
- iinfo = iinfo->parent;
- break;
- }
-
- if (iptr == bptr->iinstr)
- firstcount = count;
- } /* end instruction loop */
-
- /* create replacement points at targets of backward branches */
- /* We only need the replacement point there, if there is no */
- /* replacement point inside the block. */
-
- if (bptr->bitflags & BBFLAG_REPLACEMENT) {
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
- int test = (needentry && bptr == jd->basicblocks) ? firstcount : count;
-#else
- int test = count;
-#endif
- if (test > startcount) {
- /* we don't need an extra rplpoint */
- bptr->bitflags &= ~BBFLAG_REPLACEMENT;
- }
- else {
- count++;
- alloccount += bptr->indepth;
- if (bptr->inlineinfo)
- alloccount -= bptr->inlineinfo->throughcount;
-
- COUNT_javalocals(bptr->javalocals, bptr->method, alloccount);
- }
- }
-
- } /* end basicblock loop */
-
- /* if no points were found, there's nothing to do */
-
- if (!count)
- return true;
-
- /* allocate replacement point array and allocation array */
-
- rplpoints = MNEW(rplpoint, count);
- regalloc = MNEW(rplalloc, alloccount);
- ra = regalloc;
-
- /* initialize replacement point structs */
-
- rp = rplpoints;
-
- /* XXX try to share code with the counting loop! */
-
- for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
- /* skip dead code */
-
- if (bptr->flags < BBFINISHED)
- continue;
-
- /* get info about this block */
-
- m = bptr->method;
- iinfo = bptr->inlineinfo;
-
- /* initialize javalocals at the start of this block */
-
- COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
-
- /* create replacement points at targets of backward branches */
-
- if (bptr->bitflags & BBFLAG_REPLACEMENT) {
-
- i = (iinfo) ? iinfo->throughcount : 0;
- replace_create_replacement_point(jd, iinfo, rp++,
- bptr->type, bptr->iinstr, &ra,
- bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
-
- if (JITDATA_HAS_FLAG_COUNTDOWN(jd))
- rp[-1].flags |= RPLPOINT_FLAG_COUNTDOWN;
- }
-
- /* iterate over the instructions */
-
- iptr = bptr->iinstr;
- iend = iptr + bptr->icount;
-
- for (; iptr != iend; ++iptr) {
- switch (iptr->opc) {
-#if defined(ENABLE_GC_CACAO)
- case ICMD_BUILTIN:
- md = iptr->sx.s23.s3.bte->md;
-
- i = (iinfo) ? iinfo->throughcount : 0;
- replace_create_replacement_point(jd, iinfo, rp++,
- RPLPOINT_TYPE_CALL, iptr, &ra,
- javalocals, iptr->sx.s23.s2.args,
- iptr->s1.argcount - i,
- md->paramcount);
- break;
-#endif
-
- case ICMD_INVOKESTATIC:
- case ICMD_INVOKESPECIAL:
- case ICMD_INVOKEVIRTUAL:
- case ICMD_INVOKEINTERFACE:
- INSTRUCTION_GET_METHODDESC(iptr, md);
-
- i = (iinfo) ? iinfo->throughcount : 0;
- replace_create_replacement_point(jd, iinfo, rp++,
- RPLPOINT_TYPE_CALL, iptr, &ra,
- javalocals, iptr->sx.s23.s2.args,
- iptr->s1.argcount - i,
- md->paramcount);
- break;
-
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_ASTORE:
- stack_javalocals_store(iptr, javalocals);
- break;
-
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- replace_create_replacement_point(jd, iinfo, rp++,
- RPLPOINT_TYPE_RETURN, iptr, &ra,
- NULL, &(iptr->s1.varindex), 1, 0);
- break;
-
- case ICMD_RETURN:
- replace_create_replacement_point(jd, iinfo, rp++,
- RPLPOINT_TYPE_RETURN, iptr, &ra,
- NULL, NULL, 0, 0);
- break;
-
- case ICMD_INLINE_START:
- iinfo = replace_create_inline_start_replacement_point(
- jd, rp++, iptr, &ra, javalocals);
- m = iinfo->method;
- /* javalocals may be set at next block start, or now */
- COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
- break;
-
- case ICMD_INLINE_BODY:
- assert(iinfo == iptr->sx.s23.s3.inlineinfo);
-
- jl = iinfo->javalocals_start;
- if (jl == NULL) {
- /* get the javalocals from the following block start */
- assert(bptr->next);
- jl = bptr->next->javalocals;
- }
- /* create a non-trappable rplpoint */
- replace_create_replacement_point(jd, iinfo, rp++,
- RPLPOINT_TYPE_BODY, iptr, &ra,
- jl, NULL, 0, 0);
- rp[-1].flags |= RPLPOINT_FLAG_NOTRAP;
- break;
-
- case ICMD_INLINE_END:
- assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
- iinfo == iptr->sx.s23.s3.inlineinfo->parent);
- iinfo = iptr->sx.s23.s3.inlineinfo;
- m = iinfo->outer;
- if (iinfo->javalocals_end)
- MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
- iinfo = iinfo->parent;
- break;
- }
- } /* end instruction loop */
- } /* end basicblock loop */
-
- assert((rp - rplpoints) == count);
- assert((ra - regalloc) == alloccount);
-
- /* store the data in the codeinfo */
-
- code->rplpoints = rplpoints;
- code->rplpointcount = count;
- code->regalloc = regalloc;
- code->regalloccount = alloccount;
- code->globalcount = 0;
- code->savedintcount = INT_SAV_CNT - rd->savintreguse;
- code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- code->savedadrcount = ADR_SAV_CNT - rd->savadrreguse;
-#endif
- code->memuse = rd->memuse;
- code->stackframesize = jd->cd->stackframesize;
-
- REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
- REPLACE_COUNT_INC(stat_regallocs, alloccount);
-
- /* everything alright */
-
- return true;
-}
-
-
-/* replace_free_replacement_points *********************************************
-
- Free memory used by replacement points.
-
- IN:
- code.............codeinfo whose replacement points should be freed.
-
-*******************************************************************************/
-
-void replace_free_replacement_points(codeinfo *code)
-{
- assert(code);
-
- if (code->rplpoints)
- MFREE(code->rplpoints,rplpoint,code->rplpointcount);
-
- if (code->regalloc)
- MFREE(code->regalloc,rplalloc,code->regalloccount);
-
- code->rplpoints = NULL;
- code->rplpointcount = 0;
- code->regalloc = NULL;
- code->regalloccount = 0;
- code->globalcount = 0;
-}
-
-
-/******************************************************************************/
-/* PART II: Activating / deactivating replacement points */
-/******************************************************************************/
-
-
-/* replace_activate_replacement_points *****************************************
-
- Activate the replacement points of the given compilation unit. When this
- function returns, the replacement points are "armed", so each thread
- reaching one of the points will enter the replacement mechanism.
-
- IN:
- code.............codeinfo of which replacement points should be
- activated
- mappable.........if true, only mappable replacement points are
- activated
-
-*******************************************************************************/
-
-void replace_activate_replacement_points(codeinfo *code, bool mappable)
-{
- rplpoint *rp;
- s4 i;
- s4 count;
- u1 *savedmcode;
-
- assert(code->savedmcode == NULL);
-
- /* count trappable replacement points */
-
- count = 0;
- i = code->rplpointcount;
- rp = code->rplpoints;
- for (; i--; rp++) {
- if (rp->flags & RPLPOINT_FLAG_NOTRAP)
- continue;
-
- if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
- continue;
-
- count++;
- }
-
- /* allocate buffer for saved machine code */
-
- savedmcode = MNEW(u1, count * REPLACEMENT_PATCH_SIZE);
- code->savedmcode = savedmcode;
- savedmcode += count * REPLACEMENT_PATCH_SIZE;
-
- /* activate trappable replacement points */
- /* (in reverse order to handle overlapping points within basic blocks) */
-
- i = code->rplpointcount;
- rp = code->rplpoints + i;
- while (rp--, i--) {
- assert(!(rp->flags & RPLPOINT_FLAG_ACTIVE));
-
- if (rp->flags & RPLPOINT_FLAG_NOTRAP)
- continue;
-
- if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
- continue;
-
- DOLOG( printf("activate replacement point:\n");
- replace_replacement_point_println(rp, 1); fflush(stdout); );
-
- savedmcode -= REPLACEMENT_PATCH_SIZE;
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_DISASSEMBLER)
- DOLOG( printf("\tinstruction before: ");
- disassinstr(rp->pc); fflush(stdout); );
-# endif
-
- md_patch_replacement_point(rp->pc, savedmcode, false);
-
-# if defined(ENABLE_DISASSEMBLER)
- DOLOG( printf("\tinstruction after : ");
- disassinstr(rp->pc); fflush(stdout); );
-# endif
-#endif
-
- rp->flags |= RPLPOINT_FLAG_ACTIVE;
- }
-
- assert(savedmcode == code->savedmcode);
-}
-
-
-/* replace_deactivate_replacement_points ***************************************
-
- Deactivate a replacement points in the given compilation unit.
- When this function returns, the replacement points will be "un-armed",
- that is a each thread reaching a point will just continue normally.
-
- IN:
- code.............the compilation unit
-
-*******************************************************************************/
-
-void replace_deactivate_replacement_points(codeinfo *code)
-{
- rplpoint *rp;
- s4 i;
- s4 count;
- u1 *savedmcode;
-
- if (code->savedmcode == NULL) {
- /* disarm countdown points by patching the branches */
-
- i = code->rplpointcount;
- rp = code->rplpoints;
- for (; i--; rp++) {
- if ((rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))
- == RPLPOINT_FLAG_COUNTDOWN)
- {
-#if 0
- *(s4*) (rp->pc + 9) = 0; /* XXX machine dependent! */
-#endif
- }
- }
- return;
- }
-
- assert(code->savedmcode != NULL);
- savedmcode = code->savedmcode;
-
- /* de-activate each trappable replacement point */
-
- i = code->rplpointcount;
- rp = code->rplpoints;
- count = 0;
- for (; i--; rp++) {
- if (!(rp->flags & RPLPOINT_FLAG_ACTIVE))
- continue;
-
- count++;
-
- DOLOG( printf("deactivate replacement point:\n");
- replace_replacement_point_println(rp, 1); fflush(stdout); );
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_DISASSEMBLER)
- DOLOG( printf("\tinstruction before: ");
- disassinstr(rp->pc); fflush(stdout); );
-# endif
-
- md_patch_replacement_point(rp->pc, savedmcode, true);
-
-# if defined(ENABLE_DISASSEMBLER)
- DOLOG( printf("\tinstruction before: ");
- disassinstr(rp->pc); fflush(stdout); );
-# endif
-#endif
-
- rp->flags &= ~RPLPOINT_FLAG_ACTIVE;
-
- savedmcode += REPLACEMENT_PATCH_SIZE;
- }
-
- assert(savedmcode == code->savedmcode + count * REPLACEMENT_PATCH_SIZE);
-
- /* free saved machine code */
-
- MFREE(code->savedmcode, u1, count * REPLACEMENT_PATCH_SIZE);
- code->savedmcode = NULL;
-}
-
-
-/******************************************************************************/
-/* PART III: The replacement mechanism */
-/******************************************************************************/
-
-
-/* replace_read_value **********************************************************
-
- Read a value with the given allocation from the execution state.
-
- IN:
- es...............execution state
- ra...............allocation
- javaval..........where to put the value
-
- OUT:
- *javaval.........the value
-
-*******************************************************************************/
-
-static void replace_read_value(executionstate_t *es,
- rplalloc *ra,
- replace_val_t *javaval)
-{
- if (ra->flags & INMEMORY) {
- /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
-#ifdef HAS_4BYTE_STACKSLOT
- if (IS_2_WORD_TYPE(ra->type)) {
- javaval->l = *(u8*)(es->sp + ra->regoff);
- }
- else {
-#endif
- javaval->p = *(ptrint*)(es->sp + ra->regoff);
-#ifdef HAS_4BYTE_STACKSLOT
- }
-#endif
- }
- else {
- /* allocated register */
- if (IS_FLT_DBL_TYPE(ra->type)) {
- javaval->d = es->fltregs[ra->regoff];
-
- if (ra->type == TYPE_FLT)
- javaval->f = javaval->d;
- }
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- else if (IS_ADR_TYPE(ra->type)) {
- javaval->p = es->adrregs[ra->regoff];
- }
-#endif
- else {
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (ra->type == TYPE_LNG) {
- javaval->words.lo = es->intregs[GET_LOW_REG(ra->regoff)];
- javaval->words.hi = es->intregs[GET_HIGH_REG(ra->regoff)];
- }
- else
-#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
- javaval->p = es->intregs[ra->regoff];
- }
- }
-}
-
-
-/* replace_write_value *********************************************************
-
- Write a value to the given allocation in the execution state.
-
- IN:
- es...............execution state
- ra...............allocation
- *javaval.........the value
-
-*******************************************************************************/
-
-static void replace_write_value(executionstate_t *es,
- rplalloc *ra,
- replace_val_t *javaval)
-{
- if (ra->flags & INMEMORY) {
- /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
-#ifdef HAS_4BYTE_STACKSLOT
- if (IS_2_WORD_TYPE(ra->type)) {
- *(u8*)(es->sp + ra->regoff) = javaval->l;
- }
- else {
-#endif
- *(ptrint*)(es->sp + ra->regoff) = javaval->p;
-#ifdef HAS_4BYTE_STACKSLOT
- }
-#endif
- }
- else {
- /* allocated register */
- switch (ra->type) {
- case TYPE_FLT:
- es->fltregs[ra->regoff] = (double) javaval->f;
- break;
- case TYPE_DBL:
- es->fltregs[ra->regoff] = javaval->d;
- break;
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- case TYPE_LNG:
- es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo;
- es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi;
- break;
-#endif
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- case TYPE_ADR:
- es->adrregs[ra->regoff] = javaval->p;
-#endif
- default:
- es->intregs[ra->regoff] = javaval->p;
- }
- }
-}
-
-
-/* replace_new_sourceframe *****************************************************
-
- Allocate a new source frame and insert it at the front of the frame list.
-
- IN:
- ss...............the source state
-
- OUT:
- ss->frames.......set to new frame (the new head of the frame list).
-
- RETURN VALUE:
- returns the new frame
-
-*******************************************************************************/
-
-static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
-{
- sourceframe_t *frame;
-
- frame = DNEW(sourceframe_t);
- MZERO(frame, sourceframe_t, 1);
-
- frame->down = ss->frames;
- ss->frames = frame;
-
- return frame;
-}
-
-
-/* replace_read_executionstate *************************************************
-
- Read a source frame from the given executions state.
- The new source frame is pushed to the front of the frame list of the
- source state.
-
- IN:
- rp...............replacement point at which `es` was taken
- es...............execution state
- ss...............the source state to add the source frame to
- topframe.........true, if the first (top-most) source frame on the
- stack is to be read
-
- OUT:
- *ss..............the source state with the newly created source frame
- added
-
-*******************************************************************************/
-
-static s4 replace_normalize_type_map[] = {
-/* RPLPOINT_TYPE_STD |--> */ RPLPOINT_TYPE_STD,
-/* RPLPOINT_TYPE_EXH |--> */ RPLPOINT_TYPE_STD,
-/* RPLPOINT_TYPE_SBR |--> */ RPLPOINT_TYPE_STD,
-/* RPLPOINT_TYPE_CALL |--> */ RPLPOINT_TYPE_CALL,
-/* RPLPOINT_TYPE_INLINE |--> */ RPLPOINT_TYPE_CALL,
-/* RPLPOINT_TYPE_RETURN |--> */ RPLPOINT_TYPE_RETURN,
-/* RPLPOINT_TYPE_BODY |--> */ RPLPOINT_TYPE_STD
-};
-
-
-static void replace_read_executionstate(rplpoint *rp,
- executionstate_t *es,
- sourcestate_t *ss,
- bool topframe)
-{
- methodinfo *m;
- codeinfo *code;
- int count;
- int i;
- rplalloc *ra;
- sourceframe_t *frame;
- int topslot;
- stackslot_t *sp;
- stackslot_t *basesp;
-
- code = code_find_codeinfo_for_pc(rp->pc);
- m = rp->method;
- topslot = TOP_IS_NORMAL;
-
- /* stack pointer */
-
- sp = (stackslot_t *) es->sp;
-
- /* in some cases the top stack slot is passed in REG_ITMP1 */
-
- if (rp->type == BBTYPE_EXH) {
- topslot = TOP_IS_IN_ITMP1;
- }
-
- /* calculate base stack pointer */
-
- basesp = sp + code->stackframesize;
-
- /* create the source frame */
-
- frame = replace_new_sourceframe(ss);
- frame->method = rp->method;
- frame->id = rp->id;
- assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
- frame->type = replace_normalize_type_map[rp->type];
- frame->fromrp = rp;
- frame->fromcode = code;
-
- /* read local variables */
-
- count = m->maxlocals;
- frame->javalocalcount = count;
- frame->javalocals = DMNEW(replace_val_t, count);
- frame->javalocaltype = DMNEW(u1, count);
-
- /* mark values as undefined */
- for (i=0; i<count; ++i) {
-#if !defined(NDEBUG)
- frame->javalocals[i].l = (u8) 0x00dead0000dead00ULL;
-#endif
- frame->javalocaltype[i] = TYPE_VOID;
- }
-
- /* some entries in the intregs array are not meaningful */
- /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
-#if !defined(NDEBUG)
- es->intregs[REG_SP ] = (ptrint) 0x11dead1111dead11ULL;
-#ifdef REG_PV
- es->intregs[REG_PV ] = (ptrint) 0x11dead1111dead11ULL;
-#endif
-#endif /* !defined(NDEBUG) */
-
- /* read javalocals */
-
- count = rp->regalloccount;
- ra = rp->regalloc;
-
- while (count && (i = ra->index) >= 0) {
- assert(i < m->maxlocals);
- frame->javalocaltype[i] = ra->type;
- if (ra->type == TYPE_RET)
- frame->javalocals[i].i = ra->regoff;
- else
- replace_read_value(es, ra, frame->javalocals + i);
- ra++;
- count--;
- }
-
- /* read instance, if this is the first rplpoint */
-
-#if defined(REPLACE_PATCH_DYNAMIC_CALL)
- if (topframe && !(rp->method->flags & ACC_STATIC) && rp == code->rplpoints) {
-#if 1
- /* we are at the start of the method body, so if local 0 is set, */
- /* it is the instance. */
- if (frame->javalocaltype[0] == TYPE_ADR)
- frame->instance = frame->javalocals[0];
-#else
- rplalloc instra;
- methoddesc *md;
-
- md = rp->method->parseddesc;
- assert(md->params);
- assert(md->paramcount >= 1);
- instra.type = TYPE_ADR;
- instra.regoff = md->params[0].regoff;
- if (md->params[0].inmemory) {
- instra.flags = INMEMORY;
- instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT;
- }
- else {
- instra.flags = 0;
- }
- 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 */
-
- frame->javastackdepth = count;
- frame->javastack = DMNEW(replace_val_t, count);
- frame->javastacktype = DMNEW(u1, count);
-
-#if !defined(NDEBUG)
- /* mark values as undefined */
- for (i=0; i<count; ++i) {
- frame->javastack[i].l = (u8) 0x00dead0000dead00ULL;
- frame->javastacktype[i] = TYPE_VOID;
- }
-#endif /* !defined(NDEBUG) */
-
- i = 0;
-
- /* the first stack slot is special in SBR and EXH blocks */
-
- if (topslot == TOP_IS_ON_STACK) {
- assert(count);
-
- assert(ra->index == RPLALLOC_STACK);
- assert(ra->type == TYPE_ADR);
- frame->javastack[i].p = sp[-1];
- frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
- count--;
- i++;
- ra++;
- }
- else if (topslot == TOP_IS_IN_ITMP1) {
- assert(count);
-
- assert(ra->index == RPLALLOC_STACK);
- assert(ra->type == TYPE_ADR);
- frame->javastack[i].p = es->intregs[REG_ITMP1];
- frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
- count--;
- i++;
- ra++;
- }
- else if (topslot == TOP_IS_VOID) {
- assert(count);
-
- assert(ra->index == RPLALLOC_STACK);
- frame->javastack[i].l = 0;
- frame->javastacktype[i] = TYPE_VOID;
- count--;
- i++;
- ra++;
- }
-
- /* read remaining stack slots */
-
- for (; count--; ra++) {
- if (ra->index == RPLALLOC_SYNC) {
- assert(rp->type == RPLPOINT_TYPE_INLINE);
-
- /* only read synchronization slots when traversing an inline point */
-
- if (!topframe) {
- sourceframe_t *calleeframe = frame->down;
- assert(calleeframe);
- assert(calleeframe->syncslotcount == 0);
- assert(calleeframe->syncslots == NULL);
-
- calleeframe->syncslotcount = 1;
- calleeframe->syncslots = DMNEW(replace_val_t, 1);
- replace_read_value(es,ra,calleeframe->syncslots);
- }
-
- frame->javastackdepth--;
- continue;
- }
-
- assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
-
- /* do not read parameters of calls down the call chain */
-
- if (!topframe && ra->index == RPLALLOC_PARAM) {
- frame->javastackdepth--;
- }
- else {
- if (ra->type == TYPE_RET)
- frame->javastack[i].i = ra->regoff;
- else
- replace_read_value(es,ra,frame->javastack + i);
- frame->javastacktype[i] = ra->type;
- i++;
- }
- }
-}
-
-
-/* replace_write_executionstate ************************************************
-
- Pop a source frame from the front of the frame list of the given source state
- and write its values into the execution state.
-
- IN:
- rp...............replacement point for which execution state should be
- created
- es...............the execution state to modify
- ss...............the given source state
- topframe.........true, if this is the last (top-most) source frame to be
- translated
-
- OUT:
- *es..............the execution state derived from the source state
-
-*******************************************************************************/
-
-static void replace_write_executionstate(rplpoint *rp,
- executionstate_t *es,
- sourcestate_t *ss,
- bool topframe)
-{
- methodinfo *m;
- codeinfo *code;
- int count;
- int i;
- rplalloc *ra;
- sourceframe_t *frame;
- int topslot;
- stackslot_t *sp;
- stackslot_t *basesp;
-
- code = code_find_codeinfo_for_pc(rp->pc);
- m = rp->method;
- topslot = TOP_IS_NORMAL;
-
- /* pop a source frame */
-
- frame = ss->frames;
- assert(frame);
- ss->frames = frame->down;
-
- /* calculate stack pointer */
-
- sp = (stackslot_t *) es->sp;
-
- basesp = sp + code->stackframesize;
-
- /* in some cases the top stack slot is passed in REG_ITMP1 */
-
- if (rp->type == BBTYPE_EXH) {
- topslot = TOP_IS_IN_ITMP1;
- }
-
- /* write javalocals */
-
- ra = rp->regalloc;
- count = rp->regalloccount;
-
- while (count && (i = ra->index) >= 0) {
- assert(i < m->maxlocals);
- assert(i < frame->javalocalcount);
- assert(ra->type == frame->javalocaltype[i]);
- if (ra->type == TYPE_RET) {
- /* XXX assert that it matches this rplpoint */
- }
- else
- replace_write_value(es, ra, frame->javalocals + i);
- count--;
- ra++;
- }
-
- /* write stack slots */
-
- i = 0;
-
- /* the first stack slot is special in SBR and EXH blocks */
-
- if (topslot == TOP_IS_ON_STACK) {
- assert(count);
-
- assert(ra->index == RPLALLOC_STACK);
- assert(i < frame->javastackdepth);
- assert(frame->javastacktype[i] == TYPE_ADR);
- sp[-1] = frame->javastack[i].p;
- count--;
- i++;
- ra++;
- }
- else if (topslot == TOP_IS_IN_ITMP1) {
- assert(count);
-
- assert(ra->index == RPLALLOC_STACK);
- assert(i < frame->javastackdepth);
- assert(frame->javastacktype[i] == TYPE_ADR);
- es->intregs[REG_ITMP1] = frame->javastack[i].p;
- count--;
- i++;
- ra++;
- }
- else if (topslot == TOP_IS_VOID) {
- assert(count);
-
- assert(ra->index == RPLALLOC_STACK);
- assert(i < frame->javastackdepth);
- assert(frame->javastacktype[i] == TYPE_VOID);
- count--;
- i++;
- ra++;
- }
-
- /* write remaining stack slots */
-
- for (; count--; ra++) {
- if (ra->index == RPLALLOC_SYNC) {
- assert(rp->type == RPLPOINT_TYPE_INLINE);
-
- /* only write synchronization slots when traversing an inline point */
-
- if (!topframe) {
- assert(frame->down);
- assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
- assert(frame->down->syncslots != NULL);
-
- replace_write_value(es,ra,frame->down->syncslots);
- }
- continue;
- }
-
- assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
-
- /* do not write parameters of calls down the call chain */
-
- 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);
- assert(ra->type == frame->javastacktype[i]);
- if (ra->type == TYPE_RET) {
- /* XXX assert that it matches this rplpoint */
- }
- else {
- replace_write_value(es,ra,frame->javastack + i);
- }
- i++;
- }
- }
-
- /* set new pc */
-
- es->pc = rp->pc;
-}
-
-
-/* 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.
-
- *** This function imitates the effects of the method epilog ***
- *** and returning from the method call. ***
-
- IN:
- es...............execution state
-
- OUT:
- *es..............the execution state after popping the stack frame
- NOTE: es->code and es->pv are NOT updated.
-
-*******************************************************************************/
-
-void md_pop_stackframe(executionstate_t *es)
-{
- u1 *ra;
- s4 ra_align_off;
- s4 reg;
- s4 i;
- stackslot_t *basesp;
- stackslot_t *sp;
-
- assert(es->code);
-
- /* 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 = es->ra;
- else
-#endif
- ra = md_stacktrace_get_returnaddress(es->sp,
- 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;
-
- /* 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->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->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
-#endif /* REPLACE_RA_LINKAGE_AREA */
-
- /* restore saved int registers */
-
- reg = INT_REG_CNT;
- for (i=0; i<es->code->savedintcount; ++i) {
- while (nregdescint[--reg] != REG_SAV)
- ;
- es->intregs[reg] = *--basesp;
- }
-
- /* restore saved flt registers */
-
- /* XXX align? */
- reg = FLT_REG_CNT;
- for (i=0; i<es->code->savedfltcount; ++i) {
- while (nregdescfloat[--reg] != REG_SAV)
- ;
- basesp -= STACK_SLOTS_PER_FLOAT;
- es->fltregs[reg] = *(double*)basesp;
- }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- /* restore saved adr registers */
-
- reg = ADR_REG_CNT;
- for (i=0; i<es->code->savedadrcount; ++i) {
- while (nregdescadr[--reg] != REG_SAV)
- ;
- es->adrregs[reg] = *--basesp;
- }
-#endif
-
- /* adjust the stackpointer */
-
- es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
-
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
- es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
-#endif
-
- /* set the program counter to the return address */
-
- 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)
- es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
- for (i=0; i<FLT_REG_CNT; ++i)
- if (nregdescfloat[i] != REG_SAV)
- *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
-# if defined(HAS_ADDRESS_REGISTER_FILE)
- for (i=0; i<ADR_REG_CNT; ++i)
- if (nregdescadr[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;
-}
-
-
-/* replace_patch_method_pointer ************************************************
-
- Patch a method pointer (may be in code, data segment, vftbl, or interface
- table).
-
- IN:
- mpp..............address of the method pointer to patch
- entrypoint.......the new entrypoint of the method
- kind.............kind of call to patch, used only for debugging
-
-*******************************************************************************/
-
-static void replace_patch_method_pointer(methodptr *mpp,
- methodptr entrypoint,
- const char *kind)
-{
-#if !defined(NDEBUG)
- codeinfo *oldcode;
- codeinfo *newcode;
-#endif
-
- DOLOG( printf("patch method pointer from: %p to %p\n",
- (void*) *mpp, (void*)entrypoint); );
-
-#if !defined(NDEBUG)
- oldcode = code_get_codeinfo_for_pv(*mpp);
- newcode = code_get_codeinfo_for_pv(entrypoint);
-
- DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode);
- method_println(oldcode->m);
- printf("\t with %p ", (void*) newcode);
- method_println(newcode->m); );
-
- assert(oldcode->m == newcode->m);
-#endif
-
- /* write the new entrypoint */
-
- *mpp = (methodptr) entrypoint;
-}
-
-
-/* replace_patch_class *********************************************************
-
- Patch a method in the given class.
-
- IN:
- vftbl............vftbl of the class
- m................the method to patch
- oldentrypoint....the old entrypoint to replace
- entrypoint.......the new entrypoint
-
-*******************************************************************************/
-
-void replace_patch_class(vftbl_t *vftbl,
- methodinfo *m,
- u1 *oldentrypoint,
- u1 *entrypoint)
-{
- s4 i;
- methodptr *mpp;
- methodptr *mppend;
-
- /* patch the vftbl of the class */
-
- replace_patch_method_pointer(vftbl->table + m->vftblindex,
- entrypoint,
- "virtual ");
-
- /* patch the interface tables */
-
- assert(oldentrypoint);
-
- for (i=0; i < vftbl->interfacetablelength; ++i) {
- mpp = vftbl->interfacetable[-i];
- mppend = mpp + vftbl->interfacevftbllength[i];
- for (; mpp != mppend; ++mpp)
- if (*mpp == oldentrypoint) {
- replace_patch_method_pointer(mpp, entrypoint, "interface");
- }
- }
-}
-
-
-/* replace_patch_class_hierarchy ***********************************************
-
- Patch a method in all loaded classes.
-
- IN:
- m................the method to patch
- oldentrypoint....the old entrypoint to replace
- entrypoint.......the new entrypoint
-
-*******************************************************************************/
-
-struct replace_patch_data_t {
- methodinfo *m;
- u1 *oldentrypoint;
- u1 *entrypoint;
-};
-
-void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
-{
- vftbl_t *vftbl = c->vftbl;
-
- if (vftbl != NULL
- && vftbl->vftbllength > pd->m->vftblindex
- && vftbl->table[pd->m->vftblindex] != &asm_abstractmethoderror
- && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
- {
- replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
- }
-}
-
-void replace_patch_class_hierarchy(methodinfo *m,
- u1 *oldentrypoint,
- u1 *entrypoint)
-{
- struct replace_patch_data_t pd;
-
- pd.m = m;
- pd.oldentrypoint = oldentrypoint;
- pd.entrypoint = entrypoint;
-
- DOLOG_SHORT( printf("patching class hierarchy: ");
- method_println(m); );
-
- classcache_foreach_loaded_class(
- (classcache_foreach_functionptr_t) &replace_patch_callback,
- (void*) &pd);
-}
-
-
-/* replace_patch_future_calls **************************************************
-
- Analyse a call site and depending on the kind of call patch the call, the
- virtual function table, or the interface table.
-
- IN:
- ra...............return address pointing after the call site
- callerframe......source frame of the caller
- calleeframe......source frame of the callee, must have been mapped
-
-*******************************************************************************/
-
-void replace_patch_future_calls(u1 *ra,
- sourceframe_t *callerframe,
- sourceframe_t *calleeframe)
-{
- u1 *patchpos;
- methodptr entrypoint;
- methodptr oldentrypoint;
- bool atentry;
- void *pv;
- codeinfo *calleecode;
- methodinfo *calleem;
- java_object_t *obj;
- vftbl_t *vftbl;
-
- assert(ra);
- assert(callerframe->down == calleeframe);
-
- /* get the new codeinfo and the method that shall be entered */
-
- calleecode = calleeframe->tocode;
- assert(calleecode);
-
- calleem = calleeframe->method;
- assert(calleem == calleecode->m);
-
- entrypoint = (methodptr) calleecode->entrypoint;
-
- /* check if we are at an method entry rplpoint at the innermost frame */
-
- atentry = (calleeframe->down == NULL)
- && !(calleem->flags & ACC_STATIC)
- && (calleeframe->fromrp->id == 0); /* XXX */
-
- /* get the position to patch, in case it was a statically bound call */
-
- pv = callerframe->fromcode->entrypoint;
- patchpos = md_jit_method_patch_address(pv, ra, NULL);
-
- if (patchpos == NULL) {
- /* the call was dispatched dynamically */
-
- /* 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);
-
- oldentrypoint = calleeframe->fromcode->entrypoint;
-
- /* we need to know the instance */
-
- if (!calleeframe->instance.a) {
- DOLOG_SHORT( printf("WARNING: object instance unknown!\n"); );
- replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
- return;
- }
-
- /* get the vftbl */
-
- obj = calleeframe->instance.a;
- vftbl = obj->vftbl;
-
- assert(vftbl->clazz->vftbl == vftbl);
-
- DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
-
- replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
- }
- 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 ");
- }
-}
-
-
-/* replace_push_activation_record **********************************************
-
- Push a stack frame onto the execution state.
-
- *** This function imitates the effects of a call and the ***
- *** method prolog of the callee. ***
-
- IN:
- es...............execution state
- rpcall...........the replacement point at the call site
- callerframe......source frame of the caller, or NULL for creating the
- first frame
- calleeframe......source frame of the callee, must have been mapped
-
- OUT:
- *es..............the execution state after pushing the stack frame
-
-*******************************************************************************/
-
-void replace_push_activation_record(executionstate_t *es,
- rplpoint *rpcall,
- sourceframe_t *callerframe,
- sourceframe_t *calleeframe)
-{
- s4 i;
- s4 count;
- stackslot_t *sp;
- u1 *ra;
- codeinfo *calleecode;
-
- assert(es);
- assert(!rpcall || callerframe);
- assert(!rpcall || rpcall->type == RPLPOINT_TYPE_CALL);
- assert(!rpcall || rpcall == callerframe->torp);
- assert(calleeframe);
- assert(!callerframe || calleeframe == callerframe->down);
-
- /* the compilation unit we are entering */
-
- calleecode = calleeframe->tocode;
- assert(calleecode);
-
- /* calculate the return address */
-
- if (rpcall)
- ra = rpcall->pc + rpcall->callsize;
- else
- ra = es->pc + 1 /* XXX this is ugly */;
-
- /* push the stackframe */
-
- md_push_stackframe(es, calleecode, ra);
-
- /* we move into a new code unit, set code, PC, PV */
-
- es->code = calleecode;
- 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;
- }
-
- /* redirect future invocations */
-
- if (callerframe && rpcall) {
-#if defined(REPLACE_PATCH_ALL)
- if (rpcall->type == callerframe->fromrp->type)
-#else
- if (rpcall == callerframe->fromrp)
-#endif
- replace_patch_future_calls(ra, callerframe, calleeframe);
- }
-}
-
-
-/* replace_find_replacement_point **********************************************
-
- Find the replacement point in the given code corresponding to the
- position given in the source frame.
-
- IN:
- code.............the codeinfo in which to search the rplpoint
- frame............the source frame defining the position to look for
- parent...........parent replacement point to match
-
- RETURN VALUE:
- the replacement point
-
-*******************************************************************************/
-
-rplpoint * replace_find_replacement_point(codeinfo *code,
- sourceframe_t *frame,
- rplpoint *parent)
-{
- methodinfo *m;
- rplpoint *rp;
- s4 i;
- s4 j;
- s4 stacki;
- rplalloc *ra;
-
- assert(code);
- assert(frame);
-
- DOLOG( printf("searching replacement point for:\n");
- replace_source_frame_println(frame); );
-
- m = frame->method;
-
- DOLOG( printf("code = %p\n", (void*)code); );
-
- rp = code->rplpoints;
- i = code->rplpointcount;
- while (i--) {
- if (rp->id == frame->id && rp->method == frame->method
- && rp->parent == parent
- && replace_normalize_type_map[rp->type] == frame->type)
- {
- /* check if returnAddresses match */
- /* XXX optimize: only do this if JSRs in method */
- DOLOG( printf("checking match for:");
- replace_replacement_point_println(rp, 1); fflush(stdout); );
- ra = rp->regalloc;
- stacki = 0;
- for (j = rp->regalloccount; j--; ++ra) {
- if (ra->type == TYPE_RET) {
- if (ra->index == RPLALLOC_STACK) {
- assert(stacki < frame->javastackdepth);
- if (frame->javastack[stacki].i != ra->regoff)
- goto no_match;
- stacki++;
- }
- else {
- assert(ra->index >= 0 && ra->index < frame->javalocalcount);
- if (frame->javalocals[ra->index].i != ra->regoff)
- goto no_match;
- }
- }
- }
-
- /* found */
- return rp;
- }
-no_match:
- rp++;
- }
-
-#if !defined(NDEBUG)
- printf("candidate replacement points were:\n");
- rp = code->rplpoints;
- i = code->rplpointcount;
- for (; i--; ++rp) {
- replace_replacement_point_println(rp, 1);
- }
-#endif
-
- vm_abort("no matching replacement point found");
- return NULL; /* NOT REACHED */
-}
-
-
-/* replace_find_replacement_point_for_pc ***************************************
-
- Find the nearest replacement point at or before the given PC. The
- given PC has to be between (rp->pc) and (rp->pc+rp->callsize) for
- the replacement point to be found.
-
- IN:
- code.............compilation unit the PC is in
- pc...............the machine code PC
-
- RETURN VALUE:
- the replacement point found, or
- NULL if no replacement point was found
-
-*******************************************************************************/
-
-rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
-{
- rplpoint *found;
- rplpoint *rp;
- s4 i;
-
- DOLOG( printf("searching for rp at pc:%p in %p ", (void*)pc, (void*)code);
- method_println(code->m); );
-
- found = NULL;
-
- 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) {
- 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
- for it.
-
- IN:
- es...............current execution state
- ss...............the current source state
- sfi..............stackframeinfo for the native frame
-
- OUT:
- es...............execution state after unrolling the native frame
- ss...............gets the added native source frame
-
-*******************************************************************************/
-
-static void replace_pop_native_frame(executionstate_t *es,
- sourcestate_t *ss,
- stackframeinfo_t *sfi)
-{
- sourceframe_t *frame;
- codeinfo *code;
- s4 i,j;
-
- assert(sfi);
-
- frame = replace_new_sourceframe(ss);
-
- frame->sfi = sfi;
-
- /* remember pc and size of native frame */
-
- frame->nativepc = es->pc;
- frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
- assert(frame->nativeframesize >= 0);
-
- /* remember values of saved registers */
-
- j = 0;
- for (i=0; i<INT_REG_CNT; ++i) {
- if (nregdescint[i] == REG_SAV)
- frame->nativesavint[j++] = es->intregs[i];
- }
-
- j = 0;
- for (i=0; i<FLT_REG_CNT; ++i) {
- if (nregdescfloat[i] == REG_SAV)
- frame->nativesavflt[j++] = es->fltregs[i];
- }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- j = 0;
- for (i=0; i<ADR_REG_CNT; ++i) {
- if (nregdescadr[i] == REG_SAV)
- frame->nativesavadr[j++] = es->adrregs[i];
- }
-#endif
-
- /* restore saved registers */
-
-#if defined(ENABLE_GC_CACAO) && !defined(HAS_ADDRESS_REGISTER_FILE)
- j = 0;
- for (i=0; i<INT_REG_CNT; ++i) {
- if (nregdescint[i] == REG_SAV)
- es->intregs[i] = sfi->intregs[j++];
- }
-#else
- /* XXX we don't have them, yet, in the sfi, so clear them */
-
- for (i=0; i<INT_REG_CNT; ++i) {
- if (nregdescint[i] == REG_SAV)
- es->intregs[i] = 0;
- }
-#endif
-
- /* XXX we don't have float registers in the sfi, so clear them */
-
- for (i=0; i<FLT_REG_CNT; ++i) {
- if (nregdescfloat[i] == REG_SAV)
- es->fltregs[i] = 0.0;
- }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-# if defined(ENABLE_GC_CACAO)
- j = 0;
- for (i=0; i<ADR_REG_CNT; ++i) {
- if (nregdescadr[i] == REG_SAV)
- es->adrregs[i] = sfi->adrregs[j++];
- }
-# else
- for (i=0; i<ADR_REG_CNT; ++i) {
- if (nregdescadr[i] == REG_SAV)
- es->adrregs[i] = 0;
- }
-# endif
-#endif
-
- /* restore codeinfo of the native stub */
-
- code = code_get_codeinfo_for_pv(sfi->pv);
-
- /* restore sp, pv, pc and codeinfo of the parent method */
-
- /* XXX michi: use this instead:
- es->sp = sfi->sp + code->stackframesize; */
- 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 = (void*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
- es->code = code_get_codeinfo_for_pv(es->pv);
-}
-
-
-/* replace_push_native_frame ***************************************************
-
- Rebuild a native frame onto the execution state and remove its source frame.
-
- Note: The native frame is "rebuild" by setting fields like PC and stack
- pointer in the execution state accordingly. Values in the
- stackframeinfo may be modified, but the actual stack frame of the
- native code is not touched.
-
- IN:
- es...............current execution state
- ss...............the current source state
-
- OUT:
- es...............execution state after re-rolling the native frame
- ss...............the native source frame is removed
-
-*******************************************************************************/
-
-static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
-{
- sourceframe_t *frame;
- s4 i,j;
-
- assert(es);
- assert(ss);
-
- DOLOG( printf("pushing native frame\n"); );
-
- /* remove the frame from the source state */
-
- frame = ss->frames;
- assert(frame);
- assert(REPLACE_IS_NATIVE_FRAME(frame));
-
- ss->frames = frame->down;
-
- /* skip sp for the native stub */
-
- es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
-#if defined(REPLACE_RA_BETWEEN_FRAMES)
- es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
-#endif
-
- /* assert that the native frame has not moved */
-
- assert(es->sp == frame->sfi->sp);
-
- /* update saved registers in the stackframeinfo */
-
-#if defined(ENABLE_GC_CACAO)
- j = 0;
-# if !defined(HAS_ADDRESS_REGISTER_FILE)
- for (i=0; i<INT_REG_CNT; ++i) {
- if (nregdescint[i] == REG_SAV)
- frame->sfi->intregs[j++] = es->intregs[i];
- }
-# else
- for (i=0; i<ADR_REG_CNT; ++i) {
- if (nregdescadr[i] == REG_SAV)
- frame->sfi->adrregs[j++] = es->adrregs[i];
- }
-# endif
-
- /* XXX leave float registers untouched here */
-#endif
-
- /* restore saved registers */
-
- j = 0;
- for (i=0; i<INT_REG_CNT; ++i) {
- if (nregdescint[i] == REG_SAV)
- es->intregs[i] = frame->nativesavint[j++];
- }
-
- j = 0;
- for (i=0; i<FLT_REG_CNT; ++i) {
- if (nregdescfloat[i] == REG_SAV)
- es->fltregs[i] = frame->nativesavflt[j++];
- }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- j = 0;
- for (i=0; i<ADR_REG_CNT; ++i) {
- if (nregdescadr[i] == REG_SAV)
- es->adrregs[i] = frame->nativesavadr[j++];
- }
-#endif
-
- /* skip the native frame on the machine stack */
-
- es->sp -= frame->nativeframesize;
-
- /* set the pc the next frame must return to */
-
- es->pc = frame->nativepc;
-}
-
-
-/* replace_recover_source_state ************************************************
-
- Recover the source state from the given replacement point and execution
- state.
-
- IN:
- rp...............replacement point that has been reached, if any
- sfi..............stackframeinfo, if called from native code
- es...............execution state at the replacement point rp
-
- RETURN VALUE:
- the source state
-
-*******************************************************************************/
-
-sourcestate_t *replace_recover_source_state(rplpoint *rp,
- stackframeinfo_t *sfi,
- executionstate_t *es)
-{
- sourcestate_t *ss;
- u1 *ra;
- bool locked;
-#if defined(REPLACE_STATISTICS)
- s4 depth;
-#endif
-
- /* create the source frame structure in dump memory */
-
- ss = DNEW(sourcestate_t);
- ss->frames = NULL;
-
- /* each iteration of the loop recovers one source frame */
-
- depth = 0;
- locked = false;
-
- while (rp || sfi) {
-
- DOLOG( executionstate_println(es); );
-
- /* if we are not at a replacement point, it is a native frame */
-
- if (rp == NULL) {
- DOLOG( printf("native frame: sfi: "); replace_stackframeinfo_println(sfi); );
-
- locked = true;
- replace_pop_native_frame(es, ss, sfi);
- sfi = sfi->prev;
-
- if (es->code == NULL)
- continue;
-
- goto after_machine_frame;
- }
-
- /* read the values for this source frame from the execution state */
-
- DOLOG( printf("recovering source state for%s:\n",
- (ss->frames == NULL) ? " TOPFRAME" : "");
- replace_replacement_point_println(rp, 1); );
-
- replace_read_executionstate(rp, es, ss, ss->frames == NULL);
-
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_unrol_method(ss->frames->method);
-#endif
-
-#if defined(REPLACE_STATISTICS)
- REPLACE_COUNT(stat_frames);
- depth++;
- replace_statistics_source_frame(ss->frames);
-#endif
-
- /* in locked areas (below native frames), identity map the frame */
-
- if (locked) {
- ss->frames->torp = ss->frames->fromrp;
- ss->frames->tocode = ss->frames->fromcode;
- }
-
- /* unroll to the next (outer) frame */
-
- if (rp->parent) {
- /* this frame is in inlined code */
-
- DOLOG( printf("INLINED!\n"); );
-
- rp = rp->parent;
-
- assert(rp->type == RPLPOINT_TYPE_INLINE);
- REPLACE_COUNT(stat_unroll_inline);
- }
- else {
- /* this frame had been called at machine-level. pop it. */
-
- DOLOG( printf("UNWIND\n"); );
-
- ra = replace_pop_activation_record(es, ss->frames);
- if (ra == NULL) {
- DOLOG( printf("REACHED NATIVE CODE\n"); );
-
- rp = NULL;
-
-#if !defined(ENABLE_GC_CACAO)
- break; /* XXX remove to activate native frames */
-#endif
- continue;
- }
-
- /* find the replacement point at the call site */
-
-after_machine_frame:
- 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");
-
- DOLOG( printf("found replacement point.\n");
- replace_replacement_point_println(rp, 1); );
-
- assert(rp->type == RPLPOINT_TYPE_CALL);
- REPLACE_COUNT(stat_unroll_call);
- }
- } /* end loop over source frames */
-
- REPLACE_COUNT_DIST(stat_dist_frames, depth);
-
- return ss;
-}
-
-
-/* replace_map_source_state ****************************************************
-
- Map each source frame in the given source state to a target replacement
- point and compilation unit. If no valid code is available for a source
- frame, it is (re)compiled.
-
- IN:
- ss...............the source state
-
- OUT:
- ss...............the source state, modified: The `torp` and `tocode`
- fields of each source frame are set.
-
- RETURN VALUE:
- true.............everything went ok
- false............an exception has been thrown
-
-*******************************************************************************/
-
-static bool replace_map_source_state(sourcestate_t *ss)
-{
- sourceframe_t *frame;
- codeinfo *code;
- rplpoint *rp;
- rplpoint *parent; /* parent of inlined rplpoint */
-#if defined(REPLACE_STATISTICS)
- codeinfo *oldcode;
-#endif
-
- parent = NULL;
- code = NULL;
-
- /* iterate over the source frames from outermost to innermost */
-
- for (frame = ss->frames; frame != NULL; frame = frame->down) {
-
- /* XXX skip native frames */
-
- if (REPLACE_IS_NATIVE_FRAME(frame)) {
- parent = NULL;
- continue;
- }
-
- /* map frames which are not already mapped */
-
- if (frame->tocode) {
- code = frame->tocode;
- rp = frame->torp;
- assert(rp);
- }
- else {
- assert(frame->torp == NULL);
-
- if (parent == NULL) {
- /* find code for this frame */
-
-#if defined(REPLACE_STATISTICS)
- oldcode = frame->method->code;
-#endif
- /* request optimization of hot methods and their callers */
-
- if (frame->method->hitcountdown < 0
- || (frame->down && frame->down->method->hitcountdown < 0))
- jit_request_optimization(frame->method);
-
- code = jit_get_current_code(frame->method);
-
- if (code == NULL)
- return false; /* exception */
-
- REPLACE_COUNT_IF(stat_recompile, code != oldcode);
- }
-
- assert(code);
-
- /* map this frame */
-
- rp = replace_find_replacement_point(code, frame, parent);
-
- frame->tocode = code;
- frame->torp = rp;
- }
-
- if (rp->type == RPLPOINT_TYPE_CALL) {
- parent = NULL;
- }
- else {
- /* inlining */
- parent = rp;
- }
- }
-
- return true;
-}
-
-
-/* replace_map_source_state_identity *******************************************
-
- Map each source frame in the given source state to the same replacement
- point and compilation unit it was derived from. This is mainly used for
- garbage collection.
-
- IN:
- ss...............the source state
-
- OUT:
- ss...............the source state, modified: The `torp` and `tocode`
- fields of each source frame are set.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-static void replace_map_source_state_identity(sourcestate_t *ss)
-{
- sourceframe_t *frame;
-
- /* iterate over the source frames from outermost to innermost */
-
- for (frame = ss->frames; frame != NULL; frame = frame->down) {
-
- /* skip native frames */
-
- if (REPLACE_IS_NATIVE_FRAME(frame)) {
- continue;
- }
-
- /* map frames using the identity mapping */
-
- if (frame->tocode) {
- assert(frame->tocode == frame->fromcode);
- assert(frame->torp == frame->fromrp);
- } else {
- assert(frame->tocode == NULL);
- assert(frame->torp == NULL);
- frame->tocode = frame->fromcode;
- frame->torp = frame->fromrp;
- }
- }
-}
-#endif
-
-
-/* replace_build_execution_state ***********************************************
-
- Build an execution state for the given (mapped) source state.
-
- !!! CAUTION: This function rewrites the machine stack !!!
-
- THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
-
- IN:
- ss...............the source state. Must have been mapped by
- replace_map_source_state before.
- es...............the base execution state on which to build
-
- OUT:
- *es..............the new execution state
-
-*******************************************************************************/
-
-static void replace_build_execution_state(sourcestate_t *ss,
- executionstate_t *es)
-{
- rplpoint *rp;
- sourceframe_t *prevframe;
- rplpoint *parent;
-
- parent = NULL;
- prevframe = NULL;
- rp = NULL;
-
- while (ss->frames) {
-
- if (REPLACE_IS_NATIVE_FRAME(ss->frames)) {
- prevframe = ss->frames;
- replace_push_native_frame(es, ss);
- parent = NULL;
- rp = NULL;
- continue;
- }
-
- if (parent == NULL) {
- /* create a machine-level stack frame */
-
- DOLOG( printf("pushing activation record for:\n");
- if (rp) replace_replacement_point_println(rp, 1);
- else printf("\tfirst frame\n"); );
-
- replace_push_activation_record(es, rp, prevframe, ss->frames);
-
- DOLOG( executionstate_println(es); );
- }
-
- rp = ss->frames->torp;
- assert(rp);
-
- DOLOG( printf("creating execution state for%s:\n",
- (ss->frames->down == NULL) ? " TOPFRAME" : "");
- replace_replacement_point_println(ss->frames->fromrp, 1);
- replace_replacement_point_println(rp, 1); );
-
- es->code = ss->frames->tocode;
- prevframe = ss->frames;
-
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_rerol_method(ss->frames->method);
-#endif
-
- replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
-
- DOLOG( executionstate_println(es); );
-
- if (rp->type == RPLPOINT_TYPE_CALL) {
- parent = NULL;
- }
- else {
- /* inlining */
- parent = rp;
- }
- }
-}
-
-
-/* replace_me ******************************************************************
-
- This function is called by the signal handler when a thread reaches
- a replacement point. `replace_me` must map the execution state to the
- target replacement point and let execution continue there.
-
- THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
-
- IN:
- rp...............replacement point that has been reached
- es...............execution state read by signal handler
-
-*******************************************************************************/
-
-static void replace_me(rplpoint *rp, executionstate_t *es)
-{
- stackframeinfo_t *sfi;
- sourcestate_t *ss;
- sourceframe_t *frame;
- codeinfo *origcode;
- rplpoint *origrp;
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
- threadobject *thread;
-#endif
- int32_t dumpmarker;
-
- 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);
- method_println(es->code->m); );
-
- DOLOG( replace_replacement_point_println(rp, 1); );
-
- REPLACE_COUNT(stat_replacements);
-
- /* mark start of dump memory area */
-
- DMARKER;
-
- /* Get the stackframeinfo for the current thread. */
-
- sfi = threads_get_current_stackframeinfo();
-
- /* recover source state */
-
- ss = replace_recover_source_state(rp, sfi, es);
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
- /* if there is a collection pending, we assume the replacement point should
- suspend this thread */
-
- if (gc_pending) {
-
- thread = THREADOBJECT;
-
- DOLOG_SHORT( printf("REPLACEMENT: Suspending thread for GC now!\n"); );
-
- /* map the sourcestate using the identity mapping */
- replace_map_source_state_identity(ss);
-
- /* since we enter the same method again, we turn off rps now */
- /* XXX michi: can we really do this? what if the rp was active before
- we activated it for the gc? */
- replace_deactivate_replacement_points(origcode);
-
- /* remember executionstate and sourcestate for this thread */
- GC_EXECUTIONSTATE = es;
- GC_SOURCESTATE = ss;
-
- /* really suspend this thread now (PC = 0) */
- threads_suspend_ack(NULL, NULL);
-
- DOLOG_SHORT( printf("REPLACEMENT: Resuming thread after GC now!\n"); );
-
- } else {
-#endif /*defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)*/
-
- /* map the source state */
-
- if (!replace_map_source_state(ss))
- vm_abort("exception during method replacement");
-
- DOLOG( replace_sourcestate_println(ss); );
-
- DOLOG_SHORT( replace_sourcestate_println_short(ss); );
-
-#if !defined(NDEBUG)
- /* avoid infinite loops by self-replacement, only if not in testing mode */
-
- if (!opt_TestReplacement) {
- frame = ss->frames;
- while (frame->down)
- frame = frame->down;
-
- if (frame->torp == origrp) {
- DOLOG_SHORT(
- printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n");
- );
- replace_deactivate_replacement_points(origcode);
- }
- }
-#endif
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
- }
-#endif
-
- /* build the new execution state */
-
- replace_build_execution_state(ss, es);
-
-#if !defined(NDEBUG)
- /* continue execution after patched machine code, if testing mode enabled */
-
- if (opt_TestReplacement)
- es->pc += REPLACEMENT_PATCH_SIZE;
-#endif
-
- /* release dump area */
-
- DRELEASE;
-}
-
-
-/* replace_me_wrapper **********************************************************
-
- This function is called by the signal handler. It determines if there
- is an active replacement point pending at the given PC and returns
- accordingly.
-
- THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
-
- IN:
- pc...............the program counter that triggered the replacement.
- context..........the context (machine state) to which the
- replacement should be applied.
-
- OUT:
- context..........the context after replacement finished.
-
- RETURN VALUE:
- true.............replacement done, everything went ok
- false............no replacement done, context unchanged
-
-*******************************************************************************/
-
-bool replace_me_wrapper(u1 *pc, void *context)
-{
- 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 */
-
- code = code_find_codeinfo_for_pc(pc);
- assert(code);
-
- /* search for a replacement point at the given 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 | RPLPOINT_FLAG_COUNTDOWN))) {
-
- DOLOG( printf("valid replacement point\n"); );
-
-#if !defined(NDEBUG)
- executionstate_sanity_check(context);
-#endif
-
- /* set codeinfo pointer in execution state */
-
- es.code = code;
-
- /* read execution state from current context */
-
- md_executionstate_read(&es, context);
-
- DOLOG( printf("REPLACEMENT READ: ");
- executionstate_println(&es); );
-
- /* 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);
-
- DOLOG( printf("REPLACEMENT WRITE: ");
- executionstate_println(&es); );
-
- /* new code is entered after returning */
-
- DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
- return true;
- }
- else
- return false;
-}
-
-
-/******************************************************************************/
-/* NOTE: Stuff specific to the exact GC is below. */
-/******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
-{
- stackframeinfo_t *sfi;
- executionstate_t *es;
- sourcestate_t *ss;
-
- /* Get the stackframeinfo of this thread. */
-
- assert(thread == THREADOBJECT);
-
- sfi = threads_get_current_stackframeinfo();
-
- /* create the execution state */
- es = DNEW(executionstate_t);
- es->pc = pc;
- es->sp = sp;
- es->pv = 0; /* since we are in a native, PV is invalid! */
- es->code = NULL; /* since we are in a native, we do not have a codeinfo */
-
- /* we assume we are in a native (no replacement point)! */
- ss = replace_recover_source_state(NULL, sfi, es);
-
- /* map the sourcestate using the identity mapping */
- replace_map_source_state_identity(ss);
-
- /* remember executionstate and sourcestate for this thread */
- GC_EXECUTIONSTATE = es;
- GC_SOURCESTATE = ss;
-}
-#endif
-
-#if defined(ENABLE_GC_CACAO)
-void replace_gc_into_native(threadobject *thread)
-{
- executionstate_t *es;
- sourcestate_t *ss;
-
- /* get the executionstate and sourcestate for the given thread */
- es = GC_EXECUTIONSTATE;
- ss = GC_SOURCESTATE;
-
- /* rebuild the stack of the given thread */
- replace_build_execution_state(ss, es);
-}
-#endif
-
-
-/******************************************************************************/
-/* NOTE: No important code below. */
-/******************************************************************************/
-
-
-/* statistics *****************************************************************/
-
-#if defined(REPLACE_STATISTICS)
-static void print_freq(FILE *file,int *array,int limit)
-{
- int i;
- int sum = 0;
- int cum = 0;
- for (i=0; i<limit; ++i)
- sum += array[i];
- sum += array[limit];
- for (i=0; i<limit; ++i) {
- cum += array[i];
- fprintf(file," %3d: %8d (cum %3d%%)\n",
- i, array[i], (sum) ? ((100*cum)/sum) : 0);
- }
- fprintf(file," >=%3d: %8d\n",limit,array[limit]);
-}
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-#if defined(REPLACE_STATISTICS)
-
-#define REPLACE_PRINT_DIST(name, array) \
- printf(" " name " distribution:\n"); \
- print_freq(stdout, (array), sizeof(array)/sizeof(int) - 1);
-
-void replace_print_statistics(void)
-{
- printf("replacement statistics:\n");
- printf(" # of replacements: %d\n", stat_replacements);
- printf(" # of frames: %d\n", stat_frames);
- printf(" # of recompilations: %d\n", stat_recompile);
- printf(" patched static calls:%d\n", stat_staticpatch);
- printf(" unrolled inlines: %d\n", stat_unroll_inline);
- printf(" unrolled calls: %d\n", stat_unroll_call);
- REPLACE_PRINT_DIST("frame depth", stat_dist_frames);
- REPLACE_PRINT_DIST("locals per frame", stat_dist_locals);
- REPLACE_PRINT_DIST("ADR locals per frame", stat_dist_locals_adr);
- REPLACE_PRINT_DIST("primitive locals per frame", stat_dist_locals_prim);
- REPLACE_PRINT_DIST("RET locals per frame", stat_dist_locals_ret);
- REPLACE_PRINT_DIST("void locals per frame", stat_dist_locals_void);
- REPLACE_PRINT_DIST("stack slots per frame", stat_dist_stack);
- REPLACE_PRINT_DIST("ADR stack slots per frame", stat_dist_stack_adr);
- REPLACE_PRINT_DIST("primitive stack slots per frame", stat_dist_stack_prim);
- REPLACE_PRINT_DIST("RET stack slots per frame", stat_dist_stack_ret);
- printf("\n");
- printf(" # of methods: %d\n", stat_methods);
- printf(" # of replacement points: %d\n", stat_rploints);
- printf(" # of regallocs: %d\n", stat_regallocs);
- printf(" per rplpoint: %f\n", (double)stat_regallocs / stat_rploints);
- printf(" per method: %f\n", (double)stat_regallocs / stat_methods);
- REPLACE_PRINT_DIST("replacement points per method", stat_dist_method_rplpoints);
- printf("\n");
-
-}
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-#if defined(REPLACE_STATISTICS)
-static void replace_statistics_source_frame(sourceframe_t *frame)
-{
- int adr = 0;
- int ret = 0;
- int prim = 0;
- int vd = 0;
- int n = 0;
- int i;
-
- for (i=0; i<frame->javalocalcount; ++i) {
- switch (frame->javalocaltype[i]) {
- case TYPE_ADR: adr++; break;
- case TYPE_RET: ret++; break;
- case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
- case TYPE_VOID: vd++; break;
- default: assert(0);
- }
- n++;
- }
- REPLACE_COUNT_DIST(stat_dist_locals, n);
- REPLACE_COUNT_DIST(stat_dist_locals_adr, adr);
- REPLACE_COUNT_DIST(stat_dist_locals_void, vd);
- REPLACE_COUNT_DIST(stat_dist_locals_ret, ret);
- REPLACE_COUNT_DIST(stat_dist_locals_prim, prim);
- adr = ret = prim = n = 0;
- for (i=0; i<frame->javastackdepth; ++i) {
- switch (frame->javastacktype[i]) {
- case TYPE_ADR: adr++; break;
- case TYPE_RET: ret++; break;
- case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
- }
- n++;
- }
- REPLACE_COUNT_DIST(stat_dist_stack, n);
- REPLACE_COUNT_DIST(stat_dist_stack_adr, adr);
- REPLACE_COUNT_DIST(stat_dist_stack_ret, ret);
- REPLACE_COUNT_DIST(stat_dist_stack_prim, prim);
-}
-#endif /* defined(REPLACE_STATISTICS) */
-
-
-/* debugging helpers **********************************************************/
-
-/* replace_replacement_point_println *******************************************
-
- Print replacement point info.
-
- IN:
- rp...............the replacement point to print
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-
-#define TYPECHAR(t) (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
-
-static char *replace_type_str[] = {
- "STD",
- "EXH",
- "SBR",
- "CALL",
- "INLINE",
- "RETURN",
- "BODY"
-};
-
-void replace_replacement_point_println(rplpoint *rp, int depth)
-{
- int j;
- int index;
-
- if (!rp) {
- printf("(rplpoint *)NULL\n");
- return;
- }
-
- for (j=0; j<depth; ++j)
- putchar('\t');
-
- printf("rplpoint (id %d) %p pc:%p+%d type:%s",
- rp->id, (void*)rp,rp->pc,rp->callsize,
- replace_type_str[rp->type]);
- if (rp->flags & RPLPOINT_FLAG_NOTRAP)
- printf(" NOTRAP");
- if (rp->flags & RPLPOINT_FLAG_COUNTDOWN)
- printf(" COUNTDOWN");
- if (rp->flags & RPLPOINT_FLAG_ACTIVE)
- printf(" ACTIVE");
- printf(" parent:%p\n", (void*)rp->parent);
- for (j=0; j<depth; ++j)
- putchar('\t');
- printf("ra:%d = [", rp->regalloccount);
-
- for (j=0; j<rp->regalloccount; ++j) {
- if (j)
- putchar(' ');
- index = rp->regalloc[j].index;
- switch (index) {
- case RPLALLOC_STACK: printf("S"); break;
- case RPLALLOC_PARAM: printf("P"); break;
- case RPLALLOC_SYNC : printf("Y"); break;
- default: printf("%d", index);
- }
- printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
- if (rp->regalloc[j].type == TYPE_RET) {
- printf("ret(L%03d)", rp->regalloc[j].regoff);
- }
- else {
- show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
- }
- }
-
- printf("]\n");
- for (j=0; j<depth; ++j)
- putchar('\t');
- printf("method: ");
- method_print(rp->method);
-
- printf("\n");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* replace_show_replacement_points *********************************************
-
- Print replacement point info.
-
- IN:
- code.............codeinfo whose replacement points should be printed.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_show_replacement_points(codeinfo *code)
-{
- int i;
- int depth;
- rplpoint *rp;
- rplpoint *parent;
-
- if (!code) {
- printf("(codeinfo *)NULL\n");
- return;
- }
-
- printf("\treplacement points: %d\n",code->rplpointcount);
-
- printf("\ttotal allocations : %d\n",code->regalloccount);
- printf("\tsaved int regs : %d\n",code->savedintcount);
- printf("\tsaved flt regs : %d\n",code->savedfltcount);
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- printf("\tsaved adr regs : %d\n",code->savedadrcount);
-#endif
- printf("\tmemuse : %d\n",code->memuse);
-
- printf("\n");
-
- for (i=0; i<code->rplpointcount; ++i) {
- rp = code->rplpoints + i;
-
- depth = 1;
- parent = rp->parent;
- while (parent) {
- depth++;
- parent = parent->parent;
- }
- replace_replacement_point_println(rp, depth);
- }
-}
-#endif
-
-
-#if !defined(NDEBUG)
-static void java_value_print(s4 type, replace_val_t value)
-{
- java_object_t *obj;
- utf *u;
-
- printf("%016llx",(unsigned long long) value.l);
-
- if (type < 0 || type > TYPE_RET)
- printf(" <INVALID TYPE:%d>", type);
- else
- printf(" %s", show_jit_type_names[type]);
-
- if (type == TYPE_ADR && value.a != NULL) {
- obj = value.a;
- putchar(' ');
- utf_display_printable_ascii_classname(obj->vftbl->clazz->name);
-
- if (obj->vftbl->clazz == class_java_lang_String) {
- printf(" \"");
- u = javastring_toutf(obj, false);
- utf_display_printable_ascii(u);
- printf("\"");
- }
- }
- else if (type == TYPE_INT) {
- printf(" %ld", (long) value.i);
- }
- else if (type == TYPE_LNG) {
- printf(" %lld", (long long) value.l);
- }
- else if (type == TYPE_FLT) {
- printf(" %f", value.f);
- }
- else if (type == TYPE_DBL) {
- printf(" %f", value.d);
- }
-}
-#endif /* !defined(NDEBUG) */
-
-
-#if !defined(NDEBUG)
-void replace_source_frame_println(sourceframe_t *frame)
-{
- s4 i,j;
- s4 t;
-
- if (REPLACE_IS_NATIVE_FRAME(frame)) {
- printf("\tNATIVE\n");
- printf("\tsfi: "); replace_stackframeinfo_println(frame->sfi);
- printf("\tnativepc: %p\n", frame->nativepc);
- printf("\tframesize: %d\n", frame->nativeframesize);
-
- j = 0;
- for (i=0; i<INT_REG_CNT; ++i) {
- if (nregdescint[i] == REG_SAV)
- printf("\t%s = %p\n", abi_registers_integer_name[i], (void*)frame->nativesavint[j++]);
- }
-
- j = 0;
- for (i=0; i<FLT_REG_CNT; ++i) {
- if (nregdescfloat[i] == REG_SAV)
- printf("\tF%02d = %f\n", i, frame->nativesavflt[j++]);
- }
-
- printf("\n");
- return;
- }
-
- printf("\t");
- method_println(frame->method);
- printf("\tid: %d\n", frame->id);
- printf("\ttype: %s\n", replace_type_str[frame->type]);
- printf("\n");
-
- if (frame->instance.a) {
- printf("\tinstance: ");
- java_value_print(TYPE_ADR, frame->instance);
- printf("\n");
- }
-
- if (frame->javalocalcount) {
- printf("\tlocals (%d):\n",frame->javalocalcount);
- for (i=0; i<frame->javalocalcount; ++i) {
- t = frame->javalocaltype[i];
- if (t == TYPE_VOID) {
- printf("\tlocal[ %2d] = void\n",i);
- }
- else {
- printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
- java_value_print(t, frame->javalocals[i]);
- printf("\n");
- }
- }
- printf("\n");
- }
-
- if (frame->javastackdepth) {
- printf("\tstack (depth %d):\n",frame->javastackdepth);
- for (i=0; i<frame->javastackdepth; ++i) {
- t = frame->javastacktype[i];
- if (t == TYPE_VOID) {
- printf("\tstack[%2d] = void", i);
- }
- else {
- printf("\tstack[%2d] = ",i);
- java_value_print(frame->javastacktype[i], frame->javastack[i]);
- printf("\n");
- }
- }
- printf("\n");
- }
-
- if (frame->syncslotcount) {
- printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
- for (i=0; i<frame->syncslotcount; ++i) {
- printf("\tslot[%2d] = ",i);
-#ifdef HAS_4BYTE_STACKSLOT
- printf("%08lx\n",(unsigned long) frame->syncslots[i].p);
-#else
- printf("%016llx\n",(unsigned long long) frame->syncslots[i].p);
-#endif
- }
- printf("\n");
- }
-
- if (frame->fromcode) {
- printf("\tfrom %p ", (void*)frame->fromcode);
- method_println(frame->fromcode->m);
- }
- if (frame->tocode) {
- printf("\tto %p ", (void*)frame->tocode);
- method_println(frame->tocode->m);
- }
-
- if (frame->fromrp) {
- printf("\tfrom replacement point:\n");
- replace_replacement_point_println(frame->fromrp, 2);
- }
- if (frame->torp) {
- printf("\tto replacement point:\n");
- replace_replacement_point_println(frame->torp, 2);
- }
-
- printf("\n");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* replace_sourcestate_println *************************************************
-
- Print source state
-
- IN:
- ss...............the source state to print
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_sourcestate_println(sourcestate_t *ss)
-{
- int i;
- sourceframe_t *frame;
-
- if (!ss) {
- printf("(sourcestate_t *)NULL\n");
- return;
- }
-
- printf("sourcestate_t:\n");
-
- for (i=0, frame = ss->frames; frame != NULL; frame = frame->down, ++i) {
- printf(" frame %d:\n", i);
- replace_source_frame_println(frame);
- }
-}
-#endif
-
-
-/* replace_sourcestate_println_short *******************************************
-
- Print a compact representation of the given source state.
-
- IN:
- ss...............the source state to print
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_sourcestate_println_short(sourcestate_t *ss)
-{
- sourceframe_t *frame;
-
- for (frame = ss->frames; frame != NULL; frame = frame->down) {
- printf("\t");
-
- if (REPLACE_IS_NATIVE_FRAME(frame)) {
- printf("NATIVE (pc %p size %d) ",
- (void*)frame->nativepc, frame->nativeframesize);
- replace_stackframeinfo_println(frame->sfi);
- continue;
- }
-
- if (frame->torp) {
- printf("%c", (frame->torp == frame->fromrp) ? '=' : '+');
- }
-
- printf("%s", replace_type_str[frame->fromrp->type]);
-
- if (frame->torp && frame->torp->type != frame->fromrp->type)
- printf("->%s", replace_type_str[frame->torp->type]);
-
- if (frame->tocode != frame->fromcode)
- printf(" (%p->%p/%d) ",
- (void*) frame->fromcode, (void*) frame->tocode,
- frame->fromrp->id);
- else
- printf(" (%p/%d) ", (void*) frame->fromcode, frame->fromrp->id);
-
- method_println(frame->method);
- }
-}
-#endif
-
-#if !defined(NDEBUG)
-static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
-{
- printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=",
- (void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp,
- (void*)sfi->ra, (void*)sfi->xpc);
-
- if (sfi->code)
- method_println(sfi->code->m);
- else
- printf("(nil)\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/jit/replace.cpp - on-stack replacement of 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.
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "arch.h"
+#include "md.h"
+
+#if defined(ENABLE_GC_CACAO)
+# include "mm/cacao-gc/gc.h"
+#endif
+
+#include "mm/dumpmemory.hpp"
+#include "mm/memory.h"
+
+#include "threads/thread.hpp"
+
+#include "toolbox/logging.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/disass.h"
+#include "vm/jit/executionstate.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/methodheader.h"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/show.hpp"
+#include "vm/jit/stack.h"
+
+
+#define REPLACE_PATCH_DYNAMIC_CALL
+/*#define REPLACE_PATCH_ALL*/
+
+#if defined(ENABLE_VMLOG)
+#include <vmlog_cacao.h>
+#endif
+
+/*** architecture-dependent configuration *************************************/
+
+/* first unset the macros (default) */
+#undef REPLACE_RA_BETWEEN_FRAMES
+#undef REPLACE_RA_TOP_OF_FRAME
+#undef REPLACE_RA_LINKAGE_AREA
+#undef REPLACE_LEAFMETHODS_RA_REGISTER
+
+/* i386, x86_64 and m68k */
+#if defined(__I386__) || defined(__X86_64__) || defined(__M68K__)
+#define REPLACE_RA_BETWEEN_FRAMES
+/* alpha */
+#elif defined(__ALPHA__)
+#define REPLACE_RA_TOP_OF_FRAME
+#define REPLACE_LEAFMETHODS_RA_REGISTER
+/* powerpc */
+#elif defined(__POWERPC__)
+#define REPLACE_RA_LINKAGE_AREA
+#define REPLACE_LEAFMETHODS_RA_REGISTER
+/* s390 */
+#elif defined(__S390__)
+#define REPLACE_RA_TOP_OF_FRAME
+#endif
+
+
+/*** configuration of native stack slot size **********************************/
+
+/* XXX this should be in md-abi.h files, probably */
+
+#define SIZE_OF_STACKSLOT 8
+#define STACK_SLOTS_PER_FLOAT 1
+typedef u8 stackslot_t;
+
+
+/*** debugging ****************************************************************/
+
+#if !defined(NDEBUG)
+static void java_value_print(s4 type, replace_val_t value);
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi);
+#endif
+
+#if !defined(NDEBUG)
+#define DOLOG(code) do{ if (opt_TraceReplacement > 1) { code; } } while(0)
+#define DOLOG_SHORT(code) do{ if (opt_TraceReplacement > 0) { code; } } while(0)
+#else
+#define DOLOG(code)
+#define DOLOG_SHORT(code)
+#endif
+
+
+/*** statistics ***************************************************************/
+
+#define REPLACE_STATISTICS
+
+#if defined(REPLACE_STATISTICS)
+
+static int stat_replacements = 0;
+static int stat_frames = 0;
+static int stat_recompile = 0;
+static int stat_staticpatch = 0;
+static int stat_unroll_inline = 0;
+static int stat_unroll_call = 0;
+static int stat_dist_frames[20] = { 0 };
+static int stat_dist_locals[20] = { 0 };
+static int stat_dist_locals_adr[10] = { 0 };
+static int stat_dist_locals_prim[10] = { 0 };
+static int stat_dist_locals_ret[10] = { 0 };
+static int stat_dist_locals_void[10] = { 0 };
+static int stat_dist_stack[10] = { 0 };
+static int stat_dist_stack_adr[10] = { 0 };
+static int stat_dist_stack_prim[10] = { 0 };
+static int stat_dist_stack_ret[10] = { 0 };
+static int stat_methods = 0;
+static int stat_rploints = 0;
+static int stat_regallocs = 0;
+static int stat_dist_method_rplpoints[20] = { 0 };
+
+#define REPLACE_COUNT(cnt) (cnt)++
+#define REPLACE_COUNT_IF(cnt, cond) do{ if(cond) (cnt)++; } while(0)
+#define REPLACE_COUNT_INC(cnt, inc) ((cnt) += (inc))
+
+#define REPLACE_COUNT_DIST(array, val) \
+ do { \
+ int limit = (sizeof(array) / sizeof(int)) - 1; \
+ if ((val) < (limit)) (array)[val]++; \
+ else (array)[limit]++; \
+ } while (0)
+
+static void replace_statistics_source_frame(sourceframe_t *frame);
+
+#else
+
+#define REPLACE_COUNT(cnt)
+#define REPLACE_COUNT_IF(cnt, cond)
+#define REPLACE_COUNT_INC(cnt, inc)
+#define REPLACE_COUNT_DIST(array, val)
+
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+/*** constants used internally ************************************************/
+
+#define TOP_IS_NORMAL 0
+#define TOP_IS_ON_STACK 1
+#define TOP_IS_IN_ITMP1 2
+#define TOP_IS_VOID 3
+
+
+/******************************************************************************/
+/* PART I: Creating / freeing replacement points */
+/******************************************************************************/
+
+
+/* replace_create_replacement_point ********************************************
+
+ Create a replacement point.
+
+ IN:
+ jd...............current jitdata
+ iinfo............inlining info for the current position
+ rp...............pre-allocated (uninitialized) rplpoint
+ type.............RPLPOINT_TYPE constant
+ iptr.............current instruction
+ *pra.............current rplalloc pointer
+ javalocals.......the javalocals at the current point
+ stackvars........the stack variables at the current point
+ stackdepth.......the stack depth at the current point
+ paramcount.......number of parameters at the start of stackvars
+
+ OUT:
+ *rpa.............points to the next free rplalloc
+
+*******************************************************************************/
+
+static void replace_create_replacement_point(jitdata *jd,
+ insinfo_inline *iinfo,
+ rplpoint *rp,
+ s4 type,
+ instruction *iptr,
+ rplalloc **pra,
+ s4 *javalocals,
+ s4 *stackvars,
+ s4 stackdepth,
+ s4 paramcount)
+{
+ rplalloc *ra;
+ s4 i;
+ varinfo *v;
+ s4 index;
+
+ ra = *pra;
+
+ REPLACE_COUNT(stat_rploints);
+
+ rp->method = (iinfo) ? iinfo->method : jd->m;
+ rp->pc = NULL; /* set by codegen */
+ rp->callsize = 0; /* set by codegen */
+ rp->regalloc = ra;
+ rp->flags = 0;
+ rp->type = type;
+ rp->id = iptr->flags.bits >> INS_FLAG_ID_SHIFT;
+
+ /* XXX unify these two fields */
+ rp->parent = (iinfo) ? iinfo->rp : NULL;
+
+ /* store local allocation info of javalocals */
+
+ if (javalocals) {
+ for (i = 0; i < rp->method->maxlocals; ++i) {
+ index = javalocals[i];
+ if (index == UNUSED)
+ continue;
+
+ ra->index = i;
+ if (index >= 0) {
+ v = VAR(index);
+ ra->flags = v->flags & (INMEMORY);
+ ra->regoff = v->vv.regoff;
+ ra->type = v->type;
+ }
+ else {
+ ra->regoff = RETADDR_FROM_JAVALOCAL(index);
+ ra->type = TYPE_RET;
+ ra->flags = 0;
+ }
+ ra++;
+ }
+ }
+
+ /* store allocation info of java stack vars */
+
+ for (i = 0; i < stackdepth; ++i) {
+ v = VAR(stackvars[i]);
+ ra->flags = v->flags & (INMEMORY);
+ ra->index = (i < paramcount) ? RPLALLOC_PARAM : RPLALLOC_STACK;
+ ra->type = v->type;
+ /* XXX how to handle locals on the stack containing returnAddresses? */
+ if (v->type == TYPE_RET) {
+ assert(stackvars[i] >= jd->localcount);
+ ra->regoff = v->vv.retaddr->nr;
+ }
+ else
+ ra->regoff = v->vv.regoff;
+ ra++;
+ }
+
+ /* total number of allocations */
+
+ rp->regalloccount = ra - rp->regalloc;
+
+ *pra = ra;
+}
+
+
+/* replace_create_inline_start_replacement_point *******************************
+
+ Create an INLINE_START replacement point.
+
+ IN:
+ jd...............current jitdata
+ rp...............pre-allocated (uninitialized) rplpoint
+ iptr.............current instruction
+ *pra.............current rplalloc pointer
+ javalocals.......the javalocals at the current point
+
+ OUT:
+ *rpa.............points to the next free rplalloc
+
+ RETURN VALUE:
+ the insinfo_inline * for the following inlined body
+
+*******************************************************************************/
+
+static insinfo_inline * replace_create_inline_start_replacement_point(
+ jitdata *jd,
+ rplpoint *rp,
+ instruction *iptr,
+ rplalloc **pra,
+ s4 *javalocals)
+{
+ insinfo_inline *calleeinfo;
+ rplalloc *ra;
+
+ calleeinfo = iptr->sx.s23.s3.inlineinfo;
+
+ calleeinfo->rp = rp;
+
+ replace_create_replacement_point(jd, calleeinfo->parent, rp,
+ RPLPOINT_TYPE_INLINE, iptr, pra,
+ javalocals,
+ calleeinfo->stackvars, calleeinfo->stackvarscount,
+ calleeinfo->paramcount);
+
+ if (calleeinfo->synclocal != UNUSED) {
+ ra = (*pra)++;
+ ra->index = RPLALLOC_SYNC;
+ ra->regoff = jd->var[calleeinfo->synclocal].vv.regoff;
+ ra->flags = jd->var[calleeinfo->synclocal].flags & INMEMORY;
+ ra->type = TYPE_ADR;
+
+ rp->regalloccount++;
+ }
+
+ return calleeinfo;
+}
+
+
+/* replace_create_replacement_points *******************************************
+
+ Create the replacement points for the given code.
+
+ IN:
+ jd...............current jitdata, must not have any replacement points
+
+ OUT:
+ code->rplpoints.......set to the list of replacement points
+ code->rplpointcount...number of replacement points
+ code->regalloc........list of allocation info
+ code->regalloccount...total length of allocation info list
+ code->globalcount.....number of global allocations at the
+ start of code->regalloc
+
+ RETURN VALUE:
+ true.............everything ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#define CLEAR_javalocals(array, method) \
+ do { \
+ for (i=0; i<(method)->maxlocals; ++i) \
+ (array)[i] = UNUSED; \
+ } while (0)
+
+#define COPY_OR_CLEAR_javalocals(dest, array, method) \
+ do { \
+ if ((array) != NULL) \
+ MCOPY((dest), (array), s4, (method)->maxlocals); \
+ else \
+ CLEAR_javalocals((dest), (method)); \
+ } while (0)
+
+#define COUNT_javalocals(array, method, counter) \
+ do { \
+ for (i=0; i<(method)->maxlocals; ++i) \
+ if ((array)[i] != UNUSED) \
+ (counter)++; \
+ } while (0)
+
+bool replace_create_replacement_points(jitdata *jd)
+{
+ codeinfo *code;
+ registerdata *rd;
+ basicblock *bptr;
+ int count;
+ methodinfo *m;
+ rplpoint *rplpoints;
+ rplpoint *rp;
+ int alloccount;
+ rplalloc *regalloc;
+ rplalloc *ra;
+ int i;
+ instruction *iptr;
+ instruction *iend;
+ s4 *javalocals;
+ s4 *jl;
+ methoddesc *md;
+ insinfo_inline *iinfo;
+ s4 startcount;
+ s4 firstcount;
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+ bool needentry;
+#endif
+
+ REPLACE_COUNT(stat_methods);
+
+ /* get required compiler data */
+
+ code = jd->code;
+ rd = jd->rd;
+
+ /* assert that we wont overwrite already allocated data */
+
+ assert(code);
+ assert(code->m);
+ assert(code->rplpoints == NULL);
+ assert(code->rplpointcount == 0);
+ assert(code->regalloc == NULL);
+ assert(code->regalloccount == 0);
+ assert(code->globalcount == 0);
+
+ m = code->m;
+
+ /* in instance methods, we may need a rplpoint at the method entry */
+
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+ if (!(m->flags & ACC_STATIC)) {
+ jd->basicblocks[0].bitflags |= BBFLAG_REPLACEMENT;
+ needentry = true;
+ }
+ else {
+ needentry = false;
+ }
+#endif /* defined(REPLACE_PATCH_DYNAMIC_CALL) */
+
+ /* iterate over the basic block list to find replacement points */
+
+ count = 0;
+ alloccount = 0;
+
+ javalocals = (s4*) DumpMemory::allocate(sizeof(s4) * jd->maxlocals);
+
+ for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+
+ /* skip dead code */
+
+ if (bptr->flags < BBFINISHED)
+ continue;
+
+ /* get info about this block */
+
+ m = bptr->method;
+ iinfo = bptr->inlineinfo;
+
+ /* initialize javalocals at the start of this block */
+
+ COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
+
+ /* iterate over the instructions */
+
+ iptr = bptr->iinstr;
+ iend = iptr + bptr->icount;
+ startcount = count;
+ firstcount = count;
+
+ for (; iptr != iend; ++iptr) {
+ switch (iptr->opc) {
+#if defined(ENABLE_GC_CACAO)
+ case ICMD_BUILTIN:
+ md = iptr->sx.s23.s3.bte->md;
+ count++;
+ COUNT_javalocals(javalocals, m, alloccount);
+ alloccount += iptr->s1.argcount;
+ if (iinfo)
+ alloccount -= iinfo->throughcount;
+ break;
+#endif
+
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKEINTERFACE:
+ INSTRUCTION_GET_METHODDESC(iptr, md);
+ count++;
+ COUNT_javalocals(javalocals, m, alloccount);
+ alloccount += iptr->s1.argcount;
+ if (iinfo)
+ alloccount -= iinfo->throughcount;
+ break;
+
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+ stack_javalocals_store(iptr, javalocals);
+ break;
+
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ alloccount += 1;
+ /* FALLTHROUGH! */
+ case ICMD_RETURN:
+ count++;
+ break;
+
+ case ICMD_INLINE_START:
+ iinfo = iptr->sx.s23.s3.inlineinfo;
+
+ count++;
+ COUNT_javalocals(javalocals, m, alloccount);
+ alloccount += iinfo->stackvarscount;
+ if (iinfo->synclocal != UNUSED)
+ alloccount++;
+
+ m = iinfo->method;
+ /* javalocals may be set at next block start, or now */
+ COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
+ break;
+
+ case ICMD_INLINE_BODY:
+ assert(iinfo == iptr->sx.s23.s3.inlineinfo);
+
+ jl = iinfo->javalocals_start;
+ if (jl == NULL) {
+ /* get the javalocals from the following block start */
+ assert(bptr->next);
+ jl = bptr->next->javalocals;
+ }
+ count++;
+ COUNT_javalocals(jl, m, alloccount);
+ break;
+
+ case ICMD_INLINE_END:
+ assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
+ iinfo == iptr->sx.s23.s3.inlineinfo->parent);
+ iinfo = iptr->sx.s23.s3.inlineinfo;
+ m = iinfo->outer;
+ if (iinfo->javalocals_end)
+ MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
+ iinfo = iinfo->parent;
+ break;
+ }
+
+ if (iptr == bptr->iinstr)
+ firstcount = count;
+ } /* end instruction loop */
+
+ /* create replacement points at targets of backward branches */
+ /* We only need the replacement point there, if there is no */
+ /* replacement point inside the block. */
+
+ if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+ int test = (needentry && bptr == jd->basicblocks) ? firstcount : count;
+#else
+ int test = count;
+#endif
+ if (test > startcount) {
+ /* we don't need an extra rplpoint */
+ bptr->bitflags &= ~BBFLAG_REPLACEMENT;
+ }
+ else {
+ count++;
+ alloccount += bptr->indepth;
+ if (bptr->inlineinfo)
+ alloccount -= bptr->inlineinfo->throughcount;
+
+ COUNT_javalocals(bptr->javalocals, bptr->method, alloccount);
+ }
+ }
+
+ } /* end basicblock loop */
+
+ /* if no points were found, there's nothing to do */
+
+ if (!count)
+ return true;
+
+ /* allocate replacement point array and allocation array */
+
+ rplpoints = MNEW(rplpoint, count);
+ regalloc = MNEW(rplalloc, alloccount);
+ ra = regalloc;
+
+ /* initialize replacement point structs */
+
+ rp = rplpoints;
+
+ /* XXX try to share code with the counting loop! */
+
+ for (bptr = jd->basicblocks; bptr; bptr = bptr->next) {
+ /* skip dead code */
+
+ if (bptr->flags < BBFINISHED)
+ continue;
+
+ /* get info about this block */
+
+ m = bptr->method;
+ iinfo = bptr->inlineinfo;
+
+ /* initialize javalocals at the start of this block */
+
+ COPY_OR_CLEAR_javalocals(javalocals, bptr->javalocals, m);
+
+ /* create replacement points at targets of backward branches */
+
+ if (bptr->bitflags & BBFLAG_REPLACEMENT) {
+
+ i = (iinfo) ? iinfo->throughcount : 0;
+ replace_create_replacement_point(jd, iinfo, rp++,
+ bptr->type, bptr->iinstr, &ra,
+ bptr->javalocals, bptr->invars + i, bptr->indepth - i, 0);
+
+ if (JITDATA_HAS_FLAG_COUNTDOWN(jd))
+ rp[-1].flags |= RPLPOINT_FLAG_COUNTDOWN;
+ }
+
+ /* iterate over the instructions */
+
+ iptr = bptr->iinstr;
+ iend = iptr + bptr->icount;
+
+ for (; iptr != iend; ++iptr) {
+ switch (iptr->opc) {
+#if defined(ENABLE_GC_CACAO)
+ case ICMD_BUILTIN:
+ md = iptr->sx.s23.s3.bte->md;
+
+ i = (iinfo) ? iinfo->throughcount : 0;
+ replace_create_replacement_point(jd, iinfo, rp++,
+ RPLPOINT_TYPE_CALL, iptr, &ra,
+ javalocals, iptr->sx.s23.s2.args,
+ iptr->s1.argcount - i,
+ md->paramcount);
+ break;
+#endif
+
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKEINTERFACE:
+ INSTRUCTION_GET_METHODDESC(iptr, md);
+
+ i = (iinfo) ? iinfo->throughcount : 0;
+ replace_create_replacement_point(jd, iinfo, rp++,
+ RPLPOINT_TYPE_CALL, iptr, &ra,
+ javalocals, iptr->sx.s23.s2.args,
+ iptr->s1.argcount - i,
+ md->paramcount);
+ break;
+
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+ stack_javalocals_store(iptr, javalocals);
+ break;
+
+ case ICMD_IRETURN:
+ case ICMD_LRETURN:
+ case ICMD_FRETURN:
+ case ICMD_DRETURN:
+ case ICMD_ARETURN:
+ replace_create_replacement_point(jd, iinfo, rp++,
+ RPLPOINT_TYPE_RETURN, iptr, &ra,
+ NULL, &(iptr->s1.varindex), 1, 0);
+ break;
+
+ case ICMD_RETURN:
+ replace_create_replacement_point(jd, iinfo, rp++,
+ RPLPOINT_TYPE_RETURN, iptr, &ra,
+ NULL, NULL, 0, 0);
+ break;
+
+ case ICMD_INLINE_START:
+ iinfo = replace_create_inline_start_replacement_point(
+ jd, rp++, iptr, &ra, javalocals);
+ m = iinfo->method;
+ /* javalocals may be set at next block start, or now */
+ COPY_OR_CLEAR_javalocals(javalocals, iinfo->javalocals_start, m);
+ break;
+
+ case ICMD_INLINE_BODY:
+ assert(iinfo == iptr->sx.s23.s3.inlineinfo);
+
+ jl = iinfo->javalocals_start;
+ if (jl == NULL) {
+ /* get the javalocals from the following block start */
+ assert(bptr->next);
+ jl = bptr->next->javalocals;
+ }
+ /* create a non-trappable rplpoint */
+ replace_create_replacement_point(jd, iinfo, rp++,
+ RPLPOINT_TYPE_BODY, iptr, &ra,
+ jl, NULL, 0, 0);
+ rp[-1].flags |= RPLPOINT_FLAG_NOTRAP;
+ break;
+
+ case ICMD_INLINE_END:
+ assert(iinfo == iptr->sx.s23.s3.inlineinfo ||
+ iinfo == iptr->sx.s23.s3.inlineinfo->parent);
+ iinfo = iptr->sx.s23.s3.inlineinfo;
+ m = iinfo->outer;
+ if (iinfo->javalocals_end)
+ MCOPY(javalocals, iinfo->javalocals_end, s4, m->maxlocals);
+ iinfo = iinfo->parent;
+ break;
+ }
+ } /* end instruction loop */
+ } /* end basicblock loop */
+
+ assert((rp - rplpoints) == count);
+ assert((ra - regalloc) == alloccount);
+
+ /* store the data in the codeinfo */
+
+ code->rplpoints = rplpoints;
+ code->rplpointcount = count;
+ code->regalloc = regalloc;
+ code->regalloccount = alloccount;
+ code->globalcount = 0;
+ code->savedintcount = INT_SAV_CNT - rd->savintreguse;
+ code->savedfltcount = FLT_SAV_CNT - rd->savfltreguse;
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ code->savedadrcount = ADR_SAV_CNT - rd->savadrreguse;
+#endif
+ code->memuse = rd->memuse;
+ code->stackframesize = jd->cd->stackframesize;
+
+ REPLACE_COUNT_DIST(stat_dist_method_rplpoints, count);
+ REPLACE_COUNT_INC(stat_regallocs, alloccount);
+
+ /* everything alright */
+
+ return true;
+}
+
+
+/* replace_free_replacement_points *********************************************
+
+ Free memory used by replacement points.
+
+ IN:
+ code.............codeinfo whose replacement points should be freed.
+
+*******************************************************************************/
+
+void replace_free_replacement_points(codeinfo *code)
+{
+ assert(code);
+
+ if (code->rplpoints)
+ MFREE(code->rplpoints,rplpoint,code->rplpointcount);
+
+ if (code->regalloc)
+ MFREE(code->regalloc,rplalloc,code->regalloccount);
+
+ code->rplpoints = NULL;
+ code->rplpointcount = 0;
+ code->regalloc = NULL;
+ code->regalloccount = 0;
+ code->globalcount = 0;
+}
+
+
+/******************************************************************************/
+/* PART II: Activating / deactivating replacement points */
+/******************************************************************************/
+
+
+/* replace_activate_replacement_points *****************************************
+
+ Activate the replacement points of the given compilation unit. When this
+ function returns, the replacement points are "armed", so each thread
+ reaching one of the points will enter the replacement mechanism.
+
+ IN:
+ code.............codeinfo of which replacement points should be
+ activated
+ mappable.........if true, only mappable replacement points are
+ activated
+
+*******************************************************************************/
+
+void replace_activate_replacement_points(codeinfo *code, bool mappable)
+{
+ rplpoint *rp;
+ s4 i;
+ s4 count;
+ u1 *savedmcode;
+
+ assert(code->savedmcode == NULL);
+
+ /* count trappable replacement points */
+
+ count = 0;
+ i = code->rplpointcount;
+ rp = code->rplpoints;
+ for (; i--; rp++) {
+ if (rp->flags & RPLPOINT_FLAG_NOTRAP)
+ continue;
+
+ if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
+ continue;
+
+ count++;
+ }
+
+ /* allocate buffer for saved machine code */
+
+ savedmcode = MNEW(u1, count * REPLACEMENT_PATCH_SIZE);
+ code->savedmcode = savedmcode;
+ savedmcode += count * REPLACEMENT_PATCH_SIZE;
+
+ /* activate trappable replacement points */
+ /* (in reverse order to handle overlapping points within basic blocks) */
+
+ i = code->rplpointcount;
+ rp = code->rplpoints + i;
+ while (rp--, i--) {
+ assert(!(rp->flags & RPLPOINT_FLAG_ACTIVE));
+
+ if (rp->flags & RPLPOINT_FLAG_NOTRAP)
+ continue;
+
+ if (mappable && (rp->type == RPLPOINT_TYPE_RETURN))
+ continue;
+
+ DOLOG( printf("activate replacement point:\n");
+ replace_replacement_point_println(rp, 1); fflush(stdout); );
+
+ savedmcode -= REPLACEMENT_PATCH_SIZE;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_DISASSEMBLER)
+ DOLOG( printf("\tinstruction before: ");
+ disassinstr(rp->pc); fflush(stdout); );
+# endif
+
+ md_patch_replacement_point(rp->pc, savedmcode, false);
+
+# if defined(ENABLE_DISASSEMBLER)
+ DOLOG( printf("\tinstruction after : ");
+ disassinstr(rp->pc); fflush(stdout); );
+# endif
+#endif
+
+ rp->flags |= RPLPOINT_FLAG_ACTIVE;
+ }
+
+ assert(savedmcode == code->savedmcode);
+}
+
+
+/* replace_deactivate_replacement_points ***************************************
+
+ Deactivate a replacement points in the given compilation unit.
+ When this function returns, the replacement points will be "un-armed",
+ that is a each thread reaching a point will just continue normally.
+
+ IN:
+ code.............the compilation unit
+
+*******************************************************************************/
+
+void replace_deactivate_replacement_points(codeinfo *code)
+{
+ rplpoint *rp;
+ s4 i;
+ s4 count;
+ u1 *savedmcode;
+
+ if (code->savedmcode == NULL) {
+ /* disarm countdown points by patching the branches */
+
+ i = code->rplpointcount;
+ rp = code->rplpoints;
+ for (; i--; rp++) {
+ if ((rp->flags & (RPLPOINT_FLAG_ACTIVE | RPLPOINT_FLAG_COUNTDOWN))
+ == RPLPOINT_FLAG_COUNTDOWN)
+ {
+#if 0
+ *(s4*) (rp->pc + 9) = 0; /* XXX machine dependent! */
+#endif
+ }
+ }
+ return;
+ }
+
+ assert(code->savedmcode != NULL);
+ savedmcode = code->savedmcode;
+
+ /* de-activate each trappable replacement point */
+
+ i = code->rplpointcount;
+ rp = code->rplpoints;
+ count = 0;
+ for (; i--; rp++) {
+ if (!(rp->flags & RPLPOINT_FLAG_ACTIVE))
+ continue;
+
+ count++;
+
+ DOLOG( printf("deactivate replacement point:\n");
+ replace_replacement_point_println(rp, 1); fflush(stdout); );
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_DISASSEMBLER)
+ DOLOG( printf("\tinstruction before: ");
+ disassinstr(rp->pc); fflush(stdout); );
+# endif
+
+ md_patch_replacement_point(rp->pc, savedmcode, true);
+
+# if defined(ENABLE_DISASSEMBLER)
+ DOLOG( printf("\tinstruction before: ");
+ disassinstr(rp->pc); fflush(stdout); );
+# endif
+#endif
+
+ rp->flags &= ~RPLPOINT_FLAG_ACTIVE;
+
+ savedmcode += REPLACEMENT_PATCH_SIZE;
+ }
+
+ assert(savedmcode == code->savedmcode + count * REPLACEMENT_PATCH_SIZE);
+
+ /* free saved machine code */
+
+ MFREE(code->savedmcode, u1, count * REPLACEMENT_PATCH_SIZE);
+ code->savedmcode = NULL;
+}
+
+
+/******************************************************************************/
+/* PART III: The replacement mechanism */
+/******************************************************************************/
+
+
+/* replace_read_value **********************************************************
+
+ Read a value with the given allocation from the execution state.
+
+ IN:
+ es...............execution state
+ ra...............allocation
+ javaval..........where to put the value
+
+ OUT:
+ *javaval.........the value
+
+*******************************************************************************/
+
+static void replace_read_value(executionstate_t *es,
+ rplalloc *ra,
+ replace_val_t *javaval)
+{
+ if (ra->flags & INMEMORY) {
+ /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
+#ifdef HAS_4BYTE_STACKSLOT
+ if (IS_2_WORD_TYPE(ra->type)) {
+ javaval->l = *(u8*)(es->sp + ra->regoff);
+ }
+ else {
+#endif
+ javaval->p = *(ptrint*)(es->sp + ra->regoff);
+#ifdef HAS_4BYTE_STACKSLOT
+ }
+#endif
+ }
+ else {
+ /* allocated register */
+ if (IS_FLT_DBL_TYPE(ra->type)) {
+ javaval->d = es->fltregs[ra->regoff];
+
+ if (ra->type == TYPE_FLT)
+ javaval->f = javaval->d;
+ }
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ else if (IS_ADR_TYPE(ra->type)) {
+ javaval->p = es->adrregs[ra->regoff];
+ }
+#endif
+ else {
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ if (ra->type == TYPE_LNG) {
+ javaval->words.lo = es->intregs[GET_LOW_REG(ra->regoff)];
+ javaval->words.hi = es->intregs[GET_HIGH_REG(ra->regoff)];
+ }
+ else
+#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
+ javaval->p = es->intregs[ra->regoff];
+ }
+ }
+}
+
+
+/* replace_write_value *********************************************************
+
+ Write a value to the given allocation in the execution state.
+
+ IN:
+ es...............execution state
+ ra...............allocation
+ *javaval.........the value
+
+*******************************************************************************/
+
+static void replace_write_value(executionstate_t *es,
+ rplalloc *ra,
+ replace_val_t *javaval)
+{
+ if (ra->flags & INMEMORY) {
+ /* XXX HAS_4BYTE_STACKSLOT may not be the right discriminant here */
+#ifdef HAS_4BYTE_STACKSLOT
+ if (IS_2_WORD_TYPE(ra->type)) {
+ *(u8*)(es->sp + ra->regoff) = javaval->l;
+ }
+ else {
+#endif
+ *(ptrint*)(es->sp + ra->regoff) = javaval->p;
+#ifdef HAS_4BYTE_STACKSLOT
+ }
+#endif
+ }
+ else {
+ /* allocated register */
+ switch (ra->type) {
+ case TYPE_FLT:
+ es->fltregs[ra->regoff] = (double) javaval->f;
+ break;
+ case TYPE_DBL:
+ es->fltregs[ra->regoff] = javaval->d;
+ break;
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ case TYPE_LNG:
+ es->intregs[GET_LOW_REG(ra->regoff)] = javaval->words.lo;
+ es->intregs[GET_HIGH_REG(ra->regoff)] = javaval->words.hi;
+ break;
+#endif
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ case TYPE_ADR:
+ es->adrregs[ra->regoff] = javaval->p;
+#endif
+ default:
+ es->intregs[ra->regoff] = javaval->p;
+ }
+ }
+}
+
+
+/* replace_new_sourceframe *****************************************************
+
+ Allocate a new source frame and insert it at the front of the frame list.
+
+ IN:
+ ss...............the source state
+
+ OUT:
+ ss->frames.......set to new frame (the new head of the frame list).
+
+ RETURN VALUE:
+ returns the new frame
+
+*******************************************************************************/
+
+static sourceframe_t *replace_new_sourceframe(sourcestate_t *ss)
+{
+ sourceframe_t *frame;
+
+ frame = (sourceframe_t*) DumpMemory::allocate(sizeof(sourceframe_t));
+ MZERO(frame, sourceframe_t, 1);
+
+ frame->down = ss->frames;
+ ss->frames = frame;
+
+ return frame;
+}
+
+
+/* replace_read_executionstate *************************************************
+
+ Read a source frame from the given executions state.
+ The new source frame is pushed to the front of the frame list of the
+ source state.
+
+ IN:
+ rp...............replacement point at which `es` was taken
+ es...............execution state
+ ss...............the source state to add the source frame to
+ topframe.........true, if the first (top-most) source frame on the
+ stack is to be read
+
+ OUT:
+ *ss..............the source state with the newly created source frame
+ added
+
+*******************************************************************************/
+
+static s4 replace_normalize_type_map[] = {
+/* RPLPOINT_TYPE_STD |--> */ RPLPOINT_TYPE_STD,
+/* RPLPOINT_TYPE_EXH |--> */ RPLPOINT_TYPE_STD,
+/* RPLPOINT_TYPE_SBR |--> */ RPLPOINT_TYPE_STD,
+/* RPLPOINT_TYPE_CALL |--> */ RPLPOINT_TYPE_CALL,
+/* RPLPOINT_TYPE_INLINE |--> */ RPLPOINT_TYPE_CALL,
+/* RPLPOINT_TYPE_RETURN |--> */ RPLPOINT_TYPE_RETURN,
+/* RPLPOINT_TYPE_BODY |--> */ RPLPOINT_TYPE_STD
+};
+
+
+static void replace_read_executionstate(rplpoint *rp,
+ executionstate_t *es,
+ sourcestate_t *ss,
+ bool topframe)
+{
+ methodinfo *m;
+ codeinfo *code;
+ int count;
+ int i;
+ rplalloc *ra;
+ sourceframe_t *frame;
+ int topslot;
+ stackslot_t *sp;
+ stackslot_t *basesp;
+
+ code = code_find_codeinfo_for_pc(rp->pc);
+ m = rp->method;
+ topslot = TOP_IS_NORMAL;
+
+ /* stack pointer */
+
+ sp = (stackslot_t *) es->sp;
+
+ /* in some cases the top stack slot is passed in REG_ITMP1 */
+
+ if (rp->type == BBTYPE_EXH) {
+ topslot = TOP_IS_IN_ITMP1;
+ }
+
+ /* calculate base stack pointer */
+
+ basesp = sp + code->stackframesize;
+
+ /* create the source frame */
+
+ frame = replace_new_sourceframe(ss);
+ frame->method = rp->method;
+ frame->id = rp->id;
+ assert(rp->type >= 0 && rp->type < sizeof(replace_normalize_type_map)/sizeof(s4));
+ frame->type = replace_normalize_type_map[rp->type];
+ frame->fromrp = rp;
+ frame->fromcode = code;
+
+ /* read local variables */
+
+ count = m->maxlocals;
+ frame->javalocalcount = count;
+ frame->javalocals = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
+ frame->javalocaltype = (u1*) DumpMemory::allocate(sizeof(u1) * count);
+
+ /* mark values as undefined */
+ for (i=0; i<count; ++i) {
+#if !defined(NDEBUG)
+ frame->javalocals[i].l = (u8) 0x00dead0000dead00ULL;
+#endif
+ frame->javalocaltype[i] = TYPE_VOID;
+ }
+
+ /* some entries in the intregs array are not meaningful */
+ /*es->intregs[REG_ITMP3] = (u8) 0x11dead1111dead11ULL;*/
+#if !defined(NDEBUG)
+ es->intregs[REG_SP ] = (ptrint) 0x11dead1111dead11ULL;
+#ifdef REG_PV
+ es->intregs[REG_PV ] = (ptrint) 0x11dead1111dead11ULL;
+#endif
+#endif /* !defined(NDEBUG) */
+
+ /* read javalocals */
+
+ count = rp->regalloccount;
+ ra = rp->regalloc;
+
+ while (count && (i = ra->index) >= 0) {
+ assert(i < m->maxlocals);
+ frame->javalocaltype[i] = ra->type;
+ if (ra->type == TYPE_RET)
+ frame->javalocals[i].i = ra->regoff;
+ else
+ replace_read_value(es, ra, frame->javalocals + i);
+ ra++;
+ count--;
+ }
+
+ /* read instance, if this is the first rplpoint */
+
+#if defined(REPLACE_PATCH_DYNAMIC_CALL)
+ if (topframe && !(rp->method->flags & ACC_STATIC) && rp == code->rplpoints) {
+#if 1
+ /* we are at the start of the method body, so if local 0 is set, */
+ /* it is the instance. */
+ if (frame->javalocaltype[0] == TYPE_ADR)
+ frame->instance = frame->javalocals[0];
+#else
+ rplalloc instra;
+ methoddesc *md;
+
+ md = rp->method->parseddesc;
+ assert(md->params);
+ assert(md->paramcount >= 1);
+ instra.type = TYPE_ADR;
+ instra.regoff = md->params[0].regoff;
+ if (md->params[0].inmemory) {
+ instra.flags = INMEMORY;
+ instra.regoff += (1 + code->stackframesize) * SIZE_OF_STACKSLOT;
+ }
+ else {
+ instra.flags = 0;
+ }
+ 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 */
+
+ frame->javastackdepth = count;
+ frame->javastack = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
+ frame->javastacktype = (u1*) DumpMemory::allocate(sizeof(u1) * count);
+
+#if !defined(NDEBUG)
+ /* mark values as undefined */
+ for (i=0; i<count; ++i) {
+ frame->javastack[i].l = (u8) 0x00dead0000dead00ULL;
+ frame->javastacktype[i] = TYPE_VOID;
+ }
+#endif /* !defined(NDEBUG) */
+
+ i = 0;
+
+ /* the first stack slot is special in SBR and EXH blocks */
+
+ if (topslot == TOP_IS_ON_STACK) {
+ assert(count);
+
+ assert(ra->index == RPLALLOC_STACK);
+ assert(ra->type == TYPE_ADR);
+ frame->javastack[i].p = sp[-1];
+ frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
+ count--;
+ i++;
+ ra++;
+ }
+ else if (topslot == TOP_IS_IN_ITMP1) {
+ assert(count);
+
+ assert(ra->index == RPLALLOC_STACK);
+ assert(ra->type == TYPE_ADR);
+ frame->javastack[i].p = es->intregs[REG_ITMP1];
+ frame->javastacktype[i] = TYPE_ADR; /* XXX RET */
+ count--;
+ i++;
+ ra++;
+ }
+ else if (topslot == TOP_IS_VOID) {
+ assert(count);
+
+ assert(ra->index == RPLALLOC_STACK);
+ frame->javastack[i].l = 0;
+ frame->javastacktype[i] = TYPE_VOID;
+ count--;
+ i++;
+ ra++;
+ }
+
+ /* read remaining stack slots */
+
+ for (; count--; ra++) {
+ if (ra->index == RPLALLOC_SYNC) {
+ assert(rp->type == RPLPOINT_TYPE_INLINE);
+
+ /* only read synchronization slots when traversing an inline point */
+
+ if (!topframe) {
+ sourceframe_t *calleeframe = frame->down;
+ assert(calleeframe);
+ assert(calleeframe->syncslotcount == 0);
+ assert(calleeframe->syncslots == NULL);
+
+ calleeframe->syncslotcount = 1;
+ calleeframe->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t));
+ replace_read_value(es,ra,calleeframe->syncslots);
+ }
+
+ frame->javastackdepth--;
+ continue;
+ }
+
+ assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
+
+ /* do not read parameters of calls down the call chain */
+
+ if (!topframe && ra->index == RPLALLOC_PARAM) {
+ frame->javastackdepth--;
+ }
+ else {
+ if (ra->type == TYPE_RET)
+ frame->javastack[i].i = ra->regoff;
+ else
+ replace_read_value(es,ra,frame->javastack + i);
+ frame->javastacktype[i] = ra->type;
+ i++;
+ }
+ }
+}
+
+
+/* replace_write_executionstate ************************************************
+
+ Pop a source frame from the front of the frame list of the given source state
+ and write its values into the execution state.
+
+ IN:
+ rp...............replacement point for which execution state should be
+ created
+ es...............the execution state to modify
+ ss...............the given source state
+ topframe.........true, if this is the last (top-most) source frame to be
+ translated
+
+ OUT:
+ *es..............the execution state derived from the source state
+
+*******************************************************************************/
+
+static void replace_write_executionstate(rplpoint *rp,
+ executionstate_t *es,
+ sourcestate_t *ss,
+ bool topframe)
+{
+ methodinfo *m;
+ codeinfo *code;
+ int count;
+ int i;
+ rplalloc *ra;
+ sourceframe_t *frame;
+ int topslot;
+ stackslot_t *sp;
+ stackslot_t *basesp;
+
+ code = code_find_codeinfo_for_pc(rp->pc);
+ m = rp->method;
+ topslot = TOP_IS_NORMAL;
+
+ /* pop a source frame */
+
+ frame = ss->frames;
+ assert(frame);
+ ss->frames = frame->down;
+
+ /* calculate stack pointer */
+
+ sp = (stackslot_t *) es->sp;
+
+ basesp = sp + code->stackframesize;
+
+ /* in some cases the top stack slot is passed in REG_ITMP1 */
+
+ if (rp->type == BBTYPE_EXH) {
+ topslot = TOP_IS_IN_ITMP1;
+ }
+
+ /* write javalocals */
+
+ ra = rp->regalloc;
+ count = rp->regalloccount;
+
+ while (count && (i = ra->index) >= 0) {
+ assert(i < m->maxlocals);
+ assert(i < frame->javalocalcount);
+ assert(ra->type == frame->javalocaltype[i]);
+ if (ra->type == TYPE_RET) {
+ /* XXX assert that it matches this rplpoint */
+ }
+ else
+ replace_write_value(es, ra, frame->javalocals + i);
+ count--;
+ ra++;
+ }
+
+ /* write stack slots */
+
+ i = 0;
+
+ /* the first stack slot is special in SBR and EXH blocks */
+
+ if (topslot == TOP_IS_ON_STACK) {
+ assert(count);
+
+ assert(ra->index == RPLALLOC_STACK);
+ assert(i < frame->javastackdepth);
+ assert(frame->javastacktype[i] == TYPE_ADR);
+ sp[-1] = frame->javastack[i].p;
+ count--;
+ i++;
+ ra++;
+ }
+ else if (topslot == TOP_IS_IN_ITMP1) {
+ assert(count);
+
+ assert(ra->index == RPLALLOC_STACK);
+ assert(i < frame->javastackdepth);
+ assert(frame->javastacktype[i] == TYPE_ADR);
+ es->intregs[REG_ITMP1] = frame->javastack[i].p;
+ count--;
+ i++;
+ ra++;
+ }
+ else if (topslot == TOP_IS_VOID) {
+ assert(count);
+
+ assert(ra->index == RPLALLOC_STACK);
+ assert(i < frame->javastackdepth);
+ assert(frame->javastacktype[i] == TYPE_VOID);
+ count--;
+ i++;
+ ra++;
+ }
+
+ /* write remaining stack slots */
+
+ for (; count--; ra++) {
+ if (ra->index == RPLALLOC_SYNC) {
+ assert(rp->type == RPLPOINT_TYPE_INLINE);
+
+ /* only write synchronization slots when traversing an inline point */
+
+ if (!topframe) {
+ assert(frame->down);
+ assert(frame->down->syncslotcount == 1); /* XXX need to understand more cases */
+ assert(frame->down->syncslots != NULL);
+
+ replace_write_value(es,ra,frame->down->syncslots);
+ }
+ continue;
+ }
+
+ assert(ra->index == RPLALLOC_STACK || ra->index == RPLALLOC_PARAM);
+
+ /* do not write parameters of calls down the call chain */
+
+ 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);
+ assert(ra->type == frame->javastacktype[i]);
+ if (ra->type == TYPE_RET) {
+ /* XXX assert that it matches this rplpoint */
+ }
+ else {
+ replace_write_value(es,ra,frame->javastack + i);
+ }
+ i++;
+ }
+ }
+
+ /* set new pc */
+
+ es->pc = rp->pc;
+}
+
+
+/* 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.
+
+ *** This function imitates the effects of the method epilog ***
+ *** and returning from the method call. ***
+
+ IN:
+ es...............execution state
+
+ OUT:
+ *es..............the execution state after popping the stack frame
+ NOTE: es->code and es->pv are NOT updated.
+
+*******************************************************************************/
+
+void md_pop_stackframe(executionstate_t *es)
+{
+ u1 *ra;
+ s4 ra_align_off;
+ s4 reg;
+ s4 i;
+ stackslot_t *basesp;
+ stackslot_t *sp;
+
+ assert(es->code);
+
+ /* 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 = es->ra;
+ else
+#endif
+ ra = (u1*) md_stacktrace_get_returnaddress(es->sp,
+ 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;
+
+ /* 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->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->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
+#endif /* REPLACE_RA_LINKAGE_AREA */
+
+ /* restore saved int registers */
+
+ reg = INT_REG_CNT;
+ for (i=0; i<es->code->savedintcount; ++i) {
+ while (nregdescint[--reg] != REG_SAV)
+ ;
+ es->intregs[reg] = *--basesp;
+ }
+
+ /* restore saved flt registers */
+
+ /* XXX align? */
+ reg = FLT_REG_CNT;
+ for (i=0; i<es->code->savedfltcount; ++i) {
+ while (nregdescfloat[--reg] != REG_SAV)
+ ;
+ basesp -= STACK_SLOTS_PER_FLOAT;
+ es->fltregs[reg] = *(double*)basesp;
+ }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ /* restore saved adr registers */
+
+ reg = ADR_REG_CNT;
+ for (i=0; i<es->code->savedadrcount; ++i) {
+ while (nregdescadr[--reg] != REG_SAV)
+ ;
+ es->adrregs[reg] = *--basesp;
+ }
+#endif
+
+ /* adjust the stackpointer */
+
+ es->sp += SIZE_OF_STACKSLOT * es->code->stackframesize;
+
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+ es->sp += ra_align_off + SIZEOF_VOID_P; /* skip return address */
+#endif
+
+ /* set the program counter to the return address */
+
+ 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)
+ es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
+ for (i=0; i<FLT_REG_CNT; ++i)
+ if (nregdescfloat[i] != REG_SAV)
+ *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+ for (i=0; i<ADR_REG_CNT; ++i)
+ if (nregdescadr[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;
+ 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 = (replace_val_t*) DumpMemory::allocate(sizeof(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 */
+
+ void* pv = md_codegen_get_pv_from_pc(ra);
+ DOLOG( printf("PV = %p\n", pv); );
+
+ code = code_get_codeinfo_for_pv(pv);
+ DOLOG( printf("CODE = %p\n", (void*) code); );
+
+ /* return NULL if we reached native code */
+
+ es->pv = (uint8_t*) pv;
+ es->code = code;
+
+ return (code) ? ra : NULL;
+}
+
+
+/* replace_patch_method_pointer ************************************************
+
+ Patch a method pointer (may be in code, data segment, vftbl, or interface
+ table).
+
+ IN:
+ mpp..............address of the method pointer to patch
+ entrypoint.......the new entrypoint of the method
+ kind.............kind of call to patch, used only for debugging
+
+*******************************************************************************/
+
+static void replace_patch_method_pointer(methodptr *mpp,
+ methodptr entrypoint,
+ const char *kind)
+{
+#if !defined(NDEBUG)
+ codeinfo *oldcode;
+ codeinfo *newcode;
+#endif
+
+ DOLOG( printf("patch method pointer from: %p to %p\n",
+ (void*) *mpp, (void*)entrypoint); );
+
+#if !defined(NDEBUG)
+ oldcode = code_get_codeinfo_for_pv(*mpp);
+ newcode = code_get_codeinfo_for_pv(entrypoint);
+
+ DOLOG_SHORT( printf("\tpatch %s %p ", kind, (void*) oldcode);
+ method_println(oldcode->m);
+ printf("\t with %p ", (void*) newcode);
+ method_println(newcode->m); );
+
+ assert(oldcode->m == newcode->m);
+#endif
+
+ /* write the new entrypoint */
+
+ *mpp = (methodptr) entrypoint;
+}
+
+
+/* replace_patch_class *********************************************************
+
+ Patch a method in the given class.
+
+ IN:
+ vftbl............vftbl of the class
+ m................the method to patch
+ oldentrypoint....the old entrypoint to replace
+ entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+void replace_patch_class(vftbl_t *vftbl,
+ methodinfo *m,
+ u1 *oldentrypoint,
+ u1 *entrypoint)
+{
+ s4 i;
+ methodptr *mpp;
+ methodptr *mppend;
+
+ /* patch the vftbl of the class */
+
+ replace_patch_method_pointer(vftbl->table + m->vftblindex,
+ entrypoint,
+ "virtual ");
+
+ /* patch the interface tables */
+
+ assert(oldentrypoint);
+
+ for (i=0; i < vftbl->interfacetablelength; ++i) {
+ mpp = vftbl->interfacetable[-i];
+ mppend = mpp + vftbl->interfacevftbllength[i];
+ for (; mpp != mppend; ++mpp)
+ if (*mpp == oldentrypoint) {
+ replace_patch_method_pointer(mpp, entrypoint, "interface");
+ }
+ }
+}
+
+
+/* replace_patch_class_hierarchy ***********************************************
+
+ Patch a method in all loaded classes.
+
+ IN:
+ m................the method to patch
+ oldentrypoint....the old entrypoint to replace
+ entrypoint.......the new entrypoint
+
+*******************************************************************************/
+
+struct replace_patch_data_t {
+ methodinfo *m;
+ u1 *oldentrypoint;
+ u1 *entrypoint;
+};
+
+void replace_patch_callback(classinfo *c, struct replace_patch_data_t *pd)
+{
+ vftbl_t *vftbl = c->vftbl;
+
+ if (vftbl != NULL
+ && vftbl->vftbllength > pd->m->vftblindex
+ && (void*) vftbl->table[pd->m->vftblindex] != (void*) (uintptr_t) &asm_abstractmethoderror
+ && code_get_methodinfo_for_pv(vftbl->table[pd->m->vftblindex]) == pd->m)
+ {
+ replace_patch_class(c->vftbl, pd->m, pd->oldentrypoint, pd->entrypoint);
+ }
+}
+
+void replace_patch_class_hierarchy(methodinfo *m,
+ u1 *oldentrypoint,
+ u1 *entrypoint)
+{
+ struct replace_patch_data_t pd;
+
+ pd.m = m;
+ pd.oldentrypoint = oldentrypoint;
+ pd.entrypoint = entrypoint;
+
+ DOLOG_SHORT( printf("patching class hierarchy: ");
+ method_println(m); );
+
+ classcache_foreach_loaded_class(
+ (classcache_foreach_functionptr_t) &replace_patch_callback,
+ (void*) &pd);
+}
+
+
+/* replace_patch_future_calls **************************************************
+
+ Analyse a call site and depending on the kind of call patch the call, the
+ virtual function table, or the interface table.
+
+ IN:
+ ra...............return address pointing after the call site
+ callerframe......source frame of the caller
+ calleeframe......source frame of the callee, must have been mapped
+
+*******************************************************************************/
+
+void replace_patch_future_calls(u1 *ra,
+ sourceframe_t *callerframe,
+ sourceframe_t *calleeframe)
+{
+ u1 *patchpos;
+ methodptr entrypoint;
+ methodptr oldentrypoint;
+ bool atentry;
+ void *pv;
+ codeinfo *calleecode;
+ methodinfo *calleem;
+ java_object_t *obj;
+ vftbl_t *vftbl;
+
+ assert(ra);
+ assert(callerframe->down == calleeframe);
+
+ /* get the new codeinfo and the method that shall be entered */
+
+ calleecode = calleeframe->tocode;
+ assert(calleecode);
+
+ calleem = calleeframe->method;
+ assert(calleem == calleecode->m);
+
+ entrypoint = (methodptr) calleecode->entrypoint;
+
+ /* check if we are at an method entry rplpoint at the innermost frame */
+
+ atentry = (calleeframe->down == NULL)
+ && !(calleem->flags & ACC_STATIC)
+ && (calleeframe->fromrp->id == 0); /* XXX */
+
+ /* get the position to patch, in case it was a statically bound call */
+
+ pv = callerframe->fromcode->entrypoint;
+ patchpos = (u1*) md_jit_method_patch_address(pv, ra, NULL);
+
+ if (patchpos == NULL) {
+ /* the call was dispatched dynamically */
+
+ /* 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);
+
+ oldentrypoint = calleeframe->fromcode->entrypoint;
+
+ /* we need to know the instance */
+
+ if (!calleeframe->instance.a) {
+ DOLOG_SHORT( printf("WARNING: object instance unknown!\n"); );
+ replace_patch_class_hierarchy(calleem, oldentrypoint, entrypoint);
+ return;
+ }
+
+ /* get the vftbl */
+
+ obj = calleeframe->instance.a;
+ vftbl = obj->vftbl;
+
+ assert(vftbl->clazz->vftbl == vftbl);
+
+ DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
+
+ replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
+ }
+ 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 ");
+ }
+}
+
+
+/* replace_push_activation_record **********************************************
+
+ Push a stack frame onto the execution state.
+
+ *** This function imitates the effects of a call and the ***
+ *** method prolog of the callee. ***
+
+ IN:
+ es...............execution state
+ rpcall...........the replacement point at the call site
+ callerframe......source frame of the caller, or NULL for creating the
+ first frame
+ calleeframe......source frame of the callee, must have been mapped
+
+ OUT:
+ *es..............the execution state after pushing the stack frame
+
+*******************************************************************************/
+
+void replace_push_activation_record(executionstate_t *es,
+ rplpoint *rpcall,
+ sourceframe_t *callerframe,
+ sourceframe_t *calleeframe)
+{
+ s4 i;
+ s4 count;
+ stackslot_t *sp;
+ u1 *ra;
+ codeinfo *calleecode;
+
+ assert(es);
+ assert(!rpcall || callerframe);
+ assert(!rpcall || rpcall->type == RPLPOINT_TYPE_CALL);
+ assert(!rpcall || rpcall == callerframe->torp);
+ assert(calleeframe);
+ assert(!callerframe || calleeframe == callerframe->down);
+
+ /* the compilation unit we are entering */
+
+ calleecode = calleeframe->tocode;
+ assert(calleecode);
+
+ /* calculate the return address */
+
+ if (rpcall)
+ ra = rpcall->pc + rpcall->callsize;
+ else
+ ra = es->pc + 1 /* XXX this is ugly */;
+
+ /* push the stackframe */
+
+ md_push_stackframe(es, calleecode, ra);
+
+ /* we move into a new code unit, set code, PC, PV */
+
+ es->code = calleecode;
+ 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;
+ }
+
+ /* redirect future invocations */
+
+ if (callerframe && rpcall) {
+#if defined(REPLACE_PATCH_ALL)
+ if (rpcall->type == callerframe->fromrp->type)
+#else
+ if (rpcall == callerframe->fromrp)
+#endif
+ replace_patch_future_calls(ra, callerframe, calleeframe);
+ }
+}
+
+
+/* replace_find_replacement_point **********************************************
+
+ Find the replacement point in the given code corresponding to the
+ position given in the source frame.
+
+ IN:
+ code.............the codeinfo in which to search the rplpoint
+ frame............the source frame defining the position to look for
+ parent...........parent replacement point to match
+
+ RETURN VALUE:
+ the replacement point
+
+*******************************************************************************/
+
+rplpoint * replace_find_replacement_point(codeinfo *code,
+ sourceframe_t *frame,
+ rplpoint *parent)
+{
+ methodinfo *m;
+ rplpoint *rp;
+ s4 i;
+ s4 j;
+ s4 stacki;
+ rplalloc *ra;
+
+ assert(code);
+ assert(frame);
+
+ DOLOG( printf("searching replacement point for:\n");
+ replace_source_frame_println(frame); );
+
+ m = frame->method;
+
+ DOLOG( printf("code = %p\n", (void*)code); );
+
+ rp = code->rplpoints;
+ i = code->rplpointcount;
+ while (i--) {
+ if (rp->id == frame->id && rp->method == frame->method
+ && rp->parent == parent
+ && replace_normalize_type_map[rp->type] == frame->type)
+ {
+ /* check if returnAddresses match */
+ /* XXX optimize: only do this if JSRs in method */
+ DOLOG( printf("checking match for:");
+ replace_replacement_point_println(rp, 1); fflush(stdout); );
+ ra = rp->regalloc;
+ stacki = 0;
+ for (j = rp->regalloccount; j--; ++ra) {
+ if (ra->type == TYPE_RET) {
+ if (ra->index == RPLALLOC_STACK) {
+ assert(stacki < frame->javastackdepth);
+ if (frame->javastack[stacki].i != ra->regoff)
+ goto no_match;
+ stacki++;
+ }
+ else {
+ assert(ra->index >= 0 && ra->index < frame->javalocalcount);
+ if (frame->javalocals[ra->index].i != ra->regoff)
+ goto no_match;
+ }
+ }
+ }
+
+ /* found */
+ return rp;
+ }
+no_match:
+ rp++;
+ }
+
+#if !defined(NDEBUG)
+ printf("candidate replacement points were:\n");
+ rp = code->rplpoints;
+ i = code->rplpointcount;
+ for (; i--; ++rp) {
+ replace_replacement_point_println(rp, 1);
+ }
+#endif
+
+ vm_abort("no matching replacement point found");
+ return NULL; /* NOT REACHED */
+}
+
+
+/* replace_find_replacement_point_for_pc ***************************************
+
+ Find the nearest replacement point at or before the given PC. The
+ given PC has to be between (rp->pc) and (rp->pc+rp->callsize) for
+ the replacement point to be found.
+
+ IN:
+ code.............compilation unit the PC is in
+ pc...............the machine code PC
+
+ RETURN VALUE:
+ the replacement point found, or
+ NULL if no replacement point was found
+
+*******************************************************************************/
+
+rplpoint *replace_find_replacement_point_for_pc(codeinfo *code, u1 *pc, unsigned desired_flags)
+{
+ rplpoint *found;
+ rplpoint *rp;
+ s4 i;
+
+ DOLOG( printf("searching for rp at pc:%p in %p ", (void*)pc, (void*)code);
+ method_println(code->m); );
+
+ found = NULL;
+
+ 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) {
+ 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
+ for it.
+
+ IN:
+ es...............current execution state
+ ss...............the current source state
+ sfi..............stackframeinfo for the native frame
+
+ OUT:
+ es...............execution state after unrolling the native frame
+ ss...............gets the added native source frame
+
+*******************************************************************************/
+
+static void replace_pop_native_frame(executionstate_t *es,
+ sourcestate_t *ss,
+ stackframeinfo_t *sfi)
+{
+ sourceframe_t *frame;
+ codeinfo *code;
+ s4 i,j;
+
+ assert(sfi);
+
+ frame = replace_new_sourceframe(ss);
+
+ frame->sfi = sfi;
+
+ /* remember pc and size of native frame */
+
+ frame->nativepc = es->pc;
+ frame->nativeframesize = (es->sp != 0) ? (((uintptr_t) sfi->sp) - ((uintptr_t) es->sp)) : 0;
+ assert(frame->nativeframesize >= 0);
+
+ /* remember values of saved registers */
+
+ j = 0;
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ frame->nativesavint[j++] = es->intregs[i];
+ }
+
+ j = 0;
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ frame->nativesavflt[j++] = es->fltregs[i];
+ }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ j = 0;
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ frame->nativesavadr[j++] = es->adrregs[i];
+ }
+#endif
+
+ /* restore saved registers */
+
+#if defined(ENABLE_GC_CACAO) && !defined(HAS_ADDRESS_REGISTER_FILE)
+ j = 0;
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ es->intregs[i] = sfi->intregs[j++];
+ }
+#else
+ /* XXX we don't have them, yet, in the sfi, so clear them */
+
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ es->intregs[i] = 0;
+ }
+#endif
+
+ /* XXX we don't have float registers in the sfi, so clear them */
+
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ es->fltregs[i] = 0.0;
+ }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+# if defined(ENABLE_GC_CACAO)
+ j = 0;
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ es->adrregs[i] = sfi->adrregs[j++];
+ }
+# else
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ es->adrregs[i] = 0;
+ }
+# endif
+#endif
+
+ /* restore codeinfo of the native stub */
+
+ code = code_get_codeinfo_for_pv(sfi->pv);
+
+ /* restore sp, pv, pc and codeinfo of the parent method */
+
+ /* XXX michi: use this instead:
+ es->sp = sfi->sp + code->stackframesize; */
+ es->sp = (uint8_t*) (((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 = (uint8_t*) md_codegen_get_pv_from_pc(sfi->ra);
+ es->pc = (uint8_t*) (((uintptr_t) ((sfi->xpc) ? sfi->xpc : sfi->ra)) - 1);
+ es->code = code_get_codeinfo_for_pv(es->pv);
+}
+
+
+/* replace_push_native_frame ***************************************************
+
+ Rebuild a native frame onto the execution state and remove its source frame.
+
+ Note: The native frame is "rebuild" by setting fields like PC and stack
+ pointer in the execution state accordingly. Values in the
+ stackframeinfo may be modified, but the actual stack frame of the
+ native code is not touched.
+
+ IN:
+ es...............current execution state
+ ss...............the current source state
+
+ OUT:
+ es...............execution state after re-rolling the native frame
+ ss...............the native source frame is removed
+
+*******************************************************************************/
+
+static void replace_push_native_frame(executionstate_t *es, sourcestate_t *ss)
+{
+ sourceframe_t *frame;
+ s4 i,j;
+
+ assert(es);
+ assert(ss);
+
+ DOLOG( printf("pushing native frame\n"); );
+
+ /* remove the frame from the source state */
+
+ frame = ss->frames;
+ assert(frame);
+ assert(REPLACE_IS_NATIVE_FRAME(frame));
+
+ ss->frames = frame->down;
+
+ /* skip sp for the native stub */
+
+ es->sp -= (*(s4 *) (((uintptr_t) frame->sfi->pv) + FrameSize));
+#if defined(REPLACE_RA_BETWEEN_FRAMES)
+ es->sp -= SIZE_OF_STACKSLOT; /* skip return address */
+#endif
+
+ /* assert that the native frame has not moved */
+
+ assert(es->sp == frame->sfi->sp);
+
+ /* update saved registers in the stackframeinfo */
+
+#if defined(ENABLE_GC_CACAO)
+ j = 0;
+# if !defined(HAS_ADDRESS_REGISTER_FILE)
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ frame->sfi->intregs[j++] = es->intregs[i];
+ }
+# else
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ frame->sfi->adrregs[j++] = es->adrregs[i];
+ }
+# endif
+
+ /* XXX leave float registers untouched here */
+#endif
+
+ /* restore saved registers */
+
+ j = 0;
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ es->intregs[i] = frame->nativesavint[j++];
+ }
+
+ j = 0;
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ es->fltregs[i] = frame->nativesavflt[j++];
+ }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ j = 0;
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (nregdescadr[i] == REG_SAV)
+ es->adrregs[i] = frame->nativesavadr[j++];
+ }
+#endif
+
+ /* skip the native frame on the machine stack */
+
+ es->sp -= frame->nativeframesize;
+
+ /* set the pc the next frame must return to */
+
+ es->pc = frame->nativepc;
+}
+
+
+/* replace_recover_source_state ************************************************
+
+ Recover the source state from the given replacement point and execution
+ state.
+
+ IN:
+ rp...............replacement point that has been reached, if any
+ sfi..............stackframeinfo, if called from native code
+ es...............execution state at the replacement point rp
+
+ RETURN VALUE:
+ the source state
+
+*******************************************************************************/
+
+sourcestate_t *replace_recover_source_state(rplpoint *rp,
+ stackframeinfo_t *sfi,
+ executionstate_t *es)
+{
+ sourcestate_t *ss;
+ u1 *ra;
+ bool locked;
+#if defined(REPLACE_STATISTICS)
+ s4 depth;
+#endif
+
+ /* create the source frame structure in dump memory */
+
+ ss = (sourcestate_t*) DumpMemory::allocate(sizeof(sourcestate_t));
+ ss->frames = NULL;
+
+ /* each iteration of the loop recovers one source frame */
+
+ depth = 0;
+ locked = false;
+
+ while (rp || sfi) {
+
+ DOLOG( executionstate_println(es); );
+
+ /* if we are not at a replacement point, it is a native frame */
+
+ if (rp == NULL) {
+ DOLOG( printf("native frame: sfi: "); replace_stackframeinfo_println(sfi); );
+
+ locked = true;
+ replace_pop_native_frame(es, ss, sfi);
+ sfi = sfi->prev;
+
+ if (es->code == NULL)
+ continue;
+
+ goto after_machine_frame;
+ }
+
+ /* read the values for this source frame from the execution state */
+
+ DOLOG( printf("recovering source state for%s:\n",
+ (ss->frames == NULL) ? " TOPFRAME" : "");
+ replace_replacement_point_println(rp, 1); );
+
+ replace_read_executionstate(rp, es, ss, ss->frames == NULL);
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_unrol_method(ss->frames->method);
+#endif
+
+#if defined(REPLACE_STATISTICS)
+ REPLACE_COUNT(stat_frames);
+ depth++;
+ replace_statistics_source_frame(ss->frames);
+#endif
+
+ /* in locked areas (below native frames), identity map the frame */
+
+ if (locked) {
+ ss->frames->torp = ss->frames->fromrp;
+ ss->frames->tocode = ss->frames->fromcode;
+ }
+
+ /* unroll to the next (outer) frame */
+
+ if (rp->parent) {
+ /* this frame is in inlined code */
+
+ DOLOG( printf("INLINED!\n"); );
+
+ rp = rp->parent;
+
+ assert(rp->type == RPLPOINT_TYPE_INLINE);
+ REPLACE_COUNT(stat_unroll_inline);
+ }
+ else {
+ /* this frame had been called at machine-level. pop it. */
+
+ DOLOG( printf("UNWIND\n"); );
+
+ ra = replace_pop_activation_record(es, ss->frames);
+ if (ra == NULL) {
+ DOLOG( printf("REACHED NATIVE CODE\n"); );
+
+ rp = NULL;
+
+#if !defined(ENABLE_GC_CACAO)
+ break; /* XXX remove to activate native frames */
+#endif
+ continue;
+ }
+
+ /* find the replacement point at the call site */
+
+after_machine_frame:
+ 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");
+
+ DOLOG( printf("found replacement point.\n");
+ replace_replacement_point_println(rp, 1); );
+
+ assert(rp->type == RPLPOINT_TYPE_CALL);
+ REPLACE_COUNT(stat_unroll_call);
+ }
+ } /* end loop over source frames */
+
+ REPLACE_COUNT_DIST(stat_dist_frames, depth);
+
+ return ss;
+}
+
+
+/* replace_map_source_state ****************************************************
+
+ Map each source frame in the given source state to a target replacement
+ point and compilation unit. If no valid code is available for a source
+ frame, it is (re)compiled.
+
+ IN:
+ ss...............the source state
+
+ OUT:
+ ss...............the source state, modified: The `torp` and `tocode`
+ fields of each source frame are set.
+
+ RETURN VALUE:
+ true.............everything went ok
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool replace_map_source_state(sourcestate_t *ss)
+{
+ sourceframe_t *frame;
+ codeinfo *code;
+ rplpoint *rp;
+ rplpoint *parent; /* parent of inlined rplpoint */
+#if defined(REPLACE_STATISTICS)
+ codeinfo *oldcode;
+#endif
+
+ parent = NULL;
+ code = NULL;
+
+ /* iterate over the source frames from outermost to innermost */
+
+ for (frame = ss->frames; frame != NULL; frame = frame->down) {
+
+ /* XXX skip native frames */
+
+ if (REPLACE_IS_NATIVE_FRAME(frame)) {
+ parent = NULL;
+ continue;
+ }
+
+ /* map frames which are not already mapped */
+
+ if (frame->tocode) {
+ code = frame->tocode;
+ rp = frame->torp;
+ assert(rp);
+ }
+ else {
+ assert(frame->torp == NULL);
+
+ if (parent == NULL) {
+ /* find code for this frame */
+
+#if defined(REPLACE_STATISTICS)
+ oldcode = frame->method->code;
+#endif
+ /* request optimization of hot methods and their callers */
+
+ if (frame->method->hitcountdown < 0
+ || (frame->down && frame->down->method->hitcountdown < 0))
+ jit_request_optimization(frame->method);
+
+ code = jit_get_current_code(frame->method);
+
+ if (code == NULL)
+ return false; /* exception */
+
+ REPLACE_COUNT_IF(stat_recompile, code != oldcode);
+ }
+
+ assert(code);
+
+ /* map this frame */
+
+ rp = replace_find_replacement_point(code, frame, parent);
+
+ frame->tocode = code;
+ frame->torp = rp;
+ }
+
+ if (rp->type == RPLPOINT_TYPE_CALL) {
+ parent = NULL;
+ }
+ else {
+ /* inlining */
+ parent = rp;
+ }
+ }
+
+ return true;
+}
+
+
+/* replace_map_source_state_identity *******************************************
+
+ Map each source frame in the given source state to the same replacement
+ point and compilation unit it was derived from. This is mainly used for
+ garbage collection.
+
+ IN:
+ ss...............the source state
+
+ OUT:
+ ss...............the source state, modified: The `torp` and `tocode`
+ fields of each source frame are set.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+static void replace_map_source_state_identity(sourcestate_t *ss)
+{
+ sourceframe_t *frame;
+
+ /* iterate over the source frames from outermost to innermost */
+
+ for (frame = ss->frames; frame != NULL; frame = frame->down) {
+
+ /* skip native frames */
+
+ if (REPLACE_IS_NATIVE_FRAME(frame)) {
+ continue;
+ }
+
+ /* map frames using the identity mapping */
+
+ if (frame->tocode) {
+ assert(frame->tocode == frame->fromcode);
+ assert(frame->torp == frame->fromrp);
+ } else {
+ assert(frame->tocode == NULL);
+ assert(frame->torp == NULL);
+ frame->tocode = frame->fromcode;
+ frame->torp = frame->fromrp;
+ }
+ }
+}
+#endif
+
+
+/* replace_build_execution_state ***********************************************
+
+ Build an execution state for the given (mapped) source state.
+
+ !!! CAUTION: This function rewrites the machine stack !!!
+
+ THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
+
+ IN:
+ ss...............the source state. Must have been mapped by
+ replace_map_source_state before.
+ es...............the base execution state on which to build
+
+ OUT:
+ *es..............the new execution state
+
+*******************************************************************************/
+
+static void replace_build_execution_state(sourcestate_t *ss,
+ executionstate_t *es)
+{
+ rplpoint *rp;
+ sourceframe_t *prevframe;
+ rplpoint *parent;
+
+ parent = NULL;
+ prevframe = NULL;
+ rp = NULL;
+
+ while (ss->frames) {
+
+ if (REPLACE_IS_NATIVE_FRAME(ss->frames)) {
+ prevframe = ss->frames;
+ replace_push_native_frame(es, ss);
+ parent = NULL;
+ rp = NULL;
+ continue;
+ }
+
+ if (parent == NULL) {
+ /* create a machine-level stack frame */
+
+ DOLOG( printf("pushing activation record for:\n");
+ if (rp) replace_replacement_point_println(rp, 1);
+ else printf("\tfirst frame\n"); );
+
+ replace_push_activation_record(es, rp, prevframe, ss->frames);
+
+ DOLOG( executionstate_println(es); );
+ }
+
+ rp = ss->frames->torp;
+ assert(rp);
+
+ DOLOG( printf("creating execution state for%s:\n",
+ (ss->frames->down == NULL) ? " TOPFRAME" : "");
+ replace_replacement_point_println(ss->frames->fromrp, 1);
+ replace_replacement_point_println(rp, 1); );
+
+ es->code = ss->frames->tocode;
+ prevframe = ss->frames;
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_rerol_method(ss->frames->method);
+#endif
+
+ replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
+
+ DOLOG( executionstate_println(es); );
+
+ if (rp->type == RPLPOINT_TYPE_CALL) {
+ parent = NULL;
+ }
+ else {
+ /* inlining */
+ parent = rp;
+ }
+ }
+}
+
+
+/* replace_me ******************************************************************
+
+ This function is called by the signal handler when a thread reaches
+ a replacement point. `replace_me` must map the execution state to the
+ target replacement point and let execution continue there.
+
+ THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
+
+ IN:
+ rp...............replacement point that has been reached
+ es...............execution state read by signal handler
+
+*******************************************************************************/
+
+static void replace_me(rplpoint *rp, executionstate_t *es)
+{
+ stackframeinfo_t *sfi;
+ sourcestate_t *ss;
+ sourceframe_t *frame;
+ codeinfo *origcode;
+ rplpoint *origrp;
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+ threadobject *thread;
+#endif
+
+ 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);
+ method_println(es->code->m); );
+
+ DOLOG( replace_replacement_point_println(rp, 1); );
+
+ REPLACE_COUNT(stat_replacements);
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* Get the stackframeinfo for the current thread. */
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* recover source state */
+
+ ss = replace_recover_source_state(rp, sfi, es);
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+ /* if there is a collection pending, we assume the replacement point should
+ suspend this thread */
+
+ if (gc_pending) {
+
+ thread = THREADOBJECT;
+
+ DOLOG_SHORT( printf("REPLACEMENT: Suspending thread for GC now!\n"); );
+
+ /* map the sourcestate using the identity mapping */
+ replace_map_source_state_identity(ss);
+
+ /* since we enter the same method again, we turn off rps now */
+ /* XXX michi: can we really do this? what if the rp was active before
+ we activated it for the gc? */
+ replace_deactivate_replacement_points(origcode);
+
+ /* remember executionstate and sourcestate for this thread */
+ GC_EXECUTIONSTATE = es;
+ GC_SOURCESTATE = ss;
+
+ /* really suspend this thread now (PC = 0) */
+ threads_suspend_ack(NULL, NULL);
+
+ DOLOG_SHORT( printf("REPLACEMENT: Resuming thread after GC now!\n"); );
+
+ } else {
+#endif /*defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)*/
+
+ /* map the source state */
+
+ if (!replace_map_source_state(ss))
+ vm_abort("exception during method replacement");
+
+ DOLOG( replace_sourcestate_println(ss); );
+
+ DOLOG_SHORT( replace_sourcestate_println_short(ss); );
+
+#if !defined(NDEBUG)
+ /* avoid infinite loops by self-replacement, only if not in testing mode */
+
+ if (!opt_TestReplacement) {
+ frame = ss->frames;
+ while (frame->down)
+ frame = frame->down;
+
+ if (frame->torp == origrp) {
+ DOLOG_SHORT(
+ printf("WARNING: identity replacement, turning off rps to avoid infinite loop\n");
+ );
+ replace_deactivate_replacement_points(origcode);
+ }
+ }
+#endif
+
+#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
+ }
+#endif
+
+ /* build the new execution state */
+
+ replace_build_execution_state(ss, es);
+
+#if !defined(NDEBUG)
+ /* continue execution after patched machine code, if testing mode enabled */
+
+ if (opt_TestReplacement)
+ es->pc += REPLACEMENT_PATCH_SIZE;
+#endif
+}
+
+
+/* replace_me_wrapper **********************************************************
+
+ This function is called by the signal handler. It determines if there
+ is an active replacement point pending at the given PC and returns
+ accordingly.
+
+ THIS FUNCTION MUST BE CALLED USING A SAFE STACK AREA!
+
+ IN:
+ pc...............the program counter that triggered the replacement.
+ context..........the context (machine state) to which the
+ replacement should be applied.
+
+ OUT:
+ context..........the context after replacement finished.
+
+ RETURN VALUE:
+ true.............replacement done, everything went ok
+ false............no replacement done, context unchanged
+
+*******************************************************************************/
+
+bool replace_me_wrapper(u1 *pc, void *context)
+{
+ 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 */
+
+ code = code_find_codeinfo_for_pc(pc);
+ assert(code);
+
+ /* search for a replacement point at the given 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 | RPLPOINT_FLAG_COUNTDOWN))) {
+
+ DOLOG( printf("valid replacement point\n"); );
+
+#if !defined(NDEBUG)
+ executionstate_sanity_check(context);
+#endif
+
+ /* set codeinfo pointer in execution state */
+
+ es.code = code;
+
+ /* read execution state from current context */
+
+ md_executionstate_read(&es, context);
+
+ DOLOG( printf("REPLACEMENT READ: ");
+ executionstate_println(&es); );
+
+ /* 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);
+
+ DOLOG( printf("REPLACEMENT WRITE: ");
+ executionstate_println(&es); );
+
+ /* new code is entered after returning */
+
+ DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
+ return true;
+ }
+ else
+ return false;
+}
+
+
+/******************************************************************************/
+/* NOTE: Stuff specific to the exact GC is below. */
+/******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void replace_gc_from_native(threadobject *thread, u1 *pc, u1 *sp)
+{
+ stackframeinfo_t *sfi;
+ executionstate_t *es;
+ sourcestate_t *ss;
+
+ /* Get the stackframeinfo of this thread. */
+
+ assert(thread == THREADOBJECT);
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* create the execution state */
+ es = (executionstate_t*) DumpMemory::allocate(sizeof(executionstate_t));
+ es->pc = pc;
+ es->sp = sp;
+ es->pv = 0; /* since we are in a native, PV is invalid! */
+ es->code = NULL; /* since we are in a native, we do not have a codeinfo */
+
+ /* we assume we are in a native (no replacement point)! */
+ ss = replace_recover_source_state(NULL, sfi, es);
+
+ /* map the sourcestate using the identity mapping */
+ replace_map_source_state_identity(ss);
+
+ /* remember executionstate and sourcestate for this thread */
+ GC_EXECUTIONSTATE = es;
+ GC_SOURCESTATE = ss;
+}
+#endif
+
+#if defined(ENABLE_GC_CACAO)
+void replace_gc_into_native(threadobject *thread)
+{
+ executionstate_t *es;
+ sourcestate_t *ss;
+
+ /* get the executionstate and sourcestate for the given thread */
+ es = GC_EXECUTIONSTATE;
+ ss = GC_SOURCESTATE;
+
+ /* rebuild the stack of the given thread */
+ replace_build_execution_state(ss, es);
+}
+#endif
+
+
+/******************************************************************************/
+/* NOTE: No important code below. */
+/******************************************************************************/
+
+
+/* statistics *****************************************************************/
+
+#if defined(REPLACE_STATISTICS)
+static void print_freq(FILE *file,int *array,int limit)
+{
+ int i;
+ int sum = 0;
+ int cum = 0;
+ for (i=0; i<limit; ++i)
+ sum += array[i];
+ sum += array[limit];
+ for (i=0; i<limit; ++i) {
+ cum += array[i];
+ fprintf(file," %3d: %8d (cum %3d%%)\n",
+ i, array[i], (sum) ? ((100*cum)/sum) : 0);
+ }
+ fprintf(file," >=%3d: %8d\n",limit,array[limit]);
+}
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+#if defined(REPLACE_STATISTICS)
+
+#define REPLACE_PRINT_DIST(name, array) \
+ printf(" " name " distribution:\n"); \
+ print_freq(stdout, (array), sizeof(array)/sizeof(int) - 1);
+
+void replace_print_statistics(void)
+{
+ printf("replacement statistics:\n");
+ printf(" # of replacements: %d\n", stat_replacements);
+ printf(" # of frames: %d\n", stat_frames);
+ printf(" # of recompilations: %d\n", stat_recompile);
+ printf(" patched static calls:%d\n", stat_staticpatch);
+ printf(" unrolled inlines: %d\n", stat_unroll_inline);
+ printf(" unrolled calls: %d\n", stat_unroll_call);
+ REPLACE_PRINT_DIST("frame depth", stat_dist_frames);
+ REPLACE_PRINT_DIST("locals per frame", stat_dist_locals);
+ REPLACE_PRINT_DIST("ADR locals per frame", stat_dist_locals_adr);
+ REPLACE_PRINT_DIST("primitive locals per frame", stat_dist_locals_prim);
+ REPLACE_PRINT_DIST("RET locals per frame", stat_dist_locals_ret);
+ REPLACE_PRINT_DIST("void locals per frame", stat_dist_locals_void);
+ REPLACE_PRINT_DIST("stack slots per frame", stat_dist_stack);
+ REPLACE_PRINT_DIST("ADR stack slots per frame", stat_dist_stack_adr);
+ REPLACE_PRINT_DIST("primitive stack slots per frame", stat_dist_stack_prim);
+ REPLACE_PRINT_DIST("RET stack slots per frame", stat_dist_stack_ret);
+ printf("\n");
+ printf(" # of methods: %d\n", stat_methods);
+ printf(" # of replacement points: %d\n", stat_rploints);
+ printf(" # of regallocs: %d\n", stat_regallocs);
+ printf(" per rplpoint: %f\n", (double)stat_regallocs / stat_rploints);
+ printf(" per method: %f\n", (double)stat_regallocs / stat_methods);
+ REPLACE_PRINT_DIST("replacement points per method", stat_dist_method_rplpoints);
+ printf("\n");
+
+}
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+#if defined(REPLACE_STATISTICS)
+static void replace_statistics_source_frame(sourceframe_t *frame)
+{
+ int adr = 0;
+ int ret = 0;
+ int prim = 0;
+ int vd = 0;
+ int n = 0;
+ int i;
+
+ for (i=0; i<frame->javalocalcount; ++i) {
+ switch (frame->javalocaltype[i]) {
+ case TYPE_ADR: adr++; break;
+ case TYPE_RET: ret++; break;
+ case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
+ case TYPE_VOID: vd++; break;
+ default: assert(0);
+ }
+ n++;
+ }
+ REPLACE_COUNT_DIST(stat_dist_locals, n);
+ REPLACE_COUNT_DIST(stat_dist_locals_adr, adr);
+ REPLACE_COUNT_DIST(stat_dist_locals_void, vd);
+ REPLACE_COUNT_DIST(stat_dist_locals_ret, ret);
+ REPLACE_COUNT_DIST(stat_dist_locals_prim, prim);
+ adr = ret = prim = n = 0;
+ for (i=0; i<frame->javastackdepth; ++i) {
+ switch (frame->javastacktype[i]) {
+ case TYPE_ADR: adr++; break;
+ case TYPE_RET: ret++; break;
+ case TYPE_INT: case TYPE_LNG: case TYPE_FLT: case TYPE_DBL: prim++; break;
+ }
+ n++;
+ }
+ REPLACE_COUNT_DIST(stat_dist_stack, n);
+ REPLACE_COUNT_DIST(stat_dist_stack_adr, adr);
+ REPLACE_COUNT_DIST(stat_dist_stack_ret, ret);
+ REPLACE_COUNT_DIST(stat_dist_stack_prim, prim);
+}
+#endif /* defined(REPLACE_STATISTICS) */
+
+
+/* debugging helpers **********************************************************/
+
+/* replace_replacement_point_println *******************************************
+
+ Print replacement point info.
+
+ IN:
+ rp...............the replacement point to print
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+
+#define TYPECHAR(t) (((t) >= 0 && (t) <= TYPE_RET) ? show_jit_type_letters[t] : '?')
+
+static const char *replace_type_str[] = {
+ "STD",
+ "EXH",
+ "SBR",
+ "CALL",
+ "INLINE",
+ "RETURN",
+ "BODY"
+};
+
+void replace_replacement_point_println(rplpoint *rp, int depth)
+{
+ int j;
+ int index;
+
+ if (!rp) {
+ printf("(rplpoint *)NULL\n");
+ return;
+ }
+
+ for (j=0; j<depth; ++j)
+ putchar('\t');
+
+ printf("rplpoint (id %d) %p pc:%p+%d type:%s",
+ rp->id, (void*)rp,rp->pc,rp->callsize,
+ replace_type_str[rp->type]);
+ if (rp->flags & RPLPOINT_FLAG_NOTRAP)
+ printf(" NOTRAP");
+ if (rp->flags & RPLPOINT_FLAG_COUNTDOWN)
+ printf(" COUNTDOWN");
+ if (rp->flags & RPLPOINT_FLAG_ACTIVE)
+ printf(" ACTIVE");
+ printf(" parent:%p\n", (void*)rp->parent);
+ for (j=0; j<depth; ++j)
+ putchar('\t');
+ printf("ra:%d = [", rp->regalloccount);
+
+ for (j=0; j<rp->regalloccount; ++j) {
+ if (j)
+ putchar(' ');
+ index = rp->regalloc[j].index;
+ switch (index) {
+ case RPLALLOC_STACK: printf("S"); break;
+ case RPLALLOC_PARAM: printf("P"); break;
+ case RPLALLOC_SYNC : printf("Y"); break;
+ default: printf("%d", index);
+ }
+ printf(":%1c:", TYPECHAR(rp->regalloc[j].type));
+ if (rp->regalloc[j].type == TYPE_RET) {
+ printf("ret(L%03d)", rp->regalloc[j].regoff);
+ }
+ else {
+ show_allocation(rp->regalloc[j].type, rp->regalloc[j].flags, rp->regalloc[j].regoff);
+ }
+ }
+
+ printf("]\n");
+ for (j=0; j<depth; ++j)
+ putchar('\t');
+ printf("method: ");
+ method_print(rp->method);
+
+ printf("\n");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* replace_show_replacement_points *********************************************
+
+ Print replacement point info.
+
+ IN:
+ code.............codeinfo whose replacement points should be printed.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void replace_show_replacement_points(codeinfo *code)
+{
+ int i;
+ int depth;
+ rplpoint *rp;
+ rplpoint *parent;
+
+ if (!code) {
+ printf("(codeinfo *)NULL\n");
+ return;
+ }
+
+ printf("\treplacement points: %d\n",code->rplpointcount);
+
+ printf("\ttotal allocations : %d\n",code->regalloccount);
+ printf("\tsaved int regs : %d\n",code->savedintcount);
+ printf("\tsaved flt regs : %d\n",code->savedfltcount);
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ printf("\tsaved adr regs : %d\n",code->savedadrcount);
+#endif
+ printf("\tmemuse : %d\n",code->memuse);
+
+ printf("\n");
+
+ for (i=0; i<code->rplpointcount; ++i) {
+ rp = code->rplpoints + i;
+
+ depth = 1;
+ parent = rp->parent;
+ while (parent) {
+ depth++;
+ parent = parent->parent;
+ }
+ replace_replacement_point_println(rp, depth);
+ }
+}
+#endif
+
+
+#if !defined(NDEBUG)
+static void java_value_print(s4 type, replace_val_t value)
+{
+ java_object_t *obj;
+ utf *u;
+
+ printf("%016llx",(unsigned long long) value.l);
+
+ if (type < 0 || type > TYPE_RET)
+ printf(" <INVALID TYPE:%d>", type);
+ else
+ printf(" %s", show_jit_type_names[type]);
+
+ if (type == TYPE_ADR && value.a != NULL) {
+ obj = value.a;
+ putchar(' ');
+ utf_display_printable_ascii_classname(obj->vftbl->clazz->name);
+
+ if (obj->vftbl->clazz == class_java_lang_String) {
+ printf(" \"");
+ u = javastring_toutf(obj, false);
+ utf_display_printable_ascii(u);
+ printf("\"");
+ }
+ }
+ else if (type == TYPE_INT) {
+ printf(" %ld", (long) value.i);
+ }
+ else if (type == TYPE_LNG) {
+ printf(" %lld", (long long) value.l);
+ }
+ else if (type == TYPE_FLT) {
+ printf(" %f", value.f);
+ }
+ else if (type == TYPE_DBL) {
+ printf(" %f", value.d);
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+#if !defined(NDEBUG)
+void replace_source_frame_println(sourceframe_t *frame)
+{
+ s4 i,j;
+ s4 t;
+
+ if (REPLACE_IS_NATIVE_FRAME(frame)) {
+ printf("\tNATIVE\n");
+ printf("\tsfi: "); replace_stackframeinfo_println(frame->sfi);
+ printf("\tnativepc: %p\n", frame->nativepc);
+ printf("\tframesize: %d\n", frame->nativeframesize);
+
+ j = 0;
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (nregdescint[i] == REG_SAV)
+ printf("\t%s = %p\n", abi_registers_integer_name[i], (void*)frame->nativesavint[j++]);
+ }
+
+ j = 0;
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (nregdescfloat[i] == REG_SAV)
+ printf("\tF%02d = %f\n", i, frame->nativesavflt[j++]);
+ }
+
+ printf("\n");
+ return;
+ }
+
+ printf("\t");
+ method_println(frame->method);
+ printf("\tid: %d\n", frame->id);
+ printf("\ttype: %s\n", replace_type_str[frame->type]);
+ printf("\n");
+
+ if (frame->instance.a) {
+ printf("\tinstance: ");
+ java_value_print(TYPE_ADR, frame->instance);
+ printf("\n");
+ }
+
+ if (frame->javalocalcount) {
+ printf("\tlocals (%d):\n",frame->javalocalcount);
+ for (i=0; i<frame->javalocalcount; ++i) {
+ t = frame->javalocaltype[i];
+ if (t == TYPE_VOID) {
+ printf("\tlocal[ %2d] = void\n",i);
+ }
+ else {
+ printf("\tlocal[%c%2d] = ",TYPECHAR(t),i);
+ java_value_print(t, frame->javalocals[i]);
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+
+ if (frame->javastackdepth) {
+ printf("\tstack (depth %d):\n",frame->javastackdepth);
+ for (i=0; i<frame->javastackdepth; ++i) {
+ t = frame->javastacktype[i];
+ if (t == TYPE_VOID) {
+ printf("\tstack[%2d] = void", i);
+ }
+ else {
+ printf("\tstack[%2d] = ",i);
+ java_value_print(frame->javastacktype[i], frame->javastack[i]);
+ printf("\n");
+ }
+ }
+ printf("\n");
+ }
+
+ if (frame->syncslotcount) {
+ printf("\tsynchronization slots (%d):\n",frame->syncslotcount);
+ for (i=0; i<frame->syncslotcount; ++i) {
+ printf("\tslot[%2d] = %016llx\n",i,(unsigned long long) frame->syncslots[i].p);
+ }
+ printf("\n");
+ }
+
+ if (frame->fromcode) {
+ printf("\tfrom %p ", (void*)frame->fromcode);
+ method_println(frame->fromcode->m);
+ }
+ if (frame->tocode) {
+ printf("\tto %p ", (void*)frame->tocode);
+ method_println(frame->tocode->m);
+ }
+
+ if (frame->fromrp) {
+ printf("\tfrom replacement point:\n");
+ replace_replacement_point_println(frame->fromrp, 2);
+ }
+ if (frame->torp) {
+ printf("\tto replacement point:\n");
+ replace_replacement_point_println(frame->torp, 2);
+ }
+
+ printf("\n");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* replace_sourcestate_println *************************************************
+
+ Print source state
+
+ IN:
+ ss...............the source state to print
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void replace_sourcestate_println(sourcestate_t *ss)
+{
+ int i;
+ sourceframe_t *frame;
+
+ if (!ss) {
+ printf("(sourcestate_t *)NULL\n");
+ return;
+ }
+
+ printf("sourcestate_t:\n");
+
+ for (i=0, frame = ss->frames; frame != NULL; frame = frame->down, ++i) {
+ printf(" frame %d:\n", i);
+ replace_source_frame_println(frame);
+ }
+}
+#endif
+
+
+/* replace_sourcestate_println_short *******************************************
+
+ Print a compact representation of the given source state.
+
+ IN:
+ ss...............the source state to print
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void replace_sourcestate_println_short(sourcestate_t *ss)
+{
+ sourceframe_t *frame;
+
+ for (frame = ss->frames; frame != NULL; frame = frame->down) {
+ printf("\t");
+
+ if (REPLACE_IS_NATIVE_FRAME(frame)) {
+ printf("NATIVE (pc %p size %d) ",
+ (void*)frame->nativepc, frame->nativeframesize);
+ replace_stackframeinfo_println(frame->sfi);
+ continue;
+ }
+
+ if (frame->torp) {
+ printf("%c", (frame->torp == frame->fromrp) ? '=' : '+');
+ }
+
+ printf("%s", replace_type_str[frame->fromrp->type]);
+
+ if (frame->torp && frame->torp->type != frame->fromrp->type)
+ printf("->%s", replace_type_str[frame->torp->type]);
+
+ if (frame->tocode != frame->fromcode)
+ printf(" (%p->%p/%d) ",
+ (void*) frame->fromcode, (void*) frame->tocode,
+ frame->fromrp->id);
+ else
+ printf(" (%p/%d) ", (void*) frame->fromcode, frame->fromrp->id);
+
+ method_println(frame->method);
+ }
+}
+#endif
+
+#if !defined(NDEBUG)
+static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
+{
+ printf("prev=%p pv=%p sp=%p ra=%p xpc=%p method=",
+ (void*)sfi->prev, (void*)sfi->pv, (void*)sfi->sp,
+ (void*)sfi->ra, (void*)sfi->xpc);
+
+ if (sfi->code)
+ method_println(sfi->code->m);
+ else
+ printf("(nil)\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/jit/replace.h - on-stack replacement of 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 _REPLACE_H
-#define _REPLACE_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#if !defined(ENABLE_REPLACEMENT)
-
-/*** macros for the codegens (disabled version) ************************/
-
-#define REPLACEMENT_POINTS_INIT(cd, jd)
-#define REPLACEMENT_POINTS_RESET(cd, jd)
-#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)
-#define REPLACEMENT_POINT_INLINE_START(cd, iptr)
-#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)
-#define REPLACEMENT_POINT_RETURN(cd, iptr)
-#define REPLACEMENT_POINT_INVOKE(cd, iptr)
-#define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr)
-#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
-#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
-
-#else /* defined(ENABLE_REPLACEMENT) */
-
-/* forward typedefs ***********************************************************/
-
-typedef struct rplalloc rplalloc;
-typedef struct rplpoint rplpoint;
-typedef struct sourcestate_t sourcestate_t;
-typedef struct sourceframe_t sourceframe_t;
-typedef union replace_val_t replace_val_t;
-
-#include "arch.h"
-#include "md-abi.h"
-
-#include "vm/method.h"
-
-#include "vm/jit/reg.h"
-#include "vm/jit/stacktrace.hpp"
-
-
-/*** structs *********************************************************/
-
-#define RPLALLOC_STACK -1
-#define RPLALLOC_PARAM -2
-#define RPLALLOC_SYNC -3
-
-/* `rplalloc` is a compact struct for register allocation info */
-
-/* XXX optimize this for space efficiency */
-struct rplalloc {
- s4 index; /* local index, -1 for stack slot */
- s4 regoff; /* register index / stack slot offset */
- unsigned int flags:4; /* OR of (INMEMORY,...) */
- unsigned int type:4; /* TYPE_... constant */
-};
-
-#if INMEMORY > 0x08
-#error value of INMEMORY is too big to fit in rplalloc.flags
-#endif
-
-
-/* XXX what to do about overlapping rplpoints? */
-/* CAUTION: Do not change the numerical values. These are used as */
-/* indices into replace_normalize_type_map. */
-#define RPLPOINT_TYPE_STD BBTYPE_STD
-#define RPLPOINT_TYPE_EXH BBTYPE_EXH
-#define RPLPOINT_TYPE_SBR BBTYPE_SBR
-#define RPLPOINT_TYPE_CALL 3
-#define RPLPOINT_TYPE_INLINE 4
-#define RPLPOINT_TYPE_RETURN 5
-#define RPLPOINT_TYPE_BODY 6
-
-#define RPLPOINT_FLAG_NOTRAP 0x01 /* rplpoint cannot be trapped */
-#define RPLPOINT_FLAG_COUNTDOWN 0x02 /* count down hits */
-#define RPLPOINT_FLAG_ACTIVE 0x08 /* trap is active */
-
-
-#if !defined(NDEBUG)
-#define RPLPOINT_CHECK(type) , RPLPOINT_TYPE_##type
-#define RPLPOINT_CHECK_BB(bptr) , (bptr)->type
-#else
-#define RPLPOINT_CHECK(type)
-#define RPLPOINT_CHECK_BB(bptr)
-#endif
-
-
-/* An `rplpoint` represents a replacement point in a compiled method */
-
-struct rplpoint {
- u1 *pc; /* machine code PC of this point */
- methodinfo *method; /* source method this point is in */
- rplpoint *parent; /* rplpoint of the inlined body */ /* XXX unify with code */
- rplalloc *regalloc; /* pointer to register index table */
- s4 id; /* id of the rplpoint within method */
- s4 callsize; /* size of call code in bytes */
- unsigned int regalloccount:20; /* number of local allocations */
- unsigned int type:4; /* RPLPOINT_TYPE_... constant */
- unsigned int flags:8; /* OR of RPLPOINT_... constants */
-};
-
-
-union replace_val_t {
- s4 i;
- s8 l;
- ptrint p;
- struct {
- u4 lo;
- u4 hi;
- } words;
- float f;
- double d;
- java_object_t *a;
-};
-
-
-struct sourceframe_t {
- sourceframe_t *down; /* source frame down the call chain */
-
- methodinfo *method; /* method this frame is in */
- s4 id;
- s4 type;
-
- /* values */
- replace_val_t instance;
-
- replace_val_t *javastack; /* values of stack vars */
- u1 *javastacktype; /* types of stack vars */
- s4 javastackdepth; /* number of stack vars */
-
- replace_val_t *javalocals; /* values of javalocals */
- u1 *javalocaltype; /* types of javalocals */
- s4 javalocalcount; /* number of javalocals */
-
- replace_val_t *syncslots;
- s4 syncslotcount; /* XXX do we need more than one? */
-
- /* mapping info */
- rplpoint *fromrp; /* rplpoint used to read this frame */
- codeinfo *fromcode; /* code this frame was using */
- rplpoint *torp; /* rplpoint this frame was mapped to */
- codeinfo *tocode; /* code this frame was mapped to */
-
- /* info for native frames */
- stackframeinfo_t *sfi; /* sfi for native frames, otherwise NULL */
- s4 nativeframesize; /* size (bytes) of native frame */
- u1 *nativepc;
- ptrint nativesavint[INT_SAV_CNT]; /* XXX temporary */
- double nativesavflt[FLT_REG_CNT]; /* XXX temporary */
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- ptrint nativesavadr[ADR_SAV_CNT]; /* XXX temporary */
-#endif
-};
-
-#define REPLACE_IS_NATIVE_FRAME(frame) ((frame)->sfi != NULL)
-#define REPLACE_IS_JAVA_FRAME(frame) ((frame)->sfi == NULL)
-
-
-struct sourcestate_t {
- sourceframe_t *frames; /* list of source frames, from bottom up */
-};
-
-
-/*** macros for the codegens *******************************************/
-
-#define REPLACEMENT_POINTS_INIT(cd, jd) \
- if (!replace_create_replacement_points(jd)) \
- return false; \
- (cd)->replacementpoint = (jd)->code->rplpoints;
-
-#define REPLACEMENT_POINTS_RESET(cd, jd) \
- (cd)->replacementpoint = (jd)->code->rplpoints;
-
-#define REPLACEMENT_POINT_BLOCK_START(cd, bptr) \
- if ((bptr)->bitflags & BBFLAG_REPLACEMENT) \
- codegen_set_replacement_point((cd) RPLPOINT_CHECK_BB(bptr));
-
-#define REPLACEMENT_POINT_INLINE_START(cd, iptr) \
- codegen_set_replacement_point(cd RPLPOINT_CHECK(INLINE));
-
-#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr) \
- codegen_set_replacement_point_notrap(cd RPLPOINT_CHECK(BODY));
-
-#define REPLACEMENT_POINT_RETURN(cd, iptr) \
- codegen_set_replacement_point(cd RPLPOINT_CHECK(RETURN));
-
-#define REPLACEMENT_POINT_INVOKE(cd, iptr) \
- codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
-
-#define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr) \
- if (iptr->opc != ICMD_BUILTIN) \
- cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
- - (ptrint) cd->replacementpoint[-1].pc;
-
-
-/*** macros for the codegens (for GC) **********************************/
-
-#if defined(ENABLE_GC_CACAO)
-
-#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr) \
- codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
-
-#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr) \
- if (iptr->opc == ICMD_BUILTIN) \
- cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
- - (ptrint) cd->replacementpoint[-1].pc;
-
-#else /* defined(ENABLE_GC_CACAO) */
-
-#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
-#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
-
-#endif /* defined(ENABLE_GC_CACAO) */
-
-
-/*** prototypes ********************************************************/
-
-bool replace_create_replacement_points(jitdata *jd);
-void replace_free_replacement_points(codeinfo *code);
-
-void replace_activate_replacement_points(codeinfo *code, bool mappable);
-void replace_deactivate_replacement_points(codeinfo *code);
-
-bool replace_me_wrapper(u1 *pc, void *context);
-
-#if !defined(NDEBUG)
-void replace_show_replacement_points(codeinfo *code);
-void replace_replacement_point_println(rplpoint *rp, int depth);
-void replace_sourcestate_println(sourcestate_t *ss);
-void replace_sourcestate_println_short(sourcestate_t *ss);
-void replace_source_frame_println(sourceframe_t *frame);
-#endif
-
-/* machine dependent functions (code in ARCH_DIR/md.c) */
-
-#if defined(ENABLE_JIT)
-void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert);
-#endif
-
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-#endif /* _REPLACE_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/replace.hpp - on-stack replacement of 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 _REPLACE_HPP
+#define _REPLACE_HPP
+
+#include "config.h"
+#include "vm/types.h"
+
+#if !defined(ENABLE_REPLACEMENT)
+
+/*** macros for the codegens (disabled version) ************************/
+
+#define REPLACEMENT_POINTS_INIT(cd, jd)
+#define REPLACEMENT_POINTS_RESET(cd, jd)
+#define REPLACEMENT_POINT_BLOCK_START(cd, bptr)
+#define REPLACEMENT_POINT_INLINE_START(cd, iptr)
+#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr)
+#define REPLACEMENT_POINT_RETURN(cd, iptr)
+#define REPLACEMENT_POINT_INVOKE(cd, iptr)
+#define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
+
+#else /* defined(ENABLE_REPLACEMENT) */
+
+/* forward typedefs ***********************************************************/
+
+typedef struct rplalloc rplalloc;
+typedef struct rplpoint rplpoint;
+typedef struct sourcestate_t sourcestate_t;
+typedef struct sourceframe_t sourceframe_t;
+typedef union replace_val_t replace_val_t;
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "vm/method.h"
+
+#include "vm/jit/reg.h"
+#include "vm/jit/stacktrace.hpp"
+
+
+/*** structs *********************************************************/
+
+#define RPLALLOC_STACK -1
+#define RPLALLOC_PARAM -2
+#define RPLALLOC_SYNC -3
+
+/* `rplalloc` is a compact struct for register allocation info */
+
+/* XXX optimize this for space efficiency */
+struct rplalloc {
+ s4 index; /* local index, -1 for stack slot */
+ s4 regoff; /* register index / stack slot offset */
+ unsigned int flags:4; /* OR of (INMEMORY,...) */
+ unsigned int type:4; /* TYPE_... constant */
+};
+
+#if INMEMORY > 0x08
+#error value of INMEMORY is too big to fit in rplalloc.flags
+#endif
+
+
+/* XXX what to do about overlapping rplpoints? */
+/* CAUTION: Do not change the numerical values. These are used as */
+/* indices into replace_normalize_type_map. */
+#define RPLPOINT_TYPE_STD BBTYPE_STD
+#define RPLPOINT_TYPE_EXH BBTYPE_EXH
+#define RPLPOINT_TYPE_SBR BBTYPE_SBR
+#define RPLPOINT_TYPE_CALL 3
+#define RPLPOINT_TYPE_INLINE 4
+#define RPLPOINT_TYPE_RETURN 5
+#define RPLPOINT_TYPE_BODY 6
+
+#define RPLPOINT_FLAG_NOTRAP 0x01 /* rplpoint cannot be trapped */
+#define RPLPOINT_FLAG_COUNTDOWN 0x02 /* count down hits */
+#define RPLPOINT_FLAG_ACTIVE 0x08 /* trap is active */
+
+
+#if !defined(NDEBUG)
+#define RPLPOINT_CHECK(type) , RPLPOINT_TYPE_##type
+#define RPLPOINT_CHECK_BB(bptr) , (bptr)->type
+#else
+#define RPLPOINT_CHECK(type)
+#define RPLPOINT_CHECK_BB(bptr)
+#endif
+
+
+/* An `rplpoint` represents a replacement point in a compiled method */
+
+struct rplpoint {
+ u1 *pc; /* machine code PC of this point */
+ methodinfo *method; /* source method this point is in */
+ rplpoint *parent; /* rplpoint of the inlined body */ /* XXX unify with code */
+ rplalloc *regalloc; /* pointer to register index table */
+ s4 id; /* id of the rplpoint within method */
+ s4 callsize; /* size of call code in bytes */
+ unsigned int regalloccount:20; /* number of local allocations */
+ unsigned int type:4; /* RPLPOINT_TYPE_... constant */
+ unsigned int flags:8; /* OR of RPLPOINT_... constants */
+};
+
+
+union replace_val_t {
+ s4 i;
+ s8 l;
+ ptrint p;
+ struct {
+ u4 lo;
+ u4 hi;
+ } words;
+ float f;
+ double d;
+ java_object_t *a;
+};
+
+
+struct sourceframe_t {
+ sourceframe_t *down; /* source frame down the call chain */
+
+ methodinfo *method; /* method this frame is in */
+ s4 id;
+ s4 type;
+
+ /* values */
+ replace_val_t instance;
+
+ replace_val_t *javastack; /* values of stack vars */
+ u1 *javastacktype; /* types of stack vars */
+ s4 javastackdepth; /* number of stack vars */
+
+ replace_val_t *javalocals; /* values of javalocals */
+ u1 *javalocaltype; /* types of javalocals */
+ s4 javalocalcount; /* number of javalocals */
+
+ replace_val_t *syncslots;
+ s4 syncslotcount; /* XXX do we need more than one? */
+
+ /* mapping info */
+ rplpoint *fromrp; /* rplpoint used to read this frame */
+ codeinfo *fromcode; /* code this frame was using */
+ rplpoint *torp; /* rplpoint this frame was mapped to */
+ codeinfo *tocode; /* code this frame was mapped to */
+
+ /* info for native frames */
+ stackframeinfo_t *sfi; /* sfi for native frames, otherwise NULL */
+ s4 nativeframesize; /* size (bytes) of native frame */
+ u1 *nativepc;
+ ptrint nativesavint[INT_SAV_CNT]; /* XXX temporary */
+ double nativesavflt[FLT_REG_CNT]; /* XXX temporary */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ ptrint nativesavadr[ADR_SAV_CNT]; /* XXX temporary */
+#endif
+};
+
+#define REPLACE_IS_NATIVE_FRAME(frame) ((frame)->sfi != NULL)
+#define REPLACE_IS_JAVA_FRAME(frame) ((frame)->sfi == NULL)
+
+
+struct sourcestate_t {
+ sourceframe_t *frames; /* list of source frames, from bottom up */
+};
+
+
+/*** macros for the codegens *******************************************/
+
+#define REPLACEMENT_POINTS_INIT(cd, jd) \
+ if (!replace_create_replacement_points(jd)) \
+ return false; \
+ (cd)->replacementpoint = (jd)->code->rplpoints;
+
+#define REPLACEMENT_POINTS_RESET(cd, jd) \
+ (cd)->replacementpoint = (jd)->code->rplpoints;
+
+#define REPLACEMENT_POINT_BLOCK_START(cd, bptr) \
+ if ((bptr)->bitflags & BBFLAG_REPLACEMENT) \
+ codegen_set_replacement_point((cd) RPLPOINT_CHECK_BB(bptr));
+
+#define REPLACEMENT_POINT_INLINE_START(cd, iptr) \
+ codegen_set_replacement_point(cd RPLPOINT_CHECK(INLINE));
+
+#define REPLACEMENT_POINT_INLINE_BODY(cd, iptr) \
+ codegen_set_replacement_point_notrap(cd RPLPOINT_CHECK(BODY));
+
+#define REPLACEMENT_POINT_RETURN(cd, iptr) \
+ codegen_set_replacement_point(cd RPLPOINT_CHECK(RETURN));
+
+#define REPLACEMENT_POINT_INVOKE(cd, iptr) \
+ codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
+
+#define REPLACEMENT_POINT_INVOKE_RETURN(cd, iptr) \
+ if (iptr->opc != ICMD_BUILTIN) \
+ cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
+ - (ptrint) cd->replacementpoint[-1].pc;
+
+
+/*** macros for the codegens (for GC) **********************************/
+
+#if defined(ENABLE_GC_CACAO)
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr) \
+ codegen_set_replacement_point(cd RPLPOINT_CHECK(CALL));
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr) \
+ if (iptr->opc == ICMD_BUILTIN) \
+ cd->replacementpoint[-1].callsize = (cd->mcodeptr - cd->mcodebase)\
+ - (ptrint) cd->replacementpoint[-1].pc;
+
+#else // ENABLE_GC_CACAO
+
+#define REPLACEMENT_POINT_FORGC_BUILTIN(cd, iptr)
+#define REPLACEMENT_POINT_FORGC_BUILTIN_RETURN(cd, iptr)
+
+#endif // ENABLE_GC_CACAO
+
+
+/*** prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool replace_create_replacement_points(jitdata *jd);
+void replace_free_replacement_points(codeinfo *code);
+
+void replace_activate_replacement_points(codeinfo *code, bool mappable);
+void replace_deactivate_replacement_points(codeinfo *code);
+
+bool replace_me_wrapper(u1 *pc, void *context);
+
+#if !defined(NDEBUG)
+void replace_show_replacement_points(codeinfo *code);
+void replace_replacement_point_println(rplpoint *rp, int depth);
+void replace_sourcestate_println(sourcestate_t *ss);
+void replace_sourcestate_println_short(sourcestate_t *ss);
+void replace_source_frame_println(sourceframe_t *frame);
+#endif
+
+/* machine dependent functions (code in ARCH_DIR/md.c) */
+
+#if defined(ENABLE_JIT)
+void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // ENABLE_REPLACEMENT
+
+#endif // _REPLACE_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:
+ */
\
md-abi.c \
md-abi.h \
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 1
#define SUPPORT_LONG 1
#include "vm/jit/s390/emit.h"
#include "vm/jit/s390/md-abi.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/statistics.h"
#include "vm/types.h"
# include "vm/jit/allocator/lsra.h"
#endif
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/methodheader.h"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
/* src/vm/jit/s390/codegen.h - code generation macros for s390
- 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/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* MCODECHECK(icnt) */
#define PATCHER_CALL_SIZE 2 /* size in bytes of a patcher call */
#define PATCHER_NOPS M_NOP3
-#define PATCHER_NOPS_SKIP 2
/* branch defines ************************************************************/
} \
} while (0)
-/* stub defines **************************************************************/
-
-#define COMPILERSTUB_CODESIZE (SZ_AHI + SZ_L + SZ_L + SZ_BCR)
/* *** BIG TODO ***
* Make all this inline functions !!!!!!!!!!
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#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/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
#include "vm/global.h"
#include "vm/types.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/stack.h"
#include "vm/jit/s390/md-abi.h"
--- /dev/null
+/* src/vm/jit/s390/md-stubs.hpp - s390 JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+#include "vm/jit/s390/codegen.h"
+
+
+/**
+ * Return the code size of a compiler on a s390 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return (SZ_AHI + SZ_L + SZ_L + SZ_BCR);
+}
+
+#endif // _MD_STUBS_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 "vm/jit/disass.h" /* XXX debug */
#endif
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/s390/codegen.h"
#include "vm/jit/s390/md.h"
#include <assert.h>
#include <stdint.h>
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/methodtree.h"
#include <stdint.h>
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#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/patcher-common.hpp"
#include "vm/jit/s390/codegen.h"
#include "vm/jit/s390/md-abi.h"
PATCH_BACK_ORIGINAL_MCODE;
- /* If NOPs are generated, skip them */
-
- if (opt_shownops)
- ra += PATCHER_NOPS_SKIP;
-
/* If there is an operand load before, skip the load size passed in disp (see ICMD_PUTFIELD) */
ra += disp;
PATCH_BACK_ORIGINAL_MCODE;
- /* If NOPs are generated, skip them */
-
- if (opt_shownops)
- ra += PATCHER_NOPS_SKIP;
-
/* patch vftbl index */
PATCH_BACK_ORIGINAL_MCODE;
- /* If NOPs are generated, skip them */
-
- if (opt_shownops)
- ra += PATCHER_NOPS_SKIP;
-
/* get interfacetable index */
idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
PATCH_BACK_ORIGINAL_MCODE;
- /* If NOPs are generated, skip them */
-
- if (opt_shownops)
- ra += PATCHER_NOPS_SKIP;
-
/* patch super class index */
/* From here, split your editor and open codegen.c */
+++ /dev/null
-/* src/vm/jit/show.c - showing the intermediate representation
-
- 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 "threads/lock-common.h"
-
-#include "vm/global.h"
-#include "vm/builtin.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/show.h"
-#include "vm/jit/disass.h"
-#include "vm/jit/stack.h"
-#include "vm/jit/parse.h"
-
-#if defined(ENABLE_DEBUG_FILTER)
-# include <sys/types.h>
-# include <regex.h>
-# include "threads/thread.hpp"
-#endif
-
-
-/* global variables ***********************************************************/
-
-#if !defined(NDEBUG)
-static Mutex* mutex;
-#endif
-
-
-/* prototypes *****************************************************************/
-
-#if !defined(NDEBUG)
-static void show_variable_intern(jitdata *jd, s4 index, int stage);
-#endif
-
-
-/* show_init *******************************************************************
-
- Initialized the show subsystem (called by jit_init).
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-bool show_init(void)
-{
-#if defined(ENABLE_THREADS)
- /* initialize the show lock */
-
- mutex = Mutex_new();
-#endif
-
-#if defined(ENABLE_DEBUG_FILTER)
- show_filters_init();
-#endif
-
- /* everything's ok */
-
- return true;
-}
-#endif
-
-
-#if !defined(NDEBUG)
-char *show_jit_type_names[] = {
- "INT",
- "LNG",
- "FLT",
- "DBL",
- "ADR",
- "??5",
- "??6",
- "??7",
- "RET"
-};
-char show_jit_type_letters[] = {
- 'I',
- 'L',
- 'F',
- 'D',
- 'A',
- '5',
- '6',
- '7',
- 'R'
-};
-#endif
-
-
-/* show_method *****************************************************************
-
- Print the intermediate representation of a method.
-
- NOTE: Currently this function may only be called after register allocation!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void show_method(jitdata *jd, int stage)
-{
- methodinfo *m;
- codeinfo *code;
- codegendata *cd;
- registerdata *rd;
- basicblock *bptr;
- basicblock *lastbptr;
- exception_entry *ex;
- s4 i, j;
- int irstage;
-#if defined(ENABLE_DISASSEMBLER)
- u1 *pc;
-#endif
-
- /* get required compiler data */
-
- m = jd->m;
- code = jd->code;
- cd = jd->cd;
- rd = jd->rd;
-
- /* We need to enter a lock here, since the binutils disassembler
- is not reentrant-able and we could not read functions printed
- at the same time. */
-
- Mutex_lock(mutex);
-
-#if defined(ENABLE_INTRP)
- if (opt_intrp)
- irstage = SHOW_PARSE;
- else
-#endif
- irstage = stage;
-
- /* get the last basic block */
-
- for (lastbptr = jd->basicblocks; lastbptr->next != NULL; lastbptr = lastbptr->next);
-
- printf("\n");
-
- method_println(m);
-
- if (code_is_leafmethod(code))
- printf("LEAFMETHOD\n");
-
- printf("\nBasic blocks: %d\n", jd->basicblockcount);
- if (stage >= SHOW_CODE) {
- printf("Code length: %d\n", (lastbptr->mpc - jd->basicblocks[0].mpc));
- printf("Data length: %d\n", cd->dseglen);
- printf("Stub length: %d\n", (s4) (code->mcodelength -
- ((ptrint) cd->dseglen + lastbptr->mpc)));
- }
- printf("Variables: %d (%d used)\n", jd->varcount, jd->vartop);
- if (stage >= SHOW_STACK)
- printf("Max interfaces: %d\n", jd->maxinterfaces);
- printf("Max locals: %d\n", jd->maxlocals);
- printf("Max stack: %d\n", m->maxstack);
- printf("Linenumbers: %d\n", m->linenumbercount);
- printf("Branch to entry: %s\n", (jd->branchtoentry) ? "yes" : "no");
- printf("Branch to end: %s\n", (jd->branchtoend) ? "yes" : "no");
- if (stage >= SHOW_STACK) {
- printf("Number of RETURNs: %d", jd->returncount);
- if (jd->returncount == 1)
- printf(" (block L%03d)", jd->returnblock->nr);
- printf("\n");
- }
-
- if (stage >= SHOW_PARSE) {
- printf("Exceptions (Number: %d):\n", jd->exceptiontablelength);
- for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
- printf(" L%03d ... ", ex->start->nr );
- printf("L%03d = ", ex->end->nr);
- printf("L%03d", ex->handler->nr);
- printf(" (catchtype: ");
- if (ex->catchtype.any)
- if (IS_CLASSREF(ex->catchtype))
- class_classref_print(ex->catchtype.ref);
- else
- class_print(ex->catchtype.cls);
- else
- printf("ANY");
- printf(")\n");
- }
- }
-
- if (irstage >= SHOW_PARSE && rd && jd->localcount > 0) {
- printf("Local Table:\n");
- for (i = 0; i < jd->localcount; i++) {
- printf(" %3d: ", i);
-
-#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp) {
-# endif
- printf(" (%s) ", show_jit_type_names[VAR(i)->type]);
- if (irstage >= SHOW_REGS)
- show_allocation(VAR(i)->type, VAR(i)->flags, VAR(i)->vv.regoff);
- printf("\n");
-# if defined(ENABLE_INTRP)
- }
-# endif
-#endif /* defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) */
- }
- printf("\n");
- }
-
- if (jd->maxlocals > 0 && jd->local_map != NULL) {
- printf("Local Map:\n");
- printf(" index ");
- for (j = 0; j < jd->maxlocals; j++) {
- printf(" [%2d]", j);
- }
- printf("\n");
- for (i = 0; i < 5; i++) {
- printf(" %5s ",show_jit_type_names[i]);
- for (j = 0; j < jd->maxlocals; j++) {
- if (jd->local_map[j*5+i] == UNUSED)
- printf(" -- ");
- else
- printf("%4i ",jd->local_map[j*5+i]);
- }
- printf("\n");
- }
- printf("\n");
- }
-
- if (jd->maxinterfaces > 0 && jd->interface_map && irstage >= SHOW_STACK) {
- bool exist = false;
- interface_info *mapptr = jd->interface_map;
-
- /* look if there exist any INOUTS */
- for (i = 0; (i < (5 * jd->maxinterfaces)) && !exist; i++, mapptr++)
- exist = (mapptr->flags != UNUSED);
-
- if (exist) {
- printf("Interface Table: (In/Outvars)\n");
- printf(" depth ");
- for (j = 0; j < jd->maxinterfaces; j++) {
- printf(" [%2d]", j);
- }
- printf("\n");
-
- for (i = 0; i < 5; i++) {
- printf(" %5s ",show_jit_type_names[i]);
- for (j = 0; j < jd->maxinterfaces; j++) {
- s4 flags = jd->interface_map[j*5+i].flags;
- s4 regoff = jd->interface_map[j*5+i].regoff;
- if (flags == UNUSED)
- printf(" -- ");
- else {
- int ch;
-
- if (irstage >= SHOW_REGS) {
- if (flags & SAVEDVAR) {
- if (flags & INMEMORY)
- ch = 'M';
- else
- ch = 'R';
- }
- else {
- if (flags & INMEMORY)
- ch = 'm';
- else
- ch = 'r';
- }
- printf("%c%03d(", ch, regoff);
- show_allocation(i, flags, regoff);
- printf(") ");
- }
- else {
- if (flags & SAVEDVAR)
- printf(" I ");
- else
- printf(" i ");
- }
- }
- }
- printf("\n");
- }
- printf("\n");
- }
- }
-
- if (rd->memuse && irstage >= SHOW_REGS) {
- int max;
-
- max = rd->memuse;
- printf("Stack slots: (memuse=%d", rd->memuse);
- if (irstage >= SHOW_CODE) {
- printf(", stackframesize=%d", cd->stackframesize);
- max = cd->stackframesize;
- }
- printf(")\n");
- for (i = 0; i < max; ++i) {
-#if defined(HAS_4BYTE_STACKSLOT)
- printf(" M%02d = 0x%02x(sp): ", i, i * 4);
-#else
- printf(" M%02d = 0x%02x(sp): ", i, i * 8);
-#endif
- for (j = 0; j < jd->vartop; ++j) {
- varinfo *v = VAR(j);
- if ((v->flags & INMEMORY) && (v->vv.regoff == i)) {
- show_variable(jd, j, irstage);
- putchar(' ');
- }
- }
-
- printf("\n");
-
- }
- printf("\n");
- }
-
-#if defined(ENABLE_REPLACEMENT)
- if (code->rplpoints) {
- printf("Replacement Points:\n");
- replace_show_replacement_points(code);
- printf("\n");
- }
-#endif /* defined(ENABLE_REPLACEMENT) */
-
-#if defined(ENABLE_DISASSEMBLER)
- /* show code before first basic block */
-
- if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
- pc = (u1 *) ((ptrint) code->mcode + cd->dseglen);
-
- for (; pc < (u1 *) ((ptrint) code->mcode + cd->dseglen + jd->basicblocks[0].mpc);)
- DISASSINSTR(pc);
-
- printf("\n");
- }
-#endif
-
- /* show code of all basic blocks */
-
- for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next)
- show_basicblock(jd, bptr, stage);
-
-#if 0 && defined(ENABLE_DISASSEMBLER)
- /* show code after last basic block */
-
- if (stage >= SHOW_CODE && opt_showdisassemble) {
- printf("\nStubs code:\n");
- printf("Length: %d\n\n", (s4) (code->mcodelength -
- ((ptrint) cd->dseglen + lastbptr->mpc)));
-
- pc = (u1 *) ((ptrint) code->mcode + cd->dseglen + lastbptr->mpc);
-
- for (; (ptrint) pc < ((ptrint) code->mcode + code->mcodelength);)
- DISASSINSTR(pc);
-
- printf("\n");
- }
-#endif
-
- Mutex_unlock(mutex);
-
- /* finally flush the output */
-
- fflush(stdout);
-}
-#endif /* !defined(NDEBUG) */
-
-
-#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-static void show_inline_info(jitdata *jd, insinfo_inline *ii, s4 opcode, s4 stage)
-{
- s4 *jl;
- s4 n;
-
- printf("(pt %d+%d+%d st ",
- ii->throughcount - (ii->stackvarscount - ii->paramcount),
- ii->stackvarscount - ii->paramcount,
- ii->paramcount);
- show_variable_array(jd, ii->stackvars, ii->stackvarscount, stage);
-
- if (opcode == ICMD_INLINE_START || opcode == ICMD_INLINE_END) {
- printf(" jl ");
- jl = (opcode == ICMD_INLINE_START) ? ii->javalocals_start : ii->javalocals_end;
- n = (opcode == ICMD_INLINE_START) ? ii->method->maxlocals : ii->outer->maxlocals;
- show_javalocals_array(jd, jl, n, stage);
- }
-
- printf(") ");
-
-#if 0
- printf("(");
- method_print(ii->outer);
- printf(" ==> ");
-#endif
-
- method_print(ii->method);
-}
-#endif /* !defined(NDEBUG) && defined(ENABLE_INLINING) */
-
-
-/* show_basicblock *************************************************************
-
- Print the intermediate representation of a basic block.
-
- NOTE: Currently this function may only be called after register allocation!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
-{
- codeinfo *code;
- codegendata *cd;
- s4 i;
- bool deadcode;
- instruction *iptr;
- int irstage;
-#if defined(ENABLE_DISASSEMBLER)
- methodinfo *m; /* this is only a dummy */
- void *pc;
- s4 linenumber;
- s4 currentlinenumber;
-#endif
-
- /* get required compiler data */
-
- code = jd->code;
- cd = jd->cd;
-
- if (bptr->flags != BBDELETED) {
-#if defined(ENABLE_INTRP)
- if (opt_intrp) {
- deadcode = false;
- irstage = SHOW_PARSE;
- }
- else
-#endif
- {
- deadcode = (bptr->flags < BBREACHED);
- irstage = stage;
- }
-
- printf("======== %sL%03d ======== %s(flags: %d, bitflags: %01x, next: %d, type: ",
-#if defined(ENABLE_REPLACEMENT)
- (bptr->bitflags & BBFLAG_REPLACEMENT) ? "<REPLACE> " :
-#endif
- "",
- bptr->nr,
- (deadcode && stage >= SHOW_STACK) ? "DEADCODE! " : "",
- bptr->flags, bptr->bitflags,
- (bptr->next) ? (bptr->next->nr) : -1);
-
- switch (bptr->type) {
- case BBTYPE_STD:
- printf("STD");
- break;
- case BBTYPE_EXH:
- printf("EXH");
- break;
- case BBTYPE_SBR:
- printf("SBR");
- break;
- }
-
- printf(", icount: %d", bptr->icount);
-
- if (irstage >= SHOW_CFG) {
- printf(", preds: %d [ ", bptr->predecessorcount);
-
- for (i = 0; i < bptr->predecessorcount; i++)
- printf("%d ", bptr->predecessors[i]->nr);
-
- printf("]");
- }
-
- printf("):");
-
- if (bptr->original)
- printf(" (clone of L%03d)", bptr->original->nr);
- else {
- basicblock *b = bptr->copied_to;
- if (b) {
- printf(" (copied to ");
- for (; b; b = b->copied_to)
- printf("L%03d ", b->nr);
- printf(")");
- }
- }
-
- printf("\n");
-
- if (irstage >= SHOW_CFG) {
- printf("succs: %d [ ", bptr->successorcount);
-
- for (i = 0; i < bptr->successorcount; i++)
- printf("%d ", bptr->successors[i]->nr);
-
- printf("]\n");
- }
-
- if (irstage >= SHOW_STACK) {
- printf("IN: ");
- show_variable_array(jd, bptr->invars, bptr->indepth, irstage);
- printf(" javalocals: ");
- if (bptr->javalocals)
- show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
- else
- printf("null");
- printf("\n");
- }
-
-#if defined(ENABLE_INLINING)
- if (bptr->inlineinfo) {
- printf("inlineinfo: ");
- show_inline_info(jd, bptr->inlineinfo, -1, irstage);
- printf("\n");
- }
-#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++) {
- printf("%4d:%4d: ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
-
- show_icmd(jd, iptr, deadcode, irstage);
- printf("\n");
- }
-
- if (irstage >= SHOW_STACK) {
- printf("OUT: ");
- show_variable_array(jd, bptr->outvars, bptr->outdepth, irstage);
- printf("\n");
- }
-
-#if defined(ENABLE_DISASSEMBLER)
- if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) &&
- (!deadcode))
- {
- printf("\n");
- pc = (void *) (code->mcode + cd->dseglen + bptr->mpc);
- linenumber = 0;
-
- if (bptr->next != NULL) {
- for (; pc < (void *) (code->mcode + cd->dseglen + bptr->next->mpc);) {
- currentlinenumber =
- linenumbertable_linenumber_for_pc(&m, code, pc);
-
- if (currentlinenumber != linenumber) {
- linenumber = currentlinenumber;
- printf("%4d:\n", linenumber);
- }
-
- DISASSINSTR(pc);
- }
- }
- else {
- for (; pc < (void *) (code->mcode + code->mcodelength);) {
- currentlinenumber =
- linenumbertable_linenumber_for_pc(&m, code, pc);
-
- if (currentlinenumber != linenumber) {
- linenumber = currentlinenumber;
- printf("%4d:\n", linenumber);
- }
-
- DISASSINSTR(pc);
- }
- }
- printf("\n");
- }
-#endif
- }
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* show_icmd *******************************************************************
-
- Print the intermediate representation of an instruction.
-
- NOTE: Currently this function may only be called after register allocation!
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-
-#define SHOW_TARGET(target) \
- if (stage >= SHOW_PARSE) { \
- printf("--> L%03d ", (target).block->nr); \
- } \
- else { \
- printf("--> insindex %d ", (target).insindex); \
- }
-
-#define SHOW_INT_CONST(val) \
- if (stage >= SHOW_PARSE) { \
- printf("%d (0x%08x) ", (int32_t) (val), (int32_t) (val)); \
- } \
- else { \
- printf("iconst "); \
- }
-
-#if SIZEOF_VOID_P == 4
-#define SHOW_LNG_CONST(val) \
- if (stage >= SHOW_PARSE) \
- printf("%lld (0x%016llx) ", (val), (val)); \
- else \
- printf("lconst ");
-#else
-#define SHOW_LNG_CONST(val) \
- if (stage >= SHOW_PARSE) \
- printf("%ld (0x%016lx) ", (val), (val)); \
- else \
- printf("lconst ");
-#endif
-
-#if SIZEOF_VOID_P == 4
-#define SHOW_ADR_CONST(val) \
- if (stage >= SHOW_PARSE) \
- printf("0x%08x ", (ptrint) (val)); \
- else \
- printf("aconst ");
-#else
-#define SHOW_ADR_CONST(val) \
- if (stage >= SHOW_PARSE) \
- printf("0x%016lx ", (ptrint) (val)); \
- else \
- printf("aconst ");
-#endif
-
-#define SHOW_FLT_CONST(val) \
- if (stage >= SHOW_PARSE) { \
- imm_union v; \
- v.f = (val); \
- printf("%g (0x%08x) ", (val), v.i); \
- } \
- else { \
- printf("fconst "); \
- }
-
-#if SIZEOF_VOID_P == 4
-#define SHOW_DBL_CONST(val) \
- if (stage >= SHOW_PARSE) { \
- imm_union v; \
- v.d = (val); \
- printf("%g (0x%016llx) ", (val), v.l); \
- } \
- else \
- printf("dconst ");
-#else
-#define SHOW_DBL_CONST(val) \
- if (stage >= SHOW_PARSE) { \
- imm_union v; \
- v.d = (val); \
- printf("%g (0x%016lx) ", (val), v.l); \
- } \
- else \
- printf("dconst ");
-#endif
-
-#define SHOW_INDEX(index) \
- if (stage >= SHOW_PARSE) { \
- printf("%d ", index); \
- } \
- else { \
- printf("index"); \
- }
-
-#define SHOW_STRING(val) \
- if (stage >= SHOW_PARSE) { \
- putchar('"'); \
- utf_display_printable_ascii( \
- javastring_toutf((java_handle_t *)(val), false)); \
- printf("\" "); \
- } \
- else { \
- printf("string "); \
- }
-
-#define SHOW_CLASSREF_OR_CLASSINFO(c) \
- if (stage >= SHOW_PARSE) { \
- if (IS_CLASSREF(c)) \
- class_classref_print(c.ref); \
- else \
- class_print(c.cls); \
- putchar(' '); \
- } \
- else { \
- printf("class "); \
- }
-
-#define SHOW_FIELD(fmiref) \
- if (stage >= SHOW_PARSE) { \
- field_fieldref_print(fmiref); \
- putchar(' '); \
- } \
- else { \
- printf("field "); \
- }
-
-#define SHOW_VARIABLE(v) \
- show_variable(jd, (v), stage)
-
-#define SHOW_S1(iptr) \
- if (stage >= SHOW_STACK) { \
- SHOW_VARIABLE(iptr->s1.varindex); \
- }
-
-#define SHOW_S2(iptr) \
- if (stage >= SHOW_STACK) { \
- SHOW_VARIABLE(iptr->sx.s23.s2.varindex); \
- }
-
-#define SHOW_S3(iptr) \
- if (stage >= SHOW_STACK) { \
- SHOW_VARIABLE(iptr->sx.s23.s3.varindex); \
- }
-
-#define SHOW_DST(iptr) \
- if (stage >= SHOW_STACK) { \
- printf("=> "); \
- SHOW_VARIABLE(iptr->dst.varindex); \
- }
-
-#define SHOW_S1_LOCAL(iptr) \
- if (stage >= SHOW_STACK) { \
- printf("L%d ", iptr->s1.varindex); \
- } \
- else { \
- printf("JavaL%d ", iptr->s1.varindex); \
- }
-
-#define SHOW_DST_LOCAL(iptr) \
- if (stage >= SHOW_STACK) { \
- printf("=> L%d ", iptr->dst.varindex); \
- } \
- else { \
- printf("=> JavaL%d ", iptr->dst.varindex); \
- }
-
-void show_allocation(s4 type, s4 flags, s4 regoff)
-{
- if (type == TYPE_RET) {
- printf("N/A");
- return;
- }
-
- if (flags & INMEMORY) {
- printf("M%02d", regoff);
- return;
- }
-
-#ifdef HAS_ADDRESS_REGISTER_FILE
- if (type == TYPE_ADR) {
- printf("R%02d", regoff);
- return;
- }
-#endif
-
- if (IS_FLT_DBL_TYPE(type)) {
- printf("F%02d", regoff);
- return;
- }
-
-#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
- if (IS_2_WORD_TYPE(type)) {
-# if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- printf("%3d/%3d", GET_LOW_REG(regoff),
- GET_HIGH_REG(regoff));
- else
-# endif
- printf("%3s/%3s", abi_registers_integer_name[GET_LOW_REG(regoff)],
- abi_registers_integer_name[GET_HIGH_REG(regoff)]);
-# else
- printf("%3d/%3d", GET_LOW_REG(regoff),
- GET_HIGH_REG(regoff));
-# endif
- return;
- }
-#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
-
-#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- printf("%3d", regoff);
- else
-# endif
- printf("%3s", abi_registers_integer_name[regoff]);
-#else
- printf("%3d", regoff);
-#endif
-}
-
-void show_variable(jitdata *jd, s4 index, int stage)
-{
- show_variable_intern(jd, index, stage);
- putchar(' ');
-}
-
-static void show_variable_intern(jitdata *jd, s4 index, int stage)
-{
- char type;
- char kind;
- varinfo *v;
-
- if (index < 0 || index >= jd->vartop) {
- printf("<INVALID INDEX:%d>", index);
- return;
- }
-
- v = VAR(index);
-
- switch (v->type) {
- case TYPE_INT: type = 'i'; break;
- case TYPE_LNG: type = 'l'; break;
- case TYPE_FLT: type = 'f'; break;
- case TYPE_DBL: type = 'd'; break;
- case TYPE_ADR: type = 'a'; break;
- case TYPE_RET: type = 'r'; break;
- default: type = '?';
- }
-
- if (index < jd->localcount) {
- kind = 'L';
- if (v->flags & (PREALLOC | INOUT))
- printf("<INVALID FLAGS!>");
- }
- else {
- if (v->flags & PREALLOC) {
- kind = 'A';
- if (v->flags & INOUT) {
- /* PREALLOC is used to avoid allocation of TYPE_RET */
- if (v->type == TYPE_RET)
- kind = 'i';
- else
- printf("<INVALID FLAGS!>");
- }
- }
- else if (v->flags & INOUT)
- kind = 'I';
- else
- kind = 'T';
- }
-
- printf("%c%c%d", kind, type, index);
-
- if (v->flags & SAVEDVAR)
- putchar('!');
-
- if (stage >= SHOW_REGS || (v->flags & PREALLOC)) {
- putchar('(');
- show_allocation(v->type, v->flags, v->vv.regoff);
- putchar(')');
- }
-
- if (v->type == TYPE_RET && (v->flags & PREALLOC)) {
- printf("(L%03d)", v->vv.retaddr->nr);
- }
-}
-
-static void show_variable_array_intern(jitdata *jd, s4 *vars, int n, int stage,
- bool javalocals)
-{
- int i;
- int nr;
-
- if (vars == NULL) {
- printf("<null>");
- return;
- }
-
- printf("[");
- for (i=0; i<n; ++i) {
- if (i)
- putchar(' ');
- if (vars[i] < 0) {
- if (vars[i] == UNUSED)
- putchar('-');
- else if (javalocals) {
- nr = RETADDR_FROM_JAVALOCAL(vars[i]);
- printf("ret(L%03d)", nr);
- }
- else {
- printf("<INVALID INDEX:%d>", vars[i]);
- }
- }
- else
- show_variable_intern(jd, vars[i], stage);
- }
- printf("]");
-}
-
-void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
-{
- show_variable_array_intern(jd, vars, n, stage, false);
-}
-
-void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage)
-{
- show_variable_array_intern(jd, vars, n, stage, true);
-}
-
-void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
-{
- u2 opcode;
- branch_target_t *table;
- lookup_target_t *lookup;
- constant_FMIref *fmiref;
- s4 *argp;
- s4 i;
-
- /* get the opcode and the condition */
-
- opcode = iptr->opc;
-
- printf("%s ", icmd_table[opcode].name);
-
- if (stage < SHOW_PARSE)
- return;
-
- if (deadcode)
- stage = SHOW_PARSE;
-
- /* Print the condition for conditional instructions. */
-
- /* XXX print condition from flags */
-
- if (iptr->flags.bits & INS_FLAG_UNRESOLVED)
- printf("(UNRESOLVED) ");
-
- switch (opcode) {
-
- case ICMD_POP:
- case ICMD_CHECKNULL:
- SHOW_S1(iptr);
- break;
-
- /* unary */
- case ICMD_ARRAYLENGTH:
- case ICMD_INEG:
- case ICMD_LNEG:
- case ICMD_FNEG:
- case ICMD_DNEG:
- case ICMD_I2L:
- case ICMD_I2F:
- case ICMD_I2D:
- case ICMD_L2I:
- case ICMD_L2F:
- case ICMD_L2D:
- case ICMD_F2I:
- case ICMD_F2L:
- case ICMD_F2D:
- case ICMD_D2I:
- case ICMD_D2L:
- case ICMD_D2F:
- case ICMD_INT2BYTE:
- case ICMD_INT2CHAR:
- case ICMD_INT2SHORT:
- SHOW_S1(iptr);
- SHOW_DST(iptr);
- break;
-
- /* binary */
- case ICMD_IADD:
- case ICMD_LADD:
- case ICMD_FADD:
- case ICMD_DADD:
- case ICMD_ISUB:
- case ICMD_LSUB:
- case ICMD_FSUB:
- case ICMD_DSUB:
- case ICMD_IMUL:
- case ICMD_LMUL:
- case ICMD_FMUL:
- case ICMD_DMUL:
- case ICMD_IDIV:
- case ICMD_LDIV:
- case ICMD_FDIV:
- case ICMD_DDIV:
- case ICMD_IREM:
- case ICMD_LREM:
- case ICMD_FREM:
- case ICMD_DREM:
- case ICMD_ISHL:
- case ICMD_LSHL:
- case ICMD_ISHR:
- case ICMD_LSHR:
- case ICMD_IUSHR:
- case ICMD_LUSHR:
- case ICMD_IAND:
- case ICMD_LAND:
- case ICMD_IOR:
- case ICMD_LOR:
- case ICMD_IXOR:
- case ICMD_LXOR:
- case ICMD_LCMP:
- case ICMD_FCMPL:
- case ICMD_FCMPG:
- case ICMD_DCMPL:
- case ICMD_DCMPG:
- SHOW_S1(iptr);
- SHOW_S2(iptr);
- SHOW_DST(iptr);
- break;
-
- /* binary/const INT */
- case ICMD_IADDCONST:
- case ICMD_ISUBCONST:
- case ICMD_IMULCONST:
- case ICMD_IMULPOW2:
- case ICMD_IDIVPOW2:
- case ICMD_IREMPOW2:
- case ICMD_IANDCONST:
- case ICMD_IORCONST:
- case ICMD_IXORCONST:
- case ICMD_ISHLCONST:
- case ICMD_ISHRCONST:
- case ICMD_IUSHRCONST:
- case ICMD_LSHLCONST:
- case ICMD_LSHRCONST:
- case ICMD_LUSHRCONST:
- SHOW_S1(iptr);
- SHOW_INT_CONST(iptr->sx.val.i);
- SHOW_DST(iptr);
- break;
-
- /* ?ASTORECONST (trinary/const INT) */
- case ICMD_IASTORECONST:
- case ICMD_BASTORECONST:
- case ICMD_CASTORECONST:
- case ICMD_SASTORECONST:
- SHOW_S1(iptr);
- SHOW_S2(iptr);
- SHOW_INT_CONST(iptr->sx.s23.s3.constval);
- break;
-
- /* const INT */
- case ICMD_ICONST:
- SHOW_INT_CONST(iptr->sx.val.i);
- SHOW_DST(iptr);
- break;
-
- /* binary/const LNG */
- case ICMD_LADDCONST:
- case ICMD_LSUBCONST:
- case ICMD_LMULCONST:
- case ICMD_LMULPOW2:
- case ICMD_LDIVPOW2:
- case ICMD_LREMPOW2:
- case ICMD_LANDCONST:
- case ICMD_LORCONST:
- case ICMD_LXORCONST:
- SHOW_S1(iptr);
- SHOW_LNG_CONST(iptr->sx.val.l);
- SHOW_DST(iptr);
- break;
-
- /* trinary/const LNG (<= pointer size) */
- case ICMD_LASTORECONST:
- SHOW_S1(iptr);
- SHOW_S2(iptr);
- SHOW_ADR_CONST(iptr->sx.s23.s3.constval);
- break;
-
- /* const LNG */
- case ICMD_LCONST:
- SHOW_LNG_CONST(iptr->sx.val.l);
- SHOW_DST(iptr);
- break;
-
- /* const FLT */
- case ICMD_FCONST:
- SHOW_FLT_CONST(iptr->sx.val.f);
- SHOW_DST(iptr);
- break;
-
- /* const DBL */
- case ICMD_DCONST:
- SHOW_DBL_CONST(iptr->sx.val.d);
- SHOW_DST(iptr);
- break;
-
- /* const ADR */
- case ICMD_ACONST:
- if (iptr->flags.bits & INS_FLAG_CLASS) {
- SHOW_ADR_CONST(iptr->sx.val.anyptr);
- SHOW_CLASSREF_OR_CLASSINFO(iptr->sx.val.c);
- }
- else if (iptr->sx.val.anyptr == NULL) {
- printf("NULL ");
- }
- else {
- SHOW_ADR_CONST(iptr->sx.val.anyptr);
- SHOW_STRING(iptr->sx.val.stringconst);
- }
- SHOW_DST(iptr);
- break;
-
- case ICMD_AASTORECONST:
- SHOW_S1(iptr);
- SHOW_S2(iptr);
- printf("%p ", (void*) iptr->sx.s23.s3.constval);
- break;
-
- case ICMD_GETFIELD: /* 1 -> 1 */
- case ICMD_PUTFIELD: /* 2 -> 0 */
- case ICMD_PUTSTATIC: /* 1 -> 0 */
- case ICMD_GETSTATIC: /* 0 -> 1 */
- case ICMD_PUTSTATICCONST: /* 0 -> 0 */
- case ICMD_PUTFIELDCONST: /* 1 -> 0 */
- if (opcode != ICMD_GETSTATIC && opcode != ICMD_PUTSTATICCONST) {
- SHOW_S1(iptr);
- if (opcode == ICMD_PUTFIELD) {
- SHOW_S2(iptr);
- }
- }
- INSTRUCTION_GET_FIELDREF(iptr, fmiref);
- SHOW_FIELD(fmiref);
-
- if (opcode == ICMD_GETSTATIC || opcode == ICMD_GETFIELD) {
- SHOW_DST(iptr);
- }
- break;
-
- case ICMD_IINC:
- SHOW_S1_LOCAL(iptr);
- SHOW_INT_CONST(iptr->sx.val.i);
- SHOW_DST_LOCAL(iptr);
- break;
-
- case ICMD_IASTORE:
- case ICMD_SASTORE:
- case ICMD_BASTORE:
- case ICMD_CASTORE:
- case ICMD_LASTORE:
- case ICMD_DASTORE:
- case ICMD_FASTORE:
- case ICMD_AASTORE:
- SHOW_S1(iptr);
- SHOW_S2(iptr);
- SHOW_S3(iptr);
- break;
-
- case ICMD_IALOAD:
- case ICMD_SALOAD:
- case ICMD_BALOAD:
- case ICMD_CALOAD:
- case ICMD_LALOAD:
- case ICMD_DALOAD:
- case ICMD_FALOAD:
- case ICMD_AALOAD:
- SHOW_S1(iptr);
- SHOW_S2(iptr);
- SHOW_DST(iptr);
- break;
-
- case ICMD_RET:
- SHOW_S1_LOCAL(iptr);
- if (stage >= SHOW_STACK) {
- printf(" ---> L%03d", iptr->dst.block->nr);
- }
- break;
-
- case ICMD_ILOAD:
- case ICMD_LLOAD:
- case ICMD_FLOAD:
- case ICMD_DLOAD:
- case ICMD_ALOAD:
- SHOW_S1_LOCAL(iptr);
- SHOW_DST(iptr);
- break;
-
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
- case ICMD_ASTORE:
- SHOW_S1(iptr);
- SHOW_DST_LOCAL(iptr);
- if (stage >= SHOW_STACK && iptr->sx.s23.s3.javaindex != UNUSED)
- printf(" (javaindex %d)", iptr->sx.s23.s3.javaindex);
- if (iptr->flags.bits & INS_FLAG_RETADDR) {
- printf(" (retaddr L%03d)", RETADDR_FROM_JAVALOCAL(iptr->sx.s23.s2.retaddrnr));
- }
- break;
-
- case ICMD_NEW:
- SHOW_DST(iptr);
- break;
-
- case ICMD_NEWARRAY:
- SHOW_DST(iptr);
- break;
-
- case ICMD_ANEWARRAY:
- SHOW_DST(iptr);
- break;
-
- case ICMD_MULTIANEWARRAY:
- if (stage >= SHOW_STACK) {
- argp = iptr->sx.s23.s2.args;
- i = iptr->s1.argcount;
- while (i--) {
- SHOW_VARIABLE(*(argp++));
- }
- }
- else {
- printf("argcount=%d ", iptr->s1.argcount);
- }
- class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
- putchar(' ');
- SHOW_DST(iptr);
- break;
-
- case ICMD_CHECKCAST:
- SHOW_S1(iptr);
- class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
- putchar(' ');
- SHOW_DST(iptr);
- break;
-
- case ICMD_INSTANCEOF:
- SHOW_S1(iptr);
- SHOW_DST(iptr);
- break;
-
- case ICMD_INLINE_START:
- case ICMD_INLINE_END:
- case ICMD_INLINE_BODY:
-#if defined(ENABLE_INLINING)
- {
- insinfo_inline *ii = iptr->sx.s23.s3.inlineinfo;
- show_inline_info(jd, ii, opcode, stage);
- }
-#endif
- break;
-
- case ICMD_BUILTIN:
- if (stage >= SHOW_STACK) {
- argp = iptr->sx.s23.s2.args;
- i = iptr->s1.argcount;
- while (i--) {
- if ((iptr->s1.argcount - 1 - i) == iptr->sx.s23.s3.bte->md->paramcount)
- printf(" pass-through: ");
- SHOW_VARIABLE(*(argp++));
- }
- }
- printf("%s ", iptr->sx.s23.s3.bte->cname);
- if (iptr->sx.s23.s3.bte->md->returntype.type != TYPE_VOID) {
- SHOW_DST(iptr);
- }
- break;
-
- case ICMD_INVOKEVIRTUAL:
- case ICMD_INVOKESPECIAL:
- case ICMD_INVOKESTATIC:
- case ICMD_INVOKEINTERFACE:
- if (stage >= SHOW_STACK) {
- methoddesc *md;
- INSTRUCTION_GET_METHODDESC(iptr, md);
- argp = iptr->sx.s23.s2.args;
- i = iptr->s1.argcount;
- while (i--) {
- if ((iptr->s1.argcount - 1 - i) == md->paramcount)
- printf(" pass-through: ");
- SHOW_VARIABLE(*(argp++));
- }
- }
- INSTRUCTION_GET_METHODREF(iptr, fmiref);
- method_methodref_print(fmiref);
- if (fmiref->parseddesc.md->returntype.type != TYPE_VOID) {
- putchar(' ');
- SHOW_DST(iptr);
- }
- break;
-
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
- SHOW_S1(iptr);
- SHOW_INT_CONST(iptr->sx.val.i);
- SHOW_TARGET(iptr->dst);
- break;
-
- case ICMD_IF_LEQ:
- case ICMD_IF_LNE:
- case ICMD_IF_LLT:
- case ICMD_IF_LGE:
- case ICMD_IF_LGT:
- case ICMD_IF_LLE:
- SHOW_S1(iptr);
- SHOW_LNG_CONST(iptr->sx.val.l);
- SHOW_TARGET(iptr->dst);
- break;
-
- case ICMD_GOTO:
- SHOW_TARGET(iptr->dst);
- break;
-
- case ICMD_JSR:
- SHOW_TARGET(iptr->sx.s23.s3.jsrtarget);
- SHOW_DST(iptr);
- break;
-
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
- SHOW_S1(iptr);
- SHOW_TARGET(iptr->dst);
- break;
-
- case ICMD_IF_ICMPEQ:
- case ICMD_IF_ICMPNE:
- case ICMD_IF_ICMPLT:
- case ICMD_IF_ICMPGE:
- case ICMD_IF_ICMPGT:
- case ICMD_IF_ICMPLE:
-
- case ICMD_IF_LCMPEQ:
- case ICMD_IF_LCMPNE:
- case ICMD_IF_LCMPLT:
- case ICMD_IF_LCMPGE:
- case ICMD_IF_LCMPGT:
- case ICMD_IF_LCMPLE:
-
- case ICMD_IF_ACMPEQ:
- case ICMD_IF_ACMPNE:
- SHOW_S1(iptr);
- SHOW_S2(iptr);
- SHOW_TARGET(iptr->dst);
- break;
-
- case ICMD_TABLESWITCH:
- SHOW_S1(iptr);
- table = iptr->dst.table;
-
- i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
-
- printf("high=%d low=%d count=%d\n", iptr->sx.s23.s3.tablehigh, iptr->sx.s23.s2.tablelow, i);
- while (--i >= 0) {
- printf("\t\t%d --> ", (int) (table - iptr->dst.table));
- printf("L%03d\n", table->block->nr);
- table++;
- }
-
- break;
-
- case ICMD_LOOKUPSWITCH:
- SHOW_S1(iptr);
-
- printf("count=%d, default=L%03d\n",
- iptr->sx.s23.s2.lookupcount,
- iptr->sx.s23.s3.lookupdefault.block->nr);
-
- lookup = iptr->dst.lookup;
- i = iptr->sx.s23.s2.lookupcount;
-
- while (--i >= 0) {
- printf("\t\t%d --> L%03d\n",
- lookup->value,
- lookup->target.block->nr);
- lookup++;
- }
- break;
-
- case ICMD_FRETURN:
- case ICMD_IRETURN:
- case ICMD_DRETURN:
- case ICMD_LRETURN:
- SHOW_S1(iptr);
- break;
-
- case ICMD_ARETURN:
- case ICMD_ATHROW:
- SHOW_S1(iptr);
- if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- /* XXX this needs more work */
-#if 0
- unresolved_class_debug_dump(iptr->sx.s23.s2.uc, stdout);
-#endif
- }
- break;
-
- case ICMD_COPY:
- case ICMD_MOVE:
- SHOW_S1(iptr);
- SHOW_DST(iptr);
- break;
- 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);
-}
-#endif /* !defined(NDEBUG) */
-
-/* Debug output filtering */
-
-#if defined(ENABLE_DEBUG_FILTER)
-
-#if !defined(ENABLE_THREADS)
-u2 _no_threads_filterverbosecallctr[2] = { 0, 0 };
-#endif
-
-struct show_filter {
- /* Boolean indicating if filter is enabled. */
- u1 enabled;
- /* Regular expression the method name is matched against */
- regex_t regex;
- /* Flag set on m->filtermatches if regex matches */
- u1 flag;
-};
-
-typedef struct show_filter show_filter_t;
-
-#define SHOW_FILTERS_SIZE 3
-
-/* Array of filters applyed on a method */
-static struct show_filter show_filters[SHOW_FILTERS_SIZE];
-
-static void show_filter_init(show_filter_t *cf, const char *str, u1 flag, u1 default_flag, const char *description) {
- int err;
- char err_buf[128];
-
- if (str) {
- err = regcomp(&cf->regex, str, REG_EXTENDED | REG_NOSUB);
- if (err != 0) {
- regerror(err, &cf->regex, err_buf, sizeof(err_buf));
- vm_abort(
- "Invalid value given for %s: `%s' (%s).",
- description, str, err_buf
- );
- }
- cf->flag = flag;
- cf->enabled = 1;
- } else {
- cf->flag = default_flag;
- cf->enabled = 0;
- }
-}
-
-void show_filters_init(void) {
-
- show_filter_init(
- show_filters + 0,
- opt_filter_verbosecall_include,
- SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
- SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
- "verbose call include filter"
- );
-
- show_filter_init(
- show_filters + 1,
- opt_filter_verbosecall_exclude,
- SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE,
- 0,
- "verbose call exclude filter"
- );
-
- show_filter_init(
- show_filters + 2,
- opt_filter_show_method,
- SHOW_FILTER_FLAG_SHOW_METHOD,
- SHOW_FILTER_FLAG_SHOW_METHOD,
- "show method filter"
- );
-}
-
-/*
-
- (Pseudo)State machine:
-
- States are INITIAL, INCLUDE1, INCLUDE2, ..., EXCLUDE1, ..., EXCLUDE2, ...
-
- Enter Enter
- Enter Include Include
- Exclude | | | |
- | | Enter Enter Enter | | Enter | |
- | | Include Include Exclude | | Exclude | |
- | v ---------> ----------> ----------> | v ----------> | v
-INITIAL INCLUDE1 INCLUDE2 EXCLUDE1 EXCLUDE2
- | ^ <--------- <---------- <---------- | ^ <---------- | ^
- | | Exit Exit Exit | | Exit | |
- | | Include Include Exclude | | Exclude | |
- | | | | | |
- Exit Exit Exit
- Exclude Include Include
-
- Verbose call scope is active if we are in a INCLUDE state.
-
- State encoding:
-
- INITIAL: ctr[0] == 0, ctr[1] == 0
- INCLUDEN: ctr[1] == N, ctr[1] == 0
- EXCLUDEN: ctr[1] == N
-*/
-
-void show_filters_apply(methodinfo *m) {
- int i;
- int res;
- char *method_name;
- s4 len;
- int32_t dumpmarker;
-
- /* compose full name of method */
-
- len =
- utf_bytes(m->clazz->name) +
- 1 +
- utf_bytes(m->name) +
- utf_bytes(m->descriptor) +
- 1;
-
- DMARKER;
-
- method_name = DMNEW(char, len);
-
- utf_cat_classname(method_name, m->clazz->name);
- strcat(method_name, ".");
- utf_cat(method_name, m->name);
- utf_cat(method_name, m->descriptor);
-
- /* reset all flags */
-
- m->filtermatches = 0;
-
- for (i = 0; i < SHOW_FILTERS_SIZE; ++i) {
- if (show_filters[i].enabled) {
-
- res = regexec(&show_filters[i].regex, method_name, 0, NULL, 0);
-
- if (res == 0) {
- m->filtermatches |= show_filters[i].flag;
- }
- } else {
- /* Default is to show all */
- m->filtermatches |= show_filters[i].flag;
- }
- }
-
- /* release memory */
-
- DRELEASE;
-}
-
-#define STATE_IS_INITIAL() ((FILTERVERBOSECALLCTR[0] == 0) && (FILTERVERBOSECALLCTR[1] == 0))
-#define STATE_IS_INCLUDE() ((FILTERVERBOSECALLCTR[0] > 0) && (FILTERVERBOSECALLCTR[1] == 0))
-#define STATE_IS_EXCLUDE() (FILTERVERBOSECALLCTR[1] > 0)
-#define EVENT_INCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE)
-#define EVENT_EXCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE)
-#define TRANSITION_NEXT_INCLUDE() ++FILTERVERBOSECALLCTR[0]
-#define TRANSITION_PREV_INCLUDE() --FILTERVERBOSECALLCTR[0]
-#define TRANSITION_NEXT_EXCLUDE() ++FILTERVERBOSECALLCTR[1]
-#define TRANSITION_PREV_EXCLUDE() --FILTERVERBOSECALLCTR[1]
-
-#if 0
-void dump_state() {
- if (STATE_IS_INITIAL()) printf("<INITIAL>\n");
- else if (STATE_IS_INCLUDE()) printf("<INCLUDE %hd>\n", FILTERVERBOSECALLCTR[0]);
- else if (STATE_IS_EXCLUDE()) printf("<EXCLUDE %hd>\n", FILTERVERBOSECALLCTR[1]);
-}
-#endif
-
-int show_filters_test_verbosecall_enter(methodinfo *m) {
-
- int force_show = 0;
-
- if (STATE_IS_INITIAL()) {
- if (EVENT_INCLUDE()) {
- TRANSITION_NEXT_INCLUDE();
- }
- } else if (STATE_IS_INCLUDE()) {
- if (EVENT_EXCLUDE()) {
- TRANSITION_NEXT_EXCLUDE();
- /* just entered exclude, show this method */
- force_show = 1;
- } else if (EVENT_INCLUDE()) {
- TRANSITION_NEXT_INCLUDE();
- }
- } else if (STATE_IS_EXCLUDE()) {
- if (EVENT_EXCLUDE()) {
- TRANSITION_NEXT_EXCLUDE();
- }
- }
-
- return STATE_IS_INCLUDE() || force_show;
-}
-
-int show_filters_test_verbosecall_exit(methodinfo *m) {
-
- int force_show = 0;
-
- if (m) {
- if (STATE_IS_INCLUDE()) {
- if (EVENT_INCLUDE()) {
- TRANSITION_PREV_INCLUDE();
- /* just entered initial, show this method */
- if (STATE_IS_INITIAL()) force_show = 1;
- }
- } else if (STATE_IS_EXCLUDE()) {
- if (EVENT_EXCLUDE()) {
- TRANSITION_PREV_EXCLUDE();
- }
- }
- }
-
- return STATE_IS_INCLUDE() || force_show;
-}
-
-#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/show.cpp - showing the intermediate representation
+
+ 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 "threads/lock.hpp"
+
+#include "vm/global.h"
+#include "vm/jit/builtin.hpp"
+#include "vm/options.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/abi.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/show.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/stack.h"
+#include "vm/jit/parse.h"
+
+#if defined(ENABLE_DEBUG_FILTER)
+# include <sys/types.h>
+# include <regex.h>
+# include "threads/thread.hpp"
+#endif
+
+
+/* global variables ***********************************************************/
+
+#if !defined(NDEBUG)
+static Mutex mutex;
+#endif
+
+
+/* prototypes *****************************************************************/
+
+#if !defined(NDEBUG)
+static void show_variable_intern(jitdata *jd, s4 index, int stage);
+#endif
+
+
+/* show_init *******************************************************************
+
+ Initialized the show subsystem (called by jit_init).
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+bool show_init(void)
+{
+#if defined(ENABLE_DEBUG_FILTER)
+ show_filters_init();
+#endif
+
+ /* everything's ok */
+
+ return true;
+}
+#endif
+
+
+#if !defined(NDEBUG)
+const char *show_jit_type_names[] = {
+ "INT",
+ "LNG",
+ "FLT",
+ "DBL",
+ "ADR",
+ "??5",
+ "??6",
+ "??7",
+ "RET"
+};
+
+const char show_jit_type_letters[] = {
+ 'I',
+ 'L',
+ 'F',
+ 'D',
+ 'A',
+ '5',
+ '6',
+ '7',
+ 'R'
+};
+#endif
+
+
+/* show_method *****************************************************************
+
+ Print the intermediate representation of a method.
+
+ NOTE: Currently this function may only be called after register allocation!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void show_method(jitdata *jd, int stage)
+{
+ methodinfo *m;
+ codeinfo *code;
+ codegendata *cd;
+ registerdata *rd;
+ basicblock *bptr;
+ basicblock *lastbptr;
+ exception_entry *ex;
+ s4 i, j;
+ int irstage;
+#if defined(ENABLE_DISASSEMBLER)
+ u1 *pc;
+#endif
+
+ /* get required compiler data */
+
+ m = jd->m;
+ code = jd->code;
+ cd = jd->cd;
+ rd = jd->rd;
+
+ // We need to enter a lock here, since the binutils disassembler
+ // is not reentrant-able and we could not read functions printed
+ // at the same time.
+ mutex.lock();
+
+#if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ irstage = SHOW_PARSE;
+ else
+#endif
+ irstage = stage;
+
+ /* get the last basic block */
+
+ for (lastbptr = jd->basicblocks; lastbptr->next != NULL; lastbptr = lastbptr->next);
+
+ printf("\n");
+
+ method_println(m);
+
+ if (code_is_leafmethod(code))
+ printf("LEAFMETHOD\n");
+
+ printf("\nBasic blocks: %d\n", jd->basicblockcount);
+ if (stage >= SHOW_CODE) {
+ printf("Code length: %d\n", (lastbptr->mpc - jd->basicblocks[0].mpc));
+ printf("Data length: %d\n", cd->dseglen);
+ printf("Stub length: %d\n", (s4) (code->mcodelength -
+ ((ptrint) cd->dseglen + lastbptr->mpc)));
+ }
+ printf("Variables: %d (%d used)\n", jd->varcount, jd->vartop);
+ if (stage >= SHOW_STACK)
+ printf("Max interfaces: %d\n", jd->maxinterfaces);
+ printf("Max locals: %d\n", jd->maxlocals);
+ printf("Max stack: %d\n", m->maxstack);
+ printf("Linenumbers: %d\n", m->linenumbercount);
+ printf("Branch to entry: %s\n", (jd->branchtoentry) ? "yes" : "no");
+ printf("Branch to end: %s\n", (jd->branchtoend) ? "yes" : "no");
+ if (stage >= SHOW_STACK) {
+ printf("Number of RETURNs: %d", jd->returncount);
+ if (jd->returncount == 1)
+ printf(" (block L%03d)", jd->returnblock->nr);
+ printf("\n");
+ }
+
+ if (stage >= SHOW_PARSE) {
+ printf("Exceptions (Number: %d):\n", jd->exceptiontablelength);
+ for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
+ printf(" L%03d ... ", ex->start->nr );
+ printf("L%03d = ", ex->end->nr);
+ printf("L%03d", ex->handler->nr);
+ printf(" (catchtype: ");
+ if (ex->catchtype.any)
+ if (IS_CLASSREF(ex->catchtype))
+ class_classref_print(ex->catchtype.ref);
+ else
+ class_print(ex->catchtype.cls);
+ else
+ printf("ANY");
+ printf(")\n");
+ }
+ }
+
+ if (irstage >= SHOW_PARSE && rd && jd->localcount > 0) {
+ printf("Local Table:\n");
+ for (i = 0; i < jd->localcount; i++) {
+ printf(" %3d: ", i);
+
+#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp) {
+# endif
+ printf(" (%s) ", show_jit_type_names[VAR(i)->type]);
+ if (irstage >= SHOW_REGS)
+ show_allocation(VAR(i)->type, VAR(i)->flags, VAR(i)->vv.regoff);
+ printf("\n");
+# if defined(ENABLE_INTRP)
+ }
+# endif
+#endif /* defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) */
+ }
+ printf("\n");
+ }
+
+ if (jd->maxlocals > 0 && jd->local_map != NULL) {
+ printf("Local Map:\n");
+ printf(" index ");
+ for (j = 0; j < jd->maxlocals; j++) {
+ printf(" [%2d]", j);
+ }
+ printf("\n");
+ for (i = 0; i < 5; i++) {
+ printf(" %5s ",show_jit_type_names[i]);
+ for (j = 0; j < jd->maxlocals; j++) {
+ if (jd->local_map[j*5+i] == UNUSED)
+ printf(" -- ");
+ else
+ printf("%4i ",jd->local_map[j*5+i]);
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ if (jd->maxinterfaces > 0 && jd->interface_map && irstage >= SHOW_STACK) {
+ bool exist = false;
+ interface_info *mapptr = jd->interface_map;
+
+ /* look if there exist any INOUTS */
+ for (i = 0; (i < (5 * jd->maxinterfaces)) && !exist; i++, mapptr++)
+ exist = (mapptr->flags != UNUSED);
+
+ if (exist) {
+ printf("Interface Table: (In/Outvars)\n");
+ printf(" depth ");
+ for (j = 0; j < jd->maxinterfaces; j++) {
+ printf(" [%2d]", j);
+ }
+ printf("\n");
+
+ for (i = 0; i < 5; i++) {
+ printf(" %5s ",show_jit_type_names[i]);
+ for (j = 0; j < jd->maxinterfaces; j++) {
+ s4 flags = jd->interface_map[j*5+i].flags;
+ s4 regoff = jd->interface_map[j*5+i].regoff;
+ if (flags == UNUSED)
+ printf(" -- ");
+ else {
+ int ch;
+
+ if (irstage >= SHOW_REGS) {
+ if (flags & SAVEDVAR) {
+ if (flags & INMEMORY)
+ ch = 'M';
+ else
+ ch = 'R';
+ }
+ else {
+ if (flags & INMEMORY)
+ ch = 'm';
+ else
+ ch = 'r';
+ }
+ printf("%c%03d(", ch, regoff);
+ show_allocation(i, flags, regoff);
+ printf(") ");
+ }
+ else {
+ if (flags & SAVEDVAR)
+ printf(" I ");
+ else
+ printf(" i ");
+ }
+ }
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+ }
+
+ if (rd->memuse && irstage >= SHOW_REGS) {
+ int max;
+
+ max = rd->memuse;
+ printf("Stack slots: (memuse=%d", rd->memuse);
+ if (irstage >= SHOW_CODE) {
+ printf(", stackframesize=%d", cd->stackframesize);
+ max = cd->stackframesize;
+ }
+ printf(")\n");
+ for (i = 0; i < max; ++i) {
+ printf(" M%02d = 0x%02x(sp): ", i, i * 8);
+ for (j = 0; j < jd->vartop; ++j) {
+ varinfo *v = VAR(j);
+ if ((v->flags & INMEMORY) && (v->vv.regoff == i)) {
+ show_variable(jd, j, irstage);
+ putchar(' ');
+ }
+ }
+
+ printf("\n");
+
+ }
+ printf("\n");
+ }
+
+#if defined(ENABLE_REPLACEMENT)
+ if (code->rplpoints) {
+ printf("Replacement Points:\n");
+ replace_show_replacement_points(code);
+ printf("\n");
+ }
+#endif /* defined(ENABLE_REPLACEMENT) */
+
+#if defined(ENABLE_DISASSEMBLER)
+ /* show code before first basic block */
+
+ if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
+ pc = (u1 *) ((ptrint) code->mcode + cd->dseglen);
+
+ for (; pc < (u1 *) ((ptrint) code->mcode + cd->dseglen + jd->basicblocks[0].mpc);)
+ DISASSINSTR(pc);
+
+ printf("\n");
+ }
+#endif
+
+ /* show code of all basic blocks */
+
+ for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next)
+ show_basicblock(jd, bptr, stage);
+
+#if 0 && defined(ENABLE_DISASSEMBLER)
+ /* show code after last basic block */
+
+ if (stage >= SHOW_CODE && opt_showdisassemble) {
+ printf("\nStubs code:\n");
+ printf("Length: %d\n\n", (s4) (code->mcodelength -
+ ((ptrint) cd->dseglen + lastbptr->mpc)));
+
+ pc = (u1 *) ((ptrint) code->mcode + cd->dseglen + lastbptr->mpc);
+
+ for (; (ptrint) pc < ((ptrint) code->mcode + code->mcodelength);)
+ DISASSINSTR(pc);
+
+ printf("\n");
+ }
+#endif
+
+ mutex.unlock();
+
+ /* finally flush the output */
+
+ fflush(stdout);
+}
+#endif /* !defined(NDEBUG) */
+
+
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+static void show_inline_info(jitdata *jd, insinfo_inline *ii, s4 opcode, s4 stage)
+{
+ s4 *jl;
+ s4 n;
+
+ printf("(pt %d+%d+%d st ",
+ ii->throughcount - (ii->stackvarscount - ii->paramcount),
+ ii->stackvarscount - ii->paramcount,
+ ii->paramcount);
+ show_variable_array(jd, ii->stackvars, ii->stackvarscount, stage);
+
+ if (opcode == ICMD_INLINE_START || opcode == ICMD_INLINE_END) {
+ printf(" jl ");
+ jl = (opcode == ICMD_INLINE_START) ? ii->javalocals_start : ii->javalocals_end;
+ n = (opcode == ICMD_INLINE_START) ? ii->method->maxlocals : ii->outer->maxlocals;
+ show_javalocals_array(jd, jl, n, stage);
+ }
+
+ printf(") ");
+
+#if 0
+ printf("(");
+ method_print(ii->outer);
+ printf(" ==> ");
+#endif
+
+ method_print(ii->method);
+}
+#endif /* !defined(NDEBUG) && defined(ENABLE_INLINING) */
+
+
+/* show_basicblock *************************************************************
+
+ Print the intermediate representation of a basic block.
+
+ NOTE: Currently this function may only be called after register allocation!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
+{
+ codeinfo *code;
+ codegendata *cd;
+ s4 i;
+ bool deadcode;
+ instruction *iptr;
+ int irstage;
+#if defined(ENABLE_DISASSEMBLER)
+ methodinfo *m; /* this is only a dummy */
+ void *pc;
+ s4 linenumber;
+ s4 currentlinenumber;
+#endif
+
+ /* get required compiler data */
+
+ code = jd->code;
+ cd = jd->cd;
+
+ if (bptr->flags != BBDELETED) {
+#if defined(ENABLE_INTRP)
+ if (opt_intrp) {
+ deadcode = false;
+ irstage = SHOW_PARSE;
+ }
+ else
+#endif
+ {
+ deadcode = (bptr->flags < BBREACHED);
+ irstage = stage;
+ }
+
+ printf("======== %sL%03d ======== %s(flags: %d, bitflags: %01x, next: %d, type: ",
+#if defined(ENABLE_REPLACEMENT)
+ (bptr->bitflags & BBFLAG_REPLACEMENT) ? "<REPLACE> " :
+#endif
+ "",
+ bptr->nr,
+ (deadcode && stage >= SHOW_STACK) ? "DEADCODE! " : "",
+ bptr->flags, bptr->bitflags,
+ (bptr->next) ? (bptr->next->nr) : -1);
+
+ switch (bptr->type) {
+ case BBTYPE_STD:
+ printf("STD");
+ break;
+ case BBTYPE_EXH:
+ printf("EXH");
+ break;
+ case BBTYPE_SBR:
+ printf("SBR");
+ break;
+ }
+
+ printf(", icount: %d", bptr->icount);
+
+ if (irstage >= SHOW_CFG) {
+ printf(", preds: %d [ ", bptr->predecessorcount);
+
+ for (i = 0; i < bptr->predecessorcount; i++)
+ printf("%d ", bptr->predecessors[i]->nr);
+
+ printf("]");
+ }
+
+ printf("):");
+
+ if (bptr->original)
+ printf(" (clone of L%03d)", bptr->original->nr);
+ else {
+ basicblock *b = bptr->copied_to;
+ if (b) {
+ printf(" (copied to ");
+ for (; b; b = b->copied_to)
+ printf("L%03d ", b->nr);
+ printf(")");
+ }
+ }
+
+ printf("\n");
+
+ if (irstage >= SHOW_CFG) {
+ printf("succs: %d [ ", bptr->successorcount);
+
+ for (i = 0; i < bptr->successorcount; i++)
+ printf("%d ", bptr->successors[i]->nr);
+
+ printf("]\n");
+ }
+
+ if (irstage >= SHOW_STACK) {
+ printf("IN: ");
+ show_variable_array(jd, bptr->invars, bptr->indepth, irstage);
+ printf(" javalocals: ");
+ if (bptr->javalocals)
+ show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
+ else
+ printf("null");
+ printf("\n");
+ }
+
+#if defined(ENABLE_INLINING)
+ if (bptr->inlineinfo) {
+ printf("inlineinfo: ");
+ show_inline_info(jd, bptr->inlineinfo, -1, irstage);
+ printf("\n");
+ }
+#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++) {
+ printf("%4d:%4d: ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
+
+ show_icmd(jd, iptr, deadcode, irstage);
+ printf("\n");
+ }
+
+ if (irstage >= SHOW_STACK) {
+ printf("OUT: ");
+ show_variable_array(jd, bptr->outvars, bptr->outdepth, irstage);
+ printf("\n");
+ }
+
+#if defined(ENABLE_DISASSEMBLER)
+ if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) &&
+ (!deadcode))
+ {
+ printf("\n");
+ pc = (void *) (code->mcode + cd->dseglen + bptr->mpc);
+ linenumber = 0;
+
+ if (bptr->next != NULL) {
+ for (; pc < (void *) (code->mcode + cd->dseglen + bptr->next->mpc);) {
+ currentlinenumber = code->linenumbertable->find(&m, pc);
+
+ if (currentlinenumber != linenumber) {
+ linenumber = currentlinenumber;
+ printf("%4d:\n", linenumber);
+ }
+
+ DISASSINSTR(pc);
+ }
+ }
+ else {
+ for (; pc < (void *) (code->mcode + code->mcodelength);) {
+ currentlinenumber = code->linenumbertable->find(&m, pc);
+
+ if (currentlinenumber != linenumber) {
+ linenumber = currentlinenumber;
+ printf("%4d:\n", linenumber);
+ }
+
+ DISASSINSTR(pc);
+ }
+ }
+ printf("\n");
+ }
+#endif
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* show_icmd *******************************************************************
+
+ Print the intermediate representation of an instruction.
+
+ NOTE: Currently this function may only be called after register allocation!
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+
+#define SHOW_TARGET(target) \
+ if (stage >= SHOW_PARSE) { \
+ printf("--> L%03d ", (target).block->nr); \
+ } \
+ else { \
+ printf("--> insindex %d ", (target).insindex); \
+ }
+
+#define SHOW_INT_CONST(val) \
+ if (stage >= SHOW_PARSE) { \
+ printf("%d (0x%08x) ", (int32_t) (val), (int32_t) (val)); \
+ } \
+ else { \
+ printf("iconst "); \
+ }
+
+#if SIZEOF_VOID_P == 4
+#define SHOW_LNG_CONST(val) \
+ if (stage >= SHOW_PARSE) \
+ printf("%lld (0x%016llx) ", (val), (val)); \
+ else \
+ printf("lconst ");
+#else
+#define SHOW_LNG_CONST(val) \
+ if (stage >= SHOW_PARSE) \
+ printf("%ld (0x%016lx) ", (val), (val)); \
+ else \
+ printf("lconst ");
+#endif
+
+#if SIZEOF_VOID_P == 4
+#define SHOW_ADR_CONST(val) \
+ if (stage >= SHOW_PARSE) \
+ printf("0x%08x ", (ptrint) (val)); \
+ else \
+ printf("aconst ");
+#else
+#define SHOW_ADR_CONST(val) \
+ if (stage >= SHOW_PARSE) \
+ printf("0x%016lx ", (ptrint) (val)); \
+ else \
+ printf("aconst ");
+#endif
+
+#define SHOW_FLT_CONST(val) \
+ if (stage >= SHOW_PARSE) { \
+ imm_union v; \
+ v.f = (val); \
+ printf("%g (0x%08x) ", (val), v.i); \
+ } \
+ else { \
+ printf("fconst "); \
+ }
+
+#if SIZEOF_VOID_P == 4
+#define SHOW_DBL_CONST(val) \
+ if (stage >= SHOW_PARSE) { \
+ imm_union v; \
+ v.d = (val); \
+ printf("%g (0x%016llx) ", (val), v.l); \
+ } \
+ else \
+ printf("dconst ");
+#else
+#define SHOW_DBL_CONST(val) \
+ if (stage >= SHOW_PARSE) { \
+ imm_union v; \
+ v.d = (val); \
+ printf("%g (0x%016lx) ", (val), v.l); \
+ } \
+ else \
+ printf("dconst ");
+#endif
+
+#define SHOW_INDEX(index) \
+ if (stage >= SHOW_PARSE) { \
+ printf("%d ", index); \
+ } \
+ else { \
+ printf("index"); \
+ }
+
+#define SHOW_STRING(val) \
+ if (stage >= SHOW_PARSE) { \
+ putchar('"'); \
+ utf_display_printable_ascii( \
+ javastring_toutf((java_handle_t *)(val), false)); \
+ printf("\" "); \
+ } \
+ else { \
+ printf("string "); \
+ }
+
+#define SHOW_CLASSREF_OR_CLASSINFO(c) \
+ if (stage >= SHOW_PARSE) { \
+ if (IS_CLASSREF(c)) \
+ class_classref_print(c.ref); \
+ else \
+ class_print(c.cls); \
+ putchar(' '); \
+ } \
+ else { \
+ printf("class "); \
+ }
+
+#define SHOW_FIELD(fmiref) \
+ if (stage >= SHOW_PARSE) { \
+ field_fieldref_print(fmiref); \
+ putchar(' '); \
+ } \
+ else { \
+ printf("field "); \
+ }
+
+#define SHOW_VARIABLE(v) \
+ show_variable(jd, (v), stage)
+
+#define SHOW_S1(iptr) \
+ if (stage >= SHOW_STACK) { \
+ SHOW_VARIABLE(iptr->s1.varindex); \
+ }
+
+#define SHOW_S2(iptr) \
+ if (stage >= SHOW_STACK) { \
+ SHOW_VARIABLE(iptr->sx.s23.s2.varindex); \
+ }
+
+#define SHOW_S3(iptr) \
+ if (stage >= SHOW_STACK) { \
+ SHOW_VARIABLE(iptr->sx.s23.s3.varindex); \
+ }
+
+#define SHOW_DST(iptr) \
+ if (stage >= SHOW_STACK) { \
+ printf("=> "); \
+ SHOW_VARIABLE(iptr->dst.varindex); \
+ }
+
+#define SHOW_S1_LOCAL(iptr) \
+ if (stage >= SHOW_STACK) { \
+ printf("L%d ", iptr->s1.varindex); \
+ } \
+ else { \
+ printf("JavaL%d ", iptr->s1.varindex); \
+ }
+
+#define SHOW_DST_LOCAL(iptr) \
+ if (stage >= SHOW_STACK) { \
+ printf("=> L%d ", iptr->dst.varindex); \
+ } \
+ else { \
+ printf("=> JavaL%d ", iptr->dst.varindex); \
+ }
+
+void show_allocation(s4 type, s4 flags, s4 regoff)
+{
+ if (type == TYPE_RET) {
+ printf("N/A");
+ return;
+ }
+
+ if (flags & INMEMORY) {
+ printf("M%02d", regoff);
+ return;
+ }
+
+#ifdef HAS_ADDRESS_REGISTER_FILE
+ if (type == TYPE_ADR) {
+ printf("R%02d", regoff);
+ return;
+ }
+#endif
+
+ if (IS_FLT_DBL_TYPE(type)) {
+ printf("F%02d", regoff);
+ return;
+ }
+
+#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+ if (IS_2_WORD_TYPE(type)) {
+# if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ printf("%3d/%3d", GET_LOW_REG(regoff),
+ GET_HIGH_REG(regoff));
+ else
+# endif
+ printf("%3s/%3s", abi_registers_integer_name[GET_LOW_REG(regoff)],
+ abi_registers_integer_name[GET_HIGH_REG(regoff)]);
+# else
+ printf("%3d/%3d", GET_LOW_REG(regoff),
+ GET_HIGH_REG(regoff));
+# endif
+ return;
+ }
+#endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
+
+#if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ printf("%3d", regoff);
+ else
+# endif
+ printf("%3s", abi_registers_integer_name[regoff]);
+#else
+ printf("%3d", regoff);
+#endif
+}
+
+void show_variable(jitdata *jd, s4 index, int stage)
+{
+ show_variable_intern(jd, index, stage);
+ putchar(' ');
+}
+
+static void show_variable_intern(jitdata *jd, s4 index, int stage)
+{
+ char type;
+ char kind;
+ varinfo *v;
+
+ if (index < 0 || index >= jd->vartop) {
+ printf("<INVALID INDEX:%d>", index);
+ return;
+ }
+
+ v = VAR(index);
+
+ switch (v->type) {
+ case TYPE_INT: type = 'i'; break;
+ case TYPE_LNG: type = 'l'; break;
+ case TYPE_FLT: type = 'f'; break;
+ case TYPE_DBL: type = 'd'; break;
+ case TYPE_ADR: type = 'a'; break;
+ case TYPE_RET: type = 'r'; break;
+ default: type = '?';
+ }
+
+ if (index < jd->localcount) {
+ kind = 'L';
+ if (v->flags & (PREALLOC | INOUT))
+ printf("<INVALID FLAGS!>");
+ }
+ else {
+ if (v->flags & PREALLOC) {
+ kind = 'A';
+ if (v->flags & INOUT) {
+ /* PREALLOC is used to avoid allocation of TYPE_RET */
+ if (v->type == TYPE_RET)
+ kind = 'i';
+ else
+ printf("<INVALID FLAGS!>");
+ }
+ }
+ else if (v->flags & INOUT)
+ kind = 'I';
+ else
+ kind = 'T';
+ }
+
+ printf("%c%c%d", kind, type, index);
+
+ if (v->flags & SAVEDVAR)
+ putchar('!');
+
+ if (stage >= SHOW_REGS || (v->flags & PREALLOC)) {
+ putchar('(');
+ show_allocation(v->type, v->flags, v->vv.regoff);
+ putchar(')');
+ }
+
+ if (v->type == TYPE_RET && (v->flags & PREALLOC)) {
+ printf("(L%03d)", v->vv.retaddr->nr);
+ }
+}
+
+static void show_variable_array_intern(jitdata *jd, s4 *vars, int n, int stage,
+ bool javalocals)
+{
+ int i;
+ int nr;
+
+ if (vars == NULL) {
+ printf("<null>");
+ return;
+ }
+
+ printf("[");
+ for (i=0; i<n; ++i) {
+ if (i)
+ putchar(' ');
+ if (vars[i] < 0) {
+ if (vars[i] == UNUSED)
+ putchar('-');
+ else if (javalocals) {
+ nr = RETADDR_FROM_JAVALOCAL(vars[i]);
+ printf("ret(L%03d)", nr);
+ }
+ else {
+ printf("<INVALID INDEX:%d>", vars[i]);
+ }
+ }
+ else
+ show_variable_intern(jd, vars[i], stage);
+ }
+ printf("]");
+}
+
+void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
+{
+ show_variable_array_intern(jd, vars, n, stage, false);
+}
+
+void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage)
+{
+ show_variable_array_intern(jd, vars, n, stage, true);
+}
+
+void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
+{
+ u2 opcode;
+ branch_target_t *table;
+ lookup_target_t *lookup;
+ constant_FMIref *fmiref;
+ s4 *argp;
+ s4 i;
+
+ /* get the opcode and the condition */
+
+ opcode = iptr->opc;
+
+ printf("%s ", icmd_table[opcode].name);
+
+ if (stage < SHOW_PARSE)
+ return;
+
+ if (deadcode)
+ stage = SHOW_PARSE;
+
+ /* Print the condition for conditional instructions. */
+
+ /* XXX print condition from flags */
+
+ if (iptr->flags.bits & INS_FLAG_UNRESOLVED)
+ printf("(UNRESOLVED) ");
+
+ switch (opcode) {
+
+ case ICMD_POP:
+ case ICMD_CHECKNULL:
+ SHOW_S1(iptr);
+ break;
+
+ /* unary */
+ case ICMD_ARRAYLENGTH:
+ case ICMD_INEG:
+ case ICMD_LNEG:
+ case ICMD_FNEG:
+ case ICMD_DNEG:
+ case ICMD_I2L:
+ case ICMD_I2F:
+ case ICMD_I2D:
+ case ICMD_L2I:
+ case ICMD_L2F:
+ case ICMD_L2D:
+ case ICMD_F2I:
+ case ICMD_F2L:
+ case ICMD_F2D:
+ case ICMD_D2I:
+ case ICMD_D2L:
+ case ICMD_D2F:
+ case ICMD_INT2BYTE:
+ case ICMD_INT2CHAR:
+ case ICMD_INT2SHORT:
+ SHOW_S1(iptr);
+ SHOW_DST(iptr);
+ break;
+
+ /* binary */
+ case ICMD_IADD:
+ case ICMD_LADD:
+ case ICMD_FADD:
+ case ICMD_DADD:
+ case ICMD_ISUB:
+ case ICMD_LSUB:
+ case ICMD_FSUB:
+ case ICMD_DSUB:
+ case ICMD_IMUL:
+ case ICMD_LMUL:
+ case ICMD_FMUL:
+ case ICMD_DMUL:
+ case ICMD_IDIV:
+ case ICMD_LDIV:
+ case ICMD_FDIV:
+ case ICMD_DDIV:
+ case ICMD_IREM:
+ case ICMD_LREM:
+ case ICMD_FREM:
+ case ICMD_DREM:
+ case ICMD_ISHL:
+ case ICMD_LSHL:
+ case ICMD_ISHR:
+ case ICMD_LSHR:
+ case ICMD_IUSHR:
+ case ICMD_LUSHR:
+ case ICMD_IAND:
+ case ICMD_LAND:
+ case ICMD_IOR:
+ case ICMD_LOR:
+ case ICMD_IXOR:
+ case ICMD_LXOR:
+ case ICMD_LCMP:
+ case ICMD_FCMPL:
+ case ICMD_FCMPG:
+ case ICMD_DCMPL:
+ case ICMD_DCMPG:
+ SHOW_S1(iptr);
+ SHOW_S2(iptr);
+ SHOW_DST(iptr);
+ break;
+
+ /* binary/const INT */
+ case ICMD_IADDCONST:
+ case ICMD_ISUBCONST:
+ case ICMD_IMULCONST:
+ case ICMD_IMULPOW2:
+ case ICMD_IDIVPOW2:
+ case ICMD_IREMPOW2:
+ case ICMD_IANDCONST:
+ case ICMD_IORCONST:
+ case ICMD_IXORCONST:
+ case ICMD_ISHLCONST:
+ case ICMD_ISHRCONST:
+ case ICMD_IUSHRCONST:
+ case ICMD_LSHLCONST:
+ case ICMD_LSHRCONST:
+ case ICMD_LUSHRCONST:
+ SHOW_S1(iptr);
+ SHOW_INT_CONST(iptr->sx.val.i);
+ SHOW_DST(iptr);
+ break;
+
+ /* ?ASTORECONST (trinary/const INT) */
+ case ICMD_IASTORECONST:
+ case ICMD_BASTORECONST:
+ case ICMD_CASTORECONST:
+ case ICMD_SASTORECONST:
+ SHOW_S1(iptr);
+ SHOW_S2(iptr);
+ SHOW_INT_CONST(iptr->sx.s23.s3.constval);
+ break;
+
+ /* const INT */
+ case ICMD_ICONST:
+ SHOW_INT_CONST(iptr->sx.val.i);
+ SHOW_DST(iptr);
+ break;
+
+ /* binary/const LNG */
+ case ICMD_LADDCONST:
+ case ICMD_LSUBCONST:
+ case ICMD_LMULCONST:
+ case ICMD_LMULPOW2:
+ case ICMD_LDIVPOW2:
+ case ICMD_LREMPOW2:
+ case ICMD_LANDCONST:
+ case ICMD_LORCONST:
+ case ICMD_LXORCONST:
+ SHOW_S1(iptr);
+ SHOW_LNG_CONST(iptr->sx.val.l);
+ SHOW_DST(iptr);
+ break;
+
+ /* trinary/const LNG (<= pointer size) */
+ case ICMD_LASTORECONST:
+ SHOW_S1(iptr);
+ SHOW_S2(iptr);
+ SHOW_ADR_CONST(iptr->sx.s23.s3.constval);
+ break;
+
+ /* const LNG */
+ case ICMD_LCONST:
+ SHOW_LNG_CONST(iptr->sx.val.l);
+ SHOW_DST(iptr);
+ break;
+
+ /* const FLT */
+ case ICMD_FCONST:
+ SHOW_FLT_CONST(iptr->sx.val.f);
+ SHOW_DST(iptr);
+ break;
+
+ /* const DBL */
+ case ICMD_DCONST:
+ SHOW_DBL_CONST(iptr->sx.val.d);
+ SHOW_DST(iptr);
+ break;
+
+ /* const ADR */
+ case ICMD_ACONST:
+ if (iptr->flags.bits & INS_FLAG_CLASS) {
+ SHOW_ADR_CONST(iptr->sx.val.anyptr);
+ SHOW_CLASSREF_OR_CLASSINFO(iptr->sx.val.c);
+ }
+ else if (iptr->sx.val.anyptr == NULL) {
+ printf("NULL ");
+ }
+ else {
+ SHOW_ADR_CONST(iptr->sx.val.anyptr);
+ SHOW_STRING(iptr->sx.val.stringconst);
+ }
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_AASTORECONST:
+ SHOW_S1(iptr);
+ SHOW_S2(iptr);
+ printf("%p ", (void*) iptr->sx.s23.s3.constval);
+ break;
+
+ case ICMD_GETFIELD: /* 1 -> 1 */
+ case ICMD_PUTFIELD: /* 2 -> 0 */
+ case ICMD_PUTSTATIC: /* 1 -> 0 */
+ case ICMD_GETSTATIC: /* 0 -> 1 */
+ case ICMD_PUTSTATICCONST: /* 0 -> 0 */
+ case ICMD_PUTFIELDCONST: /* 1 -> 0 */
+ if (opcode != ICMD_GETSTATIC && opcode != ICMD_PUTSTATICCONST) {
+ SHOW_S1(iptr);
+ if (opcode == ICMD_PUTFIELD) {
+ SHOW_S2(iptr);
+ }
+ }
+ INSTRUCTION_GET_FIELDREF(iptr, fmiref);
+ SHOW_FIELD(fmiref);
+
+ if (opcode == ICMD_GETSTATIC || opcode == ICMD_GETFIELD) {
+ SHOW_DST(iptr);
+ }
+ break;
+
+ case ICMD_IINC:
+ SHOW_S1_LOCAL(iptr);
+ SHOW_INT_CONST(iptr->sx.val.i);
+ SHOW_DST_LOCAL(iptr);
+ break;
+
+ case ICMD_IASTORE:
+ case ICMD_SASTORE:
+ case ICMD_BASTORE:
+ case ICMD_CASTORE:
+ case ICMD_LASTORE:
+ case ICMD_DASTORE:
+ case ICMD_FASTORE:
+ case ICMD_AASTORE:
+ SHOW_S1(iptr);
+ SHOW_S2(iptr);
+ SHOW_S3(iptr);
+ break;
+
+ case ICMD_IALOAD:
+ case ICMD_SALOAD:
+ case ICMD_BALOAD:
+ case ICMD_CALOAD:
+ case ICMD_LALOAD:
+ case ICMD_DALOAD:
+ case ICMD_FALOAD:
+ case ICMD_AALOAD:
+ SHOW_S1(iptr);
+ SHOW_S2(iptr);
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_RET:
+ SHOW_S1_LOCAL(iptr);
+ if (stage >= SHOW_STACK) {
+ printf(" ---> L%03d", iptr->dst.block->nr);
+ }
+ break;
+
+ case ICMD_ILOAD:
+ case ICMD_LLOAD:
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ case ICMD_ALOAD:
+ SHOW_S1_LOCAL(iptr);
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
+ case ICMD_ASTORE:
+ SHOW_S1(iptr);
+ SHOW_DST_LOCAL(iptr);
+ if (stage >= SHOW_STACK && iptr->sx.s23.s3.javaindex != UNUSED)
+ printf(" (javaindex %d)", iptr->sx.s23.s3.javaindex);
+ if (iptr->flags.bits & INS_FLAG_RETADDR) {
+ printf(" (retaddr L%03d)", RETADDR_FROM_JAVALOCAL(iptr->sx.s23.s2.retaddrnr));
+ }
+ break;
+
+ case ICMD_NEW:
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_NEWARRAY:
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_ANEWARRAY:
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_MULTIANEWARRAY:
+ if (stage >= SHOW_STACK) {
+ argp = iptr->sx.s23.s2.args;
+ i = iptr->s1.argcount;
+ while (i--) {
+ SHOW_VARIABLE(*(argp++));
+ }
+ }
+ else {
+ printf("argcount=%d ", iptr->s1.argcount);
+ }
+ class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
+ putchar(' ');
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_CHECKCAST:
+ SHOW_S1(iptr);
+ class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
+ putchar(' ');
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_INSTANCEOF:
+ SHOW_S1(iptr);
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_INLINE_START:
+ case ICMD_INLINE_END:
+ case ICMD_INLINE_BODY:
+#if defined(ENABLE_INLINING)
+ {
+ insinfo_inline *ii = iptr->sx.s23.s3.inlineinfo;
+ show_inline_info(jd, ii, opcode, stage);
+ }
+#endif
+ break;
+
+ case ICMD_BUILTIN:
+ if (stage >= SHOW_STACK) {
+ argp = iptr->sx.s23.s2.args;
+ i = iptr->s1.argcount;
+ while (i--) {
+ if ((iptr->s1.argcount - 1 - i) == iptr->sx.s23.s3.bte->md->paramcount)
+ printf(" pass-through: ");
+ SHOW_VARIABLE(*(argp++));
+ }
+ }
+ printf("%s ", iptr->sx.s23.s3.bte->cname);
+ if (iptr->sx.s23.s3.bte->md->returntype.type != TYPE_VOID) {
+ SHOW_DST(iptr);
+ }
+ break;
+
+ case ICMD_INVOKEVIRTUAL:
+ case ICMD_INVOKESPECIAL:
+ case ICMD_INVOKESTATIC:
+ case ICMD_INVOKEINTERFACE:
+ if (stage >= SHOW_STACK) {
+ methoddesc *md;
+ INSTRUCTION_GET_METHODDESC(iptr, md);
+ argp = iptr->sx.s23.s2.args;
+ i = iptr->s1.argcount;
+ while (i--) {
+ if ((iptr->s1.argcount - 1 - i) == md->paramcount)
+ printf(" pass-through: ");
+ SHOW_VARIABLE(*(argp++));
+ }
+ }
+ INSTRUCTION_GET_METHODREF(iptr, fmiref);
+ method_methodref_print(fmiref);
+ if (fmiref->parseddesc.md->returntype.type != TYPE_VOID) {
+ putchar(' ');
+ SHOW_DST(iptr);
+ }
+ break;
+
+ case ICMD_IFEQ:
+ case ICMD_IFNE:
+ case ICMD_IFLT:
+ case ICMD_IFGE:
+ case ICMD_IFGT:
+ case ICMD_IFLE:
+ SHOW_S1(iptr);
+ SHOW_INT_CONST(iptr->sx.val.i);
+ SHOW_TARGET(iptr->dst);
+ break;
+
+ case ICMD_IF_LEQ:
+ case ICMD_IF_LNE:
+ case ICMD_IF_LLT:
+ case ICMD_IF_LGE:
+ case ICMD_IF_LGT:
+ case ICMD_IF_LLE:
+ SHOW_S1(iptr);
+ SHOW_LNG_CONST(iptr->sx.val.l);
+ SHOW_TARGET(iptr->dst);
+ break;
+
+ case ICMD_GOTO:
+ SHOW_TARGET(iptr->dst);
+ break;
+
+ case ICMD_JSR:
+ SHOW_TARGET(iptr->sx.s23.s3.jsrtarget);
+ SHOW_DST(iptr);
+ break;
+
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+ SHOW_S1(iptr);
+ SHOW_TARGET(iptr->dst);
+ break;
+
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+
+ case ICMD_IF_LCMPEQ:
+ case ICMD_IF_LCMPNE:
+ case ICMD_IF_LCMPLT:
+ case ICMD_IF_LCMPGE:
+ case ICMD_IF_LCMPGT:
+ case ICMD_IF_LCMPLE:
+
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ SHOW_S1(iptr);
+ SHOW_S2(iptr);
+ SHOW_TARGET(iptr->dst);
+ break;
+
+ case ICMD_TABLESWITCH:
+ SHOW_S1(iptr);
+ table = iptr->dst.table;
+
+ i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
+
+ printf("high=%d low=%d count=%d\n", iptr->sx.s23.s3.tablehigh, iptr->sx.s23.s2.tablelow, i);
+ while (--i >= 0) {
+ printf("\t\t%d --> ", (int) (table - iptr->dst.table));
+ printf("L%03d\n", table->block->nr);
+ table++;
+ }
+
+ break;
+
+ case ICMD_LOOKUPSWITCH:
+ SHOW_S1(iptr);
+
+ printf("count=%d, default=L%03d\n",
+ iptr->sx.s23.s2.lookupcount,
+ iptr->sx.s23.s3.lookupdefault.block->nr);
+
+ lookup = iptr->dst.lookup;
+ i = iptr->sx.s23.s2.lookupcount;
+
+ while (--i >= 0) {
+ printf("\t\t%d --> L%03d\n",
+ lookup->value,
+ lookup->target.block->nr);
+ lookup++;
+ }
+ break;
+
+ case ICMD_FRETURN:
+ case ICMD_IRETURN:
+ case ICMD_DRETURN:
+ case ICMD_LRETURN:
+ SHOW_S1(iptr);
+ break;
+
+ case ICMD_ARETURN:
+ case ICMD_ATHROW:
+ SHOW_S1(iptr);
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ /* XXX this needs more work */
+#if 0
+ unresolved_class_debug_dump(iptr->sx.s23.s2.uc, stdout);
+#endif
+ }
+ break;
+
+ case ICMD_COPY:
+ case ICMD_MOVE:
+ SHOW_S1(iptr);
+ SHOW_DST(iptr);
+ break;
+ 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);
+}
+#endif /* !defined(NDEBUG) */
+
+/* Debug output filtering */
+
+#if defined(ENABLE_DEBUG_FILTER)
+
+#if !defined(ENABLE_THREADS)
+u2 _no_threads_filterverbosecallctr[2] = { 0, 0 };
+#endif
+
+struct show_filter {
+ /* Boolean indicating if filter is enabled. */
+ u1 enabled;
+ /* Regular expression the method name is matched against */
+ regex_t regex;
+ /* Flag set on m->filtermatches if regex matches */
+ u1 flag;
+};
+
+typedef struct show_filter show_filter_t;
+
+#define SHOW_FILTERS_SIZE 3
+
+/* Array of filters applyed on a method */
+static struct show_filter show_filters[SHOW_FILTERS_SIZE];
+
+static void show_filter_init(show_filter_t *cf, const char *str, u1 flag, u1 default_flag, const char *description) {
+ int err;
+ char err_buf[128];
+
+ if (str) {
+ err = regcomp(&cf->regex, str, REG_EXTENDED | REG_NOSUB);
+ if (err != 0) {
+ regerror(err, &cf->regex, err_buf, sizeof(err_buf));
+ vm_abort(
+ "Invalid value given for %s: `%s' (%s).",
+ description, str, err_buf
+ );
+ }
+ cf->flag = flag;
+ cf->enabled = 1;
+ } else {
+ cf->flag = default_flag;
+ cf->enabled = 0;
+ }
+}
+
+void show_filters_init(void) {
+
+ show_filter_init(
+ show_filters + 0,
+ opt_filter_verbosecall_include,
+ SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
+ SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
+ "verbose call include filter"
+ );
+
+ show_filter_init(
+ show_filters + 1,
+ opt_filter_verbosecall_exclude,
+ SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE,
+ 0,
+ "verbose call exclude filter"
+ );
+
+ show_filter_init(
+ show_filters + 2,
+ opt_filter_show_method,
+ SHOW_FILTER_FLAG_SHOW_METHOD,
+ SHOW_FILTER_FLAG_SHOW_METHOD,
+ "show method filter"
+ );
+}
+
+/*
+
+ (Pseudo)State machine:
+
+ States are INITIAL, INCLUDE1, INCLUDE2, ..., EXCLUDE1, ..., EXCLUDE2, ...
+
+ Enter Enter
+ Enter Include Include
+ Exclude | | | |
+ | | Enter Enter Enter | | Enter | |
+ | | Include Include Exclude | | Exclude | |
+ | v ---------> ----------> ----------> | v ----------> | v
+INITIAL INCLUDE1 INCLUDE2 EXCLUDE1 EXCLUDE2
+ | ^ <--------- <---------- <---------- | ^ <---------- | ^
+ | | Exit Exit Exit | | Exit | |
+ | | Include Include Exclude | | Exclude | |
+ | | | | | |
+ Exit Exit Exit
+ Exclude Include Include
+
+ Verbose call scope is active if we are in a INCLUDE state.
+
+ State encoding:
+
+ INITIAL: ctr[0] == 0, ctr[1] == 0
+ INCLUDEN: ctr[1] == N, ctr[1] == 0
+ EXCLUDEN: ctr[1] == N
+*/
+
+void show_filters_apply(methodinfo *m) {
+ int i;
+ int res;
+ char *method_name;
+ s4 len;
+
+ /* compose full name of method */
+
+ len =
+ utf_bytes(m->clazz->name) +
+ 1 +
+ utf_bytes(m->name) +
+ utf_bytes(m->descriptor) +
+ 1;
+
+ method_name = MNEW(char, len);
+
+ utf_cat_classname(method_name, m->clazz->name);
+ strcat(method_name, ".");
+ utf_cat(method_name, m->name);
+ utf_cat(method_name, m->descriptor);
+
+ /* reset all flags */
+
+ m->filtermatches = 0;
+
+ for (i = 0; i < SHOW_FILTERS_SIZE; ++i) {
+ if (show_filters[i].enabled) {
+
+ res = regexec(&show_filters[i].regex, method_name, 0, NULL, 0);
+
+ if (res == 0) {
+ m->filtermatches |= show_filters[i].flag;
+ }
+ } else {
+ /* Default is to show all */
+ m->filtermatches |= show_filters[i].flag;
+ }
+ }
+
+ // Release memory.
+ MFREE(method_name, char, len);
+}
+
+#define STATE_IS_INITIAL() ((FILTERVERBOSECALLCTR[0] == 0) && (FILTERVERBOSECALLCTR[1] == 0))
+#define STATE_IS_INCLUDE() ((FILTERVERBOSECALLCTR[0] > 0) && (FILTERVERBOSECALLCTR[1] == 0))
+#define STATE_IS_EXCLUDE() (FILTERVERBOSECALLCTR[1] > 0)
+#define EVENT_INCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE)
+#define EVENT_EXCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE)
+#define TRANSITION_NEXT_INCLUDE() ++FILTERVERBOSECALLCTR[0]
+#define TRANSITION_PREV_INCLUDE() --FILTERVERBOSECALLCTR[0]
+#define TRANSITION_NEXT_EXCLUDE() ++FILTERVERBOSECALLCTR[1]
+#define TRANSITION_PREV_EXCLUDE() --FILTERVERBOSECALLCTR[1]
+
+#if 0
+void dump_state() {
+ if (STATE_IS_INITIAL()) printf("<INITIAL>\n");
+ else if (STATE_IS_INCLUDE()) printf("<INCLUDE %hd>\n", FILTERVERBOSECALLCTR[0]);
+ else if (STATE_IS_EXCLUDE()) printf("<EXCLUDE %hd>\n", FILTERVERBOSECALLCTR[1]);
+}
+#endif
+
+int show_filters_test_verbosecall_enter(methodinfo *m) {
+
+ int force_show = 0;
+
+ if (STATE_IS_INITIAL()) {
+ if (EVENT_INCLUDE()) {
+ TRANSITION_NEXT_INCLUDE();
+ }
+ } else if (STATE_IS_INCLUDE()) {
+ if (EVENT_EXCLUDE()) {
+ TRANSITION_NEXT_EXCLUDE();
+ /* just entered exclude, show this method */
+ force_show = 1;
+ } else if (EVENT_INCLUDE()) {
+ TRANSITION_NEXT_INCLUDE();
+ }
+ } else if (STATE_IS_EXCLUDE()) {
+ if (EVENT_EXCLUDE()) {
+ TRANSITION_NEXT_EXCLUDE();
+ }
+ }
+
+ return STATE_IS_INCLUDE() || force_show;
+}
+
+int show_filters_test_verbosecall_exit(methodinfo *m) {
+
+ int force_show = 0;
+
+ if (m) {
+ if (STATE_IS_INCLUDE()) {
+ if (EVENT_INCLUDE()) {
+ TRANSITION_PREV_INCLUDE();
+ /* just entered initial, show this method */
+ if (STATE_IS_INITIAL()) force_show = 1;
+ }
+ } else if (STATE_IS_EXCLUDE()) {
+ if (EVENT_EXCLUDE()) {
+ TRANSITION_PREV_EXCLUDE();
+ }
+ }
+ }
+
+ return STATE_IS_INCLUDE() || force_show;
+}
+
+#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/show.h - showing the intermediate representation
-
- 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.
-
-*/
-
-
-#ifndef _SHOW_H
-#define _SHOW_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/jit/jit.h"
-
-
-/* compiler stage defines *****************************************************/
-
-#define SHOW_INSTRUCTIONS 0
-#define SHOW_PARSE 1
-#define SHOW_STACK 2
-#define SHOW_CFG 3
-#define SHOW_REGS 4
-#define SHOW_CODE 5
-
-
-/* function prototypes ********************************************************/
-
-#if !defined(NDEBUG)
-extern char *show_jit_type_names[];
-extern char show_jit_type_letters[];
-
-bool show_init(void);
-
-void show_method(jitdata *jd, int stage);
-void show_basicblock(jitdata *jd, basicblock *bptr, int stage);
-void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage);
-void show_variable(jitdata *jd, s4 index, int stage);
-void show_variable_array(jitdata *jd, s4 *vars, int n, int stage);
-void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage);
-void show_allocation(s4 type, s4 flags, s4 regoff);
-#endif /* !defined(NDEBUG) */
-
-/* Debug output filtering */
-
-#if defined(ENABLE_DEBUG_FILTER)
-void show_filters_init(void);
-#define SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE 0x01
-#define SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE 0x02
-#define SHOW_FILTER_FLAG_SHOW_METHOD 0x04
-void show_filters_apply(methodinfo *m);
-int show_filters_test_verbosecall_enter(methodinfo *m);
-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
- * 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/show.hpp - showing the intermediate representation
+
+ 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.
+
+*/
+
+
+#ifndef _SHOW_HPP
+#define _SHOW_HPP
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/jit/jit.hpp"
+
+
+/* compiler stage defines *****************************************************/
+
+#define SHOW_INSTRUCTIONS 0
+#define SHOW_PARSE 1
+#define SHOW_STACK 2
+#define SHOW_CFG 3
+#define SHOW_REGS 4
+#define SHOW_CODE 5
+
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(NDEBUG)
+extern const char *show_jit_type_names[];
+extern const char show_jit_type_letters[];
+
+bool show_init(void);
+
+void show_method(jitdata *jd, int stage);
+void show_basicblock(jitdata *jd, basicblock *bptr, int stage);
+void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage);
+void show_variable(jitdata *jd, s4 index, int stage);
+void show_variable_array(jitdata *jd, s4 *vars, int n, int stage);
+void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage);
+void show_allocation(s4 type, s4 flags, s4 regoff);
+#endif /* !defined(NDEBUG) */
+
+/* Debug output filtering */
+
+#if defined(ENABLE_DEBUG_FILTER)
+void show_filters_init(void);
+#define SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE 0x01
+#define SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE 0x02
+#define SHOW_FILTER_FLAG_SHOW_METHOD 0x04
+void show_filters_apply(methodinfo *m);
+int show_filters_test_verbosecall_enter(methodinfo *m);
+int show_filters_test_verbosecall_exit(methodinfo *m);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _SHOW_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:
+ */
\
md-abi.c \
md-abi.h \
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 1
#define SUPPORT_LONG 1
#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/patcher.h"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/sparc64/solaris/macro_rename.h"
-/* src/vm/jit/sparc64/codegen.h - code generation macros and definitions for
- Sparc64
+/* src/vm/jit/sparc64/codegen.h - code generation macros and
+ definitions for SPARC64
- 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"
#include "vm/types.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "md-abi.h" /* for INT_NATARG_CNT */
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 4 * 4
-
-
/* additional functions and macros to generate code ***************************/
#include "mm/memory.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.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/replace.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/sparc64/solaris/macro_rename.h"
--- /dev/null
+/* src/vm/jit/sparc64/md-stubs.hpp - SPARC64 JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a SPARC64 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 4 * 4;
+}
+
+#endif // _MD_STUBS_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 "vm/jit/sparc64/md-abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
/* assembler function prototypes **********************************************/
#include "vm/types.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
/* md_stacktrace_get_returnaddress *********************************************
#include "vm/jit/sparc64/md.h"
#include "vm/jit/sparc64/md-abi.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/exceptions.hpp"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/initialize.h"
#include "vm/options.h"
#include "vm/references.h"
if (!(fi = resolve_field_eager(uf)))
return false;
- /* if we show disassembly, we have to skip the nop's */
+ /* store the patched instruction on the stack */
- if (opt_shownops) {
- /* patch the field's offset into the instruction */
-
- *((u4 *) (ra + 2 * 4)) |= (s2) (fi->offset & 0x00001fff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 2 * 4, 1 * 4);
- }
- else {
- /* otherwise store the patched instruction on the stack */
-
- *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
- }
+ *((u4 *) (sp + 3 * 8)) |= (s2) (fi->offset & 0x00001fff);
return true;
}
if (!(m = resolve_method_eager(um)))
return false;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops) {
- ra = ra + PATCHER_CALL_SIZE;
+ /* patch vftbl index */
- /* patch vftbl index */
-
- *((s4 *) (ra + 1 * 4)) |=
- (s4) ((OFFSET(vftbl_t, table[0]) +
- sizeof(methodptr) * m->vftblindex) & 0x00001fff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 1 * 4, 1 * 4);
- }
- else {
- /* patch vftbl index */
-
- *((s4 *) (sp + 3 * 8 + 4)) |=
- (s4) ((OFFSET(vftbl_t, table[0]) +
- sizeof(methodptr) * m->vftblindex) & 0x00001fff);
- }
+ *((s4 *) (sp + 3 * 8 + 4)) |=
+ (s4) ((OFFSET(vftbl_t, table[0]) +
+ sizeof(methodptr) * m->vftblindex) & 0x00001fff);
return true;
}
if (!(m = resolve_method_eager(um)))
return false;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops) {
- ra = ra + PATCHER_CALL_SIZE;
+ /* patch interfacetable index */
- /* patch interfacetable index */
-
- *((s4 *) (ra + 1 * 4)) |=
- (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
-
- /* patch method offset */
-
- *((s4 *) (ra + 2 * 4)) |=
- (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
-
- /* synchronize instruction cache */
-
- md_icacheflush(ra + 1 * 4, 2 * 4);
- }
- else {
- /* patch interfacetable index */
-
- *((s4 *) (sp + 3 * 8 + 4)) |=
- (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
+ *((s4 *) (sp + 3 * 8 + 4)) |=
+ (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
+ sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
- /* patch method offset */
+ /* patch method offset */
- *((s4 *) (ra + 2 * 4)) |=
- (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
+ *((s4 *) (ra + 2 * 4)) |=
+ (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
- /* synchronize instruction cache */
+ /* synchronize instruction cache */
- md_icacheflush(ra + 2 * 4, 1 * 4);
- }
+ md_icacheflush(ra + 2 * 4, 1 * 4);
return true;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch super class index */
*((s4 *) (ra + 2 * 4)) |= (s4) (-(c->index) & 0x00001fff);
/* synchronize instruction cache */
- if (opt_shownops)
- md_icacheflush(ra - 2 * 4, (6 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
- else
- md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
+ md_icacheflush(ra, (4 + EXCEPTION_CHECK_INSTRUCTIONS) * 4);
return true;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
/* patch super class index */
*((s4 *) (ra + 2 * 4)) |= (s4) ((c->index) & 0x00001fff);
/* synchronize instruction cache */
- if (opt_shownops)
- md_icacheflush(ra - PATCHER_CALL_SIZE * 4, 8 * 4);
- else
- md_icacheflush(ra, 6 * 4);
+ md_icacheflush(ra, 6 * 4);
return true;
}
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
#include "toolbox/logging.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/cfg.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#if defined(ENABLE_DISASSEMBLER)
# include "vm/jit/disass.h"
#endif
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/stack.h"
#if 0
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/reg.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
bool stack_init(void);
bool stack_analyse(jitdata *jd);
void stack_javalocals_store(instruction *iptr, s4 *javalocals);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _STACK_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/array.hpp"
+#include "vm/jit/builtin.hpp"
#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/loader.hpp"
#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/codegen-common.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/methodheader.h"
#include "vm/jit/methodtree.h"
/* Get the line number. */
- linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
+ linenumber = ste->code->linenumbertable->find(&m, ste->pc);
stacktrace_print_entry(m, linenumber);
}
code = tmpsfi.code;
m = code->m;
- /* Get the line number. */
-
- linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+ // Get the line number.
+ linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
stacktrace_print_entry(m, linenumber);
}
code = tmpsfi.code;
m = code->m;
- /* Get the line number. */
-
- linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+ // Get the line number.
+ linenumber = code->linenumbertable->find(&m, tmpsfi.xpc);
stacktrace_print_entry(m, linenumber);
}
#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;
#include "vm/class.h"
#include "vm/global.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
/* stackframeinfo **************************************************************
/* function prototypes ********************************************************/
+// FIXME Use C-linkage for now.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void stacktrace_stackframeinfo_add(stackframeinfo_t* sfi, void* pv, void* sp, void* ra, void* xpc);
void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi);
#endif
#if defined(ENABLE_INTRP)
-u1 *intrp_md_stacktrace_get_returnaddress(u1 *sp, u4 framesize);
+void* intrp_md_stacktrace_get_returnaddress(void* sp, int32_t framesize);
#endif
#if defined(ENABLE_CYCLES_STATS)
--- /dev/null
+/* src/vm/jit/stubs.cpp - JIT stubs
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ 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 machine dependent headers.
+#include "md.h"
+
+#include "mm/dumpmemory.hpp"
+
+#include "vm/method.h"
+#include "vm/options.h"
+
+#include "vm/jit/abi.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/show.hpp"
+#include "vm/jit/stubs.hpp"
+
+
+/**
+ * Wrapper for codegen_emit_stub_compiler.
+ *
+ * @param m Method object.
+ *
+ * @return Pointer to the compiler stub code.
+ */
+void* CompilerStub::generate(methodinfo *m)
+{
+ jitdata *jd;
+ codegendata *cd;
+ ptrint *d; /* pointer to data memory */
+ u1 *c; /* pointer to code memory */
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* allocate required data structures */
+
+ jd = (jitdata*) DumpMemory::allocate(sizeof(jitdata));
+
+ jd->m = m;
+ jd->cd = (codegendata*) DumpMemory::allocate(sizeof(codegendata));
+ jd->flags = 0;
+
+ /* get required compiler data */
+
+ cd = jd->cd;
+
+#if !defined(JIT_COMPILER_VIA_SIGNAL)
+ /* allocate code memory */
+
+ c = CNEW(u1, 3 * SIZEOF_VOID_P + get_code_size());
+
+ /* set pointers correctly */
+
+ d = (ptrint *) c;
+
+ cd->mcodebase = c;
+
+ c = c + 3 * SIZEOF_VOID_P;
+ cd->mcodeptr = c;
+
+ /* NOTE: The codeinfo pointer is actually a pointer to the
+ methodinfo (this fakes a codeinfo structure). */
+
+ d[0] = (ptrint) asm_call_jit_compiler;
+ d[1] = (ptrint) m;
+ d[2] = (ptrint) &d[1]; /* fake code->m */
+
+ /* call the emit function */
+
+ codegen_emit_stub_compiler(jd);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_cstub_len += 3 * SIZEOF_VOID_P + get_code_size();
+#endif
+
+ /* flush caches */
+
+ md_cacheflush(cd->mcodebase, 3 * SIZEOF_VOID_P + get_code_size());
+#else
+ /* Allocate code memory. */
+
+ c = CNEW(uint8_t, 2 * SIZEOF_VOID_P + get_code_size());
+
+ /* Set pointers correctly. */
+
+ d = (ptrint *) c;
+
+ cd->mcodebase = c;
+
+ c = c + 2 * SIZEOF_VOID_P;
+ cd->mcodeptr = c;
+
+ /* NOTE: The codeinfo pointer is actually a pointer to the
+ methodinfo (this fakes a codeinfo structure). */
+
+ d[0] = (ptrint) m;
+ d[1] = (ptrint) &d[0]; /* fake code->m */
+
+ /* Emit the trap instruction. */
+
+ emit_trap_compiler(cd);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_cstub_len += 2 * SIZEOF_VOID_P + get_code_size();
+#endif
+
+ /* Flush caches. */
+
+ md_cacheflush(cd->mcodebase, 2 * SIZEOF_VOID_P + get_code_size());
+#endif
+
+ /* return native stub code */
+
+ return c;
+}
+
+
+/**
+ * Free a compiler stub from memory.
+ *
+ * @param
+ */
+void CompilerStub::remove(void* stub)
+{
+ // Pass size 1 to keep the intern function happy.
+ CFREE(stub, 1);
+}
+
+
+/* codegen_disassemble_nativestub **********************************************
+
+ Disassembles the generated builtin or native stub.
+
+*******************************************************************************/
+
+#if defined(ENABLE_DISASSEMBLER)
+static void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
+{
+ printf("Stub code: ");
+ if (m->clazz != NULL)
+ utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
+ else
+ printf("NULL");
+ printf(".");
+ utf_fprint_printable_ascii(stdout, m->name);
+ utf_fprint_printable_ascii(stdout, m->descriptor);
+ printf("\nLength: %d\n\n", (s4) (end - start));
+
+ DISASSEMBLE(start, end);
+}
+#endif
+
+
+/**
+ * Wrapper for codegen_emit_stub_native.
+ *
+ * @param m Method object.
+ * @param bte Builtin function structure.
+ */
+void BuiltinStub::generate(methodinfo* m, builtintable_entry* bte)
+{
+ jitdata *jd;
+ codeinfo *code;
+ int skipparams;
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* Create JIT data structure. */
+
+ jd = jit_jitdata_new(m);
+
+ /* Get required compiler data. */
+
+ code = jd->code;
+
+ /* Stubs are non-leaf methods. */
+
+ code_unflag_leafmethod(code);
+
+ /* setup code generation stuff */
+
+ codegen_setup(jd);
+
+ /* Set the number of native arguments we need to skip. */
+
+ skipparams = 0;
+
+ /* generate the code */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp) {
+# endif
+ assert(bte->fp != NULL);
+ codegen_emit_stub_native(jd, bte->md, bte->fp, skipparams);
+# if defined(ENABLE_INTRP)
+ }
+# endif
+#endif
+
+ /* reallocate the memory and finish the code generation */
+
+ codegen_finish(jd);
+
+ /* set the stub entry point in the builtin table */
+
+ bte->stub = code->entrypoint;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_stub_native += code->mcodelength;
+#endif
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+ /* disassemble native stub */
+
+ if (opt_DisassembleStubs) {
+ codegen_disassemble_stub(m,
+ (u1 *) (ptrint) code->entrypoint,
+ (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+
+ /* show data segment */
+
+ if (opt_showddatasegment)
+ dseg_display(jd);
+ }
+#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
+}
+
+
+/**
+ * Wrapper for codegen_emit_stub_native.
+ *
+ * @param m Method object of the native function.
+ * @param f Native function pointer.
+ *
+ * @return The codeinfo representing the stub code.
+ */
+codeinfo* NativeStub::generate(methodinfo* m, functionptr f)
+{
+ jitdata *jd;
+ codeinfo *code;
+ methoddesc *md;
+ methoddesc *nmd;
+ int skipparams;
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ /* Create JIT data structure. */
+
+ jd = jit_jitdata_new(m);
+
+ /* Get required compiler data. */
+
+ code = jd->code;
+
+ /* Stubs are non-leaf methods. */
+
+ code_unflag_leafmethod(code);
+
+ /* set the flags for the current JIT run */
+
+#if defined(ENABLE_PROFILING)
+ if (opt_prof)
+ jd->flags |= JITDATA_FLAG_INSTRUMENT;
+#endif
+
+ if (opt_verbosecall)
+ jd->flags |= JITDATA_FLAG_VERBOSECALL;
+
+ /* setup code generation stuff */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ reg_setup(jd);
+#endif
+
+ codegen_setup(jd);
+
+ /* create new method descriptor with additional native parameters */
+
+ md = m->parseddesc;
+
+ /* Set the number of native arguments we need to skip. */
+
+ if (m->flags & ACC_STATIC)
+ skipparams = 2;
+ else
+ skipparams = 1;
+
+ nmd = (methoddesc*) DumpMemory::allocate(sizeof(methoddesc) - sizeof(typedesc) +
+ md->paramcount * sizeof(typedesc) +
+ skipparams * sizeof(typedesc));
+
+ nmd->paramcount = md->paramcount + skipparams;
+
+ nmd->params = (paramdesc*) DumpMemory::allocate(sizeof(paramdesc) * nmd->paramcount);
+
+ nmd->paramtypes[0].type = TYPE_ADR; /* add environment pointer */
+
+ if (m->flags & ACC_STATIC)
+ nmd->paramtypes[1].type = TYPE_ADR; /* add class pointer */
+
+ MCOPY(nmd->paramtypes + skipparams, md->paramtypes, typedesc,
+ md->paramcount);
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ /* pre-allocate the arguments for the native ABI */
+
+ md_param_alloc_native(nmd);
+#endif
+
+ /* generate the code */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ intrp_createnativestub(f, jd, nmd);
+ else
+# endif
+ codegen_emit_stub_native(jd, nmd, f, skipparams);
+#else
+ intrp_createnativestub(f, jd, nmd);
+#endif
+
+ /* reallocate the memory and finish the code generation */
+
+ codegen_finish(jd);
+
+#if defined(ENABLE_STATISTICS)
+ /* must be done after codegen_finish() */
+
+ if (opt_stat)
+ size_stub_native += code->mcodelength;
+#endif
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+ /* disassemble native stub */
+
+ if (opt_DisassembleStubs) {
+# if defined(ENABLE_DEBUG_FILTER)
+ if (m->filtermatches & SHOW_FILTER_FLAG_SHOW_METHOD)
+# endif
+ {
+ codegen_disassemble_stub(m,
+ (u1 *) (ptrint) code->entrypoint,
+ (u1 *) (ptrint) code->entrypoint + (code->mcodelength - jd->cd->dseglen));
+
+ /* show data segment */
+
+ if (opt_showddatasegment)
+ dseg_display(jd);
+ }
+ }
+#endif /* !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) */
+
+ /* return native stub code */
+
+ return code;
+}
+
+
+/**
+ * Free a native stub from memory.
+ *
+ * @param stub Pointer to stub memory.
+ */
+void NativeStub::remove(void* stub)
+{
+ // Pass size 1 to keep the intern function happy.
+ CFREE(stub, 1);
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+ void* CompilerStub_generate(methodinfo* m) { return CompilerStub::generate(m); }
+ void CompilerStub_remove(void* stub) { CompilerStub::remove(stub); }
+
+ void BuiltinStub_generate(methodinfo* m, builtintable_entry* bte) { BuiltinStub::generate(m, bte); }
+
+ void NativeStub_remove(void* stub) { NativeStub::remove(stub); }
+}
+
+
+/*
+ * These 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/stubs.hpp - JIT stubs
+
+ 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 _STUBS_HPP
+#define _STUBS_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/method.h"
+
+#include "vm/jit/code.hpp"
+
+
+#ifdef __cplusplus
+
+/**
+ * Class for compiler stub generation.
+ */
+class CompilerStub {
+public:
+ static inline int get_code_size();
+
+ static void* generate(methodinfo* m);
+ static void remove(void* stub);
+};
+
+
+/**
+ * Class for builtin stub generation.
+ */
+class BuiltinStub {
+public:
+ static void generate(methodinfo* m, builtintable_entry* bte);
+};
+
+
+/**
+ * Class for native stub generation.
+ */
+class NativeStub {
+public:
+ static codeinfo* generate(methodinfo* m, functionptr f);
+ static void remove(void* stub);
+};
+
+
+// Include machine dependent implementation.
+#include "md-stubs.hpp"
+
+#else
+
+// Legacy C interface.
+
+void* CompilerStub_generate(methodinfo* m);
+void* CompilerStub_remove(void* stub);
+void BuiltinStub_generate(methodinfo* m, builtintable_entry* bte);
+void NativeStub_remove(void* stub);
+
+#endif
+
+#endif // _STUBS_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 "native/jni.h"
#include "native/llni.h"
#include "threads/thread.hpp"
#include "vm/string.hpp"
#include "vm/utf8.h"
-#include "vm/jit/argument.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/argument.hpp"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/trace.hpp"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#if !defined(NDEBUG)
/* Cast to java.lang.Object. */
- o = (java_object_t *) (ptrint) imu.l;
+ o = (java_handle_t*) (uintptr_t) imu.l;
/* Check return argument for java.lang.Class or
java.lang.String. */
/* realloc memory for string length */
- logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
+ logtext = (char*) DumpMemory::reallocate(logtext, *logtextlen, *logtextlen + len);
*logtextlen += len;
/* convert to utf8 string and strcat it to the logtext */
/* realloc memory for string length */
- logtext = DMREALLOC(logtext, char, *logtextlen, *logtextlen + len);
+ logtext = (char*) DumpMemory::reallocate(logtext, *logtextlen, *logtextlen + len);
*logtextlen += len;
/* strcat to the 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
strlen("...(255)") +
strlen(")");
- /* allocate memory */
+ // Create new dump memory area.
+ DumpMemoryArea dma;
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
+ // TODO Use a std::string here.
+ logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
TRACEJAVACALLCOUNT++;
log_text(logtext);
- /* release memory */
-
- DRELEASE;
-
TRACEJAVACALLINDENT++;
-
}
/* trace_java_call_exit ********************************************************
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
logtextlen += strlen("->0.4872328470301428 (0x0123456789abcdef)");
- /* allocate memory */
+ // Create new dump memory area.
+ DumpMemoryArea dma;
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
+ // TODO Use a std::string here.
+ logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
/* generate the message */
}
log_text(logtext);
-
- /* release memory */
-
- DRELEASE;
}
char *logtext;
s4 logtextlen;
codeinfo *code;
- int32_t dumpmarker;
/* calculate message length */
logtextlen += strlen("0");
- /* allocate memory */
+ // Create new dump memory area.
+ DumpMemoryArea dma;
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
+ // TODO Use a std::string here.
+ logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
if (xptr) {
strcpy(logtext, "Exception ");
strcat(logtext, "call_java_method");
log_text(logtext);
-
- /* release memory */
-
- DRELEASE;
}
{
char *logtext;
s4 logtextlen;
- int32_t dumpmarker;
java_lang_Throwable jlt(h);
logtextlen += strlen("(nil)");
}
- /* allocate memory */
+ // Create new dump memory area.
+ DumpMemoryArea dma;
- DMARKER;
-
- logtext = DMNEW(char, logtextlen);
+ logtext = (char*) DumpMemory::allocate(sizeof(char) * logtextlen);
strcpy(logtext, "Builtin exception thrown: ");
}
log_text(logtext);
-
- /* release memory */
-
- DRELEASE;
}
} // extern "C"
/* Include machine dependent trap stuff. */
+#include "md.h"
#include "md-trap.h"
#include "mm/memory.h"
#include "vm/os.hpp"
#include "vm/vm.hpp"
-#include "vm/jit/code.h"
+#include "vm/jit/asmpart.h"
+#include "vm/jit/code.hpp"
#include "vm/jit/disass.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/executionstate.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/methodtree.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
*/
void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context)
{
+ executionstate_t es;
stackframeinfo_t sfi;
int32_t index;
java_handle_t *o;
o = NULL;
m = NULL;
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
+# if !defined(NDEBUG)
+ /* Perform a sanity check on our execution state functions. */
+
+ executionstate_sanity_check(context);
+# endif
+
+ /* Read execution state from current context. */
+
+ es.code = NULL;
+ md_executionstate_read(&es, context);
+#endif
+
/* wrap the value into a handle if it is a reference */
/* BEFORE: creating stackframeinfo */
stacktrace_stackframeinfo_remove(&sfi);
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
+ /* Update execution state and set registers. */
+ /* AFTER: removing stackframeinfo */
+
+ switch (type) {
+ case TRAP_COMPILER:
+ // The normal case for a compiler trap is to jump directly to
+ // the newly compiled method.
+
+ if (p != NULL) {
+ es.pc = (uint8_t *) (uintptr_t) p;
+ es.pv = (uint8_t *) (uintptr_t) p;
+ break;
+ }
+
+ // In case of an exception during JIT compilation, we fetch
+ // the exception here and proceed with exception handling.
+
+ java_handle_t *e = exceptions_get_and_clear_exception();
+ assert(e != NULL);
+
+ // Get and set the PV from the parent Java method.
+
+ es.pv = md_codegen_get_pv_from_pc(ra);
+
+ // XXX: Make the code below a fall-through to default case!
+
+ es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(e);
+ es.intregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
+ es.pc = (uint8_t *) (uintptr_t) asm_handle_exception;
+ break;
+
+ case TRAP_PATCHER:
+ // The normal case for a patcher trap is to continue execution at
+ // the trap instruction. On some archs the PC may point after the
+ // trap instruction, so we reset it here.
+
+ if (p == NULL) {
+ es.pc = (uint8_t *) (uintptr_t) xpc;
+ break;
+ }
+
+ /* fall-through */
+
+ default:
+ if (p != NULL) {
+ es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(p);
+ es.intregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
+ es.pc = (uint8_t *) (uintptr_t) asm_handle_exception;
+ }
+ }
+
+ /* Write back execution state to current context. */
+
+ md_executionstate_write(&es, context);
+#endif
+
/* unwrap and return the exception object */
/* AFTER: removing stackframeinfo */
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#include "typecheck-common.h"
#include <assert.h>
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/****************************************************************************/
#include "vm/types.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "mm/memory.h"
-#include "vm/array.h"
+#include "vm/array.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/primitive.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#include "vm/jit/stack.h"
#include "vm/jit/verify/typecheck-common.h"
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
#include "toolbox/logging.h"
#include "vm/access.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/vm.hpp"
-#include "vm/jit/jit.h"
-#include "vm/jit/show.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/show.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/verify/typecheck-typeinferer.h"
#include "config.h"
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* function prototypes ********************************************************/
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
#include "toolbox/logging.h"
#include "vm/access.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/parse.h"
-#include "vm/jit/show.h"
+#include "vm/jit/show.hpp"
#include <typecheck-common.h>
/* src/vm/jit/verify/typecheck.h - type checking 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
-
-
*/
#include "config.h"
#include "vm/global.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#if defined(ENABLE_VERIFIER)
bool typecheck(jitdata *jd);
bool typecheck_stackbased(jitdata *jd);
#endif
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _TYPECHECK_H */
#include "toolbox/logging.h"
-#include "vm/array.h"
+#include "vm/array.hpp"
#include "vm/class.h"
#include "vm/descriptor.h"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/verify/typeinfo.h"
\
md-abi.c \
md-abi.h \
+ md-stubs.hpp \
md-trap.h \
md.c \
md.h
/* define architecture features ***********************************************/
-#define U8_AVAILABLE 1
-
#define SUPPORT_DIVISION 1
#define SUPPORT_LONG 1
#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/statistics.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/dseg.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/linenumbertable.h"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/linenumbertable.hpp"
#include "vm/jit/methodheader.h"
#include "vm/jit/parse.h"
-#include "vm/jit/patcher-common.h"
+#include "vm/jit/patcher-common.hpp"
#include "vm/jit/reg.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/replace.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
/* src/vm/jit/x86_64/codegen.h - code generation macros 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 "vm/jit/x86_64/emit.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
/* additional functions and macros to generate code ***************************/
} while (0)
-/* stub defines ***************************************************************/
-
-#define COMPILERSTUB_CODESIZE 8
-
-
/* macros to create code ******************************************************/
#define M_BYTE1(a) \
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/emit-common.h"
-#include "vm/jit/jit.h"
-#include "vm/jit/patcher-common.h"
-#include "vm/jit/replace.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/emit-common.hpp"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
#include "config.h"
#include "vm/types.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
/* macros to create code ******************************************************/
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
int type;
intptr_t val;
void *p;
- java_object_t *o;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
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;
- }
}
u1 *xpc;
int type;
intptr_t val;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
/* 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;
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
u1 *xpc;
int type;
intptr_t val;
- void *p;
_uc = (ucontext_t *) _p;
_mc = &_uc->uc_mcontext;
/* 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;
- }
+ trap_handle(type, val, pv, sp, ra, xpc, _p);
}
#include "vm/global.h"
#include "vm/jit/abi.h"
-#include "vm/jit/jit.h" /* for REG_* (maybe can be removed) */
+#include "vm/jit/jit.hpp" /* for REG_* (maybe can be removed) */
#include "vm/jit/stack.h"
--- /dev/null
+/* src/vm/jit/x86_64/md-stubs.hpp - x86_64 JIT stubs
+
+ 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 _MD_STUBS_HPP
+#define _MD_STUBS_HPP
+
+#include "config.h"
+
+
+/**
+ * Return the code size of a compiler on a x86_64 architecture.
+ *
+ * @return Code size in bytes.
+ */
+int CompilerStub::get_code_size()
+{
+ return 8;
+}
+
+#endif // _MD_STUBS_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 "vm/vm.hpp"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/codegen-common.hpp"
+#include "vm/jit/jit.hpp"
/* md_init *********************************************************************
/* src/vm/jit/x86_64/md.h - machine dependent x86_64 functions
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 <stdint.h>
-#include "vm/jit/codegen-common.h"
+#include "vm/jit/codegen-common.hpp"
#include "vm/jit/methodtree.h"
*******************************************************************************/
-inline static void md_cacheflush(u1 *addr, s4 nbytes)
+inline static void md_cacheflush(void* addr, int nbytes)
{
- /* do nothing */
+ // Compiler optimization barrier (see PR97).
+ __asm__ __volatile__ ("" : : : "memory");
}
*******************************************************************************/
-inline static void md_icacheflush(u1 *addr, s4 nbytes)
+inline static void md_icacheflush(void* addr, int nbytes)
{
- /* do nothing */
+ // Compiler optimization barrier (see PR97).
+ __asm__ __volatile__ ("" : : : "memory");
}
*******************************************************************************/
-inline static void md_dcacheflush(u1 *addr, s4 nbytes)
+inline static void md_dcacheflush(void* addr, int nbytes)
{
- /* do nothing */
+ // Compiler optimization barrier (see PR97).
+ __asm__ __volatile__ ("" : : : "memory");
}
#endif /* _VM_JIT_X86_64_MD_H */
#include "vm/types.h"
#include "vm/jit/x86_64/codegen.h"
+#include "vm/jit/x86_64/md.h"
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/initialize.h"
#include "vm/options.h"
#include "vm/references.h"
#include "vm/resolve.h"
-#include "vm/jit/patcher-common.h"
-
-
-#define PATCH_BACK_ORIGINAL_MCODE \
- do { \
- *((uint16_t *) pr->mpc) = (uint16_t) pr->mcode; \
- } while (0)
+#include "vm/jit/patcher-common.hpp"
/* patcher_patch_code **********************************************************
void patcher_patch_code(patchref_t *pr)
{
- PATCH_BACK_ORIGINAL_MCODE;
+ *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode;
+ md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
}
bool patcher_resolve_classref_to_classinfo(patchref_t *pr)
{
- constant_classref *cr;
- intptr_t *datap;
- classinfo *c;
+ constant_classref* cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- cr = (constant_classref *) pr->ref;
- datap = (intptr_t *) pr->datap;
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the classinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch the class.
+ *datap = (uintptr_t) c;
- /* patch the classinfo pointer */
+ // Synchronize data cache.
+ md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
- *datap = (intptr_t) c;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_resolve_classref_to_vftbl(patchref_t *pr)
{
- constant_classref *cr;
- intptr_t *datap;
- classinfo *c;
-
- /* get stuff from the stack */
+ constant_classref* cr = (constant_classref*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- cr = (constant_classref *) pr->ref;
- datap = (intptr_t *) pr->datap;
+ // Resolve the field.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch super class' vftbl.
+ *datap = (uintptr_t) c->vftbl;
- /* patch super class' vftbl */
+ // Synchronize data cache.
+ md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
- *datap = (intptr_t) c->vftbl;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_resolve_classref_to_flags(patchref_t *pr)
{
- constant_classref *cr;
- int32_t *datap;
- classinfo *c;
- uint8_t *ra;
-
- cr = (constant_classref *) pr->ref;
- datap = (int32_t *) pr->datap;
- ra = (uint8_t *) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
+/* int32_t* datap = (int32_t*) pr->datap; */
+ uint8_t* ra = (uint8_t*) pr->mpc;
- /* get the fieldinfo */
+ // Resolve the field.
+ classinfo* c = resolve_classref_eager(cr);
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
+ // Patch class flags.
+/* *datap = c->flags; */
+ *((int32_t*) (ra + 2)) = c->flags;
- /* patch class flags */
+ // Synchronize data cache.
+/* md_dcacheflush(datap, sizeof(int32_t)); */
+ md_icacheflush(ra + 2, sizeof(int32_t));
-/* *datap = c->flags; */
- *((int32_t *) (ra + 2)) = c->flags;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_get_putstatic(patchref_t *pr)
{
- unresolved_field *uf;
- intptr_t *datap;
- fieldinfo *fi;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- uf = (unresolved_field *) pr->ref;
- datap = (intptr_t *) pr->datap;
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- /* get the fieldinfo */
-
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- /* check if the field's class is initialized */
-
+ // Check if the field's class is initialized/
if (!(fi->clazz->state & CLASS_INITIALIZED))
if (!initialize_class(fi->clazz))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch the field value's address.
+ *datap = (uintptr_t) fi->value;
- /* patch the field value's address */
+ // Synchronize data cache.
+ md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
- *datap = (intptr_t) fi->value;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_get_putfield(patchref_t *pr)
{
- uint8_t *ra;
- unresolved_field *uf;
- fieldinfo *fi;
- uint8_t byte;
-
- ra = (uint8_t *) pr->mpc;
- uf = (unresolved_field *) pr->ref;
+ uint8_t* pc = (uint8_t*) pr->mpc;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
- /* Patch the field's offset: we check for the field type, because
- the instructions have different lengths. */
-
+ // Patch the field's offset: we check for the field type, because
+ // the instructions have different lengths.
if (IS_INT_LNG_TYPE(fi->type)) {
- /* Check for special case: %rsp or %r12 as base register. */
-
- byte = *(ra + 3);
-
- if (byte == 0x24)
- *((int32_t *) (ra + 4)) = fi->offset;
+ // Check for special case: %rsp or %r12 as base register.
+ if (pc[3] == 0x24)
+ *((int32_t*) (pc + 4)) = fi->offset;
else
- *((int32_t *) (ra + 3)) = fi->offset;
+ *((int32_t*) (pc + 3)) = fi->offset;
}
else {
- /* Check for special case: %rsp or %r12 as base register. */
-
- byte = *(ra + 5);
-
- if (byte == 0x24)
- *((int32_t *) (ra + 6)) = fi->offset;
+ // Check for special case: %rsp or %r12 as base register.
+ if (pc[5] == 0x24)
+ *((int32_t*) (pc + 6)) = fi->offset;
else
- *((int32_t *) (ra + 5)) = fi->offset;
+ *((int32_t*) (pc + 5)) = fi->offset;
}
+ // Synchronize instruction cache.
+ md_icacheflush(pc, 6 + sizeof(int32_t));
+
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_putfieldconst(patchref_t *pr)
{
- uint8_t *ra;
- unresolved_field *uf;
- fieldinfo *fi;
- uint8_t byte;
+ uint8_t* pc = (uint8_t*) pr->mpc;
+ unresolved_field* uf = (unresolved_field*) pr->ref;
- ra = (uint8_t *) pr->mpc;
- uf = (unresolved_field *) pr->ref;
+ // Resolve the field.
+ fieldinfo* fi = resolve_field_eager(uf);
- /* get the fieldinfo */
-
- if (!(fi = resolve_field_eager(uf)))
+ if (fi == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
- /* patch the field's offset */
-
+ // Patch the field's offset.
if (IS_2_WORD_TYPE(fi->type) || IS_ADR_TYPE(fi->type)) {
- /* handle special case when the base register is %r12 */
-
- byte = *(ra + 12);
-
- if (byte == 0x94) {
- *((uint32_t *) (ra + 14)) = fi->offset;
- }
- else {
- *((uint32_t *) (ra + 13)) = fi->offset;
- }
+ // Handle special case when the base register is %r12.
+ if (pc[12] == 0x94)
+ *((uint32_t*) (pc + 14)) = fi->offset;
+ else
+ *((uint32_t*) (pc + 13)) = fi->offset;
}
else {
- /* handle special case when the base register is %r12 */
-
- byte = *(ra + 2);
-
- if (byte == 0x84)
- *((uint32_t *) (ra + 4)) = fi->offset;
+ // Handle special case when the base register is %r12.
+ if (pc[2] == 0x84)
+ *((uint32_t*) (pc + 4)) = fi->offset;
else
- *((uint32_t *) (ra + 3)) = fi->offset;
+ *((uint32_t*) (pc + 3)) = fi->offset;
}
+ // Synchronize instruction cache.
+ md_icacheflush(pc, 14 + sizeof(int32_t));
+
+ // Patch back the original code.
+ patcher_patch_code(pr);
+
return true;
}
bool patcher_invokestatic_special(patchref_t *pr)
{
- unresolved_method *um;
- intptr_t *datap;
- methodinfo *m;
-
- /* get stuff from the stack */
+ unresolved_method* um = (unresolved_method*) pr->ref;
+ uintptr_t* datap = (uintptr_t*) pr->datap;
- um = (unresolved_method *) pr->ref;
- datap = (intptr_t *) pr->datap;
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- /* get the fieldinfo */
-
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
+ // Patch stubroutine.
+ *datap = (uintptr_t) m->stubroutine;
- /* patch stubroutine */
+ // Synchronize data cache.
+ md_dcacheflush((void*) pr->datap, SIZEOF_VOID_P);
- *datap = (intptr_t) m->stubroutine;
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokevirtual(patchref_t *pr)
{
- uint8_t *ra;
- unresolved_method *um;
- methodinfo *m;
-
- ra = (uint8_t *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ uint8_t* pc = (uint8_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- /* get the methodinfo */
+ // Resovlve the method.
+ methodinfo* m = resolve_method_eager(um);
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
+ // Patch vftbl index.
+ *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, table[0]) + sizeof(methodptr) * m->vftblindex);
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P);
- /* patch vftbl index */
-
- *((int32_t *) (ra + 3 + 3)) =
- (int32_t) (OFFSET(vftbl_t, table[0]) +
- sizeof(methodptr) * m->vftblindex);
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_invokeinterface(patchref_t *pr)
{
- uint8_t *ra;
- unresolved_method *um;
- methodinfo *m;
-
- /* get stuff from the stack */
-
- ra = (uint8_t *) pr->mpc;
- um = (unresolved_method *) pr->ref;
+ uint8_t* pc = (uint8_t*) pr->mpc;
+ unresolved_method* um = (unresolved_method*) pr->ref;
- /* get the fieldinfo */
+ // Resolve the method.
+ methodinfo* m = resolve_method_eager(um);
- if (!(m = resolve_method_eager(um)))
+ if (m == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
-
- /* patch interfacetable index */
+ // Patch interfacetable index.
+ *((int32_t*) (pc + 3 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr) * m->clazz->index);
- *((int32_t *) (ra + 3 + 3)) =
- (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr) * m->clazz->index);
+ // Patch method offset.
+ *((int32_t*) (pc + 3 + 7 + 3)) = (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
- /* patch method offset */
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 3 + 3, SIZEOF_VOID_P + 3 + SIZEOF_VOID_P);
- *((int32_t *) (ra + 3 + 7 + 3)) =
- (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_checkcast_interface(patchref_t *pr)
{
- uint8_t *ra;
- constant_classref *cr;
- classinfo *c;
+ uint8_t* pc = (uint8_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- ra = (uint8_t *) pr->mpc;
- cr = (constant_classref *) pr->ref;
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
+ // Patch super class index.
+ *((int32_t*) (pc + 7 + 3)) = c->index;
- /* patch super class index */
+ *((int32_t*) (pc + 7 + 7 + 6 + 8 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*));
- *((int32_t *) (ra + 7 + 3)) = c->index;
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 8 + 3 + sizeof(int32_t));
- *((int32_t *) (ra + 7 + 7 + 6 + 8 + 3)) =
- (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
- c->index * sizeof(methodptr*));
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
bool patcher_instanceof_interface(patchref_t *pr)
{
- uint8_t *ra;
- constant_classref *cr;
- classinfo *c;
+ uint8_t* pc = (uint8_t*) pr->mpc;
+ constant_classref* cr = (constant_classref*) pr->ref;
- ra = (uint8_t *) pr->mpc;
- cr = (constant_classref *) pr->ref;
+ // Resolve the class.
+ classinfo* c = resolve_classref_eager(cr);
- /* get the fieldinfo */
-
- if (!(c = resolve_classref_eager(cr)))
+ if (c == NULL)
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
- /* if we show disassembly, we have to skip the nop's */
-
- if (opt_shownops)
- ra = ra + PATCHER_CALL_SIZE;
+ // Patch super class index.
+ *((int32_t*) (pc + 7 + 3)) = c->index;
- /* patch super class index */
+ *((int32_t*) (pc + 7 + 7 + 6 + 3)) = (int32_t) (OFFSET(vftbl_t, interfacetable[0]) - c->index * sizeof(methodptr*));
- *((int32_t *) (ra + 7 + 3)) = c->index;
+ // Synchronize instruction cache.
+ md_icacheflush(pc + 7 + 3, sizeof(int32_t) + 6 + 3 + sizeof(int32_t));
- *((int32_t *) (ra + 7 + 7 + 6 + 3)) =
- (int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
- c->index * sizeof(methodptr*));
+ // Patch back the original code.
+ patcher_patch_code(pr);
return true;
}
#include "threads/thread.hpp"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
#include "mm/memory.h"
-#include "native/native.h"
+#include "native/native.hpp"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
+#include "threads/mutex.hpp"
#include "toolbox/logging.h"
#include "vm/access.h"
-#include "vm/array.h"
+#include "vm/array.hpp"
#include "vm/class.h"
#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/rt-timing.h"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
+#include "vm/jit/stubs.hpp"
/* debugging macros ***********************************************************/
static s4 interfaceindex; /* sequential numbering of interfaces */
static s4 classvalue;
-java_object_t *linker_classrenumber_lock;
+Mutex *linker_classrenumber_mutex;
/* private functions **********************************************************/
interfaceindex = 0;
#if defined(ENABLE_THREADS)
- /* create the global lock object */
+ /* create the global mutex */
- linker_classrenumber_lock = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
+ linker_classrenumber_mutex = Mutex_new();
#endif
/* Link the most basic classes. */
m->stubroutine = intrp_createcompilerstub(m);
else
#endif
- m->stubroutine = codegen_generate_stub_compiler(m);
+ m->stubroutine = CompilerStub_generate(m);
#else
m->stubroutine = intrp_createcompilerstub(m);
#endif
static void linker_compute_subclasses(classinfo *c)
{
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+ Mutex_lock(linker_classrenumber_mutex);
if (!(c->flags & ACC_INTERFACE)) {
c->nextsub = NULL;
linker_compute_class_values(class_java_lang_Object);
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+ Mutex_unlock(linker_classrenumber_mutex);
}
/* forward typedefs ***********************************************************/
-typedef struct _vftbl vftbl_t;
typedef struct arraydescriptor arraydescriptor;
typedef struct primitivetypeinfo primitivetypeinfo;
#include "config.h"
#include "vm/types.h"
+#include "threads/mutex.hpp"
+
#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 */
-};
+#include "vm/vftbl.hpp"
/* arraydescriptor *************************************************************
/* This lock must be taken while renumbering classes or while atomically */
/* accessing classes. */
-extern java_object_t *linker_classrenumber_lock;
+extern Mutex *linker_classrenumber_mutex;
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void linker_preinit(void);
void linker_init(void);
classinfo *link_class(classinfo *c);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _LINKER_H */
+++ /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.cpp - 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/dumpmemory.hpp"
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/logging.h"
+
+#include "vm/jit/builtin.hpp"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.hpp"
+#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.hpp"
+#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
+
+#include "vm/jit/stubs.hpp"
+
+#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)
+{
+ TRACESUBSYSTEMINITIALIZATION("loader_preinit");
+
+#if defined(ENABLE_THREADS)
+ /* Initialize the monitor pointer for zip/jar file locking. */
+
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+ list_classpath_entry* lce = *it;
+
+ if (lce->type == CLASSPATH_ARCHIVE)
+ lce->mutex = new Mutex();
+ }
+#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::get_current()->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::get_current()->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;
+
+ hashtable_classloader->mutex->lock();
+
+ 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_entry*) 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_entry*) hashtable_classloader->ptr[slot];
+ hashtable_classloader->ptr[slot] = cle;
+
+ /* update number of entries */
+
+ hashtable_classloader->entries++;
+ }
+
+ hashtable_classloader->mutex->unlock();
+
+#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_entry*) 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)
+{
+#if defined(ENABLE_ZLIB)
+ hashtable *ht;
+ hashtable_zipfile_entry *htzfe;
+ utf *u;
+#endif
+
+ for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+ list_classpath_entry* lce = *it;
+
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+ /* get the classes hashtable */
+
+ ht = lce->htclasses;
+
+ for (uint32_t 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:
+#warning Use list.
+ nfc = (forward_class*) DumpMemory::allocate(sizeof(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:
+#warning Use list.
+ nfs = (forward_string*) DumpMemory::allocate(sizeof(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:
+#warning Use list.
+ nfn = (forward_nameandtype*) DumpMemory::allocate(sizeof(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:
+#warning Use list.
+ nff = (forward_fieldmethint*) DumpMemory::allocate(sizeof(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 = (utf*) 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 = (utf*) 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 = (utf*) class_getconstant(c,
+ forward_nameandtypes->name_index,
+ CONSTANT_Utf8);
+ if (!cn->name)
+ return false;
+
+ cn->descriptor = (utf*) 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 = (constant_nameandtype*) 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);
+
+ *signature = (utf*) class_getconstant(c, signature_index, CONSTANT_Utf8);
+
+ if (*signature == NULL)
+ 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 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
+
+ // Create new dump memory area.
+ DumpMemoryArea dma;
+
+ 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 = (utf**) DumpMemory::allocate(sizeof(utf*) * c->interfacescount);
+
+ for (int32_t 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 (int32_t 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 (int32_t 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 = (u1*) 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 (int32_t 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 */
+ int32_t len;
+ int32_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 (int32_t 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 (int32_t 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;
+
+ /* 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
+
+ /* Class is currently loading. */
+
+ c->state |= CLASS_LOADING;
+
+ /* Parse the classbuffer. */
+
+ result = load_class_from_classbuffer_intern(cb);
+
+ /* 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);
+
+ /* ATTENTION: if you delete the ACC_NATIVE below, set
+ clone->maxlocals=1 (interpreter related) */
+
+ clone->mutex = new Mutex();
+ 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 = NativeStub::generate(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/loader.hpp - 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_HPP
+#define _LOADER_HPP
+
+/* 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 ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LOADER_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/llni.h"
-#include "threads/lock-common.h"
+#include "threads/mutex.hpp"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#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/loader.hpp"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/resolve.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
#include "vm/jit/methodheader.h"
+#include "vm/jit/stubs.hpp"
#if !defined(NDEBUG) && defined(ENABLE_INLINING)
c = cb->clazz;
- LOCK_INIT_OBJECT_LOCK(&(m->header));
+ m->mutex = Mutex_new();
#if defined(ENABLE_STATISTICS)
if (opt_stat)
void method_free(methodinfo *m)
{
+ if (m->mutex)
+ Mutex_delete(m->mutex);
+
if (m->jcode)
MFREE(m->jcode, u1, m->jcodelength);
if (m->stubroutine) {
if (m->flags & ACC_NATIVE) {
- removenativestub(m->stubroutine);
-
- } else {
- removecompilerstub(m->stubroutine);
+ NativeStub_remove(m->stubroutine);
+ }
+ else {
+ CompilerStub_remove(m->stubroutine);
}
}
}
/* initialize methodinfo structure */
MZERO(m, methodinfo, 1);
- LOCK_INIT_OBJECT_LOCK(&(m->header));
-
+
+ m->mutex = Mutex_new();
m->flags = ACC_METHOD_BUILTIN;
m->parseddesc = bte->md;
m->name = bte->name;
#ifndef _METHOD_H
#define _METHOD_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/* forward typedefs ***********************************************************/
typedef struct methodinfo methodinfo;
#include "config.h"
#include "vm/types.h"
-#include "vm/builtin.h"
+#include "threads/mutex.hpp"
+
+#include "vm/jit/builtin.hpp"
#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/references.h"
#if defined(ENABLE_JAVASE)
/* methodinfo *****************************************************************/
struct methodinfo { /* method structure */
- java_object_t header; /* we need this in jit's monitorenter */
+ Mutex *mutex; /* we need this in jit's locking */
s4 flags; /* ACC flags */
utf *name; /* name of method */
utf *descriptor; /* JavaVM descriptor string of method */
extern methodinfo *method_java_lang_reflect_Method_invoke;
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* inline functions ***********************************************************/
inline static bool method_is_builtin(methodinfo* m)
#include "mm/memory.h"
-#include "native/jni.h"
-
#include "vm/options.h"
#include "vm/os.hpp"
#include "vm/vm.hpp"
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 */
#include "vm/types.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "vm/global.h"
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;
Copyright (C) 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#include "vm/vm.hpp"
+/**
+ * Prints an error message and aborts the VM.
+ *
+ * @param text Error message to print.
+ */
+void os::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();
+
+ // Print a backtrace.
+ os::print_backtrace();
+
+ // Now abort the VM.
+ os::abort();
+}
+
+
+/**
+ * Prints an error message, appends ":" plus the strerror-message of
+ * errnum and aborts the VM.
+ *
+ * @param errnum Error number.
+ * @param text Error message to print.
+ */
+void os::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();
+
+ // Print a backtrace.
+ os::print_backtrace();
+
+ // Now abort the VM.
+ os::abort();
+}
+
+
+/**
+ * Equal to abort_errnum, but uses errno to get the error number.
+ *
+ * @param text Error message to print.
+ */
+void os::abort_errno(const char* text, ...)
+{
+ va_list ap;
+
+ va_start(ap, text);
+ abort_errnum(errno, text, ap);
+ va_end(ap);
+}
+
+
/**
* Maps anonymous memory, even on systems not defining
* MAP_ANON(YMOUS).
fd = open("/dev/zero", O_RDONLY, 0);
if (fd == -1)
- vm_abort("os::mmap_anonymous: open failed: %s", os::strerror(errno));
+ os::abort_errno("os::mmap_anonymous: open failed");
p = mmap(addr, len, prot, flags, fd, 0);
#endif
#else
if (p == (void *) -1)
#endif
- vm_abort("os::mmap_anonymous: mmap failed: %s", os::strerror(errno));
+ os::abort_errno("os::mmap_anonymous: mmap failed");
return p;
}
+/**
+ * Print a C backtrace.
+ */
+void os::print_backtrace()
+{
+#define BACKTRACE_SIZE 100
+ void** array = new void*[SIZEOF_VOID_P * BACKTRACE_SIZE];
+
+ // Get the backtrace.
+ int size = backtrace(array, BACKTRACE_SIZE);
+
+ // Resolve the symbols.
+ char** strings = backtrace_symbols(array, size);
+
+ log_println("Backtrace (%d stack frames):", size);
+
+ for (int i = 0; i < size; i++)
+ log_println("%s", strings[i]);
+
+ // We have to free the strings.
+ free(strings);
+}
+
+
/**
* Returns the number of online processors in the system.
*
#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); }
Copyright (C) 2007, 2008
CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+ Copyright (C) 2008 Theobroma Systems Ltd.
This file is part of CACAO.
#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. */
+// NOTE: In this file we check for all system headers, because we wrap
+// all system calls into inline functions for better portability.
+
+// Please don't include CACAO headers here as this header should be a
+// very low-level one.
#if defined(HAVE_DIRENT_H)
# include <dirent.h>
# include <errno.h>
#endif
+#if defined(HAVE_EXECINFO_H)
+# include <execinfo.h>
+#endif
+
#if defined(HAVE_FCNTL_H)
# include <fcntl.h>
#endif
# include <signal.h>
#endif
+#if defined(HAVE_STDARG_H)
+# include <stdarg.h>
+#endif
+
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#endif
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);
+ 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 int backtrace(void** array, int size);
+ static inline char** backtrace_symbols(void* const* array, int size) throw ();
+ 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);
+ 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 int fprintf(FILE* stream, const char* format, ...);
+ static inline size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+ static inline void free(void* ptr);
+ static inline char* getenv(const char* name);
+ 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 ssize_t readlink(const char* path, char* buf, size_t bufsiz);
+ 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 inline int str2sig(const char* str, int* signum);
+#endif
+ static inline char* strcat(char* dest, const char* src);
+ static inline int strcmp(const char* s1, const char* s2);
+ 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);
+
+ // Convenience functions.
+ static void abort(const char* text, ...);
+ static void abort_errnum(int errnum, const char* text, ...);
+ static void abort_errno(const char* text, ...);
static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
- static int processors_online(void);
+ static void print_backtrace();
+ static int processors_online();
};
#endif
}
+inline int os::backtrace(void** array, int size)
+{
+#if defined(HAVE_BACKTRACE)
+ return ::backtrace(array, size);
+#else
+ fprintf(stderr, "os::backtrace: Not available.");
+ return 0;
+#endif
+}
+
+inline char** os::backtrace_symbols(void* const* array, int size) throw ()
+{
+#if defined(HAVE_BACKTRACE_SYMBOLS)
+ return ::backtrace_symbols(array, size);
+#else
+ fprintf(stderr, "os::backtrace_symbols: Not available.");
+ return NULL;
+#endif
+}
+
inline void* os::calloc(size_t nmemb, size_t size)
{
#if defined(HAVE_CALLOC)
inline char* os::dlerror(void)
{
#if defined(HAVE_DLERROR)
- return ::dlerror();
+ // At least FreeBSD defines dlerror() to return a const char*, so
+ // we simply cast it.
+ return (char*) ::dlerror();
#else
# error dlerror not available
#endif
#endif
}
+inline int os::fprintf(FILE* stream, const char* format, ...)
+{
+#if defined(HAVE_FPRINTF)
+ va_list ap;
+ va_start(ap, format);
+ int result = ::fprintf(stream, format, ap);
+ va_end(ap);
+ return result;
+#else
+# error fprintf not available
+#endif
+}
+
inline size_t os::fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
{
#if defined(HAVE_FREAD)
#endif
}
+inline char* os::getenv(const char* name)
+{
+#if defined(HAVE_GETENV)
+ return ::getenv(name);
+#else
+# error getenv not available
+#endif
+}
+
inline int os::gethostname(char* name, size_t len)
{
#if defined(HAVE_GETHOSTNAME)
#endif
}
+inline ssize_t os::readlink(const char* path, char* buf, size_t bufsiz)
+{
+#if defined(HAVE_READLINK)
+ return ::readlink(path, buf, bufsiz);
+#else
+# error readlink not available
+#endif
+}
+
inline static void *system_realloc(void *ptr, size_t size)
{
#if defined(HAVE_REALLOC)
#endif
}
+inline int os::strcmp(const char* s1, const char* s2)
+{
+#if defined(HAVE_STRCMP)
+ return ::strcmp(s1, s2);
+#else
+# error strcmp not available
+#endif
+}
+
inline char* os::strcpy(char* dest, const char* src)
{
#if defined(HAVE_STRCPY)
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);
#include <stdint.h>
-#include "toolbox/list.h"
-
#include "mm/memory.h"
-#include "native/jni.h"
-
#include "vm/options.h"
#include "vm/package.hpp"
#include "vm/string.hpp"
#include "vm/utf8.h"
-/* internal property structure ************************************************/
-
-typedef struct list_package_entry_t list_package_entry_t;
-
-struct list_package_entry_t {
-/* java_string_t *packagename; */
- utf *packagename;
- listnode_t linkage;
-};
-
+// Package list.
-/* global variables ***********************************************************/
-
-static list_t *list_package = NULL;
-
-
-/**
- * Initialize the package list.
- */
-void Package::initialize(void)
-{
- TRACESUBSYSTEMINITIALIZATION("package_init");
-
- /* create the properties list */
-
- list_package = list_create(OFFSET(list_package_entry_t, linkage));
-}
+std::set<utf*> Package::_packages;
/**
*
* @param packagename Package name as Java string.
*/
-/* void package_add(java_handle_t *packagename) */
-void Package::add(utf *packagename)
+void Package::add(utf* packagename)
{
-/* java_string_t *s; */
- list_package_entry_t *lpe;
-
- /* Intern the Java string to get a unique address. */
-
+ // Intern the Java string to get a unique address.
/* s = javastring_intern(packagename); */
- /* Check if the package is already stored. */
-
- if (Package::find(packagename) != NULL)
- return;
-
- /* Add the package. */
-
#if !defined(NDEBUG)
if (opt_DebugPackage) {
log_start();
}
#endif
- lpe = NEW(list_package_entry_t);
-
- lpe->packagename = packagename;
-
- list_add_last(list_package, lpe);
+ // Add the package name.
+ _packages.insert(packagename);
}
*
* @return Package name as Java string.
*/
-/* java_handle_t *package_find(java_handle_t *packagename) */
-utf* Package::find(utf *packagename)
+utf* Package::find(utf* packagename)
{
-/* java_string_t *s; */
- list_t *l;
- list_package_entry_t *lpe;
-
- /* Intern the Java string to get a unique address. */
-
-/* s = javastring_intern(packagename); */
-
- /* For convenience. */
-
- l = list_package;
-
- for (lpe = (list_package_entry_t*) list_first(l); lpe != NULL; lpe = (list_package_entry_t*) list_next(l, lpe)) {
-/* if (lpe->packagename == s) */
- if (lpe->packagename == packagename)
- return lpe->packagename;
- }
-
- return NULL;
-}
-
-
-/* Legacy C interface *********************************************************/
-
-extern "C" {
+ std::set<utf*>::iterator it = _packages.find(packagename);
-void Package_initialize(void) { Package::initialize(); }
-void Package_add(utf* packagename) { Package::add(packagename); }
-utf* Package_find(utf *packagename) { return Package::find(packagename); }
+ if (it == _packages.end())
+ return NULL;
+ return *it;
}
#include "config.h"
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include <stdint.h>
-#include "native/jni.h"
-
-#include "vm/global.h"
-
-#ifdef __cplusplus
-}
-#endif
+#include <set>
+#include "vm/utf8.h"
-#ifdef __cplusplus
/**
*
*/
class Package {
+private:
+ static std::set<utf*> _packages;
+
public:
- static void initialize();
- /* static void add(java_handle_t *packagename); */
- static void add(utf *packagename);
- /* static java_handle_t* find(java_handle_t *packagename); */
- static utf* find(utf *packagename);
+ static void add (utf* packagename);
+ static utf* find(utf* packagename);
};
-#else
-
-/* Legacy C interface *********************************************************/
-
-typedef struct Package Package;
-
-void Package_initialize();
-void Package_add(utf* packagename);
-utf* Package_find(utf* packagename);
-
-#endif
-
-#endif /* _VM_PACKAGE_HPP */
+#endif // _VM_PACKAGE_HPP
/*
#include <assert.h>
#include <stdint.h>
-#include "native/jni.h"
#include "native/llni.h"
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/class.h"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
#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
+};
+
+
+/**
+ * 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::initialize_table()
+{
+ utf *name;
+ classinfo *c;
+ utf *u;
+ classinfo *ac;
+
+ TRACESUBSYSTEMINITIALIZATION("primitive_init");
+
+ /* Load and link primitive-type classes and array-classes. */
+
+ for (int 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 (int 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;
+ }
+}
+
+
+/**
+ * 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::post_initialize_table()
+{
+ 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;
+ }
+}
/**
break;
default:
o = NULL;
- vm_abort("primitive_box: invalid primitive type %d", type);
+ os::abort("Primitive::box: Invalid primitive type %d", type);
}
return o;
value.a = h;
break;
default:
- vm_abort("Primitive::unbox: invalid primitive type %d", type);
+ os::abort("Primitive::unbox: Invalid primitive type %d", type);
}
return value;
extern "C" {
- classinfo* Primitive_get_class_by_name(utf *name) { return Primitive::get_class_by_name(name); }
+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); }
}
class Primitive {
public:
+ static void initialize_table();
+ static void post_initialize_table();
+
static classinfo* get_class_by_name(utf *name);
static classinfo* get_class_by_type(int type);
static classinfo* get_class_by_char(char ch);
/* 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 */
+ const 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 */
+ const char* wrapname; /* name of class for wrapping */
+ const char typesig; /* one character type signature */
+ const char* arrayname; /* name of primitive array class */
+ classinfo* arrayclass; /* primitive array class */
};
// 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
+++ /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:
- */
+++ /dev/null
-/* src/vm/properties.c - handling commandline properties
-
- 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 <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/utsname.h>
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.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/string.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit/asmpart.h"
-
-
-/* internal property structure ************************************************/
-
-typedef struct list_properties_entry_t list_properties_entry_t;
-
-struct list_properties_entry_t {
- const char* key;
- const char* value;
- listnode_t linkage;
-};
-
-
-/* global variables ***********************************************************/
-
-static list_t *list_properties = NULL;
-
-
-/* properties_init *************************************************************
-
- Initialize the properties list and fill the list with default
- values.
-
-*******************************************************************************/
-
-void properties_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("properties_init");
-
- list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
-}
-
-
-/* properties_set **************************************************************
-
- Fill the properties list with default values.
-
-*******************************************************************************/
-
-void properties_set(void)
-{
- int len;
- char *p;
-
- char *java_home;
- char *boot_class_path;
-
-#if defined(ENABLE_JAVASE)
- char *class_path;
- char *boot_library_path;
- char *extdirs;
- char *endorseddirs;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- char *cwd;
- char *env_user;
- char *env_home;
- char *env_lang;
- char *lang;
- char *country;
- struct utsname *utsnamebuf;
-
- char *java_library_path;
-# endif
-#endif
-
-#if defined(ENABLE_JRE_LAYOUT)
- /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
-
- p = MNEW(char, 4096);
-
- if (readlink("/proc/self/exe", p, 4095) == -1)
- vm_abort("properties_set: readlink failed: %s\n", strerror(errno));
-
- /* We have a path like:
-
- /path/to/executable/bin/java
-
- or
-
- /path/to/executeable/jre/bin/java
-
- Now let's strip two levels. */
-
- p = os_dirname(p);
- p = os_dirname(p);
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Set java.home. */
-
- java_home = strdup(p);
-
- /* Set the path to Java core native libraries. */
-
- len = strlen(java_home) + strlen("/lib/classpath") + strlen("0");
-
- boot_library_path = MNEW(char, len);
-
- strcpy(boot_library_path, java_home);
- strcat(boot_library_path, "/lib/classpath");
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* Find correct java.home. We check if there is a JRE
- co-located. */
-
- /* NOTE: We use the server VM here as it should be available on
- all architectures. */
-
- len =
- strlen(p) +
- strlen("/jre/lib/"JAVA_ARCH"/server/libjvm.so") +
- strlen("0");
-
- java_home = MNEW(char, len);
-
- strcpy(java_home, p);
- strcat(java_home, "/jre/lib/"JAVA_ARCH"/server/libjvm.so");
-
- /* Check if that libjvm.so exists. */
-
- if (os_access(java_home, F_OK) == 0) {
- /* Yes, we add /jre to java.home. */
-
- strcpy(java_home, p);
- strcat(java_home, "/jre");
- }
- else {
- /* No, java.home is parent directory. */
-
- strcpy(java_home, p);
- }
-
- /* Set the path to Java core native libraries. */
-
- len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
-
- boot_library_path = MNEW(char, len);
-
- strcpy(boot_library_path, java_home);
- strcat(boot_library_path, "/lib/"JAVA_ARCH);
-
-# else
-# error unknown classpath configuration
-# endif
-
- /* Free path. */
-
- MFREE(p, char, len);
-
-#else
- java_home = CACAO_PREFIX;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR"/classpath";
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR;
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- /* No boot_library_path required. */
-
-# else
-# error unknown classpath configuration
-# endif
-#endif
-
- properties_add("java.home", java_home);
-
- /* Set the bootclasspath. */
-
- p = getenv("BOOTCLASSPATH");
-
- if (p != NULL) {
- boot_class_path = MNEW(char, strlen(p) + strlen("0"));
- strcpy(boot_class_path, p);
- }
- else {
-#if defined(ENABLE_JRE_LAYOUT)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- len =
- strlen(java_home) + strlen("/share/cacao/vm.zip:") +
- strlen(java_home) + strlen("/share/classpath/glibj.zip") +
- strlen("0");
-
- boot_class_path = MNEW(char, len);
-
- strcpy(boot_class_path, java_home);
- strcat(boot_class_path, "/share/cacao/vm.zip");
- strcat(boot_class_path, ":");
- strcat(boot_class_path, java_home);
- strcat(boot_class_path, "/share/classpath/glibj.zip");
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* This is the bootclasspath taken from HotSpot (see
- hotspot/src/share/vm/runtime/os.cpp
- (os::set_boot_path)). */
-
- len =
- strlen(java_home) + strlen("/lib/resources.jar:") +
- strlen(java_home) + strlen("/lib/rt.jar:") +
- strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
- strlen(java_home) + strlen("/lib/jsse.jar:") +
- strlen(java_home) + strlen("/lib/jce.jar:") +
- strlen(java_home) + strlen("/lib/charsets.jar:") +
- strlen(java_home) + strlen("/classes") +
- strlen("0");
-
- boot_class_path = MNEW(char, len);
-
- strcpy(boot_class_path, java_home);
- strcat(boot_class_path, "/lib/resources.jar:");
- strcat(boot_class_path, java_home);
- strcat(boot_class_path, "/lib/rt.jar:");
- strcat(boot_class_path, java_home);
- strcat(boot_class_path, "/lib/sunrsasign.jar:");
- strcat(boot_class_path, java_home);
- strcat(boot_class_path, "/lib/jsse.jar:");
- strcat(boot_class_path, java_home);
- strcat(boot_class_path, "/lib/jce.jar:");
- strcat(boot_class_path, java_home);
- strcat(boot_class_path, "/lib/charsets.jar:");
- strcat(boot_class_path, java_home);
- strcat(boot_class_path, "/classes");
-
-# else
-# error unknown classpath configuration
-# endif
-#else
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- len =
- strlen(CACAO_VM_ZIP) +
- strlen(":") +
- strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
- strlen("0");
-
- boot_class_path = MNEW(char, len);
-
- strcpy(boot_class_path, CACAO_VM_ZIP);
- strcat(boot_class_path, ":");
- strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* This is the bootclasspath taken from HotSpot (see
- hotspot/src/share/vm/runtime/os.cpp
- (os::set_boot_path)). */
-
- len =
- strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:") +
- strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:") +
- strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:") +
- strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:") +
- strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:") +
- strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:") +
- strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/classes") +
- strlen("0");
-
- boot_class_path = MNEW(char, len);
-
- strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:");
- strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:");
- strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:");
- strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:");
- strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:");
- strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:");
- strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/classes");
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
- len =
- strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
- strlen("0");
-
- boot_class_path = MNEW(char, len);
-
- strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
-
-# else
-# error unknown classpath configuration
-# endif
-#endif
- }
-
- properties_add("sun.boot.class.path", boot_class_path);
- properties_add("java.boot.class.path", boot_class_path);
-
-#if defined(ENABLE_JAVASE)
-
- /* Set the classpath. */
-
- p = getenv("CLASSPATH");
-
- if (p != NULL) {
- class_path = MNEW(char, strlen(p) + strlen("0"));
- strcpy(class_path, p);
- }
- else {
- class_path = MNEW(char, strlen(".") + strlen("0"));
- strcpy(class_path, ".");
- }
-
- properties_add("java.class.path", class_path);
-
- /* Add java.vm properties. */
-
- properties_add("java.vm.specification.version", "1.0");
- properties_add("java.vm.specification.vendor", "Sun Microsystems Inc.");
- properties_add("java.vm.specification.name", "Java Virtual Machine Specification");
- properties_add("java.vm.version", VERSION);
- properties_add("java.vm.vendor", "CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
- properties_add("java.vm.name", "CACAO");
-
-# if defined(ENABLE_INTRP)
- if (opt_intrp) {
- /* XXX We don't support java.lang.Compiler */
-/* properties_add("java.compiler", "cacao.intrp"); */
- properties_add("java.vm.info", "interpreted mode");
- }
- else
-# endif
- {
- /* XXX We don't support java.lang.Compiler */
-/* properties_add("java.compiler", "cacao.jit"); */
- properties_add("java.vm.info", "JIT mode");
- }
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
- /* Get properties from system. */
-
- cwd = _Jv_getcwd();
-
- env_user = getenv("USER");
- env_home = getenv("HOME");
- env_lang = getenv("LANG");
-
- utsnamebuf = NEW(struct utsname);
-
- uname(utsnamebuf);
-
- properties_add("java.runtime.version", VERSION);
- properties_add("java.runtime.name", "CACAO");
-
- properties_add("java.specification.version", "1.5");
- properties_add("java.specification.vendor", "Sun Microsystems Inc.");
- properties_add("java.specification.name", "Java Platform API Specification");
-
- properties_add("java.version", JAVA_VERSION);
- properties_add("java.vendor", "GNU Classpath");
- properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
-
- properties_add("java.class.version", CLASS_VERSION);
-
- properties_add("gnu.classpath.boot.library.path", boot_library_path);
-
- /* Get and set java.library.path. */
-
- java_library_path = getenv("LD_LIBRARY_PATH");
-
- if (java_library_path == NULL)
- java_library_path = "";
-
- properties_add("java.library.path", java_library_path);
-
- properties_add("java.io.tmpdir", "/tmp");
-
-# if defined(ENABLE_INTRP)
- if (opt_intrp) {
- properties_add("gnu.java.compiler.name", "cacao.intrp");
- }
- else
-# endif
- {
- properties_add("gnu.java.compiler.name", "cacao.jit");
- }
-
- /* Set the java.ext.dirs property. */
-
- len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
-
- extdirs = MNEW(char, len);
-
- sprintf(extdirs, "%s/jre/lib/ext", java_home);
-
- properties_add("java.ext.dirs", extdirs);
-
- /* Set the java.ext.endorsed property. */
-
- len = strlen(java_home) + strlen("/jre/lib/endorsed") + strlen("0");
-
- endorseddirs = MNEW(char, len);
-
- sprintf(endorseddirs, "%s/jre/lib/endorsed", java_home);
-
- properties_add("java.endorsed.dirs", endorseddirs);
-
-# if defined(DISABLE_GC)
- /* When we disable the GC, we mmap the whole heap to a specific
- address, so we can compare call traces. For this reason we have
- to add the same properties on different machines, otherwise
- more memory may be allocated (e.g. strlen("i386")
- vs. strlen("alpha"). */
-
- properties_add("os.arch", "unknown");
- properties_add("os.name", "unknown");
- properties_add("os.version", "unknown");
-# else
- properties_add("os.arch", JAVA_ARCH);
- properties_add("os.name", utsnamebuf->sysname);
- properties_add("os.version", utsnamebuf->release);
-# endif
-
-# if WORDS_BIGENDIAN == 1
- properties_add("gnu.cpu.endian", "big");
-# else
- properties_add("gnu.cpu.endian", "little");
-# endif
-
- properties_add("file.separator", "/");
- properties_add("path.separator", ":");
- properties_add("line.separator", "\n");
-
- properties_add("user.name", env_user ? env_user : "null");
- properties_add("user.home", env_home ? env_home : "null");
- properties_add("user.dir", cwd ? cwd : "null");
-
- /* get locale */
-
- if (env_lang != NULL) {
- /* get the local stuff from the environment */
-
- if (strlen(env_lang) <= 2) {
- properties_add("user.language", env_lang);
- }
- else {
- if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
- lang = MNEW(char, 3);
- strncpy(lang, (char *) &env_lang[0], 2);
- lang[2] = '\0';
-
- country = MNEW(char, 3);
- strncpy(country, (char *) &env_lang[3], 2);
- country[2] = '\0';
-
- properties_add("user.language", lang);
- properties_add("user.country", country);
- }
- }
- }
- else {
- /* if no default locale was specified, use `en_US' */
-
- properties_add("user.language", "en");
- properties_add("user.country", "US");
- }
-
-# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
- /* Actually this property is set by OpenJDK, but we need it in
- nativevm_preinit(). */
-
- properties_add("sun.boot.library.path", boot_library_path);
-
- /* Set the java.ext.dirs property. */
-
- len =
- strlen(java_home) + strlen("/lib/ext") +
- strlen(":") +
- strlen("/usr/java/packages/lib/ext") +
- strlen("0");
-
- extdirs = MNEW(char, len);
-
- sprintf(extdirs, "%s/lib/ext:/usr/java/packages/lib/ext", java_home);
-
- properties_add("java.ext.dirs", extdirs);
-
- /* Set the java.ext.endorsed property. */
-
- len = strlen(java_home) + strlen("/lib/endorsed") + strlen("0");
-
- endorseddirs = MNEW(char, len);
-
- sprintf(endorseddirs, "%s/lib/endorsed", java_home);
-
- properties_add("java.endorsed.dirs", endorseddirs);
-
-# else
-
-# error unknown classpath configuration
-
-# endif
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- properties_add("microedition.configuration", "CLDC-1.1");
- properties_add("microedition.platform", "generic");
- properties_add("microedition.encoding", "ISO8859_1");
- properties_add("microedition.profiles", "");
-
-#else
-
-# error unknown Java configuration
-
-#endif
-}
-
-
-/* properties_add **************************************************************
-
- Adds a property entry to the internal property list. If there's
- already an entry with the same key, replace it.
-
-*******************************************************************************/
-
-void properties_add(const char *key, const char *value)
-{
- list_properties_entry_t *pe;
-
- /* search for the entry */
-
- for (pe = list_first(list_properties); pe != NULL;
- pe = list_next(list_properties, pe)) {
- if (strcmp(pe->key, key) == 0) {
- /* entry was found, replace the value */
-
-#if !defined(NDEBUG)
- if (opt_DebugProperties) {
- printf("[properties_add: key=%s, old value=%s, new value=%s]\n",
- key, pe->value, value);
- }
-#endif
-
- pe->value = value;
-
- return;
- }
- }
-
- /* entry was not found, insert a new one */
-
-#if !defined(NDEBUG)
- if (opt_DebugProperties) {
- printf("[properties_add: key=%s, value=%s]\n", key, value);
- }
-#endif
-
- pe = NEW(list_properties_entry_t);
-
- pe->key = key;
- pe->value = value;
-
- list_add_last(list_properties, pe);
-}
-
-
-/* properties_get **************************************************************
-
- Get a property entry from the internal property list.
-
-*******************************************************************************/
-
-const char *properties_get(const char *key)
-{
- list_properties_entry_t *pe;
-
- for (pe = list_first(list_properties); pe != NULL;
- pe = list_next(list_properties, pe)) {
- if (strcmp(pe->key, key) == 0)
- return pe->value;
- }
-
- return NULL;
-}
-
-
-/* properties_system_add *******************************************************
-
- Adds a given property to the Java system properties.
-
-*******************************************************************************/
-
-void properties_system_add(java_handle_t *p, const char *key, const char *value)
-{
- classinfo *c;
- methodinfo *m;
- java_handle_t *k;
- java_handle_t *v;
-
- /* search for method to add properties */
-
- LLNI_class_get(p, c);
-
- m = class_resolveclassmethod(c,
- utf_put,
- utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
- NULL,
- true);
-
- if (m == NULL)
- return;
-
- /* add to the Java system properties */
-
- k = javastring_new_from_utf_string(key);
- v = javastring_new_from_utf_string(value);
-
- (void) vm_call_method(m, p, k, v);
-}
-
-
-/* properties_system_add_all ***************************************************
-
- Adds all properties from the properties list to the Java system
- properties.
-
- ARGUMENTS:
- p.... is actually a java_util_Properties structure
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-void properties_system_add_all(java_handle_t *p)
-{
- list_properties_entry_t *pe;
- classinfo *c;
- methodinfo *m;
- java_handle_t *key;
- java_handle_t *value;
-
- /* search for method to add properties */
-
- LLNI_class_get(p, c);
-
- m = class_resolveclassmethod(c,
- utf_put,
- utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
- NULL,
- true);
-
- if (m == NULL)
- return;
-
- /* process all properties stored in the internal table */
-
- for (pe = list_first(list_properties); pe != NULL;
- pe = list_next(list_properties, pe)) {
- /* add to the Java system properties */
-
- key = javastring_new_from_utf_string(pe->key);
- value = javastring_new_from_utf_string(pe->value);
-
- (void) vm_call_method(m, (java_handle_t *) p, key, value);
- }
-}
-#endif /* defined(ENABLE_JAVASE) */
-
-
-/* properties_dump *************************************************************
-
- Dump all property entries.
-
-*******************************************************************************/
-
-void properties_dump(void)
-{
- list_t *l;
- list_properties_entry_t *pe;
-
- /* For convenience. */
-
- l = list_properties;
-
- for (pe = list_first(l); pe != NULL; pe = list_next(l, pe)) {
- log_println("[properties_dump: key=%s, value=%s]", pe->key, pe->value);
- }
-}
-
-
-/*
- * These 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/properties.cpp - handling commandline properties
+
+ 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 <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+
+#include "mm/memory.h"
+
+#include "native/llni.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.hpp"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+
+
+/**
+ * Constructor fills the properties list with default values.
+ */
+Properties::Properties()
+{
+ int len;
+ char *p;
+
+ char *boot_class_path;
+
+#if defined(ENABLE_JAVASE)
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ struct utsname *utsnamebuf;
+# endif
+#endif
+
+#if defined(ENABLE_JRE_LAYOUT)
+ /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
+
+ p = MNEW(char, 4096);
+
+ if (os::readlink("/proc/self/exe", p, 4095) == -1)
+ os::abort_errno("readlink failed");
+
+ /* We have a path like:
+
+ /path/to/executable/bin/java
+
+ or
+
+ /path/to/executeable/jre/bin/java
+
+ Now let's strip two levels. */
+
+ p = os::dirname(p);
+ p = os::dirname(p);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ /* Set java.home. */
+
+ char* java_home = strdup(p);
+
+ /* Set the path to Java core native libraries. */
+
+ len = strlen(java_home) + strlen("/lib/classpath") + strlen("0");
+
+ char* boot_library_path = MNEW(char, len);
+
+ strcpy(boot_library_path, java_home);
+ strcat(boot_library_path, "/lib/classpath");
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ /* Find correct java.home. We check if there is a JRE
+ co-located. */
+
+ /* NOTE: We use the server VM here as it should be available on
+ all architectures. */
+
+ len =
+ strlen(p) +
+ strlen("/jre/lib/"JAVA_ARCH"/server/libjvm.so") +
+ strlen("0");
+
+ char* java_home = MNEW(char, len);
+
+ strcpy(java_home, p);
+ strcat(java_home, "/jre/lib/"JAVA_ARCH"/server/libjvm.so");
+
+ // Check if that libjvm.so exists.
+ if (os::access(java_home, F_OK) == 0) {
+ // Yes, we add /jre to java.home.
+ strcpy(java_home, p);
+ strcat(java_home, "/jre");
+ }
+ else {
+ // No, java.home is parent directory.
+ strcpy(java_home, p);
+ }
+
+ /* Set the path to Java core native libraries. */
+
+ len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
+
+ char* boot_library_path = MNEW(char, len);
+
+ strcpy(boot_library_path, java_home);
+ strcat(boot_library_path, "/lib/"JAVA_ARCH);
+
+# else
+# error unknown classpath configuration
+# endif
+
+ /* Free path. */
+
+ MFREE(p, char, len);
+
+#else
+ const char* java_home = CACAO_PREFIX;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ const char* boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR"/classpath";
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ const char* boot_library_path = JAVA_RUNTIME_LIBRARY_LIBDIR;
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ // No boot_library_path required.
+
+# else
+# error unknown classpath configuration
+# endif
+#endif
+
+ put("java.home", java_home);
+
+ /* Set the bootclasspath. */
+
+ p = os::getenv("BOOTCLASSPATH");
+
+ if (p != NULL) {
+ boot_class_path = MNEW(char, strlen(p) + strlen("0"));
+ strcpy(boot_class_path, p);
+ }
+ else {
+#if defined(ENABLE_JRE_LAYOUT)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ len =
+ strlen(java_home) + strlen("/share/cacao/vm.zip:") +
+ strlen(java_home) + strlen("/share/classpath/glibj.zip") +
+ strlen("0");
+
+ boot_class_path = MNEW(char, len);
+
+ strcpy(boot_class_path, java_home);
+ strcat(boot_class_path, "/share/cacao/vm.zip");
+ strcat(boot_class_path, ":");
+ strcat(boot_class_path, java_home);
+ strcat(boot_class_path, "/share/classpath/glibj.zip");
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ /* This is the bootclasspath taken from HotSpot (see
+ hotspot/src/share/vm/runtime/os.cpp
+ (os::set_boot_path)). */
+
+ len =
+ strlen(java_home) + strlen("/lib/resources.jar:") +
+ strlen(java_home) + strlen("/lib/rt.jar:") +
+ strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
+ strlen(java_home) + strlen("/lib/jsse.jar:") +
+ strlen(java_home) + strlen("/lib/jce.jar:") +
+ strlen(java_home) + strlen("/lib/charsets.jar:") +
+ strlen(java_home) + strlen("/classes") +
+ strlen("0");
+
+ boot_class_path = MNEW(char, len);
+
+ strcpy(boot_class_path, java_home);
+ strcat(boot_class_path, "/lib/resources.jar:");
+ strcat(boot_class_path, java_home);
+ strcat(boot_class_path, "/lib/rt.jar:");
+ strcat(boot_class_path, java_home);
+ strcat(boot_class_path, "/lib/sunrsasign.jar:");
+ strcat(boot_class_path, java_home);
+ strcat(boot_class_path, "/lib/jsse.jar:");
+ strcat(boot_class_path, java_home);
+ strcat(boot_class_path, "/lib/jce.jar:");
+ strcat(boot_class_path, java_home);
+ strcat(boot_class_path, "/lib/charsets.jar:");
+ strcat(boot_class_path, java_home);
+ strcat(boot_class_path, "/classes");
+
+# else
+# error unknown classpath configuration
+# endif
+#else
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ len =
+ strlen(CACAO_VM_ZIP) +
+ strlen(":") +
+ strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
+ strlen("0");
+
+ boot_class_path = MNEW(char, len);
+
+ strcpy(boot_class_path, CACAO_VM_ZIP);
+ strcat(boot_class_path, ":");
+ strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ /* This is the bootclasspath taken from HotSpot (see
+ hotspot/src/share/vm/runtime/os.cpp
+ (os::set_boot_path)). */
+
+ len =
+ strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:") +
+ strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:") +
+ strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:") +
+ strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:") +
+ strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:") +
+ strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:") +
+ strlen(JAVA_RUNTIME_LIBRARY_PREFIX"/classes") +
+ strlen("0");
+
+ boot_class_path = MNEW(char, len);
+
+ strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/resources.jar:");
+ strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/rt.jar:");
+ strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/sunrsasign.jar:");
+ strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jsse.jar:");
+ strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/jce.jar:");
+ strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/lib/charsets.jar:");
+ strcat(boot_class_path, JAVA_RUNTIME_LIBRARY_PREFIX"/classes");
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+ len =
+ strlen(JAVA_RUNTIME_LIBRARY_CLASSES) +
+ strlen("0");
+
+ boot_class_path = MNEW(char, len);
+
+ strcpy(boot_class_path, JAVA_RUNTIME_LIBRARY_CLASSES);
+
+# else
+# error unknown classpath configuration
+# endif
+#endif
+ }
+
+ put("sun.boot.class.path", boot_class_path);
+ put("java.boot.class.path", boot_class_path);
+
+#if defined(ENABLE_JAVASE)
+
+ /* Set the classpath. */
+
+ p = os::getenv("CLASSPATH");
+
+ char* class_path;
+
+ if (p != NULL) {
+ class_path = MNEW(char, strlen(p) + strlen("0"));
+ strcpy(class_path, p);
+ }
+ else {
+ class_path = MNEW(char, strlen(".") + strlen("0"));
+ strcpy(class_path, ".");
+ }
+
+ put("java.class.path", class_path);
+
+ // Add java.vm properties.
+ put("java.vm.specification.version", "1.0");
+ put("java.vm.specification.vendor", "Sun Microsystems Inc.");
+ put("java.vm.specification.name", "Java Virtual Machine Specification");
+ put("java.vm.version", VERSION);
+ put("java.vm.vendor", "CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
+ put("java.vm.name", "CACAO");
+
+# if defined(ENABLE_INTRP)
+ if (opt_intrp) {
+ /* XXX We don't support java.lang.Compiler */
+/* put("java.compiler", "cacao.intrp"); */
+ put("java.vm.info", "interpreted mode");
+ }
+ else
+# endif
+ {
+ /* XXX We don't support java.lang.Compiler */
+/* put("java.compiler", "cacao.jit"); */
+ put("java.vm.info", "compiled mode");
+ }
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+ /* Get properties from system. */
+
+ char* cwd = _Jv_getcwd();
+
+ char* env_user = os::getenv("USER");
+ char* env_home = os::getenv("HOME");
+ char* env_lang = os::getenv("LANG");
+
+ utsnamebuf = NEW(struct utsname);
+
+ uname(utsnamebuf);
+
+ put("java.runtime.version", VERSION);
+ put("java.runtime.name", "CACAO");
+
+ put("java.specification.version", "1.5");
+ put("java.specification.vendor", "Sun Microsystems Inc.");
+ put("java.specification.name", "Java Platform API Specification");
+
+ put("java.version", JAVA_VERSION);
+ put("java.vendor", "GNU Classpath");
+ put("java.vendor.url", "http://www.gnu.org/software/classpath/");
+
+ put("java.class.version", CLASS_VERSION);
+
+ put("gnu.classpath.boot.library.path", boot_library_path);
+
+ // Get and set java.library.path.
+ const char* java_library_path = os::getenv("LD_LIBRARY_PATH");
+
+ if (java_library_path == NULL)
+ java_library_path = "";
+
+ put("java.library.path", java_library_path);
+
+ put("java.io.tmpdir", "/tmp");
+
+# if defined(ENABLE_INTRP)
+ if (opt_intrp) {
+ put("gnu.java.compiler.name", "cacao.intrp");
+ }
+ else
+# endif
+ {
+ put("gnu.java.compiler.name", "cacao.jit");
+ }
+
+ /* Set the java.ext.dirs property. */
+
+ len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
+
+ char* extdirs = MNEW(char, len);
+
+ sprintf(extdirs, "%s/jre/lib/ext", java_home);
+
+ put("java.ext.dirs", extdirs);
+
+ /* Set the java.ext.endorsed property. */
+
+ len = strlen(java_home) + strlen("/jre/lib/endorsed") + strlen("0");
+
+ char* endorseddirs = MNEW(char, len);
+
+ sprintf(endorseddirs, "%s/jre/lib/endorsed", java_home);
+
+ put("java.endorsed.dirs", endorseddirs);
+
+# if defined(DISABLE_GC)
+ /* When we disable the GC, we mmap the whole heap to a specific
+ address, so we can compare call traces. For this reason we have
+ to add the same properties on different machines, otherwise
+ more memory may be allocated (e.g. strlen("i386")
+ vs. strlen("alpha"). */
+
+ put("os.arch", "unknown");
+ put("os.name", "unknown");
+ put("os.version", "unknown");
+# else
+ put("os.arch", JAVA_ARCH);
+ put("os.name", utsnamebuf->sysname);
+ put("os.version", utsnamebuf->release);
+# endif
+
+# if WORDS_BIGENDIAN == 1
+ put("gnu.cpu.endian", "big");
+# else
+ put("gnu.cpu.endian", "little");
+# endif
+
+ put("file.separator", "/");
+ put("path.separator", ":");
+ put("line.separator", "\n");
+
+ put("user.name", env_user ? env_user : "null");
+ put("user.home", env_home ? env_home : "null");
+ put("user.dir", cwd ? cwd : "null");
+
+ /* get locale */
+
+ if (env_lang != NULL) {
+ /* get the local stuff from the environment */
+
+ if (strlen(env_lang) <= 2) {
+ put("user.language", env_lang);
+ }
+ else {
+ if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
+ char* lang = MNEW(char, 3);
+ strncpy(lang, (char*) &env_lang[0], 2);
+ lang[2] = '\0';
+
+ char* country = MNEW(char, 3);
+ strncpy(country, (char*) &env_lang[3], 2);
+ country[2] = '\0';
+
+ put("user.language", lang);
+ put("user.country", country);
+ }
+ }
+ }
+ else {
+ /* if no default locale was specified, use `en_US' */
+
+ put("user.language", "en");
+ put("user.country", "US");
+ }
+
+# elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+ /* Actually this property is set by OpenJDK, but we need it in
+ nativevm_preinit(). */
+
+ put("sun.boot.library.path", boot_library_path);
+
+ // Set the java.ext.dirs property.
+ len =
+ strlen(java_home) + strlen("/lib/ext") +
+ strlen(":") +
+ strlen("/usr/java/packages/lib/ext") +
+ strlen("0");
+
+ char* extdirs = MNEW(char, len);
+
+ sprintf(extdirs, "%s/lib/ext:/usr/java/packages/lib/ext", java_home);
+
+ put("java.ext.dirs", extdirs);
+
+ // Set the java.ext.endorsed property.
+ len = strlen(java_home) + strlen("/lib/endorsed") + strlen("0");
+
+ char* endorseddirs = MNEW(char, len);
+
+ sprintf(endorseddirs, "%s/lib/endorsed", java_home);
+
+ put("java.endorsed.dirs", endorseddirs);
+
+# else
+
+# error unknown classpath configuration
+
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ put("microedition.configuration", "CLDC-1.1");
+ put("microedition.platform", "generic");
+ put("microedition.encoding", "ISO8859_1");
+ put("microedition.profiles", "");
+
+#else
+
+# error unknown Java configuration
+
+#endif
+}
+
+
+/**
+ * Add the given property to the given Java system properties.
+ *
+ * @param p Java properties object.
+ * @param key Key.
+ * @param value Value.
+ */
+void Properties::put(java_handle_t* p, const char* key, const char* value)
+{
+ // Get Properties.put() method to add properties.
+ classinfo* c;
+ LLNI_class_get(p, c);
+
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_put,
+ utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ // Add to the Java system properties.
+ java_handle_t* k = javastring_new_from_utf_string(key);
+ java_handle_t* v = javastring_new_from_utf_string(value);
+
+ (void) vm_call_method(m, p, k, v);
+}
+
+
+/**
+ * Put the given property into the internal property map. If there's
+ * already an entry with the same key, replace it.
+ *
+ * @param key Key.
+ * @param value Value.
+ */
+void Properties::put(const char* key, const char* value)
+{
+ // Try to find the key.
+ std::map<const char*, const char*>::iterator it = _properties.find(key);
+
+ // The key is already in the map.
+ if (it != _properties.end()) {
+#if !defined(NDEBUG)
+ if (opt_DebugProperties) {
+ printf("[Properties::put: key=%s, old value=%s, new value=%s]\n",
+ key, it->second, value);
+ }
+#endif
+
+ // Replace the value in the current entry.
+ it->second = value;
+
+ return;
+ }
+
+ // The key was not found, insert the pair.
+#if !defined(NDEBUG)
+ if (opt_DebugProperties) {
+ printf("[Properties::put: key=%s, value=%s]\n", key, value);
+ }
+#endif
+
+ _properties.insert(std::make_pair(key, value));
+}
+
+
+/**
+ * Get a property entry from the internal property map.
+ *
+ * @param key Key.
+ *
+ * @return Value associated with the key or NULL when not found.
+ */
+const char* Properties::get(const char* key)
+{
+ // Try to find the key.
+ std::map<const char*, const char*>::iterator it = _properties.find(key);
+
+ // The key is not in the map.
+ if (it == _properties.end())
+ return NULL;
+
+ // Return the value.
+ return it->second;
+}
+
+
+/**
+ * Fill the given Java system properties with all properties from the
+ * internal properties map.
+ *
+ * @param p Java Properties object.
+ */
+#if defined(ENABLE_JAVASE)
+void Properties::fill(java_handle_t* p)
+{
+ // Get Properties.put() method to add properties.
+ classinfo* c;
+ LLNI_class_get(p, c);
+
+ methodinfo* m = class_resolveclassmethod(c,
+ utf_put,
+ utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
+ NULL,
+ true);
+
+ if (m == NULL)
+ return;
+
+ // Iterator over all properties.
+ for (std::map<const char*, const char*>::iterator it = _properties.begin(); it != _properties.end(); it++) {
+ // Put into the Java system properties.
+ java_handle_t* key = javastring_new_from_utf_string(it->first);
+ java_handle_t* value = javastring_new_from_utf_string(it->second);
+
+ (void) vm_call_method(m, p, key, value);
+ }
+}
+#endif
+
+
+/**
+ * Dump all property entries.
+ */
+#if !defined(NDEBUG)
+void Properties::dump()
+{
+ for (std::map<const char*, const char*>::iterator it = _properties.begin(); it != _properties.end(); it++) {
+ log_println("[Properties::dump: key=%s, value=%s]", it->first, it->second);
+ }
+}
+#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/properties.h - handling commandline properties
-
- 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 _PROPERTIES_H
-#define _PROPERTIES_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-void properties_init(void);
-void properties_set(void);
-
-void properties_add(const char *key, const char *value);
-const char *properties_get(const char *key);
-
-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);
-#endif
-
-void properties_dump(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _PROPERTIES_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/properties.hpp - handling commandline properties
+
+ 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 _PROPERTIES_HPP
+#define _PROPERTIES_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+
+#include <map>
+
+#include "vm/os.hpp"
+
+
+class ltstr {
+public:
+ bool operator()(const char* s1, const char* s2) const
+ {
+ return os::strcmp(s1, s2) < 0;
+ }
+};
+
+
+/**
+ * Commandline properties.
+ */
+class Properties {
+private:
+ std::map<const char*, const char*, ltstr> _properties;
+
+public:
+ Properties();
+
+ // Static function.
+ static void put(java_handle_t* p, const char* key, const char* value);
+
+ void put(const char* key, const char* value);
+ const char* get(const char* key);
+ void fill(java_handle_t* p);
+#if !defined(NDEBUG)
+ void dump();
+#endif
+};
+
+#endif
+
+#endif // _PROPERTIES_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 "vm/class.h"
#include "vm/descriptor.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/utf8.h"
#include "vm/global.h"
#include "vm/globals.hpp"
#include "vm/linker.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/verify/typeinfo.h"
#include "vm/types.h"
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/references.h"
-#include "vm/jit/jit.h"
+#include "vm/jit/jit.hpp"
#include "vm/jit/reg.h"
+
+#include "vm/jit/ir/instruction.hpp"
#include "vm/jit/verify/typeinfo.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
void resolve_handle_pending_exception(bool throwError);
bool resolve_class_from_name(classinfo* referer,methodinfo *refmethod,
void unresolved_method_debug_dump(unresolved_method *ref,FILE *file);
void unresolved_subtype_set_debug_dump(unresolved_subtype_set *stset,FILE *file);
#endif
+
+#ifdef __cplusplus
+}
+#endif
#endif /* _RESOLVE_H */
#endif
#include "threads/thread.hpp"
+#include "threads/threadlist.hpp"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
SA_NODEFER | SA_SIGINFO);
# endif
-# if defined(__ARM__) || defined(__I386__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+# if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
/* XXX use better defines for that (in arch.h) */
/* SIGILL handler */
case SIGQUIT:
/* print a thread dump */
#if defined(ENABLE_THREADS)
- threads_dump();
+ ThreadList_dump_threads();
#endif
#if defined(ENABLE_STATISTICS)
void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p);
#endif
-#if defined(__ARM__) || defined(__I386__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__MIPS__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__S390__) || defined(__X86_64__) || defined(__M68K__)
/* XXX use better defines for that (in arch.h) */
void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p);
#endif
#include "vm/options.h"
#include "vm/stackmap.h"
#include "vm/statistics.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
/* stackmap_get_verification_type_info *****************************************
#include "vm/types.h"
#include "vm/global.h"
-#include "vm/loader.h"
+#include "vm/loader.hpp"
#include "vm/method.h"
#include "toolbox/logging.h"
+#include "threads/thread.hpp"
+
#include "vm/class.h"
-#include "vm/field.h"
+#include "vm/field.hpp"
#include "vm/global.h"
#include "vm/method.h"
#include "vm/options.h"
#include "vm/statistics.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
/* global variables ***********************************************************/
*******************************************************************************/
+Mutex *loadingtime_lock = Mutex_new();
+
void loadingtime_start(void)
{
+ Mutex_lock(loadingtime_lock);
+
loadingtime_recursion++;
if (loadingtime_recursion == 1)
loadingstarttime = getcputime();
+ else {
+ int end = getcputime();
+ loadingtime += (end - loadingstarttime);
+
+ loadingstarttime = loadingstoptime = end;
+ }
+
+
+ Mutex_unlock(loadingtime_lock);
}
void loadingtime_stop(void)
{
- if (loadingtime_recursion == 1) {
- loadingstoptime = getcputime();
- loadingtime += (loadingstoptime - loadingstarttime);
+ Mutex_lock(loadingtime_lock);
+
+ loadingstoptime = getcputime();
+ loadingtime += (loadingstoptime - loadingstarttime);
+
+ if (loadingtime_recursion > 1) {
+ loadingstarttime = loadingstoptime;
}
loadingtime_recursion--;
+
+ Mutex_unlock(loadingtime_lock);
}
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
s8 getcputime(void);
void loadingtime_start(void);
void jnicallXmethodnvokation(void);
void jniinvokation(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _STATISTICS_H */
#include "mm/memory.h"
-#include "native/jni.h"
#include "native/llni.h"
-#include "threads/lock-common.h"
+#include "threads/lock.hpp"
-#include "vm/array.h"
-#include "vm/builtin.h"
+#include "vm/array.hpp"
+#include "vm/jit/builtin.hpp"
#include "vm/exceptions.hpp"
#include "vm/globals.hpp"
#include "vm/javaobjects.hpp"
#include "vm/statistics.h"
#include "vm/string.hpp"
#include "vm/utf8.h"
-#include "vm/vm.hpp"
/* global variables ***********************************************************/
if (js.is_null() || (js.get_value() == NULL)) {
/* error in hashtable found */
-
- vm_abort("stringtable_update: invalid literalstring in hashtable");
+ os::abort("stringtable_update: invalid literalstring in hashtable");
}
a = LLNI_UNWRAP(js.get_value());
#endif
#if defined(ENABLE_THREADS)
- lock_init_object_lock(o);
+ o->lockword.init();
#endif
o->vftbl = class_java_lang_String->vftbl;
+++ /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.cpp - 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/mutex.hpp"
+
+#include "toolbox/list.hpp"
+#include "toolbox/logging.h"
+#include "toolbox/util.h"
+
+#include "vm/exceptions.hpp"
+#include "vm/loader.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/properties.hpp"
+#include "vm/suck.hpp"
+#include "vm/vm.hpp"
+#include "vm/zip.h"
+
+
+/* global variables ***********************************************************/
+
+List<list_classpath_entry*>* list_classpath_entries;
+
+
+/* suck_init *******************************************************************
+
+ Initializes the suck subsystem like initializing the classpath
+ entries list.
+
+*******************************************************************************/
+
+bool suck_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("suck_init");
+
+#warning Move this list into VM.
+ list_classpath_entries = new List<list_classpath_entry*>();
+
+ /* 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
+ os::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_classpath_entries->push_back(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;
+ s4 pathlen;
+ struct dirent **namelist;
+ s4 n;
+ s4 i;
+ s4 namlen;
+ char *p;
+
+ /* get the property value */
+ Properties properties = VM::get_current()->get_properties();
+ 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;
+ char* 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((const char*) path, &namelist, &scandir_filter, (int (*)(const void*, const void*)) &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*.
+ 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.put("sun.boot.class.path", p);
+ properties.put("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)
+{
+ u8 a;
+
+ a = SUCK_BE_U8(cb->pos);
+ cb->pos += 8;
+
+ return a;
+}
+
+
+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 (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end() && cb == NULL; it++) {
+ lce = *it;
+
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+
+ /* enter a monitor on zip/jar archives */
+
+ lce->mutex->lock();
+
+ /* try to get the file in current archive */
+
+ cb = zip_get(lce, c);
+
+ /* leave the monitor */
+
+ lce->mutex->unlock();
+
+ } 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:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+++ /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/suck.hpp - 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_HPP
+#define _SUCK_HPP
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "threads/mutex.hpp"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/list.hpp"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.hpp"
+
+
+/* list_classpath_entry *******************************************************/
+
+enum {
+ CLASSPATH_PATH,
+ CLASSPATH_ARCHIVE
+};
+
+typedef struct list_classpath_entry list_classpath_entry;
+
+struct list_classpath_entry {
+#if defined(ENABLE_THREADS)
+ Mutex *mutex; /* mutex locking on zip/jar files */
+#endif
+ s4 type;
+ char *path;
+ s4 pathlen;
+#if defined(ENABLE_ZLIB)
+ hashtable *htclasses;
+#endif
+};
+
+
+/* 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))
+#define SUCK_LE_U8(p) *((u8 *) (p))
+
+#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]))
+
+#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 /* 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]))
+
+#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]))
+
+
+#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 ***********************************************************/
+
+#ifdef __cplusplus
+extern List<list_classpath_entry*>* list_classpath_entries;
+#else
+extern List* list_classpath_entries;
+#endif
+
+/* function prototypes ********************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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_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/lock-common.h"
+#include "threads/mutex.hpp"
#include "toolbox/hashtable.h"
utf *u; /* hashtable element */
u2 i;
- LOCK_MONITOR_ENTER(hashtable_utf->header);
+ Mutex_lock(hashtable_utf->mutex);
#if defined(ENABLE_STATISTICS)
if (opt_stat)
/* symbol found in hashtable */
- LOCK_MONITOR_EXIT(hashtable_utf->header);
+ Mutex_unlock(hashtable_utf->mutex);
return u;
}
hashtable_utf = newhash;
}
- LOCK_MONITOR_EXIT(hashtable_utf->header);
+ Mutex_unlock(hashtable_utf->mutex);
return u;
}
u4 left; /* unicode characters left */
u4 buflength; /* utf length in bytes of the u2 array */
utf *result; /* resulting utf-string */
- int i;
+ int i;
/* determine utf length in bytes and allocate memory */
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* initialize the utf8 subsystem */
void utf8_init(void);
/* show utf-table */
void utf_show(void);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _UTF_H */
--- /dev/null
+/* src/vm/vftbl.hpp - virtual function table
+
+ 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 _VFTBL_HPP
+#define _VFTBL_HPP
+
+// Forward declaration.
+typedef struct _vftbl vftbl_t;
+
+#include "config.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 ---> +---------------+
+
+*******************************************************************************/
+
+// Includes.
+#include "vm/class.h"
+#include "vm/references.h"
+
+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 */
+};
+
+#endif // _VFTBL_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 "vm/jit/abi-asm.h"
#include "mm/codememory.h"
+#include "mm/dumpmemory.hpp"
#include "mm/gc.hpp"
#include "mm/memory.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
#include "native/llni.h"
-#include "native/localref.h"
-#include "native/native.h"
+#include "native/localref.hpp"
+#include "native/native.hpp"
-#include "native/vm/nativevm.h"
+#include "native/vm/nativevm.hpp"
-#include "threads/lock-common.h"
-#include "threads/threadlist.h"
+#include "threads/lock.hpp"
#include "threads/thread.hpp"
#include "toolbox/logging.h"
-#include "vm/array.h"
+#include "vm/array.hpp"
#if defined(ENABLE_ASSERTION)
-#include "vm/assertion.h"
+#include "vm/assertion.hpp"
#endif
-#include "vm/builtin.h"
+#include "vm/jit/builtin.hpp"
#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/finalizer.h"
#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/properties.hpp"
#include "vm/signallocal.h"
#include "vm/statistics.h"
#include "vm/string.hpp"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
#include "vm/vm.hpp"
-#include "vm/jit/argument.h"
+#include "vm/jit/argument.hpp"
#include "vm/jit/asmpart.h"
-#include "vm/jit/code.h"
+#include "vm/jit/code.hpp"
#if defined(ENABLE_DISASSEMBLER)
# include "vm/jit/disass.h"
#endif
-#include "vm/jit/jit.h"
#include "vm/jit/jitcache.hpp"
#include "vm/jit/methodtree.h"
# include "vm/jit/optimizing/profile.h"
#endif
-#include "vm/jit/optimizing/recompile.h"
+#include "vm/jit/optimizing/recompiler.hpp"
#if defined(ENABLE_PYTHON)
# include "vm/jit/python.h"
/**
- * This is _the_ instance of the VM.
+ * This is _the_ VM instance.
*/
-VM* vm;
+VM* VM::_vm = NULL;
/* global variables ***********************************************************/
/* CACAO options */
OPT_VERBOSE1,
- OPT_NOIEEE,
#if defined(ENABLE_STATISTICS)
OPT_TIME,
#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 },
#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
}
-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);
// Instantiate a new VM.
try {
- vm = new VM(_vm_args);
+ _vm = new VM(_vm_args);
}
catch (std::exception e) {
// FIXME How can we delete the resources allocated?
// FREE(env, _Jv_JNIEnv);
// FREE(vm, _Jv_JavaVM);
- vm = NULL;
+ _vm = NULL;
return false;
}
// Return the values.
- *p_vm = vm->get_javavm();
- *p_env = vm->get_jnienv();
+ *p_vm = _vm->get_javavm();
+ *p_env = _vm->get_jnienv();
return true;
}
// Make ourself globally visible.
// XXX Is this a good idea?
- vm = this;
+ _vm = this;
/* create and fill a JavaVM structure */
/* Install the exit handler. */
if (atexit(vm_exit_handler))
- vm_abort("atexit failed: %s\n", strerror(errno));
+ os::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. */
+ // First of all, parse the -XX options.
#if defined(ENABLE_VMLOG)
vmlog_cacao_init_options();
options_xx(vm_args);
+ // After -XX options are parsed, print the build-time
+ // configuration, if requested.
+ if (opt_PrintConfig)
+ print_build_time_config();
+
#if defined(ENABLE_VMLOG)
vmlog_cacao_init();
#endif
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) {
classpath. */
// FIXME Make class_path const char*.
- class_path = (char*) properties_get("java.class.path");
+ 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);
+ _properties.put("java.class.path", p);
#endif
MFREE(class_path, char, strlen(class_path));
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);
+ _properties.put(opt_arg, opt_arg + i + 1);
goto opt_d_done;
}
}
/* if no '=' is given, just create an empty property */
- properties_add(opt_arg, "");
+ _properties.put(opt_arg, "");
opt_d_done:
break;
new boot classpath. */
// FIXME Make boot_class_path const char*.
- boot_class_path = (char*) properties_get("sun.boot.class.path");
+ 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);
+ _properties.put("sun.boot.class.path", p);
+ _properties.put("java.boot.class.path", p);
MFREE(boot_class_path, char, strlen(boot_class_path));
break;
/* Append to bootclasspath. */
// FIXME Make boot_class_path const char*.
- boot_class_path = (char*) properties_get("sun.boot.class.path");
+ boot_class_path = (char*) _properties.get("sun.boot.class.path");
len = strlen(boot_class_path);
strcat(p, ":");
strcat(p, opt_arg);
- properties_add("sun.boot.class.path", p);
- properties_add("java.boot.class.path", p);
+ _properties.put("sun.boot.class.path", p);
+ _properties.put("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");
+ boot_class_path = (char*) _properties.get("sun.boot.class.path");
len = strlen(boot_class_path);
strcat(p, ":");
strcat(p, boot_class_path);
- properties_add("sun.boot.class.path", p);
- properties_add("java.boot.class.path", p);
+ _properties.put("sun.boot.class.path", p);
+ _properties.put("java.boot.class.path", p);
MFREE(boot_class_path, char, len);
break;
classes. */
// FIXME Make boot_class_path const char*.
- boot_class_path = (char*) properties_get("sun.boot.class.path");
+ boot_class_path = (char*) _properties.get("sun.boot.class.path");
len =
strlen(CACAO_VM_ZIP) +
strcat(p, ":");
strcat(p, opt_arg);
- properties_add("sun.boot.class.path", p);
- properties_add("java.boot.class.path", p);
+ _properties.put("sun.boot.class.path", p);
+ _properties.put("java.boot.class.path", p);
MFREE(boot_class_path, char, strlen(boot_class_path));
break;
opt_version = true;
break;
- case OPT_NOIEEE:
- opt_noieee = true;
- break;
-
#if defined(ENABLE_VERIFIER)
case OPT_NOVERIFY:
opt_verify = false;
opt_showdisassemble = true;
compileverbose = true;
break;
-
- case 'o':
- opt_shownops = true;
- break;
#endif
case 'd':
}
}
+ // Print the preliminary run-time VM configuration after options
+ // are parsed.
+ if (opt_PrintConfig)
+ print_run_time_config();
+
#if defined(ENABLE_JVMTI)
if (jvmti) {
jvmti_set_phase(JVMTI_PHASE_ONLOAD);
gc_init(opt_heapmaxsize, opt_heapstartsize);
#if defined(ENABLE_THREADS)
- /* BEFORE: threads_preinit */
-
- threadlist_init();
-
/* AFTER: gc_init */
threads_preinit();
/* install architecture dependent signal handlers */
if (!signal_init())
- vm_abort("vm_create: signal_init failed");
+ os::abort("vm_create: signal_init failed");
#if defined(ENABLE_INTRP)
/* Allocate main thread stack on the Java heap. */
/* AFTER: threads_preinit */
if (!string_init())
- vm_abort("vm_create: string_init failed");
+ os::abort("vm_create: string_init failed");
/* AFTER: threads_preinit */
/* AFTER: thread_preinit */
if (!suck_init())
- vm_abort("vm_create: suck_init failed");
+ os::abort("vm_create: suck_init failed");
suck_add_from_property("java.endorsed.dirs");
/* AFTER: utf8_init */
// FIXME Make boot_class_path const char*.
- boot_class_path = (char*) properties_get("sun.boot.class.path");
+ 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");
+ os::abort("vm_create: classcache_init failed");
/* Initialize the code memory management. */
/* AFTER: threads_preinit */
threads_preinit) */
if (!finalizer_init())
- vm_abort("vm_create: finalizer_init failed");
+ os::abort("vm_create: finalizer_init failed");
/* Initialize the JIT compiler. */
pythonpass_init();
#endif
- /* BEFORE: loader_preinit */
-
- Package::initialize();
-
/* AFTER: utf8_init, classcache_init */
loader_preinit();
linker_preinit();
- /* AFTER: loader_preinit, linker_preinit */
-
- primitive_init();
+ // AFTER: loader_preinit, linker_preinit
+ Primitive::initialize_table();
loader_init();
linker_init();
- /* AFTER: loader_init, linker_init */
-
- primitive_postinit();
+ // AFTER: loader_init, linker_init
+ Primitive::post_initialize_table();
method_init();
#if defined(ENABLE_JIT)
#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");
+ os::abort("vm_create: builtin_init failed");
/* Register the native methods implemented in the VM. */
/* BEFORE: threads_init */
(e.g. NewGlobalRef). */
if (!jni_init())
- vm_abort("vm_create: jni_init failed");
+ os::abort("vm_create: jni_init failed");
#endif
#if defined(ENABLE_JNI) || defined(ENABLE_HANDLES)
/* BEFORE: threads_init */
if (!localref_table_init())
- vm_abort("vm_create: localref_table_init failed");
+ os::abort("vm_create: localref_table_init failed");
#endif
/* Iinitialize some important system classes. */
/* initialize profiling */
if (!profile_init())
- vm_abort("vm_create: profile_init failed");
+ os::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__)
if (threads_pthreads_implementation_nptl)
#endif
if (!signal_start_thread())
- vm_abort("vm_create: signal_start_thread failed");
+ os::abort("vm_create: signal_start_thread failed");
/* finally, start the finalizer thread */
if (!finalizer_start_thread())
- vm_abort("vm_create: finalizer_start_thread failed");
+ os::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");
+ os::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");
+ // Start the recompilation thread (must be done before the
+ // profiling thread).
+ // FIXME Only works for one recompiler.
+ _recompiler.start();
# if defined(ENABLE_PROFILING)
/* start the profile sampling thread */
/* if (opt_prof) */
/* if (!profile_start_thread()) */
-/* vm_abort("vm_create: profile_start_thread failed"); */
+/* os::abort("vm_create: profile_start_thread failed"); */
# endif
#endif
_created = true;
_initializing = false;
- /* Print the VM configuration after all stuff is set and the VM is
- initialized. */
-
+ // Print the run-time VM configuration after all stuff is set and
+ // the VM is initialized.
if (opt_PrintConfig)
- vm_printconfig();
+ print_run_time_config();
+}
+
+
+/**
+ * Print build-time (default) VM configuration.
+ */
+void VM::print_build_time_config(void)
+{
+ puts("CACAO "VERSION" configure/build options:");
+ puts("");
+ puts(" ./configure: "VERSION_CONFIGURE_ARGS"");
+#if defined(__VERSION__)
+ puts(" CC : "VERSION_CC" ("__VERSION__")");
+ puts(" CXX : "VERSION_CXX" ("__VERSION__")");
+#else
+ puts(" CC : "VERSION_CC"");
+ puts(" CXX : "VERSION_CXX"");
+#endif
+ puts(" CFLAGS : "VERSION_CFLAGS"");
+ puts(" CXXFLAGS : "VERSION_CXXFLAGS"");
+
+ puts("");
+
+ puts("Build-time (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("");
+}
+
+
+/**
+ * Print run-time VM configuration.
+ */
+void VM::print_run_time_config()
+{
+ puts("Run-time 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"));
+
+ puts("");
}
strcpy(p, mainname);
#if defined(ENABLE_JAVASE)
- properties_add("java.class.path", p);
+ VM::get_current()->get_properties().put("java.class.path", p);
#endif
}
else {
the application's main method exits. */
if (!thread_detach_current_thread())
- vm_abort("vm_run: Could not detach main thread.");
+ os::abort("vm_run: Could not detach main thread.");
#endif
/* Destroy the JavaVM. */
}
-/* 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
pc = disassinstr((u1*) pc);
#endif
- vm_abort("Aborting...");
+ os::abort("Aborting...");
}
}
if (m == NULL)
- vm_abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
+ os::abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
opt_method, opt_signature ? opt_signature : "");
jit_compile(m);
{ \
uint64_t *array; \
type value; \
- int32_t dumpmarker; \
\
if (m->code == NULL) \
if (!jit_compile(m)) \
return 0; \
\
THREAD_NATIVEWORLD_EXIT; \
- DMARKER; \
+ \
+ DumpMemoryArea dma; \
\
array = argument_vmarray_from_valist(m, o, ap); \
value = vm_call##name##_array(m, array); \
\
- DRELEASE; \
THREAD_NATIVEWORLD_ENTER; \
\
return value; \
{ \
uint64_t *array; \
type value; \
- int32_t dumpmarker; \
\
if (m->code == NULL) \
if (!jit_compile(m)) \
return 0; \
\
THREAD_NATIVEWORLD_EXIT; \
- DMARKER; \
+ \
+ DumpMemoryArea dma; \
\
array = argument_vmarray_from_jvalue(m, o, args); \
value = vm_call##name##_array(m, array); \
\
- DRELEASE; \
THREAD_NATIVEWORLD_ENTER; \
\
return value; \
java_handle_t *xptr;
java_handle_t *ro;
imm_union value;
- int32_t dumpmarker;
/* Prevent compiler warnings. */
THREAD_NATIVEWORLD_EXIT;
- /* mark start of dump memory area */
-
- DMARKER;
+ // Create new dump memory area.
+ DumpMemoryArea dma;
/* 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;
break;
default:
- vm_abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
+ os::abort("vm_call_method_objectarray: invalid return type %d", m->parseddesc->returntype.primitivetype);
}
- /* release dump area */
-
- DRELEASE;
-
/* enter the nativeworld again */
THREAD_NATIVEWORLD_ENTER;
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(); }
+JavaVM* VM_get_javavm() { return VM::get_current()->get_javavm(); }
+JNIEnv* VM_get_jnienv() { return VM::get_current()->get_jnienv(); }
+bool VM_is_initializing() { return VM::get_current()->is_initializing(); }
+bool VM_is_created() { return VM::get_current()->is_created(); }
+int64_t VM_get_starttime() { return VM::get_current()->get_starttime(); }
+
+void vm_abort(const char* text, ...)
+{
+ va_list ap;
+
+ va_start(ap, text);
+ os::abort(text, ap);
+ va_end(ap);
+}
+
+void vm_abort_errnum(int errnum, const char* text, ...)
+{
+ va_list ap;
+
+ va_start(ap, text);
+ os::abort_errnum(errnum, text, ap);
+ va_end(ap);
+}
+
+void vm_abort_errno(const char* text, ...)
+{
+ va_list ap;
+
+ va_start(ap, text);
+ os::abort_errno(text, ap);
+ va_end(ap);
+}
}
#include <stdarg.h>
#include <stdint.h>
-#include "vm/types.h"
+// We need the JNI types for the VM class.
+#include "native/jni.hpp"
+#include "native/native.hpp"
-#include "native/jni.h"
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+# include "native/vm/openjdk/hpi.hpp"
+# include "native/vm/openjdk/management.hpp"
+#endif
-#include "vm/global.h"
+#include "vm/properties.hpp"
+
+#include "vm/jit/optimizing/recompiler.hpp"
-#include "vm/class.h"
-#include "vm/method.h"
#ifdef __cplusplus
*/
class VM {
private:
+ // This is _the_ VM instance.
+ static VM* _vm;
+
// JNI variables.
JavaVM* _javavm;
JNIEnv* _jnienv;
bool _exiting;
int64_t _starttime;
+ // Subsystems.
+ Properties _properties; ///< Commandline properties.
+#if defined(ENABLE_THREADS)
+ Recompiler _recompiler; ///< JIT recompilation framework.
+#endif
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ HPI _hpi; ///< Host Porting Interface.
+ Management _management; ///< Java management interface.
+#endif
+ NativeLibraries _nativelibraries; ///< Native library table.
+ NativeMethods _nativemethods; ///< Native methods table.
+
public:
// Constructor, Destructor.
VM(JavaVMInitArgs*);
// Static methods.
static bool create(JavaVM** p_vm, void** p_env, void* vm_args);
+ static VM* get_current() { return _vm; }
+
+ static void print_build_time_config();
+ void print_run_time_config();
// Getters for private members.
JavaVM* get_javavm() { return _javavm; }
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;
+ Properties& get_properties () { return _properties; }
+ Recompiler& get_recompiler () { return _recompiler; } // REMOVEME
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ HPI& get_hpi () { return _hpi; }
+ Management& get_management () { return _management; }
+#endif
+ NativeLibraries& get_nativelibraries() { return _nativelibraries; }
+ NativeMethods& get_nativemethods () { return _nativemethods; }
+};
#else
#endif
+
+// Includes.
+#include "vm/global.h"
+#include "vm/method.h"
+
+
/* These C methods are the exported interface. ********************************/
#ifdef __cplusplus
/* export global variables ****************************************************/
#if defined(ENABLE_INTRP)
-extern u1 *intrp_main_stack;
+extern uint8_t* intrp_main_stack;
#endif
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);
+int32_t vm_destroy(JavaVM *vm);
+void vm_exit(int32_t status);
+void vm_shutdown(int32_t 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_objectarray(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params);
+
+// Legacy C interface.
+void vm_abort(const char* text, ...);
+void vm_abort_errnum(int errnum, const char* text, ...);
+void vm_abort_errno(const char* text, ...);
+
#ifdef __cplusplus
}
#endif
#include "vm/types.h"
+#include "vm/descriptor.h" /* needed to prevent circular dependency */
#include "toolbox/hashtable.h"
#include "mm/memory.h"
#include "vm/global.h"
-#include "vm/suck.h"
+#include "vm/suck.hpp"
#include "vm/utf8.h"
#include "vm/vm.hpp"
#include "vm/zip.h"
#ifndef _ZIP_H
#define _ZIP_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#include "config.h"
#include "vm/types.h"
#include "vm/class.h"
#include "vm/global.h"
-#include "vm/loader.h"
-#include "vm/suck.h"
+#include "vm/loader.hpp"
+#include "vm/suck.hpp"
#include "vm/utf8.h"
/* function prototypes ********************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
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);
/* src/tests/native/checkjni.c - for testing JNI stuff
- 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,
- 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 "config.h"
+
#include <stdio.h>
#include <string.h>
-#include "config.h"
-#include "native/jni.h"
+#include INCLUDE_JNI_MD_H
+#include INCLUDE_JNI_H
JNIEXPORT jboolean JNICALL Java_checkjni_IsAssignableFrom(JNIEnv *env, jclass clazz, jclass sub, jclass sup)
/* tests/native/test.c - for testing native stuff
- 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,
- 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
-
-
*/
+#include "config.h"
+
#include <stdio.h>
-#include "config.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
JNIEXPORT void JNICALL Java_test_nsub(JNIEnv *env, jclass clazz)
/* tests/regression/native/testarguments.c - tests argument passing
- 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,
- 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"
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include "native/jni.h"
+#include INCLUDE_JNI_MD_H
+#include INCLUDE_JNI_H
JNIEXPORT jobject JNICALL Java_testarguments_adr(JNIEnv *env, jclass clazz, jint i)
/* tests/native/testgetobjectclass0.c - tests argument passing
- 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,
- 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: Joseph Wenninger
-
-
*/
#include "config.h"
-#include "native/jni.h"
+#include "native/jni.hpp"
JNIEXPORT void JNICALL Java_testgetobjectclass0_getobjectclass0(JNIEnv *env, jclass clazz)
--- /dev/null
+// This pathological test tries to grow a FLC list as long as possible before
+// the threads from the previous FLC list have resumed running. Every one on
+// the old list then has to scan the entire new list.
+
+// The CACAO patch in file sableContention.patch can be used to examine the
+// maximum length. With 500 threads on a quad-core system, I managed to get to
+// about 120.
+
+class sableContention {
+ public Object a[] = null;
+ public tt ts[] = null;
+ final int NUM = 500;
+
+ class tt extends Thread {
+ sableContention y;
+ int x;
+ tt(sableContention y, int x) {
+ this.y = y;
+ this.x = x;
+ }
+ public void run() {
+ int i = 1;
+ synchronized(y.a[x]) {
+ if (x==0) {
+ for (; i<NUM*3/4; i++)
+ y.ts[i].start();
+ y.a[x].notify();
+ }
+ }
+ if (x==0)
+ for (; i<NUM; i++)
+ y.ts[i].start();
+ for (int j=0; j<NUM/10; j++)
+ synchronized(y.a[(x+j)%(NUM-1)+1]) {
+ }
+ }
+ }
+
+ private void l(int f) {
+ try {
+ synchronized(a[NUM-1-f]) {
+ if (f > 0) {
+ l(f-1);
+ if (f<10)
+ Thread.sleep(0, f*100 * 1000);
+ }
+ else {
+ ts = new tt[NUM];
+ for (int i=0; i<NUM; i++)
+ ts[i] = new tt(this, i);
+ ts[0].start();
+ a[0].wait();
+ }
+ }
+ } catch (InterruptedException e) {
+ }
+ }
+
+ private void r() {
+ for (;;) {
+ a = new Object[NUM];
+ for (int i=0; i<NUM; i++)
+ a[i] = new Object();
+ l(NUM-1);
+ for (int i=0; i<NUM; i++)
+ try {
+ ts[i].join();
+ } catch (InterruptedException e) {
+ }
+ System.out.println("running");
+ }
+ }
+
+ public static void main(String[] args) {
+ new sableContention().r();
+ }
+}
+
+/*
+ * These 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: java
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+--- a/src/threads/lock.cpp Thu Sep 11 14:52:50 2008 +0200
++++ b/src/threads/lock.cpp Thu Sep 11 15:13:24 2008 +0200
+@@ -717,6 +717,7 @@
+ for (;;)
+ {
+ threadobject *current;
++ int i = 0;
+
+ // Wait until another thread sees the flc bit and notifies
+ // us of unlocking.
+@@ -726,8 +727,17 @@
+ break;
+ /* Traverse FLC list looking if we're still there */
+ current = t_other->flc_list;
+- while (current && current != t)
++ while (current && current != t) {
++ i++;
+ current = current->flc_next;
++ }
++ {
++ static int umax = 0;
++ if (i>umax) {
++ printf("sable len %d\n", i);
++ umax = i;
++ }
++ }
+ if (!current)
+ /* not in list anymore, can stop waiting */
+ break;