*.lo
*.a
*.o
+*.aux
+*.ids
+*.idx
+*.log
+*.out
+*.toc
Makefile
Makefile.in
TAGS
missing
contrib/setenvinstalled
contrib/setenvsource
+doc/doxygen/html
+doc/doxygen/latex
+m4/libtool.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
src/cacao/cacao
src/cacaoh/cacaoh
-src/lib/classes/
-src/lib/vm.zip
+src/classes/classes/
+src/classes/vm.zip
src/native/include/*.h
src/scripts/java
tests/*.class
tests/regression/*.class
-tests/regression/codepatching/*.class
+tests/regression/assertion/*.class
+tests/regression/assertion/packagetest/*.class
+tests/regression/bugzilla/*.class
tests/regression/jasmin/*.class
+tests/regression/junit/*.class
tests/regression/native/*.class
tests/regression/native/*.h
tests/regression/native/*.so
tests/regression/resolving/classes1/*.class
tests/regression/resolving/classes2/*.class
tests/regression/resolving/classes3/*.class
+tests/threads/*.class
## Makefile.am
##
-## 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.
##
## 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@cacaojvm.org
-##
-## Authors: Christian Thalinger
-##
-## Changes:
ACLOCAL_AMFLAGS = -I m4
-New in release 0.99 (August x, 2007)
+New in release 0.99 (March x, 2008)
* Initial support to use OpenJDK as Java core library.
* Fixed memory leak in Boehm-GC.
* Removed genoffsets, cross-compilation is now much easier.
* Implemented Class.isAnonymousClass(), isLocalClass() and
isMemberClass() for GNU Classpath.
+ * Annotation support.
+ * Assertion support.
+ * Linenumber table code rewritten.
+ * Exception table code rewritten.
+ * Replaced --with-classpath-includedir with --with-jni_h and
+ --with-jni_md_h to better support OpenJDK/IcedTea build.s
New in release 0.98 (June 6, 2007)
CACAO_LIBTOOLIZE_VERSION=`${CACAO_LIBTOOLIZE} --version | sed 's/^.*[^0-9.]\([0-9]\{1,\}\.[0-9.]\{1,\}\).*/\1/'`
# echo ${CACAO_LIBTOOLIZE_VERSION}
case ${CACAO_LIBTOOLIZE_VERSION} in
- 1.5* )
+ 1.5* | 2.* )
CACAO_HAVE_LIBTOOLIZE=true
break;
;;
if test ${CACAO_HAVE_LIBTOOLIZE} = false; then
echo "No proper libtoolize was found."
- echo "You must have libtool 1.5 installed."
+ echo "You must have libtool 1.5 or later installed."
exit 1
fi
dnl configure.ac
dnl
-dnl Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-dnl C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-dnl E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-dnl J. Wenninger, Institut f. Computersprachen - TU Wien
+dnl Copyright (C) 1996-2005, 2006, 2007, 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
dnl
dnl This file is part of CACAO.
dnl
dnl Process this file with autoconf to produce a configure script.
-AC_INIT(cacao, 0.98+svn, cacao@cacaojvm.org)
+AC_INIT(cacao, 0.99rc3, cacao@cacaojvm.org)
AC_CONFIG_SRCDIR(src/cacao/cacao.c)
AC_CANONICAL_HOST
AC_PREREQ(2.59)
dnl set interpreter flags
AC_SUBST(INTRP_CFLAGS)
-dnl define some stuff required for --fullversion
-AC_DEFINE_UNQUOTED(VERSION_CONFIGURE_ARGS, "$ac_configure_args", [configure arguments])
-AC_DEFINE_UNQUOTED(VERSION_CC, "$CC", [CC used])
-AC_DEFINE_UNQUOTED(VERSION_CFLAGS, "$OPT_CFLAGS $ARCH_CFLAGS", [CFLAGS used])
-
-
dnl define and substitute some architecture specific variables
AC_DEFINE_UNQUOTED([ARCH_DIR], "${ARCH_DIR}", [architecture directory])
AC_DEFINE_UNQUOTED([JAVA_ARCH], "${JAVA_ARCH}", [Java architecture name])
AC_CHECK_HEADERS([fcntl.h])
AC_CHECK_HEADERS([libgen.h])
AC_CHECK_HEADERS([netdb.h])
+AC_CHECK_HEADERS([stdint.h])
+AC_CHECK_HEADERS([stdio.h])
AC_CHECK_HEADERS([stdlib.h])
AC_CHECK_HEADERS([string.h])
AC_CHECK_HEADERS([time.h])
AC_CHECK_HEADERS([sys/types.h])
dnl this is for fdlibm
-AC_CHECK_HEADERS([stdint.h])
AC_CHECK_HEADERS([inttypes.h])
AC_CHECK_HEADERS([sys/config.h])
AC_CHECK_HEADERS([sys/types.h])
AC_FUNC_MMAP
dnl keep them alpha-sorted!
+AC_CHECK_FUNCS([abort])
AC_CHECK_FUNCS([accept])
AC_CHECK_FUNCS([access])
AC_CHECK_FUNCS([atoi])
AC_CHECK_FUNCS([confstr])
AC_CHECK_FUNCS([connect])
AC_CHECK_FUNCS([dirname])
+AC_CHECK_FUNCS([fclose])
AC_CHECK_FUNCS([fflush])
AC_CHECK_FUNCS([fopen])
AC_CHECK_FUNCS([fprintf])
+AC_CHECK_FUNCS([fread])
AC_CHECK_FUNCS([free])
AC_CHECK_FUNCS([fstat])
AC_CHECK_FUNCS([fsync])
AC_CHECK_FUNCS([mmap])
AC_CHECK_FUNCS([mprotect])
AC_CHECK_FUNCS([open])
+AC_CHECK_FUNCS([read])
AC_CHECK_FUNCS([readlink])
AC_CHECK_FUNCS([realloc])
AC_CHECK_FUNCS([recv])
AC_CHECK_FUNCS([setsockopt])
AC_CHECK_FUNCS([shutdown])
AC_CHECK_FUNCS([socket])
+AC_CHECK_FUNCS([stat])
+AC_CHECK_FUNCS([strcat])
AC_CHECK_FUNCS([strchr])
+AC_CHECK_FUNCS([strcpy])
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([write])
dnl Checks for libraries.
dnl check for verifier
AC_MSG_CHECKING(whether classfile verification should be enabled)
AC_ARG_ENABLE([verifier],
- [AS_HELP_STRING(--disable-verifier,disable classfile verification [[default=yes]])],
+ [AS_HELP_STRING(--disable-verifier,disable classfile verification [[default=enabled]])],
[case "${enableval}" in
no) ENABLE_VERIFIER=no;;
*) ENABLE_VERIFIER=yes;;
dnl check if if-conversion should be supported
AC_MSG_CHECKING(whether if-conversion should be supported)
AC_ARG_ENABLE([ifconv],
- [AS_HELP_STRING(--disable-ifconv,disable if-conversion [[default=yes]])],
+ [AS_HELP_STRING(--disable-ifconv,disable if-conversion [[default=enabled]])],
[case "${enableval}" in
no) ENABLE_IFCONV=no;;
*) ENABLE_IFCONV=yes;;
dnl check if linear scan register allocator(lsra) with SSA should be used
AC_MSG_CHECKING(whether lsra with ssa should be supported)
AC_ARG_ENABLE([ssa],
- [AS_HELP_STRING(--disable-ssa,disable ssa [[default=no]])],
+ [AS_HELP_STRING(--disable-ssa,disable ssa [[default=disabled]])],
[case "${enableval}" in
no) ENABLE_SSA=no;;
*) ENABLE_SSA=yes;;
AC_CHECK_WITH_CACAOH
AC_CHECK_WITH_CLASSPATH
+
+dnl Now we check for jre-layout so we can skip some checks that are
+dnl not required.
+AC_CHECK_ENABLE_JRE_LAYOUT
+
AC_CHECK_WITH_CLASSPATH_PREFIX
AC_CHECK_WITH_CLASSPATH_CLASSES
-AC_CHECK_WITH_CLASSPATH_LIBDIR
-AC_CHECK_WITH_CLASSPATH_INCLUDEDIR
-AC_CHECK_WITH_JRE_LAYOUT
+if test x"${ENABLE_JRE_LAYOUT}" = "xno"; then
+ AC_CHECK_WITH_CLASSPATH_LIBDIR
+fi
+
+dnl The check for jni_md.h must be before jni.h.
+AC_CHECK_WITH_JNI_MD_H
+AC_CHECK_WITH_JNI_H
+
+dnl HPI is only required for OpenJDK
+case "${WITH_CLASSPATH}" in
+ sun)
+ AC_CHECK_WITH_HPI_MD_H
+ AC_CHECK_WITH_HPI_H
+ ;;
+ *)
+ ;;
+esac
dnl check for some programs we need
]
)
+dnl python
+
+AZ_PYTHON_DEFAULT
+AZ_PYTHON_ENABLE
+AZ_PYTHON_WITH
+AZ_PYTHON_VERSION_ENSURE( [2.4] )
+AZ_PYTHON_CSPEC
+AZ_PYTHON_LSPEC
+
+
+dnl define some stuff required for --fullversion
+AC_DEFINE_UNQUOTED(VERSION_CONFIGURE_ARGS, "$ac_configure_args", [configure arguments])
+AC_DEFINE_UNQUOTED(VERSION_CC, "$CC", [CC used])
+AC_DEFINE_UNQUOTED(VERSION_CFLAGS, "$OPT_CFLAGS $ARCH_CFLAGS $CPPFLAGS", [CFLAGS used])
+
+
dnl finally pass CFLAGS to Makefiles via AM_CFLAGS
-CFLAGS=$OPT_CFLAGS
+CFLAGS="$OPT_CFLAGS"
AM_CFLAGS=$ARCH_CFLAGS
+AM_CPPFLAGS="$CPPFLAGS"
AC_SUBST(AM_CFLAGS)
+AC_SUBST(AM_CPPFLAGS)
AC_CONFIG_FILES([Makefile]
[contrib/vmlog/Makefile]
[contrib/vmlog/t/Makefile]
[doc/Makefile]
+ [doc/doxygen/Makefile]
[doc/handbook/Makefile]
[man/Makefile]
[src/Makefile]
[src/cacao/Makefile]
[src/cacaoh/Makefile]
+ [src/classes/Makefile]
[src/fdlibm/Makefile]
- [src/lib/Makefile]
[src/mm/Makefile]
[src/mm/cacao-gc/Makefile]
[src/native/Makefile]
[src/scripts/Makefile]
[src/scripts/java]
[src/threads/Makefile]
- [src/threads/native/Makefile]
[src/threads/none/Makefile]
+ [src/threads/posix/Makefile]
[src/toolbox/Makefile]
[src/vm/Makefile]
[src/vm/jit/Makefile]
[src/vm/jit/i386/linux/Makefile]
[src/vm/jit/intrp/Makefile]
[src/vm/jit/inline/Makefile]
+ [src/vm/jit/ir/Makefile]
[src/vm/jit/loop/Makefile]
[src/vm/jit/m68k/Makefile]
[src/vm/jit/m68k/linux/Makefile]
[src/vmcore/Makefile]
[tests/Makefile]
[tests/regression/Makefile]
- [tests/regression/codepatching/Makefile]
+ [tests/regression/bugzilla/Makefile]
+ [tests/regression/assertion/Makefile]
[tests/regression/jasmin/Makefile]
+ [tests/regression/junit/Makefile]
[tests/regression/native/Makefile]
[tests/regression/resolving/Makefile]
[tests/regression/resolving/classes1/Makefile]
## contrib/Makefile.am
##
-## 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.
##
## 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
-##
-## Changes:
-## Process this file with automake to produce Makefile.in
SUBDIRS = vmlog
-# sets the environment variables when GNU classpath is installed, but
-# CACAO not
+# Sets the environment variables properly when GNU Classpath is
+# installed, but CACAO is not.
export PATH=$PWD/src/cacao:$PATH
export LD_LIBRARY_PATH=$PWD/src/cacao/.libs
-export BOOTCLASSPATH=$PWD/src/lib/vm.zip:@CLASSPATH_CLASSES@
+export BOOTCLASSPATH=$PWD/src/classes/vm.zip:@CLASSPATH_CLASSES@
-# sets the environment variables when GNU classpath and CACAO are not
-# installed
+# Sets the environment variables properly when GNU Classpath and CACAO
+# are not installed.
export PATH=$PWD/src/cacao:$PATH
@CLASSPATH_PREFIX@/native/jni/java-util/.libs:\
$LD_LIBRARY_PATH
-export BOOTCLASSPATH=$PWD/src/lib/vm.zip:@CLASSPATH_CLASSES@
+export BOOTCLASSPATH=$PWD/src/classes/vm.zip:@CLASSPATH_CLASSES@
/*** option parsing **************************************************/
+vmlog_options *vmlog_opt_new(void)
+{
+ vmlog_options *opts;
+
+ VMLOG_XZNEW(opts,vmlog_options);
+
+ return opts;
+}
+
int vmlog_opt_parse_seq(const char *arg,int len,vmlog_seq_t *seq)
{
char *buf;
return 1;
}
+void vmlog_opt_set_prefix(vmlog_options *opts, const char *arg)
+{
+ opts->prefix = vmlog_strdup(arg,strlen(arg));
+}
+
+void vmlog_opt_set_stringprefix(vmlog_options *opts, const char *arg)
+{
+ opts->stringprefix = vmlog_strdup(arg,strlen(arg));
+}
+
+void vmlog_opt_set_ignoreprefix(vmlog_options *opts, const char *arg)
+{
+ opts->ignoreprefix = vmlog_strdup(arg,strlen(arg));
+}
+
static int vmlog_opt_parse_one_option(vmlog_options *opts, const char *arg, const char *nextarg)
{
int eat;
if (strcmp(arg,"-vmlog:prefix") == 0) {
if (!nextarg)
vmlog_die("expected a prefix after -vmlog:prefix");
- opts->prefix = vmlog_strdup(nextarg,strlen(nextarg));
+ vmlog_opt_set_prefix(opts,nextarg);
eat++;
}
else if (strcmp(arg,"-vmlog:strings") == 0) {
if (!nextarg)
vmlog_die("expected a prefix after -vmlog:strings");
- opts->stringprefix = vmlog_strdup(nextarg,strlen(nextarg));
+ vmlog_opt_set_stringprefix(opts,nextarg);
eat++;
}
else if (strcmp(arg,"-vmlog:ignore") == 0) {
if (!nextarg)
vmlog_die("expected a prefix after -vmlog:ignore");
- opts->ignoreprefix = vmlog_strdup(nextarg,strlen(nextarg));
+ vmlog_opt_set_ignoreprefix(opts,nextarg);
eat++;
}
else {
assert(pargc);
- VMLOG_XZNEW(opts,vmlog_options);
+ opts = vmlog_opt_new();
if (*pargc && argv[0])
opts->progname = vmlog_strdup(argv[0],strlen(argv[0]));
assert(vmargs);
- VMLOG_XZNEW(opts,vmlog_options);
+ opts = vmlog_opt_new();
i = 0;
while (i < vmargs->nOptions) {
vmlog_log_entry * vmlog_ringbuf_prev(vmlog_ringbuf *ring,int prefetch);
/* option parsing */
+vmlog_options *vmlog_opt_new(void);
+void vmlog_opt_set_prefix(vmlog_options *opts, const char *arg);
+void vmlog_opt_set_stringprefix(vmlog_options *opts, const char *arg);
+void vmlog_opt_set_ignoreprefix(vmlog_options *opts, const char *arg);
int vmlog_opt_parse_seq(const char *arg,int len,vmlog_seq_t *seq);
int vmlog_opt_parse_range(const char *arg,vmlog_seq_t *start,vmlog_seq_t *end);
vmlog_options *vmlog_opt_parse_cmd_line(int *pargc,char **argv);
/*** global variables ************************************************/
static vmlog_log *vmlog_global_log = NULL;
-static java_objectheader vmlog_global_lock;
+static java_object_t *vmlog_global_lock = NULL;
+static vmlog_options *vmlog_cacao_options = NULL;
/*** locking *********************************************************/
-#define VMLOG_LOCK(vml) lock_monitor_enter(&vmlog_global_lock)
-#define VMLOG_UNLOCK(vml) lock_monitor_exit(&vmlog_global_lock)
+#define VMLOG_LOCK(vml) lock_monitor_enter(vmlog_global_lock)
+#define VMLOG_UNLOCK(vml) lock_monitor_exit(vmlog_global_lock)
/*** include the vmlog code ******************************************/
/*** internal functions **********************************************/
-void vmlog_cacao_init(JavaVMInitArgs *vmargs)
+void vmlog_cacao_init()
{
- vmlog_options *opts;
-
- opts = vmlog_opt_parse_vmargs(vmargs);
-
- if (!opts->prefix)
+ if (!vmlog_cacao_options->prefix)
return;
- vmlog_global_log = vmlog_log_new(opts->prefix,1);
+ vmlog_global_log = vmlog_log_new(vmlog_cacao_options->prefix,1);
- if (opts->ignoreprefix) {
+ if (vmlog_cacao_options->ignoreprefix) {
vmlog_log_load_ignorelist(vmlog_global_log,
- opts->ignoreprefix);
+ vmlog_cacao_options->ignoreprefix);
}
- if (opts->stringprefix) {
+ if (vmlog_cacao_options->stringprefix) {
vmlog_load_stringhash(vmlog_global_log,
- opts->stringprefix);
+ vmlog_cacao_options->stringprefix);
}
- vmlog_opt_free(opts);
+ vmlog_opt_free(vmlog_cacao_options);
+ vmlog_cacao_options = NULL;
}
void vmlog_cacao_init_lock(void)
{
- lock_init_object_lock(&vmlog_global_lock);
+ vmlog_global_lock = NEW(java_object_t);
+ lock_init_object_lock(vmlog_global_lock);
}
static void vmlog_cacao_do_log(vmlog_log_function fun,
{
char *name;
int namelen;
+ char *cname;
+ int cnamelen;
assert(m);
if (!vmlog_global_log)
return;
- name = vmlog_concat4len(m->class->name->text,m->class->name->blength,
+ if (m->class) {
+ cname = m->class->name->text;
+ cnamelen = m->class->name->blength;
+ }
+ else {
+ cname = "<NULL>";
+ cnamelen = 6;
+ }
+
+ name = vmlog_concat4len(cname,cnamelen,
".",1,
m->name->text,m->name->blength,
m->descriptor->text,m->descriptor->blength,
vmlog_cacao_do_log(vmlog_log_unwnd,m);
}
-void vmlog_cacao_throw(java_objectheader *xptr)
+void vmlog_cacao_throw(java_object_t *xptr)
{
classinfo *c;
}
}
-void vmlog_cacao_catch(java_objectheader *xptr)
+void vmlog_cacao_catch(java_object_t *xptr)
{
classinfo *c;
name, strlen(name));
}
+void vmlog_cacao_signl_type(int type)
+{
+ char message[20];
+
+ if (!vmlog_global_log)
+ return;
+
+ sprintf(message, "EXC %d", type);
+
+ vmlog_log_signl(vmlog_global_log,(void*) THREADOBJECT,
+ message, strlen(message));
+}
+
+void vmlog_cacao_init_options(void)
+{
+ vmlog_cacao_options = vmlog_opt_new();
+}
+
+void vmlog_cacao_set_prefix(const char *arg)
+{
+ vmlog_opt_set_prefix(vmlog_cacao_options, arg);
+}
+
+void vmlog_cacao_set_stringprefix(const char *arg)
+{
+ vmlog_opt_set_stringprefix(vmlog_cacao_options, arg);
+}
+
+void vmlog_cacao_set_ignoreprefix(const char *arg)
+{
+ vmlog_opt_set_ignoreprefix(vmlog_cacao_options, arg);
+}
+
/* vim: noet ts=8 sw=8
*/
#ifndef _VMLOG_CACAO_H_
#define _VMLOG_CACAO_H_
-#include <threads/native/threads.h>
+void vmlog_cacao_init_options(void);
-void vmlog_cacao_init(JavaVMInitArgs *vmargs);
+void vmlog_cacao_set_prefix(const char *arg);
+void vmlog_cacao_set_stringprefix(const char *arg);
+void vmlog_cacao_set_ignoreprefix(const char *arg);
+
+void vmlog_cacao_init(void);
void vmlog_cacao_init_lock(void);
void vmlog_cacao_unrol_method(methodinfo *m);
void vmlog_cacao_rerol_method(methodinfo *m);
-void vmlog_cacao_throw(java_objectheader *xptr);
-void vmlog_cacao_catch(java_objectheader *xptr);
+void vmlog_cacao_throw(java_object_t *xptr);
+void vmlog_cacao_catch(java_object_t *xptr);
void vmlog_cacao_signl(const char *name);
+void vmlog_cacao_signl_type(int type);
#endif
## doc/Makefile.am
##
-## 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.
##
## 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
-##
-## Changes:
-## Process this file with automake to produce Makefile.in
-SUBDIRS = handbook
+SUBDIRS = \
+ doxygen \
+ handbook
-dist_noinst_DATA = annotations.tex jsr.bib
+dist_noinst_DATA = \
+ assertions.tex \
+ annotations.tex \
+ jsr.bib
-EXTRA_DIST = inlining_stacktrace.txt native_threads.txt stack.txt
+EXTRA_DIST = \
+ inlining_stacktrace.txt \
+ native_threads.txt \
+ stack.txt
CLEANFILES = \
annotations.aux \
annotations.toc \
annotations.idx \
annotations.out \
- annotations.tex~
+ annotations.tex~ \
+ assertions.aux \
+ assertions.dvi \
+ assertions.log \
+ assertions.toc
annotations:
latex annotations
latex annotations
latex annotations
+assertions:
+ latex assertions
+ latex assertions
+
## Local variables:
## mode: Makefile
## indent-tabs-mode: t
--- /dev/null
+\documentclass{article}%
+\usepackage{amsmath}
+\usepackage{amsfonts}
+\usepackage{amssymb}
+\usepackage{graphicx}
+\usepackage{listings}
+\lstloadlanguages{Java,C}
+\lstset{basicstyle=\scriptsize, numbers=left, tabsize=4, frame=none, breaklines=true}
+%-------------------------------------------
+\newtheorem{theorem}{Theorem}
+\newtheorem{acknowledgement}[theorem]{Acknowledgement}
+\newtheorem{algorithm}[theorem]{Algorithm}
+\newtheorem{axiom}[theorem]{Axiom}
+\newtheorem{case}[theorem]{Case}
+\newtheorem{claim}[theorem]{Claim}
+\newtheorem{conclusion}[theorem]{Conclusion}
+\newtheorem{condition}[theorem]{Condition}
+\newtheorem{conjecture}[theorem]{Conjecture}
+\newtheorem{corollary}[theorem]{Corollary}
+\newtheorem{criterion}[theorem]{Criterion}
+\newtheorem{definition}[theorem]{Definition}
+\newtheorem{example}[theorem]{Example}
+\newtheorem{exercise}[theorem]{Exercise}
+\newtheorem{lemma}[theorem]{Lemma}
+\newtheorem{notation}[theorem]{Notation}
+\newtheorem{problem}[theorem]{Problem}
+\newtheorem{proposition}[theorem]{Proposition}
+\newtheorem{remark}[theorem]{Remark}
+\newtheorem{solution}[theorem]{Solution}
+\newtheorem{summary}[theorem]{Summary}
+\newenvironment{proof}[1][Proof]{\textbf{#1.} }{\ \rule{0.5em}{0.5em}}
+
+\begin{document}
+
+\title{Assertion support \\for the CACAO Virtual Machine}
+\author{{Gregor Kaufmann}
+\\0247381 033 534
+\\gregor@complang.tuwien.ac.at}
+\date{January 1, 2008}
+\maketitle
+\pagebreak
+
+\tableofcontents
+\pagebreak
+
+
+\section{Introduction to assertions in Java}
+\subsection{General Introduction}
+The assertion keyword in Java allows to assert the correctness of assumptions made in a program. It was first introdcuded in JDK 1.2 (see JSR41\footnote{http://jcp.org/aboutJava/communityprocess/review/jsr041/publicDraft.html}). An assertion works on an expression, evaluating to a boolean type, that must be true during the execution of a program (or else the execution halts and an exception gets thrown). Short example: a function that calculates from celsius to kelvin. This function might use an assertion to assure that the calculated value is not below 0.
+
+An assertion statement comes in two forms:
+\begin{itemize}
+\item \verb'assert BooleanExpression ;'
+\item \verb'assert BooleanExpression : ValueExpression ;'
+\end{itemize}
+The "BooleanExpression" can be any java expression resulting in a boolean value. If this "BoolenExpression" evalutes to false an (unnamed) AssertionError gets thrown. The second form of the assertion statement is used to generate detailed error messages: the value of "ValueExpression" gets passed to the constructor of the thrown AssertionError exception, building a more detailed error message. An assertion statement is equal to: if (BooleanExpression == false) throw new AssertionError(ValueExpression); (without the possibility to easily turn on/off this code at runtime).
+Examples:
+\begin{itemize}
+\item \verb'assert val < 10;'
+\item \verb'assert val > 99: val;'
+\item \verb'assert isValid(val): val;'
+\item \verb'assert val.isEnabled(): val.getStatus();'
+\end{itemize}
+
+\pagebreak
+\subsection{Interpreter options}
+Assertions can be turned on or off at runtime (turned off by default). The following options for the interpreter are available (\verb'>'JDK1.2 and \verb'>'CACAO-0.98):
+\begin{itemize}
+\item \verb'-ea[:<packagename>...|:<classname>]'
+\item \verb'-enableassertions[:<packagename>...|:<classname>]'
+\item \verb'-da[:<packagename>...|:<classname>]'
+\item \verb'-disableassertions[:<packagename>...|:<classname>]'
+\item \verb'-esa | -enablesystemassertions'
+\item \verb'-dsa | -disablesystemassertions}'
+\end{itemize}
+Detailed explanation of the available options:
+\begin{itemize}
+\item{\verb'-enableassertions/-ea' -- \tiny{Turns on assertions for all non-system/user classes}}
+\item{\verb'-disableassertions/-da' -- \tiny{Turns off assertions for all non-system/user classes}}
+\item{\verb'-enablesystemassertions/-esa' -- \tiny{Turns on assertions for all system/non-user classes}}
+\item{\verb'-disablesystemassertions/-dsa' -- \tiny{Turns off assertions for all system/non-user classes}}
+\item{\verb'-enableassertions/-ea:my.package...' -- \tiny{Turns on assertions for all classes in the "my.package" package (and all subpackages)}}
+\item{\verb'-disableassertions/-da:my.package...' -- \tiny{Turns off assertions for all classes in the "my.package" package (and all subpackages)}}
+\item{\verb'-enableassertions/-ea:Myclass' -- \tiny{Turns on assertions a class named "Myclass"}}
+\item{\verb'-disableassertions/-da:Myclass' -- \tiny{Turns off assertions a class named "Myclass"}}
+\end{itemize}
+Note 1: Specifing multiple class/package names is possible.
+\\
+\\
+Note 2: The assertion switches -ea/-da/-esa/-dsa are currently not implemented correctly in cacao+classpath (use cacao+openjdk or a patched classpath [see section \ref{see1}]).
+\pagebreak
+\subsection{Bytecode of an assertion statement} \label{bytecode}
+The following example shows how an assertion statement is translated into bytecode.
+\\
+\\
+I've compiled the following class with JDK-6.0 (other compilers produce slightly different bytecode).
+\begin{lstlisting}[language=Java]
+public class Test {
+ public static void main(String[] args) {
+ int x = 1;
+ assert x == 2 : x;
+ }
+}
+\end{lstlisting}
+The following bytecode gets produced:
+\\
+\begin{lstlisting}[language=Java]
+static {};
+ Code:
+ 0: ldc\_w #5; //class Test
+ 3: invokevirtual #6; //Method java/lang/Class.desiredAssertionStatus:()Z
+ 6: ifne 13
+ 9: iconst\_1
+ 10: goto 14
+ 13: iconst\_0
+ 14: putstatic #2; //Field \$assertionsDisabled:Z
+ 17: return
+\end{lstlisting}
+A static block is used to iniatilizes the boolean variable describing the assertion status of the class "Test".
+The assertion status, as set by the user/vm for, gets loaded (lines 3,4), and saved into constant\_pool[2] (line 9).
+\\
+\begin{lstlisting}[language=Java]
+public static void main(java.lang.String[]);
+ Code:
+ 0: iconst\_1
+ 1: istore\_1
+ 2: getstatic #2; //Field \$assertionsDisabled:Z
+ 5: ifne 22
+ 8: iload\_1
+ 9: iconst\_2
+ 10: if\_icmpeq 22
+ 13: new #3; //class java/lang/AssertionError
+ 16: dup
+ 17: iload\_1
+ 18: invokespecial #4; //Method java/lang/AssertionError."<init>":(I)V
+ 21: athrow
+ 22: return
+\end{lstlisting}
+The assertion status gets loaded from constant\_pool[2] (line 5), if assertions are disabled the function returns immediatly (lines 6,15). Otherwise, the assertion statement gets evaluated and an AssertionError exception gets thrown (lines 6-15).
+
+\pagebreak
+\section{Implementation of java assertions in CACAO}
+
+When I started working on the assertion support for cacao, a basic functionality to toggle assertions on and off was already implemented. It was possible to toggle assertions on and off at a systemwide level, but this only worked when cacao was used together with the GNU classpath classes. Because at least something was already implemented, I decided to start my work on cacao+classpath.
+\\
+\\
+Each class implements a method called desiredAssertionStatus that returns the desired assertion status of a class, see section \ref{bytecode} on how this is used by an assertion statement.
+\\
+\\
+The desiredAssertionStatus method in java.lang.Class of classpath looks like this:
+\begin{lstlisting}[language=Java,firstnumber=1216]
+ public boolean desiredAssertionStatus()
+ {
+ ClassLoader c = getClassLoader();
+ Object status;
+ if (c == null)
+ return VMClassLoader.defaultAssertionStatus();
+ if (c.classAssertionStatus != null)
+ synchronized (c)
+ {
+ status = c.classAssertionStatus.get(getName());
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ else
+ {
+ status = ClassLoader.StaticData.
+ systemClassAssertionStatus.get(getName());
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ if (c.packageAssertionStatus != null)
+ synchronized (c)
+ {
+ String name = getPackagePortion(getName());
+ if ("".equals(name))
+ status = c.packageAssertionStatus.get(null);
+ else
+ do
+ {
+ status = c.packageAssertionStatus.get(name);
+ name = getPackagePortion(name);
+ }
+ while (! "".equals(name) && status == null);
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ else
+ {
+ String name = getPackagePortion(getName());
+ if ("".equals(name))
+ status = ClassLoader.StaticData.
+ systemPackageAssertionStatus.get(null);
+ else
+ do
+ {
+ status = ClassLoader.StaticData.
+ systemPackageAssertionStatus.get(name);
+ name = getPackagePortion(name);
+ }
+ while (! "".equals(name) && status == null);
+ if (status != null)
+ return status.equals(Boolean.TRUE);
+ }
+ return c.defaultAssertionStatus;
+ }
+\end{lstlisting}
+The ClassLoader class stores the global assertion status for user classes and the individual status for classes and packages:
+\begin{itemize}
+\item{\verb'boolean defaultAssertionStatus'}
+\item{\verb'Map<String, Boolean> systemPackageAssertionStatus'}
+\item{\verb'Map<String, Boolean> systemClassAssertionStatus'}
+\end{itemize}
+
+\noindent The VMClassLoader class is a special class that needs to implemented by virtual machines that use the classpath classes.
+The following methods are used by the ClassLoader to initialize the variables above (in the same order):
+\begin{itemize}
+\item{\verb'boolean defaultUserAssertionStatus()'}
+\item{\verb'Map<String, Boolean> packageAssertionStatus()'}
+\item{\verb'Map<String, Boolean> classAssertionStatus()'}
+\end{itemize}
+See: java.lang.Class\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/java/lang/Class.java?revision=1.54\&root=classpath\&view=markup}, java.lang.ClassLoader\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/java/lang/ClassLoader.java?revision=1.62\&root=classpath\&view=markup}, java.lang.VMClassLoader\footnote{http://cvs.savannah.gnu.org/viewvc/classpath/vm/reference/java/lang/VMClassLoader.java?revision=1.16.2.18\&root=classpath\&view=markup}
+\\
+\\
+What had to be done:
+\begin{itemize}
+\item{Implement the methods: defaultUserAssertionStatus, packageAssertionStatus, classAssertionStatus}
+\item{Write a function to parse the commandline options}
+\end{itemize}
+See: src/lib/gnu/java/lang/VMClassLoader.java (section \ref{see1}), src/native/vm/gnu/java\_lang\_VMClassLoader.c (section \ref{see2}), src/vm/assertion.c (section \ref{see3}) and src/vm/assertion.c (section \ref{see4})
+\\\\
+For cacao+openjdk I could reuse most of the code I wrote for cacao+classpath:
+\\\\
+The desiredAssertionStatus method in java.lang.Class of openjdk looks like this:
+\begin{lstlisting}[language=Java, firstnumber=2849]
+public boolean desiredAssertionStatus() {
+ ClassLoader loader = getClassLoader();
+ // If the loader is null this is a system class, so ask the VM
+ if (loader == null)
+ return desiredAssertionStatus0(this);
+
+ synchronized(loader) {
+ // If the classloader has been initialized with
+ // the assertion directives, ask it. Otherwise,
+ // ask the VM.
+ return (loader.classAssertionStatus == null ?
+ desiredAssertionStatus0(this) :
+ loader.desiredAssertionStatus(getName()));
+ }
+}
+
+\end{lstlisting}
+The native function called by desiredAssertionStatus0 is JVM\_DesiredAssertionStatus, and that's the only function that had to be implemented by me to make assertions work with cacao+openjdk. I've also corrected the implementation of the JVM\_AssertionStatusDirectives function, which is used by java.lang.ClassLoader.
+\\
+\\
+See: src/native/vm/sun/jvm.c (section \ref{see5})
+
+\pagebreak
+\section{Patch overview}
+\subsection{Changed/New files}
+\begin{itemize}
+\item{\verb'configure.ac'}
+\item{\verb'm4/assertion.m4'}
+\item{\verb'src/lib/gnu/java/lang/VMClassLoader.java'}
+\item{\verb'src/native/include/Makefile.am'}
+\item{\verb'src/native/jni.h'}
+\item{\verb'src/native/vm/gnu/java_lang_VMClassLoader.c'}
+\item{\verb'src/native/vm/sun/jvm.c'}
+\item{\verb'src/vm/Makefile.am'}
+\item{\verb'src/vm/assertion.c'}
+\item{\verb'src/vm/assertion.h'}
+\item{\verb'src/vm/vm.c'}
+\item{\verb'src/vmcore/class.c'}
+\item{\verb'src/vmcore/class.h'}
+\item{\verb'src/vmcore/linker.c'}
+\item{\verb'src/vmcore/loader.c'}
+\item{\verb'configure.ac'}
+\end{itemize}
+
+\subsection{configure.ac}
+Added configure option "--enable-assertion" (turned on by default).
+\\
+Most of the assertion code will be turned off if this switch is disabled.
+\\\\
+Actual configure logic is in m4/assertion.m4.
+
+\subsection{m4/assertion.m4}
+Added autoconf logic to enable/disable building of assertion support.
+
+\subsection{src/lib/gnu/java/lang/VMClassLoader.java}
+\label{see1}
+Replaced the dummy implementations of:
+\begin{itemize}
+\item{\verb'defaultAssertionStatus'}
+\item{\verb'packageAssertionStatus'}
+\item{\verb'classAssertionStatus'}
+\end{itemize}
+
+Added:
+\begin{itemize}
+\item{\verb'defaultUserAssertionStatus'}
+\end{itemize}
+
+\noindent This function returns the user assertion status. Due to incorrect handling of user/system assertion status in GNU classpath\footnote{http://www.gnu.org/software/classpath/}, enabling (default) system assertions will also enable assertions in all user classes (a patch\footnote{http://www.mail-archive.com/classpath-patches@gnu.org/msg10400/assertion\_cp.patch} to fix this behaviour was submitted in August 07).
+\\\\
+Actual implementations now call into native code to get status.
+
+\subsection{src/native/include/Makefile.am}
+Added:
+\begin{itemize}
+\item{\verb'java_util_HashMap.h'}
+\item{\verb'java_util_Map.h'}
+\end{itemize}
+\noindent Headers needed to allow construction of Map/HashMap in native code.
+
+\subsection{src/native/jni.h}
+Removed:
+\begin{itemize}
+\item{\verb'_Jv_JavaVM->Java_java_lang_VMClassLoader_defaultAssertionStatus'}
+\end{itemize}
+\noindent This variable was used to hold the system's assertion status and was replaced by assertion\_user\_enabled and assertion\_system\_enabled.
+
+\subsection{src/native/vm/gnu/java\_lang\_VMClassLoader.c}
+\label{see2}
+This file holds native implementations of the VMClassLoader for GNU classpath.
+\\\\
+The following functions were added/replaced:
+\begin{itemize}
+\item{\verb'Java_java_lang_VMClassLoader_defaultUserAssertionStatus'}
+\end{itemize}
+\noindent Native implementation of VMClassLoader.defaultUserAssertionStatus. This function returns the default user assertion status of the system (user\_assertion\_status). Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
+\begin{itemize}
+\item{\verb'Java_java_lang_VMClassLoader_defaultAssertionStatus'}
+\end{itemize}
+\noindent Previous implemention was replaced. Native implementation of VMClassLoader.defaultAssertionStatus. This function returns the default assertion status of the system (system\_assertion\_status). Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
+\begin{itemize}
+\item{\verb'Java_java_lang_VMClassLoader_packageAssertionStatus0'}
+\end{itemize}
+\noindent Native implementation of VMClassLoader.packageAssertionStatus. Builds and returns a HashMap containing key and value pairs of packagenames and their assertion status (as expected by the ClassLoader). Returns an empty HashMap if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
+\begin{itemize}
+\item{\verb'Java_java_lang_VMClassLoader_classAssertionStatus0'}
+\end{itemize}
+\noindent Native implementation of VMClassLoader.classAssertionStatus. Builds and returns a HashMap containing key and value pairs of classnames and their assertion status (as expected by the ClassLoader). Returns an empty HashMap if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
+
+\subsection{src/native/jni.h}
+Removed:
+\begin{itemize}
+\item{\verb'_Jv_JavaVM->Java_java_lang_VMClassLoader_defaultAssertionStatus'}
+\end{itemize}
+\noindent This variable was used to hold the system's assertion status and was replaced by assertion\_user\_enabled and assertion\_system\_enabled.
+
+\subsection{src/native/vm/sun/jvm.c}
+\label{see5}
+This file holds various native implementations needed by OpenJDK\footnote{http://openjdk.java.net/}.
+\\\\
+The following functions were added/replaced:
+\begin{itemize}
+\item{\verb'JVM_DesiredAssertionStatus'}
+\end{itemize}
+\noindent Dummy implementation was replaced. Returns the desired assertion status for a given class. Returns false if ENABLE\_ASSERTION is not defined (--enable-assertions=no).
+\begin{itemize}
+\item{\verb'JVM_AssertionStatusDirectives'}
+\end{itemize}
+\noindent Previous implementation was incomplete. Builds and returns an AssertionStatusDirectives object. This object contains the names of all packages and classes and their assertion status.
+
+\subsection{src/vm/Makefile.am}
+Added (optional) building of the assertion module (assertion.c/assertion.h). Will only be built if ENABLE\_ASSERTION is defined (--enable-assertions=yes).
+
+\subsection{src/vm/assertion.c}
+\label{see3}
+This file handles the various assertion commandline options (-ea/-da/-esa/-dsa).
+
+\subsection{src/vm/assertion.h}
+\label{see4}
+Defines the following global variables:
+\begin{lstlisting}[language=C,firstnumber=46]
+extern list\_t *list\_assertion\_names;
+\end{lstlisting}
+This variable stores class/package names and their assertion status.
+\begin{lstlisting}[language=C,firstnumber=47]
+extern int32\_t assertion\_class\_count;
+\end{lstlisting}
+This variable stores the amount of classnames specified on the commandline.
+\begin{lstlisting}[language=C,firstnumber=48]
+extern int32\_t assertion\_package\_count;
+\end{lstlisting}
+This variable stores the amount of packagenames specified on the commandline.
+\begin{lstlisting}[language=C,firstnumber=49]
+extern bool assertion\_user\_enabled;
+\end{lstlisting}
+This variable stores the systemwide user default assertion status.
+\begin{lstlisting}[language=C,firstnumber=50]
+extern bool assertion_system_enabled;
+\end{lstlisting}
+This variable stores the systemwide default assertion status.
+\\\\
+Defines the following functions:
+\begin{lstlisting}[language=C,firstnumber=54]
+void assertion\_ea\_da(const char *name, bool enabled);
+\end{lstlisting}
+This function is used to initialize the variables described aboved.
+
+\subsection{src/vm/vm.c}
+Handling of assertion commandline options was added/changed. Package and classname parsing is handled by src/vm/assertion.c (assertion\_ea\_da function).
+
+\subsection{src/vmcore/class.c}
+Added class\_java\_util\_HashMap
+
+\subsection{src/vmcore/class.h}
+Added class\_java\_util\_HashMap.
+
+\subsection{src/vmcore/linker.c}
+Added linking of class\_java\_util\_HashMap.
+
+\subsection{src/vmcore/loader.c}
+Added loading of class\_java\_util\_HashMap.
+
+\end{document}
--- /dev/null
+# Doxyfile 1.5.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = CACAO
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek,
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish,
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish,
+# and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../../src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = ../../src/classes ../../src/fdlibm ../../src/mm/boehm-gc ../../src/native/include
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = NO
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is enabled by default, which results in a transparent
+# background. Warning: Depending on the platform used, enabling this option
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they
+# become hard to read).
+
+DOT_TRANSPARENT = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
--- /dev/null
+## doc/doxygen/Makefile.am
+##
+## Copyright (C) 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+
+dist_noinst_DATA = \
+ Doxyfile
+
+doxygen:
+ doxygen
+
+clean-local:
+ -rm -rf html latex
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
\include{arm}
\include{mips}
\include{powerpc}
+ \include{s390}
\include{x86}
\include{x86_64}
\include{jvmti}
%\include{}
-\bibliography{java}
\bibliographystyle{alpha}
+\bibliography{java}
\end{document}
HOWPUBLISHED = {{\tt http://www.gnu.org/software/gdb/}}
}
+@MISC{s390:bib:principles,
+ KEY = {PRINCIPLES},
+ TITLE = {Enterprise Systems Architecture/390, Principles of Operation, Seventh Edition},
+ YEAR = 1999,
+ ORGANIZATION = {International Business Machines Corporation}
+}
+
+@MISC{s390:bib:gcc,
+ KEY = {GCC},
+ TITLE = {Porting GCC to the IBM S/390 platform},
+ AUTHOR = {Hartmut Penner, Ulrich Weigand},
+ ORGANIZATION = {IBM Deutschland Entwicklung GmbH},
+}
+
+@MISC{s390:bib:abi,
+ KEY = {ABI},
+ TITLE = {LINUX for S/390, ELF Application Binary Interface Supplement},
+ YEAR = 2001,
+ ORGANIZATION = {International Business Machines Corporation}
+}
+
--- /dev/null
+%\newcommand{\code}{\texttt}
+
+%\chapter{The Just-In-Time Compiler}
+
+\section{ESA/390 code generator}
+
+\subsection{About s390 Architecture}
+
+IBM's mainframe architecture s390 is the living architecture with the longest heritage, defined in a time where assembler programming was predominant and compilers where in their childhood. This fact made already porting of the GNU Compiler Collection a difficult task, as reported by the developers in \cite{s390:bib:gcc}. However the existence of a paper describing the experiences and difficulties encountered while porting an existing C compiler to the s390 architecture made the task of porting CACAO a little easier.
+
+s390 being a CISC architecture provides an extensive instruction set defined in \cite{s390:bib:principles}. There is a wide range of I/O related instructions and control instructions used by the operating system. For the CACAO port, only a small subset of instructions is from interest. \cite{s390:bib:principles} categorises them into into three sections: general instructions, floating point instructions and binary floating point instructions.
+
+The architecture defines 16 general purpose registers and 16 floating point registers. Instructions have variable length, which always is a multiple of 2 bytes. There are 2, 4 and 6 bytes long instructions and more than 30 \cite{s390:bib:gcc} instruction formats defined. Most instructions take 2 operands: the first operand being also the destination one of the operation. Most arithmetic instructions exist in two flavours: in the RR format they take two register operands, while in the RX format they take one register and one memory operand. There is also the RI format taking one register and one signed 16 bit immediate operand.
+
+For conditional execution, there exists a 2 bit condition code. A lot of instructions set this condition code depending on their result to a value defined for each instruction individually. The \emph{branch on condition} and \emph{branch relative on condition} instructions take a 4 bit bitmask, containing one bit for each possible condition code value. The branch is taken if the bit corresponding the the current condition code value is set. To branch unconditionnaly, one sets all bits in the bitmask. A \emph{branch on condition} instruction with all bits cleared in the bitmask is a nop instruction.
+
+\subsection{The ELF ABI}
+
+The \emph{application binary interface} (ABI) for GNU/Linux, the target operating system of the s390 CACAO port is defined in \cite{s390:bib:abi} and referred to as \emph{ELF ABI}.
+
+The \emph{ELF ABI} defines a system interface for compiled application programs with the purpose of establishing a standard binary interface for application programs on Linux for s390~\cite{s390:bib:abi}. The part of interest for this work is the function calling sequence, that defines register usage, stack layout and the way function parameters are passed. These are summarised in the following tables: table~\ref{s390:tbl:elf:intreg} for the general purpose register usage, table~\ref{s390:tbl:elf:fpreg} for the floating point register usage and table~\ref{s390:tbl:elf:stack} for the layout of a stack frame. To illustrate the typical function prologue, epilogue and calling conventions, figure~\ref{s390:fig:elf:hello} lists the assembly code of a simple function printing the string ``Hello world''.
+
+\begin{table}
+\centering
+\begin{tabular}{|l|l|l|}
+\hline
+Register & Usage & Call effect \\
+\hline
+\%r0, \%r1 & General purpose & Volatile \\
+\%r2, \%r3 & Parameter passing and return values & Volatile \\
+\%r4, \%r5 & Parameter passing & Volatile \\
+\%r6 & Parameter passing & Saved \\
+\%r7 - \%r11 & Local variables & Saved \\
+\%r12 & Local variable, commonly used as GOT pointer & Saved \\
+\%r13 & Local variable, commonly used as Literal Pool pointer & Saved \\
+\%r14 & Return address & Volatile \\
+\%r15 & Stack pointer & Saved \\
+\hline
+\end{tabular}
+\caption{General purpose register usage in the \emph{ELF ABI}}
+\label{s390:tbl:elf:intreg}
+\end{table}
+
+\begin{table}
+\centering
+\begin{tabular}{|l|l|l|}
+\hline
+Register & Usage & Call effect \\
+\hline
+\%f0, \%f2 & Parameter passing and return values & Volatile \\
+\%f4, \%f6 & General purpose & Saved \\
+\%f1, \%f3, \%f5, \%f7 – \%f15 & General purpose & Volatile \\
+\hline
+\end{tabular}
+\caption{Floating point register usage in the \emph{ELF ABI}}
+\label{s390:tbl:elf:fpreg}
+\end{table}
+
+\begin{table}
+\centering
+\begin{tabular}{|l|l|l|}
+\hline
+Use & Size & Offset \\
+\hline
+Local and spill variable area of calling function & Varies & Varies \\
+On stack parameters passed to called function & Varies & 96 \\
+Register save area for called function use & 88 & 8 \\
+Reserved for compiler use & 4 & 4 \\
+Back chain (optional pointer to previous frame) & 4 & 0, 8 byte aligned \\
+\hline
+\end{tabular}
+\caption{Stackframe layout in the \emph{ELF ABI}}
+\label{s390:tbl:elf:stack}
+\end{table}
+
+\begin{figure}
+\begin{verbatim}
+.data
+L_data_hello:
+ .asciz "Hello world\n"
+.text
+
+.globl hello
+
+hello:
+ ; Store callee saved registers in register save area.
+ ; The ELF ABI requires the registers to be stored at particular offsets.
+ ; %r14 is not callee saved, but contains the return address.
+ stm %r11, %r15, 44(%r15)
+ ; Setup literal pool pointer in %r13 and jump over literal pool.
+ bras %r13, L_literal_pool_end
+
+ ; Literal pool.
+L_literal_pool:
+L_hello:
+ .long L_data_hello
+L_printf:
+ .long printf
+L_literal_pool_end:
+
+ ; Allocate mandatory register save area for callee.
+ ahi %r15, -96
+ ; Load pointer to string as argument from literal pool.
+ l %r2, L_hello - L_literal_pool(%r13)
+ ; Load address of printf function from literal pool.
+ l %r1, L_printf - L_literal_pool(%r13)
+ ; Save program counter of next instruction in %r14 and jump to address in %r1
+ basr %r14, %r1
+
+ ; Restore callee saved registers from stack.
+ ; Restore return address as well
+ lm %r11, %r15, 96 + 44(%r15)
+ ; Branch to return address
+ br %r14
+\end{verbatim}
+\caption{Function that prints the string ``Hello world'' using the \emph{ELF ABI}}
+\label{s390:fig:elf:hello}
+\end{figure}
+
+\subsection{The JIT ABI}
+\label{s390:sec:jitabi}
+
+In just-in-time compiled Java code we try to stay as close as possible to the requirements of the \emph{ELF ABI}. However, some conventions of the \emph{ELF ABI} are violated for various reasons and an alternate ABI, the \emph{JIT ABI} was defined.
+
+Tables~\ref{s390:tbl:jit:intreg} and~\ref{s390:tbl:jit:fpreg} show the general purpose register and floating point register usage in the \emph{JIT ABI} respectively. The stack frame layout in the \emph{JIT ABI} is shown in table~\ref{s390:tbl:jit:stack}.
+
+\begin{table}[H]
+ \centering
+ \begin{tabular}{|c|c|c|}
+ \hline
+ Register & Use & CACAO mnemonic \\
+ \hline
+ \%r0 & Scratch register & ITMP3, ITMP3\_XPTR \\
+ \%r1 & Scratch register & ITMP1, ITMP1\_XPC, METHODPTR \\
+ \%r2 & Parameter passing, return value & RESULT \\
+ \%r3 & Parameter passing, return value & RESULT2 \\
+ \%r4 - \%r6 & Parameter passing & - \\
+ \%r7 - \%r12 & Callee saved & - \\
+ \%r13 & Procedure vector & PV \\
+ \%r14 & Return address, scratch register & RA, ITMP2 \\
+ \%r15 & Stack pointer & SP \\
+ \hline
+ \end{tabular}
+ \caption{General purpose register usage in the \emph{JIT ABI}}
+ \label{s390:tbl:jit:intreg}
+\end{table}
+
+\begin{table}[H]
+ \centering
+ \begin{tabular}{|c|c|c|}
+ \hline
+ Register & Use & CACAO mnemonic \\
+ \hline
+ \%f0 & Parameter passing, return value & FRESULT \\
+ \%f2 & Parameter passing & - \\
+ \%f4 & Scratch register & FTMP1 \\
+ \%f6 & Scratch register & FTMP2 \\
+ \%f3, \%f5, \%f7 - \%f15 & Caller saved & - \\
+ \hline
+ \end{tabular}
+ \caption{Floating point register usage in the \emph{JIT ABI}}
+ \label{s390:tbl:jit:fpreg}
+\end{table}
+
+\begin{table}[H]
+ \centering
+ \begin{tabular}{|c|c|c|}
+ \hline
+ Use & Size & Offset \\
+ \hline
+ Return address & 1 slot & Stackframesize - 8 \\
+ Callee saved integer registers & 0 - 5 slots & \\
+ Callee saved floating point registers & Currently there are none & \\
+ Temporary slot & 1 slot & \\
+ \code{monitorenter} argument & 1 slot & \\
+ Local variables & 0 to n slots & 0 \\
+ \hline
+ \end{tabular}
+ \caption{Stackframe layout in the \emph{JIT ABI}}
+ \label{s390:tbl:jit:stack}
+\end{table}
+
+Register \code{\%r0} is treated by some instructions in a special way. The \emph{branch and save operation} for example takes two registers as operands. The second operand is used as branch address. If however register \code{\%r0} is passed as second operand, the operation is performed without branching. But the most notable special treatment is that \code{\%r0} can't be used as base or index register for storage operands.
+
+To make the \emph{JIT} and \emph{ELF ABI}s compatible, there were two options for the use of the limited \code{\%r0} register: use it as scratch register or as caller saved temporary register. It was first used as caller saved register, what turned out to be a mistake. The final version of the \emph{JIT ABI} uses it as scratch register for the following reasons:
+
+\begin{itemize}
+ \item For some instructions it is handy to have a consecutive \emph{even-odd pair} of scratch registers.
+ \item Using \code{\%r0} as general purpose register leads to a lot of corner cases in the code generation algorithm.
+ \item Among all scratch registers, \code{REG\_ITMP3} is by convention the one used the least likely. So the best allocation for a register with limited usability is \code{REG\_ITMP3}.
+\end{itemize}
+
+To illustrate the typical prologue, epilogue and calling conventions in just-in-time code, consider the typical \emph{Hello world} program as shown in figure~\ref{s390:fig:jit:helloj}. The assembly code it is translated into is listed in figure~\ref{s390:fig:jit:hellojdis}.
+
+\begin{figure}
+\begin{verbatim}
+class Hello {
+ public static void main(String[] args) {
+ System.out.println("Hello world");
+ }
+}
+\end{verbatim}
+
+\caption{Source code of Java program printing the string ``Hello world''}
+\label{s390:fig:jit:helloj}
+\end{figure}
+
+\begin{figure}
+\begin{verbatim}
+ahi %r13,-4092 ; Offset procedure vector
+ahi %r15,-16 ; Allocate stack frame
+st %r14,12(%r15) ; Store return address
+l %r1,4052(%r13) ; Get java.lang.System.out into argument register #1
+l %r2,0(%r1)
+l %r3,4048(%r13) ; Load "Hello world" from data segment into argument register #2
+l %r12,0(%r2) ; Load virtual function table pointer of java.lang.System.out
+l %r13,192(%r12) ; Load method address from virtual function table
+basr %r14,%r13 ; Call method
+basr %r13,%r0 ; Restore procedure vector
+ahi %r13,-4128
+l %r14,12(%r15) ; Load return address
+ahi %r15,16 ; Remove stack frame
+br %r14 ; Return
+bc 0,0 ; NOP
+\end{verbatim}
+\caption{Disassembly of translated java program printing the string ``Hello world''}
+\label{s390:fig:jit:hellojdis}
+\end{figure}
+
+\subsection{Register allocation}
+
+For s390 the \emph{simplereg} register allocator was not changed at all and worked out of the box. But as described in section~\ref{s390:sec:long}, there is still potential for optimising long arithmetics by tuning the register allocator for s390.
+
+\subsection{Address constants}
+
+On s390, while registers are 32 bit wide, the width of addresses is 31 bit. If the CPU uses addresses given as 32 bit values, it always ignores the most significant bit of the value. This showed to be a problem in the machine independent part of the code base that uses addresses as lookup keys, like the AVL tree of all methods, because each memory location can be address using two different 32 bit pointers. This code had to be extended to always clear the most significant bit of the passed pointers, if compiled for s390.
+
+A statistical analysis of the static instruction frequency shows that 8\% of all generated intermediate instructions are \code{ACONST}. An \code{ACONST} loads an address literal into the destination operated. As 8\% is fairly a lot, two approaches were considered to implement this instruction:
+
+\begin{itemize}
+ \item Put the address constant on the data segment and implement \code{ACONST} as a load from the data segment.
+ \item Load the address using two immediate 16 bit loads and one 16 bit left shift.
+\end{itemize}
+
+When running the benchmarks, no considerable difference could be observed. Because of the jitter in the benchmark run times, none of the two approaches took the lead. So we decided to always load address constants from the data segment, with the exception of the \code{null} pointer, that can be satisfied with a single immediate load. The GNU C Compiler loads address constants from the literal pool too.
+
+\subsection{Integer arithmetics}
+
+s390 provides native instructions for 32 bit arithmetics. These include addition, substraction, multiplication, division, reminder, bitwise logical operations, arithmetic and logical shift. Most of the instructions can handle either two register operands, or one register and one memory operand. So all 32 bit arithmetics could be implemented inline.
+
+Java's 8 bit signed integer type \code{byte} and 16 bit unsigned integer type \code{char} are both handled through 32 bit arithmetics. Internally they are always represented as 32 bit values in both storage and registers. The only exception are arrays of those types. Here the array loads must sign extend the loaded values, and the array stores must store only the respective number of bytes into memory.
+
+\subsection{Long arithmetics}
+\label{s390:sec:long}
+
+Java's 64 bit integer type \code{long} is stored either as 64 bit value in storage or in two 32 bit registers. Almost all long instructions are inline except \code{LMUL}, \code{LDIV} and \code{LREM} that are delegated to builtins. Addition is performed as one 32 bit addition followed by a second 32 bit addition with carry, substraction works in a similar way. s390 provides 64 bit shift instructions that are used to implement the \code{I2L} intermediate instruction and long shift operations. Those shift instructions always operate on an \emph{even-odd pair of registers}. If not already in such a register pair, the value has to be copied into \code{REG\_ITMP31\_PACKED}. This is actually always the case with the current register allocator, because it allocates the least significant half of the 64 bit value to the lower register of the pair. This could however be simply improved by making the register allocator always prefer an \emph{even-odd pair of registers} for the allocation of 64 bit variables.
+
+\subsection{Floating point arithmetics}
+
+s390 defines 16 64 bit wide floating point registers, that can hold single or double precision IEEE floating point values. Two of those registers can be combined to hold an extended precision IEEE floating value, but this feature is not needed for CACAO. Note that not all 16 registers must be available: registers \code{\%f0}, \code{\%f2}, \code{\%f4}, \code{\%f6} are available on all ESA/390 models. The remaining registers are referred to as additional \emph{floating-point registers} (AFR) and they are present only if the \emph{basic-floating-point-extensions facility} is installed. The current code base blindly assumes that all 16 registers are available. We took care to allocate the AFRs only as temporary registers, thus in future releases we can easily support models without AFRs by simply marking the respective registers as reserved in the register descriptor arrays (\code{nregdescfloat}) and by not storing and restoring them at \emph{ELF ABI} - \emph{CACAO ABI} boundaries.
+
+Java floating point semantics require a IEEE 754 \emph{round to nearest mode}. The rounding mode is controlled via the floating point control register \code{fpc}. On Linux/s390 the \code{fpc} register of newly started processes is always initialised to 0, meaning \emph{round to nearest} \cite{s390:bib:abi}, so no extra effort needs to be made here.
+
+\subsection{Machine code generation}
+
+The usual way to generate machine code in CACAO is to use code generation macros defined in the architecture dependent header file \code{codegen.h}. For example on alpha, to generate machine code equivalent to the following assembly code:
+
+\begin{verbatim}
+ild 16(%r9), %r10
+\end{verbatim}
+
+one would place the following macro into the code generation algorithm:
+
+\begin{verbatim}
+M_ILD(R9, 16, R10)
+\end{verbatim}
+
+On s390, the equivalent instruction in assembly language would be:
+
+\begin{verbatim}
+l %r10, 16(%r9)
+\end{verbatim}
+
+and would lead to definition of the following macro:
+
+\begin{verbatim}
+M_L(R10, 16, 0, R9)
+\end{verbatim}
+
+For ease of maintenance there is an effort to keep all code generators as similar as possible. The proffered signature of the code generation macros is the one used in the alpha code generator. To honour this requirement but keep the possibility of using special s390 instructions not available in the alpha instruction set, the code generation macros were defined in two layers:
+
+The instructions prefixed with the prefix \code{N\_} follow exactly to the s390 naming and conventions as defined in~\cite{s390:bib:principles}.
+
+\begin{verbatim}
+N_L(dest, disp, index, base)
+\end{verbatim}
+
+The widely used code generation macros prefixed with an \code{M\_} are an alpha compatibility layer. They define alpha-like code generation macros in terms of \code{N\_} prefixed code generation macros.
+
+\begin{verbatim}
+#define M_ALD(base, disp, dest) N_L(dest, disp, 0, base)
+\end{verbatim}
+
+To prevent subtle errors, if CACAO is compiled in debug mode, all code generation macros validate the passed parameters. In release mode, no run-time checks are performed.
+
+As already mentioned in section~\ref{s390:sec:jitabi}, some instructions don't accept register \code{\%r0} as operand, but rather treat it as \emph{optional operand not given}. Again, to prevent subtle errors, if CACAO is compiled in debug mode, the corresponding code generation macros don't accept \code{\%r0} as operand. Instead a special value, \code{RN}, meaning \emph{register none} must be given. In release mode, \code{RN} just expands to \code{\%r0} and no run-time checks are performed.
+
+\subsection{Exception handling}
+
+In contrast to other ports, in the s390 one we try to perform most of exception handling in C code. A port is required to implement an \code{asm\_handle\_exception} function in assembly language that is called only from JIT code with special conventions: register \code{xptr} contains the exception object and register \code{xpc} contains the program counter of the failing instruction, which can be mapped to a java byte code index. All other registers are required to be left unchanged. The s390 version is a thin wrapper around a C function \code{md\_handle\_exception} and does the following:
+
+\begin{itemize}
+ \item Allocates 3 arrays on the stack: \code{regs[16]}, \code{fregs[16]}, \code{out[3]}.
+ \item Stores special, temporary and argument integer registers into \code{regs}.
+ \item Stores temporary and argument floating point registers into \code{fregs}.
+ \item Calls \code{md\_handle\_exception} with the 3 arrays as arguments.
+ \item \code{md\_handle\_exception} while handling the exception computes new values for registers and puts them into the respective arrays. This eventually includes a new stack pointer, a new procedure vector, new values for callee saved registers and a new program counter.
+ \item Restores registers from the respective arrays.
+ \item Jumps to the address contained in register \code{xpc}.
+\end{itemize}
+
+\subsection{Exception raising}
+
+Currently there are two approaches to raise an exception in JIT code:
+
+\begin{itemize}
+ \item A call to \code{asm\_handle\_exception}.
+ \item Make the JIT code produce a hardware exception, and call \code{asm\_handle\_exception} from a signal handler.
+\end{itemize}
+
+The first approach requires special stub code to be generated for the call while the second requires generation of very little code: a single instruction or even none at all. Handling of hardware exceptions on the other side involves the kernel and a context switch and can therefore be a costy operation. But because of the fundamental property of exceptions being rare, we prefer to reduce the code size at the price of occasional performance penalty.
+
+Consider for example the assembly code corresponding to the load an object's field in figure~\ref{s390:fig:exceptionrise}. If the value in \code{\%r10} points to a valid java object, the field value is loaded. If however the value in \code{\%r10} is a \code{null} pointer, the process receives a \code{SIGSEGV} signal and the operating system passes control to a function \code{md\_handle\_sigsegv}, the registered handler for this signal. This signal handler has access to all registers and the faulting program counter as well. It examines the opcode of the faulting instruction to see whether it corresponds to the use of a \code{null} pointer. If so, an exception object is allocated and put into the \code{xpc} register, \code{xptr} is set to the faulting address and program flow is resumed at \code{asm\_handle\_exception}.
+
+\begin{figure}[H]
+\begin{verbatim}
+l %r9, 36(%r10)
+\end{verbatim}
+\caption{Load of an object's field with the potential of rising a \code{NullPointerException}.}
+\label{s390:fig:exceptionrise}
+\end{figure}
+
+For explicit exception raising, we have defined the \code{ill} pseudo instruction in RR format. Its mnemonic is defined if figure~\ref{s390:fig:ill} and its machine code format in table~\ref{s390:tbl:ill}.
+
+\begin{figure}
+\centering
+\begin{verbatim}
+ill register, exception_number
+\end{verbatim}
+\caption{Mnemonic of the \code{ill} pseudo instruction}
+\label{s390:fig:ill}
+\end{figure}
+
+\begin{table}
+\centering
+\begin{tabular}{|c|c|c|c|}
+ \hline
+ Bits & 0 - 7 & 8 - 11 & 12 - 15 \\
+ \hline
+ Contents & 0x02 & register & exception number \\
+ \hline
+\end{tabular}
+\caption{Machine code for the \code{ill} pseudo instruction}
+\label{s390:tbl:ill}
+\end{table}
+
+As the opcode \code{0x02} is no valid opcode according to~\cite{s390:bib:principles} , once that instruction is reached, it will lead to an illegal instruction exception. The operating system delivers a \code{SIGILL} signal to the process and control is passed to the registered signal handler. This signal handler then examines the opcode of the instruction at the faulting address. In case it corresponds to the \code{ill} pseudo-instruction, the second register field is interpreted as exception number. The corresponding exception object is then instantiated and control passed to \code{asm\_handle\_exception}.
+
+Signal handling can be used to support corner cases of arithmetics that can't be handled by the architecture natively. Consider for example the special case of the division of \code{0x80000000} (\code{Integer.MIN}) by \code{0xFFFFFFFF} (-1) that raises a fixed-point divide exception which is signalled to the process by a \code{SIGFPE} signal. If the signal handler determines that the faulting operation was an integer division with those special values as operands, the destination operand is set to the expected result (-1) and normal program flow is resumed.
+
+Table~\ref{s390:tbl:signals} contains an overview of signals used in CACAO JIT code.
+
+\begin{table}
+\centering
+\begin{tabular}{|c|c|c|}
+\hline
+Signal & Faulting instruction & Thrown runtime exception \\
+\hline
+\code{SIGSEGV} & \code{L} & \code{EXCEPTION\_HARDWARE\_NULLPOINTER} \\
+\code{SIGSEGV} & \code{ST} & \code{EXCEPTION\_HARDWARE\_NULLPOINTER} \\
+\code{SIGSEGV} & \code{CL} & \code{EXCEPTION\_HARDWARE\_NULLPOINTER} \\
+\code{SIGILL} & \code{ILL} & \code{EXCEPTION\_HARDWARE\_ARITHMETIC} \\
+\code{SIGILL} & \code{ILL} & \code{EXCEPTION\_HARDWARE\_ARRAYINDEXOUTOFBOUNDS} \\
+\code{SIGILL} & \code{ILL} & \code{EXCEPTION\_HARDWARE\_CLASSCAST} \\
+\code{SIGILL} & \code{ILL} & \code{EXCEPTION\_HARDWARE\_PATCHER} \\
+\code{SIGFPE} & \code{DR} & \code{EXCEPTION\_HARDWARE\_ARITHMETIC} \\
+\code{SIGFPE} & \code{DR} & \code{EXCEPTION\_HARDWARE\_ARITHMETIC} \\
+\hline
+\end{tabular}
+\caption{Overview of signals used by JIT code in Cacao}
+\label{s390:tbl:signals}
+\end{table}
+
+\subsection{Code patching}
+
+Not all the information needed for program execution is available at compile time. Therefore some parts of the JIT-code need to be \emph{patched} at runtime. A trap instruction is placed at the beginning of the code in question. Further, a \emph{patcher reference} is created. This is a tiny data structure associated with the patched position encapsulating metadata about the information to be patched. The trap instruction used is the \code{ill} pseudo-instruction with a exception number of \code{EXCEPTION\_HADRWARE\_PATCHER}.
+
+Once the patched position is reached and the trap instruction executed the operating system passes control the the \code{md\_signal\_handler\_sigill} function. This function inspects the faulting instruction and then passes control to the machine independent \code{signal\_handle} function, which in turn invokes the machine independent entry into the patching subsystem: \code{patcher\_handler}. Here the faulting program counter is used to look up the associated \emph{patcher reference}. The address of the machine dependent patcher function is extracted from the \emph{patcher reference} and the patcher is invoked with the \emph{patcher reference} as argument. After the patcher function has finished, and the signal handler exits, program flow is resumed at the now reconstructed patched position. The anatomy of a patcher function is the following:
+
+\begin{itemize}
+ \item Examine the patcher reference to determine what information needs to be retrieved.
+ \item Retrieve required information.
+ \item Overwrite the trap instruction at the patched position with the original machine code.
+ \item Patch required information. This is usually done in one of the following ways:
+ \begin{itemize}
+ \item Modify a value on the data segment. The offset of the value is extracted from the \emph{patcher reference}.
+ \item Modify machine code near the patched position.
+ \end{itemize}
+\end{itemize}
+
+Consider the example of calling an object's virtual method in figure~\ref{s390:fig:patch1}. At the time the code for the call is assembled, the called method's class may not have been loaded and thus the offset in the virtual function table may not yet be known. The code generator simply generates the second load with a displacement of 0. It then replaces the machine code at the current location with a trap instruction and creates a \emph{patcher reference} (figure~\ref{s390:fig:patch2}). In the case of a virtual function call it contains an \code{unresolved\_method *}, a data structure encapsulating information needed to resolve the method. Once the trap instruction is reached, the responsible patcher, \code{patcher\_invokevirtual} will be invoked by the patcher subsystem. It resolves the method, then removes the trap instruction and finally, modifies the displacement of the second load, to reflect the offset in the virtual function table (figure~\ref{s390:fig:patch3}).
+
+\begin{figure}
+\begin{verbatim}
+l mptr, offset_vftbl_ptr(a0) ; Load the object's VFTBL pointer
+l pv, offset_method(mptr) ; Load pointer to method from VFTBL
+\end{verbatim}
+\caption{Machine code for normal virtual function call}
+\label{s390:fig:patch1}
+\end{figure}
+
+\begin{figure}
+\begin{verbatim}
+; Machine code replaced with trap instruction
+; Patcher reference created for this program counter
+ill EXCEPTION_HARDWARE_PATCHER
+l pv, 0(mptr)
+\end{verbatim}
+\caption{Machine code for virtual function call before being patched}
+\label{s390:fig:patch2}
+\end{figure}
+
+\begin{figure}
+\begin{verbatim}
+; Trap instruction removed and original machine code restored
+l mptr, offset_vftbl_pointer(a0)
+; Load instruction patched
+l pv, 16(mptr)
+\end{verbatim}
+\caption{Machine code for virtual function call after being patched}
+\label{s390:fig:patch3}
+\end{figure}
+
+The above example shows, that patchers that modify machine code are tightly coupled with the code used for its generation. Here, given the program counter of the patched position, the patcher is expected to exactly determine the load instruction to patch. On one hand, its easy, because it's simply the next instruction after the trap. On the other hand, care must be taken when modifying the code generation portion to not forget keep the patchers up to date.
+
+\subsection{Data segment access}
+
+One speciality of s390 compared with other architectures is the format of memory addresses in instructions. This can be given as \code{displacement(base)} or \code{displacement(index, base)} where \code{displacement} is an unsigned 12 bit value while \code{base} and \code{index} designate registers. The resulting memory address is calculated as the sum of the displacement and the values in the registers. The conventional way to address a value on the data segment is to use a negative displacement with the procedure vector register. As this obviously can't be done on s390 a workaround was needed. \\
+
+We decided to add a negative constant \code{N\_PV\_OFFSET} to the procedure vector in each java methods prologue. This way, a load of the form as in figure~\ref{s390:fig:dsegload1} turns into a load of the form as in figure~\ref{s390:fig:dsegload2} with a non-negative displacement for the first 4 kB of the data segment. For data segment access beyond that barrier, special code has to be generated. Most of those accesses can be fullfitted by first loading the negative displacement as 16 bit signed immediate value into the destination register and then using that register as an index register for the actual load as in figure~\ref{s390:fig:dsegload3}. Note however, that the code does not work if the destination register is \code{\%r0}, because \code{\%r0} can't be used as index register.
+
+\begin{figure}[H]
+\begin{verbatim}
+ l reg, negative_displacement(pv)
+\end{verbatim}
+\caption{Usual way to load a value from the data segment}
+\label{s390:fig:dsegload1}
+\end{figure}
+
+\begin{figure}[H]
+\begin{verbatim}
+ l reg, negative_displacement - N_PV_OFFSET(pv)
+\end{verbatim}
+\caption{Load from data segment with non-negative displacement}
+\label{s390:fig:dsegload2}
+\end{figure}
+
+\begin{figure}[H]
+\begin{verbatim}
+ lhi reg, negative_displacement
+ l reg, 0(reg, pv)
+\end{verbatim}
+\caption{Load from data segment for large displacements}
+\label{s390:fig:dsegload3}
+\end{figure}
+
+In very rare cases, where the data can't be addressed using a signed 16 bit offset, we place the negative displacement into the instruction flow and load it in a PC relative fashion, as seen in figure~\ref{s390:fig:dsegload4}.
+
+\begin{figure}[H]
+\begin{verbatim}
+ bras reg, L_bras ; Branch over constant dseg offset in instruction stream
+ ; and store current PC of next instruction in reg
+ .long negative_displacement
+L_bras:
+ l reg, 0(reg) ; Load constant dseg offset into reg
+ l reg, 0(reg, pv) ; Address dseg using two registers
+\end{verbatim}
+\caption{Load from data segment for very large displacements}
+\label{s390:fig:dsegload4}
+\end{figure}
+
+The fact, that in JIT code the procedure vector is always set off must be kept in mind when passing its value to architecture independent code, for example the patcher subsystem, that expects it to point to the methods entry point. \code{N\_PV\_OFFSET} must first be substracted from the procedure vector value.
+
+\subsection{Recalculation of the procedure vector}
+
+Because the procedure vector is a caller saved register in the \emph{JIT ABI}, but a callee saved register in the \emph{ELF ABI}, the procedure vector has to be recalculated after each Java-to-Java call. This is done by the snippet of assembly code seen in figure~\ref{s390:fig:pvrestore1}
+
+\begin{figure}[H]
+\begin{verbatim}
+ ; get program counter into pv
+ basr pv, 0
+L_basr:
+ ; substract offset to start of method
+ ahi pv, -(L_basr - L_mcodebase) + N_PV_OFFSET
+\end{verbatim}
+\caption{Assembly code for the recalculation of the procedure vector}
+\label{s390:fig:pvrestore1}
+\end{figure}
+
+Although rare, it happens for large methods that the that the immediate operand to \code{ahi} does not fit into the range of valid immediates. Care has to be taken to still generate correct code as seen in the assembly code in figure~\ref{s390:fig:pvrestore2}.
+
+\begin{figure}[H]
+\begin{verbatim}
+ ; Jump over (big) constant in instruction flow and
+ ; get program counter of next instruction into PV.
+ bras pv, L_bras
+ ; offset to start of method is placed in instruction flow
+ .long -(L_bras - L_mcodebase) + N_PV_OFFSET
+L_bras:
+ ; Add offset to program counter retrieved above.
+ a pv, 0(pv)
+\end{verbatim}
+\caption{Assembly code for the recalculation of the procedure vector for large methods}
+\label{s390:fig:pvrestore2}
+\end{figure}
+
+\subsection{Long branches}
+
+For program counter relative branches, that are used for inter-method branching, the offset is specified as signed 17 bit integer. The size of most methods does not exceed 64kB. But occasionally, there are large methods that require a branch with a offset not fitting into this range. We call this kind of branches \emph{long branches}. If a backward \emph{long branch} is generated, this does not cause further troubles. The problem are forward branches: branches to not yet generated code. In such cases, instead of generating a branch, we reserve exactly the size of a branch instruction. This space will be filled with a (short) branch as soon as the referenced code gets generated. This is obviously a problem if the branch generated later shows to be a \emph{long branch}, because the code generated for a \emph{long branch} does not fit into the reserved space.
+
+This condition is detected in \code{emit\_branch} by checking the passed displacement to fit into the 17 bit signed range. If this condition does not hold and the flag \code{CODEGENDATA\_FLAG\_LONGBRANCHES} is not set, then both flags \code{CODEGENDATA\_FLAG\_ERROR} and \code{CODEGENDATA\_FLAG\_LONGBRANCHES} are set and no branch is generated. After \code{codegen\_emit} returns, \code{codegen\_generate} checks for those two flags. If they are both set, the method is recompiled, with only the \code{CODEGENDATA\_FLAG\_LONGBRANCHES} flags set.
+
+This causes that more space is reserved for forward branches: enough to patch either a (short) branch or a \emph{long branch}.
+
+A long branch is implemented by storing the long displacement in the data segment. The generated code loads the displacement from the data segment, combines it with the procedure vector and then jumps to the resulting address.
+
+\subsection{The development environment}
+
+Most of the development has been done on a Debian GNU/Linux system running on the Hercules emulator. Installing the system on the emulator can be tricky and needs several hours to complete. It is not recommended to setup such a system from scratch, but rather use the disk image floating around at the complang group.
+
+As the emulator showed to be slow for native compiling, a cross compiler was used instead. To eliminate the need of cross compiling all dependencies of CACAO on the development system, the following approach was chosen instead:
+
+\begin{itemize}
+ \item The root of the target system was mounted via NFS on the development system.
+ \item The cross compiler was set up to use the mounted NFS root as sysroot.
+\end{itemize}
+
+The procedure of building the cross compiler in practice is shown in figure~\ref{s390:fig:crosgcc}.
+
+\begin{figure}
+\begin{verbatim}
+$ mount s390-system:/ /foo
+$ cd binutils-2.17
+$ ./configure \
+ --target=s390-ibm-linux-gnu \
+ --with-build-sysroot=/foo \
+ --with-sysroot=/foo
+$ make install
+$ cd gcc-4.1.1
+$ ./configure \
+ --target=s390-ibm-linux-gnu \
+ --prefix=/usr/local \
+ --with-sysroot=/foo \
+ --enable-languages=c
+$ make install
+\end{verbatim}
+\caption{Building an s390 cross compiler with the sysroot feature}
+\label{s390:fig:crosgcc}
+\end{figure}
+
+In the final phase of development, we got a free account at the \emph{IBM community development system} for three months. This account provided us with root access to a ESA/390 virtual machine with 256MB of RAM preinstalled with a GNU/Linux system. Development on that system worked perfectly and it had a more reasonable performance than the emulated system.
+
+
+
+
AC_DEFUN([AC_PROG_JAVAC],[
AC_REQUIRE([AC_EXEEXT])dnl
if test "x$JAVAPREFIX" = x; then
- test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, "javac$EXEEXT -bootclasspath ${CLASSPATH_CLASSES}" "ecj$EXEEXT -bootclasspath ${CLASSPATH_CLASSES}" "gcj$EXEEXT -C -bootclasspath ${CLASSPATH_CLASSES}" "jikes$EXEEXT -bootclasspath ${CLASSPATH_CLASSES}")
+ test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, "javac$EXEEXT" "ecj$EXEEXT" "gcj$EXEEXT -C")
else
- test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, "javac$EXEEXT -bootclasspath ${CLASSPATH_CLASSES}" "ecj$EXEEXT -bootclasspath ${CLASSPATH_CLASSES}" "gcj$EXEEXT -C -bootclasspath ${CLASSPATH_CLASSES}" "jikes$EXEEXT -bootclasspath ${CLASSPATH_CLASSES}", $JAVAPREFIX)
+ test "x$JAVAC" = x && AC_CHECK_PROGS(JAVAC, "javac$EXEEXT" "ecj$EXEEXT" "gcj$EXEEXT -C", $JAVAPREFIX)
fi
test "x$JAVAC" = x && AC_MSG_ERROR([no acceptable Java compiler found in \$PATH])
AC_PROG_JAVAC_WORKS
dnl m4/annotations.m4
dnl
-dnl Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
-dnl C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-dnl E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-dnl J. Wenninger, Institut f. Computersprachen - TU Wien
+dnl Copyright (C) 2007, 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
dnl
dnl This file is part of CACAO.
dnl
AC_DEFUN([AC_CHECK_ENABLE_ANNOTATIONS],[
AC_MSG_CHECKING(wether to build annotations support)
AC_ARG_ENABLE([annotations],
- [AS_HELP_STRING(--enable-annotations,build annotations support [[default=no]])],
+ [AS_HELP_STRING(--enable-annotations,build annotations support [[default=(cldc1.1:no,javase:yes]])],
[case "${enableval}" in
yes)
ENABLE_ANNOTATIONS=yes
;;
- *)
+ no)
ENABLE_ANNOTATIONS=no
;;
+ *)
+ AC_CHECK_ENABLE_ANNOTATIONS_DEFAULT
+ ;;
esac],
- [ENABLE_ANNOTATIONS=no])
+ [AC_CHECK_ENABLE_ANNOTATIONS_DEFAULT])
AC_MSG_RESULT(${ENABLE_ANNOTATIONS})
AM_CONDITIONAL([ENABLE_ANNOTATIONS], test x"${ENABLE_ANNOTATIONS}" = "xyes")
AC_DEFINE([ENABLE_ANNOTATIONS], 1, [enable annotations])
fi
])
+
+
+dnl check for the default value for --enable-annotations
+
+AC_DEFUN([AC_CHECK_ENABLE_ANNOTATIONS_DEFAULT],[
+if test x"${ENABLE_JAVAME_CLDC1_1}" = "xyes"; then
+ ENABLE_ANNOTATIONS=no
+else
+ ENABLE_ANNOTATIONS=yes
+fi
+])
dnl m4/assertion.m4
dnl
dnl Copyright (C) 2007
-dnl CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
dnl
dnl This file is part of CACAO.
dnl
--- /dev/null
+##### http://autoconf-archive.cryp.to/az_python.html
+#
+# SYNOPSIS
+#
+# AZ_PYTHON_DEFAULT
+# AZ_PYTHON_ENABLE
+# AZ_PYTHON_WITH
+# AZ_PYTHON_PATH
+# AZ_PYTHON_VERSION_ENSURE( [2.2] )
+# AZ_PYTHON_CSPEC
+# AZ_PYTHON_LSPEC
+#
+# DESCRIPTION
+#
+# This file provides autoconf support for those applications that
+# want to embed python. It supports all pythons >= 2.2 which is the
+# first official release containing distutils. Version 2.2 of python
+# was released December 21, 2001. Since it actually executes the
+# python, cross platform configuration will probably not work. Also,
+# most of the platforms supported are consistent until you look into
+# MacOSX. The python included with it is installed as a framework
+# which is a very different environment to set up the normal tools
+# such as gcc and libtool to deal with. Therefore, once we establish
+# which python that we are going to use, we use its distutils to
+# actually compile and link our modules or applications.
+#
+# At this time, it does NOT support linking with Python statically.
+# It does support dynamic linking.
+#
+# This set of macros help define $PYTHON, $ENABLE_PYTHON, $PYTHON_CSPEC
+# and $PYTHON_LSPEC. $PYTHON defines the full executable path for the
+# Python being linked to and is used within these macros to determine
+# if that has been specified or found. These macros do execute this
+# python version so it must be present on the system at configure
+# time.
+#
+# $ENABLE_PYTHON is an automake variable that defines whether Python
+# support should be included or not in your application.
+# $PYTHON_CSPEC is a variable that supplies additional CFLAGS for the
+# compilation of the application/shared library. $PYTHON_LSPEC is a
+# variable that supplies additional LDFLAGS for linking the
+# application/shared library.
+#
+# The following is an example of how to set up for python usage
+# within your application in your configure.in:
+#
+# AZ_PYTHON_DEFAULT( )
+# AZ_PYTHON_ENABLE( ) # Optional
+# AZ_PYTHON_WITH( ) # Optional
+# AZ_PYTHON_PATH( ) # or AZ_PYTHON_INSIST( )
+# # if $PYTHON is not defined, then the following do nothing.
+# AZ_PYTHON_VERSION_ENSURE( [2.2] )
+# AZ_PYTHON_CSPEC
+# AZ_PYTHON_LSPEC
+#
+# The AZ_PYTHON_DEFAULT sets the $ENABLE_PYTHON to false. Thereby,
+# excluding it if it was optional.
+#
+# The AZ_PYTHON_ENABLE looks for the optional configure parameters of
+# --enable-python/--disable-python and establishes the $PYTHON and
+# $ENABLE_PYTHON variables accordingly.
+#
+# The AZ_PYTHON_WITH looks for the optional configure parameters of
+# --with-python/--without-python and establishes the $PYTHON and
+# $ENABLE_PYTHON variables accordingly.
+#
+# The AZ_PYTHON_PATH looks for python assuming that none has been
+# previously found or defined and issues an error if it does not find
+# it. If it does find it, it establishes the $PYTHON and $ENABLE_PYTHON
+# variables accordingly. AZ_PYTHON_INSIST could be used here instead
+# if you want to insist that Python support be included using the
+# --enable-python or --with-python checks previously done.
+#
+# The AZ_PYTHON_VERSION_ENSURE issues an error if the Python
+# previously found is not of version 2.2 or greater.
+#
+# Once that these macros have be run, we can use ENABLE_PYTHON within
+# the makefile.am file to conditionally add the Python support such
+# as:
+#
+# Makefile.am example showing optional inclusion of directories:
+#
+# if ENABLE_PYTHON
+# plugins = plugins
+# src = src
+# else
+# plugins =
+# src =
+# endif
+#
+# SUBDIRS = . $(plugins) $(src)
+#
+# Makefile.am example showing optional shared library build:
+#
+# if ENABLE_PYTHON
+# lib_LTLIBRARIES = libElemList.la
+# libElemList_la_SOURCES = libElemList.c
+# libElemList_la_CFLAGS = @PYTHON_CSPEC@
+# libElemList_la_LDFLAGS = @PYTHON_LSPEC@
+# endif
+#
+# Makefile.am example showing optional program build:
+#
+# if ENABLE_PYTHON
+# bin_PROGRAMS = runFunc
+# runFunc_SOURCES = runFunc.c
+# runFunc_CFLAGS = @PYTHON_CSPEC@
+# runFunc_LDFLAGS = @PYTHON_LSPEC@
+# endif
+#
+# The above compiles the modules only if ENABLE_PYTHON was specified as
+# true. Also, the else portion of the if was optional.
+#
+# LAST MODIFICATION
+#
+# 2007-08-04
+#
+# COPYLEFT
+#
+# Copyright (c) 2007 Robert White <kranki@mac.com>
+# Copyright (c) 2007 Dustin J. Mitchell <dustin@cs.uchicago.edu>
+#
+# Copying and distribution of this file, with or without
+# modification, are permitted in any medium without royalty provided
+# the copyright notice and this notice are preserved.
+
+# AZ_PYTHON_DEFAULT( )
+# -----------------
+# Sets the default to not include Python support.
+
+AC_DEFUN([AZ_PYTHON_DEFAULT],
+[
+ az_python_use=false
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+])
+
+
+
+# AZ_PYTHON_ENABLE( [path] )
+# -----------------------------------------------------------------
+# Handles the various --enable-python commands.
+# Input:
+# $1 is the optional search path for the python executable if needed
+# Ouput:
+# ENABLE_PYTHON (AM_CONDITIONAL) is true if python executable found
+# and --enable-python was requested; otherwise false.
+# $PYTHON contains the full executable path to python if PYTHON_ENABLE_USE
+# is true.
+#
+# Example:
+# AZ_PYTHON_ENABLE( )
+# or
+# AZ_PYTHON_ENABLE( "/usr/bin" )
+
+AC_DEFUN([AZ_PYTHON_ENABLE],
+[
+ AC_ARG_VAR([PYTHON],[Python Executable Path])
+
+ # unless PYTHON was supplied to us (as a precious variable),
+ # see if --enable-python[=PythonExecutablePath], --enable-python,
+ # --disable-python or --enable-python=no was given.
+ if test -z "$PYTHON"
+ then
+ AC_MSG_CHECKING(for --enable-python)
+ AC_ARG_ENABLE(
+ python,
+ AC_HELP_STRING([--enable-python@<:@=PYTHON@:>@],
+ [absolute path name of Python executable]
+ ),
+ [
+ if test "$enableval" = "yes"
+ then
+ # "yes" was specified, but we don't have a path
+ # for the executable.
+ # So, let's searth the PATH Environment Variable.
+ AC_MSG_RESULT(yes)
+ AC_PATH_PROG(
+ [PYTHON],
+ python,
+ [],
+ $1
+ )
+ if test -z "$PYTHON"
+ then
+ AC_MSG_ERROR(no path to python found)
+ fi
+ az_python_use=true
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ AZ_PYTHON_PREFIX( )
+ elif test "$enableval" = "no"
+ then
+ AC_MSG_RESULT(no)
+ az_python_use=false
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ else
+ # $enableval must be the executable path then.
+ AC_SUBST([PYTHON], ["${enableval}"])
+ AC_MSG_RESULT($withval)
+ az_python_use=true
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ AZ_PYTHON_PREFIX( )
+ fi
+ ],
+ [
+ # --with-python was not specified.
+ AC_MSG_RESULT(no)
+ az_python_use=false
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ ]
+ )
+ fi
+])
+
+
+
+# AZ_PYTHON_CSPEC( )
+# -----------------
+# Set up the c compiler options to compile Python
+# embedded programs/libraries in $PYTHON_CSPEC if
+# $PYTHON has been defined.
+
+AC_DEFUN([AZ_PYTHON_CSPEC],
+[
+ AC_ARG_VAR( [PYTHON], [Python Executable Path] )
+ if test -n "$PYTHON"
+ then
+ az_python_prefix=`${PYTHON} -c "import sys; print sys.prefix"`
+ if test -z "$az_python_prefix"
+ then
+ AC_MSG_ERROR([Python Prefix is not known])
+ fi
+ az_python_execprefix=`${PYTHON} -c "import sys; print sys.exec_prefix"`
+ az_python_version=`$PYTHON -c "import sys; print sys.version[[:3]]"`
+ az_python_includespec="-I${az_python_prefix}/include/python${az_python_version}"
+ if test x"$python_prefix" != x"$python_execprefix"; then
+ az_python_execspec="-I${az_python_execprefix}/include/python${az_python_version}"
+ az_python_includespec="${az_python_includespec} $az_python_execspec"
+ fi
+ az_python_ccshared=`${PYTHON} -c "import distutils.sysconfig; print distutils.sysconfig.get_config_var('CFLAGSFORSHARED')"`
+ az_python_cspec="${az_python_ccshared} ${az_python_includespec}"
+ AC_SUBST([PYTHON_CSPEC], [${az_python_cspec}])
+ AC_MSG_NOTICE([PYTHON_CSPEC=${az_python_cspec}])
+ AC_DEFINE(ENABLE_PYTHON, 1, [enabled python pass])
+ fi
+])
+
+
+
+# AZ_PYTHON_INSIST( )
+# -----------------
+# Look for Python and set the output variable 'PYTHON'
+# to 'python' if found, empty otherwise.
+
+AC_DEFUN([AZ_PYTHON_PATH],
+[
+ AC_ARG_VAR( [PYTHON], [Python Executable Path] )
+ if test -z "$PYTHON"
+ then
+ AC_MSG_ERROR([Python Executable not found])
+ fi
+])
+
+
+
+# AZ_PYTHON_LSPEC( )
+# -----------------
+# Set up the linker options to link Python embedded
+# programs/libraries in $PYTHON_LSPEC if $PYTHON
+# has been defined.
+
+AC_DEFUN([AZ_PYTHON_LSPEC],
+[
+ AC_ARG_VAR( [PYTHON], [Python Executable Path] )
+ if test -n "$PYTHON"
+ then
+ AZ_PYTHON_RUN([
+import sys
+import distutils.sysconfig
+strUseFrameWork = "--enable-framework"
+dictConfig = distutils.sysconfig.get_config_vars( )
+strConfigArgs = dictConfig.get("CONFIG_ARGS")
+strLinkSpec = dictConfig.get('LDFLAGS')
+if -1 == strConfigArgs.find(strUseFrameWork):
+ strLibPL = dictConfig.get("LIBPL")
+ if strLibPL and (strLibPL != ""):
+ strLinkSpec += " -L%s" % (strLibPL)
+ strSys = dictConfig.get("SYSLIBS")
+ if strSys and (strSys != ""):
+ strLinkSpec += " %s" % (strSys)
+ strSHL = dictConfig.get("SHLIBS")
+ if strSHL and (strSHL != ""):
+ strLinkSpec += " %s" % (strSHL)
+ # Construct the Python Library Name.
+ strTmplte = " -lpython%d.%d"
+ if (sys.platform == "win32") or (sys.platform == "os2emx"):
+ strTmplte = " -lpython%d%d"
+ strWrk = strTmplte % ( (sys.hexversion >> 24),
+ ((sys.hexversion >> 16) & 0xff))
+ strLinkSpec += strWrk
+else:
+ # This is not ideal since it changes the search path
+ # for Frameworks which could have side-effects on
+ # other included Frameworks. However, it is necessary
+ # where someone has installed more than one frameworked
+ # Python. Frameworks are really only used in MacOSX.
+ strLibFW = dictConfig.get("PYTHONFRAMEWORKPREFIX")
+ if strLibFW and (strLibFW != ""):
+ strLinkSpec += " -F%s" % (strLibFW)
+strLinkSpec += " %s" % (dictConfig.get('LINKFORSHARED'))
+print strLinkSpec
+ ])
+ AC_SUBST([PYTHON_LSPEC], [${az_python_output}])
+ AC_MSG_NOTICE([PYTHON_LSPEC=${az_python_output}])
+ fi
+])
+
+
+
+# AZ_PYTHON_PATH( )
+# -----------------
+# Look for Python and set the output variable 'PYTHON'
+# to 'python' if found, empty otherwise.
+
+AC_DEFUN([AZ_PYTHON_PATH],
+[
+ AC_ARG_VAR( [PYTHON], [Python Executable Path] )
+ AC_PATH_PROG( PYTHON, python, [], $1 )
+ if test -z "$PYTHON"
+ then
+ AC_MSG_ERROR([Python Executable not found])
+ else
+ az_python_use=true
+ fi
+ AM_CONDITIONAL(ENABLE_PYTHON, test "$az_python_use" = "true")
+])
+
+
+
+# AZ_PYTHON_PREFIX( )
+# -------------------
+# Use the values of $prefix and $exec_prefix for the corresponding
+# values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX.
+
+AC_DEFUN([AZ_PYTHON_PREFIX],
+[
+ if test -z "$PYTHON"
+ then
+ AC_MSG_ERROR([Python Executable Path is not known])
+ fi
+ ax_python_prefix=`${PYTHON} -c "import sys; print sys.prefix"`
+ ax_python_execprefix=`${PYTHON} -c "import sys; print sys.exec_prefix"`
+ AC_SUBST([PYTHON_PREFIX], ["${ax_python_prefix}"])
+ AC_SUBST([PYTHON_EXECPREFIX], ["${ax_python_execprefix}"])
+])
+
+
+
+# AZ_PYTHON_RUN( PYTHON_PROGRAM )
+# -----------------
+# Run a Python Test Program saving its output
+# in az_python_output and its condition code
+# in az_python_cc.
+
+AC_DEFUN([AZ_PYTHON_RUN],
+[
+ AC_ARG_VAR( [PYTHON], [Python Executable Path] )
+ if test -z "$PYTHON"
+ then
+ AC_MSG_ERROR([Python Executable not found])
+ else
+ cat >conftest.py <<_ACEOF
+$1
+_ACEOF
+ az_python_output=`$PYTHON conftest.py`
+ az_python_cc=$?
+ rm conftest.py
+ if test -f "conftest.pyc"
+ then
+ rm conftest.pyc
+ fi
+ fi
+])
+
+
+
+# AZ_PYTHON_VERSION_CHECK( VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE] )
+# -----------------------------------------------------------------------------
+# Run ACTION-IF-TRUE if the Python interpreter has version >= VERSION.
+# Run ACTION-IF-FALSE otherwise.
+# This test uses sys.hexversion instead of the string equivalant (first
+# word of sys.version), in order to cope with versions such as 2.2c1.
+# hexversion has been introduced in Python 1.5.2; it's probably not
+# worth to support older versions (1.5.1 was released on October 31, 1998).
+
+AC_DEFUN([AZ_PYTHON_VERSION_CHECK],
+ [
+ AC_ARG_VAR( [PYTHON], [Python Executable Path] )
+ if test -n "$PYTHON"
+ then
+ AC_MSG_CHECKING([whether $PYTHON version >= $1])
+ AZ_PYTHON_RUN([
+import sys, string
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+minver = map(int, string.split('$1', '.')) + [[0, 0, 0]]
+minverhex = 0
+for i in xrange(0, 4): minverhex = (minverhex << 8) + minver[[i]]
+if sys.hexversion >= minverhex:
+ sys.exit( 0 )
+else:
+ sys.exit( 1 )
+ ])
+ if test $az_python_cc -eq 0
+ then
+ $2
+ m4_ifvaln(
+ [$3],
+ [else $3]
+ )
+ fi
+ fi
+])
+
+
+
+# AZ_PYTHON_VERSION_ENSURE( VERSION )
+# -----------------
+# Insure that the Python Interpreter Version
+# is greater than or equal to the VERSION
+# parameter.
+
+AC_DEFUN([AZ_PYTHON_VERSION_ENSURE],
+[
+ AZ_PYTHON_VERSION_CHECK(
+ [$1],
+ [AC_MSG_RESULT(yes)],
+ [AC_MSG_ERROR(too old)]
+ )
+])
+
+
+
+# AZ_PYTHON_WITH( [path] )
+# -----------------------------------------------------------------
+# Handles the various --with-python commands.
+# Input:
+# $1 is the optional search path for the python executable if needed
+# Ouput:
+# ENABLE_PYTHON (AM_CONDITIONAL) is true if python executable found
+# and --with-python was requested; otherwise false.
+# $PYTHON contains the full executable path to python if ENABLE_PYTHON
+# is true.
+#
+# Example:
+# AZ_PYTHON_WITH( )
+# or
+# AZ_PYTHON_WITH("/usr/bin")
+
+AC_DEFUN([AZ_PYTHON_WITH],
+[
+ AC_ARG_VAR([PYTHON],[Python Executable Path])
+
+ # unless PYTHON was supplied to us (as a precious variable),
+ # see if --with-python[=PythonExecutablePath], --with-python,
+ # --without-python or --with-python=no was given.
+ if test -z "$PYTHON"
+ then
+ AC_MSG_CHECKING(for --with-python)
+ AC_ARG_WITH(
+ python,
+ AC_HELP_STRING([--with-python@<:@=PYTHON@:>@],
+ [absolute path name of Python executable]
+ ),
+ [
+ if test "$withval" = "yes"
+ then
+ # "yes" was specified, but we don't have a path
+ # for the executable.
+ # So, let's searth the PATH Environment Variable.
+ AC_MSG_RESULT(yes)
+ AC_PATH_PROG(
+ [PYTHON],
+ python,
+ [],
+ $1
+ )
+ if test -z "$PYTHON"
+ then
+ AC_MSG_ERROR(no path to python found)
+ fi
+ az_python_use=true
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ AZ_PYTHON_PREFIX( )
+ elif test "$withval" = "no"
+ then
+ AC_MSG_RESULT(no)
+ az_python_use=false
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ else
+ # $withval must be the executable path then.
+ AC_SUBST([PYTHON], ["${withval}"])
+ AC_MSG_RESULT($withval)
+ az_python_use=true
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ AZ_PYTHON_PREFIX( )
+ fi
+ ],
+ [
+ # --with-python was not specified.
+ AC_MSG_RESULT(no)
+ az_python_use=false
+ AM_CONDITIONAL(ENABLE_PYTHON, test x"$az_python_use" = x"true")
+ ]
+ )
+ fi
+
+])
+
dnl m4/classpath.m4
dnl
-dnl Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
-dnl C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-dnl E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-dnl J. Wenninger, Institut f. Computersprachen - TU Wien
-dnl
+dnl Copyright (C) 2007, 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+dnl
dnl This file is part of CACAO.
-dnl
+dnl
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
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
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
-dnl $Id: classpath.m4 8398 2007-08-22 16:56:45Z twisti $
dnl which Java core library should we use
AC_DEFUN([AC_CHECK_WITH_CLASSPATH_CLASSES],[
AC_MSG_CHECKING(where Java core library classes are installed)
AC_ARG_WITH([classpath-classes],
- [AS_HELP_STRING(--with-classpath-classes=<path>,path to Java core library classes (includes the name of the file and may be flat) [[default=CLASSPATH_PREFIX/{share/classpath/glibj.zip,classes}]])],
+ [AS_HELP_STRING(--with-classpath-classes=<path>,path to Java core library classes (includes the name of the file and may be flat) [[default=(gnu:${CLASSPATH_PREFIX}/share/classpath/glibj.zip,sun:${CLASSPATH_PREFIX}/control/build/${OS_DIR}-${JAVA_ARCH}/classes,*:${CLASSPATH_PREFIX})]])],
[CLASSPATH_CLASSES=${withval}],
[case "${WITH_CLASSPATH}" in
gnu)
CLASSPATH_CLASSES=${CLASSPATH_PREFIX}/share/classpath/glibj.zip
;;
sun)
- CLASSPATH_CLASSES=${CLASSPATH_PREFIX}/classes
+ CLASSPATH_CLASSES=${CLASSPATH_PREFIX}/control/build/${OS_DIR}-${JAVA_ARCH}/classes
;;
*)
CLASSPATH_CLASSES=${CLASSPATH_PREFIX}
AC_MSG_RESULT(${CLASSPATH_CLASSES})
AC_DEFINE_UNQUOTED([CLASSPATH_CLASSES], "${CLASSPATH_CLASSES}", [Java core library classes])
AC_SUBST(CLASSPATH_CLASSES)
+
+dnl define BOOTCLASSPATH for Makefiles
+case "${WITH_CLASSPATH}" in
+ cldc1.1 | gnu)
+ BOOTCLASSPATH="\$(top_builddir)/src/classes/classes:\$(CLASSPATH_CLASSES)"
+ ;;
+ *)
+ BOOTCLASSPATH="\$(CLASSPATH_CLASSES)"
+ ;;
+esac
+AC_SUBST(BOOTCLASSPATH)
])
AC_DEFUN([AC_CHECK_WITH_CLASSPATH_LIBDIR],[
AC_MSG_CHECKING(where Java core library native libraries are installed)
AC_ARG_WITH([classpath-libdir],
- [AS_HELP_STRING(--with-classpath-libdir=<dir>,installation directory of Java core library native libraries [[default=CLASSPATH_PREFIX/{lib,lib/${JAVA_ARCH}]])],
+ [AS_HELP_STRING(--with-classpath-libdir=<dir>,installation directory of Java core library native libraries [[default=(gnu:${CLASSPATH_PREFIX}/lib,sun:${CLASSPATH_PREFIX}/control/build/${OS_DIR}-${JAVA_ARCH}/lib/${JAVA_ARCH},*:${CLASSPATH_PREFIX})]])],
[CLASSPATH_LIBDIR=${withval}],
[case "${WITH_CLASSPATH}" in
gnu)
CLASSPATH_LIBDIR=${CLASSPATH_PREFIX}/lib
;;
sun)
- CLASSPATH_LIBDIR=${CLASSPATH_PREFIX}/lib/${JAVA_ARCH}
+ CLASSPATH_LIBDIR=${CLASSPATH_PREFIX}/control/build/${OS_DIR}-${JAVA_ARCH}/lib/${JAVA_ARCH}
;;
*)
CLASSPATH_LIBDIR=${CLASSPATH_PREFIX}
])
-dnl where are Java core library headers installed
-
-AC_DEFUN([AC_CHECK_WITH_CLASSPATH_INCLUDEDIR],[
-AC_MSG_CHECKING(where Java core library headers are installed)
-AC_ARG_WITH([classpath-includedir],
- [AS_HELP_STRING(--with-classpath-includedir=<dir>,installation directory of Java core library headers [[default=/usr/local/classpath/include]])],
- [CLASSPATH_INCLUDEDIR=${withval}],
- [CLASSPATH_INCLUDEDIR=${CLASSPATH_PREFIX}/include])
-AC_MSG_RESULT(${CLASSPATH_INCLUDEDIR})
-
-if test x"${WITH_CLASSPATH}" = "xsun"; then
- AC_CHECK_HEADER([${CLASSPATH_INCLUDEDIR}/${OS_DIR}/jni_md.h],
- [AC_DEFINE_UNQUOTED([CLASSPATH_JNI_MD_H], "${CLASSPATH_INCLUDEDIR}/${OS_DIR}/jni_md.h", [Java core library jni_md.h header])],
- [AC_MSG_ERROR(cannot find jni_md.h)])
-else
- AC_CHECK_HEADER([${CLASSPATH_INCLUDEDIR}/jni_md.h],
- [AC_DEFINE_UNQUOTED([CLASSPATH_JNI_MD_H], "${CLASSPATH_INCLUDEDIR}/jni_md.h", [Java core library jni_md.h header])],
- [AC_MSG_ERROR(cannot find jni_md.h)])
-fi
-
-AC_CHECK_HEADER([${CLASSPATH_INCLUDEDIR}/jni.h],
- [AC_DEFINE_UNQUOTED([CLASSPATH_JNI_H], "${CLASSPATH_INCLUDEDIR}/jni.h", [Java core library jni.h header])],
+dnl where jni_md.h is installed
+
+AC_DEFUN([AC_CHECK_WITH_JNI_MD_H],[
+AC_MSG_CHECKING(where jni_md.h is installed)
+AC_ARG_WITH([jni_md_h],
+ [AS_HELP_STRING(--with-jni_md_h=<dir>,path to jni_md.h [[default=(sun:${CLASSPATH_PREFIX}/jdk/src/solaris/javavm/export,*:${CLASSPATH_PREFIX}/include)]])],
+ [WITH_JNI_MD_H=${withval}],
+ [case "${WITH_CLASSPATH}" in
+ sun)
+ WITH_JNI_MD_H=${CLASSPATH_PREFIX}/jdk/src/solaris/javavm/export
+ ;;
+ *)
+ WITH_JNI_MD_H=${CLASSPATH_PREFIX}/include
+ ;;
+ esac])
+AC_MSG_RESULT(${WITH_JNI_MD_H})
+
+dnl We use CPPFLAGS so jni.h can find jni_md.h
+CPPFLAGS="${CPPFLAGS} -I${WITH_JNI_MD_H}"
+
+AC_CHECK_HEADER([${WITH_JNI_MD_H}/jni_md.h],
+ [AC_DEFINE_UNQUOTED([INCLUDE_JNI_MD_H], "${WITH_JNI_MD_H}/jni_md.h", [Java core library jni_md.h header])],
+ [AC_MSG_ERROR(cannot find jni_md.h)])
+])
+
+
+dnl where jni.h is installed
+
+AC_DEFUN([AC_CHECK_WITH_JNI_H],[
+AC_MSG_CHECKING(where jni.h is installed)
+AC_ARG_WITH([jni_h],
+ [AS_HELP_STRING(--with-jni_h=<dir>,path to jni.h [[default=(sun:${CLASSPATH_PREFIX}/jdk/src/share/javavm/export,*:${CLASSPATH_PREFIX}/include)]])],
+ [WITH_JNI_H=${withval}],
+ [case "${WITH_CLASSPATH}" in
+ sun)
+ WITH_JNI_H=${CLASSPATH_PREFIX}/jdk/src/share/javavm/export
+ ;;
+ *)
+ WITH_JNI_H=${CLASSPATH_PREFIX}/include
+ ;;
+ esac])
+AC_MSG_RESULT(${WITH_JNI_H})
+
+dnl We use CPPFLAGS so jni.h can find jni_md.h
+CPPFLAGS="${CPPFLAGS} -I${WITH_JNI_H}"
+
+AC_CHECK_HEADER([${WITH_JNI_H}/jni.h],
+ [AC_DEFINE_UNQUOTED([INCLUDE_JNI_H], "${WITH_JNI_H}/jni.h", [Java core library jni.h header])],
[AC_MSG_ERROR(cannot find jni.h)],
- [#define __GCJ_JNI_MD_H__
- #include CLASSPATH_JNI_MD_H])
+ [#include INCLUDE_JNI_MD_H])
])
AC_DEFUN([AC_CHECK_ENABLE_DEBUG],[
AC_MSG_CHECKING(whether debug code generation should be enabled)
AC_ARG_ENABLE([debug],
- [AS_HELP_STRING(--disable-debug,disable debug code generation [[default=yes]])],
+ [AS_HELP_STRING(--disable-debug,disable debug code generation [[default=enabled]])],
[case "${enableval}" in
no)
NDEBUG=yes
dnl m4/dump.m4
dnl
-dnl Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
-dnl C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-dnl E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-dnl J. Wenninger, Institut f. Computersprachen - TU Wien
+dnl Copyright (C) 2007, 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
dnl
dnl This file is part of CACAO.
dnl
AC_DEFUN([AC_CHECK_ENABLE_DUMP],[
AC_MSG_CHECKING(whether dump memory should be disabled)
AC_ARG_ENABLE([dump],
- [AS_HELP_STRING(--disable-dump,disable dump memory (for debugging only!) [[default=yes]])],
+ [AS_HELP_STRING(--disable-dump,disable dump memory (for debugging only!) [[default=enabled]])],
[case "${enableval}" in
no)
DISABLE_DUMP=yes
AC_DEFINE([DISABLE_DUMP], 1, [disable dump memory])
;;
- *) DISABLE_DUMP=no;;
+ *)
+ DISABLE_DUMP=no
+ ;;
esac],
[DISABLE_DUMP=no])
AC_MSG_RESULT(${DISABLE_DUMP})
+AM_CONDITIONAL([DISABLE_DUMP], test x"${DISABLE_DUMP}" = "xno")
])
--- /dev/null
+dnl m4/hpi.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 hpi_md.h is installed
+
+AC_DEFUN([AC_CHECK_WITH_HPI_MD_H],[
+AC_MSG_CHECKING(where hpi_md.h is installed)
+AC_ARG_WITH([hpi_md_h],
+ [AS_HELP_STRING(--with-hpi_md_h=<dir>,path to hpi_md.h (only with --with-classpath=sun) [[default=${CLASSPATH_PREFIX}/jdk/src/solaris/hpi/export]])],
+ [WITH_HPI_MD_H=${withval}],
+ [case "${WITH_CLASSPATH}" in
+ sun)
+ WITH_HPI_MD_H=${CLASSPATH_PREFIX}/jdk/src/solaris/hpi/export
+ ;;
+ *)
+ ;;
+ esac])
+AC_MSG_RESULT(${WITH_HPI_MD_H})
+
+dnl We use CPPFLAGS so hpi.h can find hpi_md.h
+CPPFLAGS="${CPPFLAGS} -I${WITH_HPI_MD_H}"
+
+AC_CHECK_HEADER([${WITH_HPI_MD_H}/hpi_md.h],
+ [AC_DEFINE_UNQUOTED([INCLUDE_HPI_MD_H], "${WITH_HPI_MD_H}/hpi_md.h", [Java core library hpi_md.h header])],
+ [AC_MSG_ERROR(cannot find hpi_md.h)])
+])
+
+
+dnl where hpi.h is installed
+
+AC_DEFUN([AC_CHECK_WITH_HPI_H],[
+AC_MSG_CHECKING(where hpi.h is installed)
+AC_ARG_WITH([hpi_h],
+ [AS_HELP_STRING(--with-hpi_h=<dir>,path to hpi.h (only with --with-classpath=sun) [[default=${CLASSPATH_PREFIX}/jdk/src/share/hpi/export]])],
+ [WITH_HPI_H=${withval}],
+ [WITH_HPI_H=${CLASSPATH_PREFIX}/jdk/src/share/hpi/export])
+AC_MSG_RESULT(${WITH_HPI_H})
+
+dnl We use CPPFLAGS so hpi.h can find hpi_md.h
+CPPFLAGS="${CPPFLAGS} -I${WITH_HPI_H}"
+
+AC_CHECK_HEADER([${WITH_HPI_H}/hpi.h],
+ [AC_DEFINE_UNQUOTED([INCLUDE_HPI_H], "${WITH_HPI_H}/hpi.h", [Java core library hpi.h header])],
+ [AC_MSG_ERROR(cannot find hpi.h)],
+ [#include INCLUDE_HPI_MD_H])
+])
AC_DEFUN([AC_CHECK_ENABLE_JIT],[
AC_MSG_CHECKING(whether JIT compiler should be compiled)
AC_ARG_ENABLE([jit],
- [AS_HELP_STRING(--disable-jit,disable JIT compiler [[default=yes]])],
+ [AS_HELP_STRING(--disable-jit,disable JIT compiler [[default=enabled]])],
[case "${enableval}" in
no)
ENABLE_JIT=no
dnl m4/jni.m4
dnl
-dnl Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
-dnl C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-dnl E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-dnl J. Wenninger, Institut f. Computersprachen - TU Wien
+dnl Copyright (C) 2007, 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
dnl
dnl This file is part of CACAO.
dnl
AC_DEFUN([AC_CHECK_ENABLE_JNI],[
AC_MSG_CHECKING(whether JNI should be enabled)
AC_ARG_ENABLE([jni],
- [AS_HELP_STRING(--enable-jni,enable JNI [[default=yes]])],
+ [AS_HELP_STRING(--enable-jni,enable JNI [[default=(cldc1.1:no,javase:yes)]])],
[case "${enableval}" in
yes)
ENABLE_JNI=yes
dnl m4/jre-layout.m4
dnl
-dnl Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
-dnl C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-dnl E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-dnl J. Wenninger, Institut f. Computersprachen - TU Wien
+dnl Copyright (C) 2007, 2008
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
dnl
dnl This file is part of CACAO.
dnl
dnl if we compile for a JRE-style directory layout
-AC_DEFUN([AC_CHECK_WITH_JRE_LAYOUT],[
+AC_DEFUN([AC_CHECK_ENABLE_JRE_LAYOUT],[
AC_MSG_CHECKING(if we compile for a JRE-style directory layout)
-AC_ARG_WITH([jre-layout],
- [AS_HELP_STRING(--with-jre-layout,compile for JRE-style directory layout [[default=no]])],
- [case "${enableval}" in
- yes)
- WITH_JRE_LAYOUT=yes
- AC_DEFINE([WITH_JRE_LAYOUT], 1, [with JRE layout])
- ;;
- *)
- WITH_JRE_LAYOUT=no
- ;;
- esac],
- [WITH_JRE_LAYOUT=no])
-AC_MSG_RESULT(${WITH_JRE_LAYOUT})
+AC_ARG_ENABLE([jre-layout],
+ [AS_HELP_STRING(--enable-jre-layout,compile for JRE-style directory layout [[default=disabled]])],
+ [case "${enableval}" in
+ yes)
+ ENABLE_JRE_LAYOUT=yes
+ AC_DEFINE([ENABLE_JRE_LAYOUT], 1, [enable JRE layout])
+ ;;
+ *)
+ ENABLE_JRE_LAYOUT=no
+ ;;
+ esac],
+ [ENABLE_JRE_LAYOUT=no])
+AC_MSG_RESULT(${ENABLE_JRE_LAYOUT})
])
AC_DEFUN([AC_CHECK_ENABLE_LIBJVM],[
AC_MSG_CHECKING(whether to build a libjvm.so)
AC_ARG_ENABLE([libjvm],
- [AS_HELP_STRING(--disable-libjvm,build a libjvm.so [[default=yes]])],
+ [AS_HELP_STRING(--disable-libjvm,build a libjvm.so [[default=enabled]])],
[case "${enableval}" in
no)
ENABLE_LIBJVM=no
AC_DEFUN([AC_CHECK_ENABLE_LTDL],[
AC_MSG_CHECKING(whether ltdl should be used)
AC_ARG_ENABLE([ltdl],
- [AS_HELP_STRING(--disable-ltdl,disable ltdl support [[default=yes]])],
+ [AS_HELP_STRING(--disable-ltdl,disable ltdl support [[default=enabled]])],
[case "${enableval}" in
no)
ENABLE_LTDL=no
AC_DEFUN([AC_CHECK_ENABLE_ZLIB],[
AC_MSG_CHECKING(whether ZIP/JAR archives should be supported)
AC_ARG_ENABLE([zlib],
- [AS_HELP_STRING(--disable-zlib,disable ZIP/JAR archive support (needs zlib) [[default=yes]])],
+ [AS_HELP_STRING(--disable-zlib,disable ZIP/JAR archive support (needs zlib) [[default=enabled]])],
[case "${enableval}" in
no) ENABLE_ZLIB=no;;
*) ENABLE_ZLIB=yes;;
## man/Makefile.am
##
-## 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.
##
## 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
-##
-## Changes:
-## Process this file with automake to produce Makefile.in
man_MANS = cacao.1
-EXTRA_DIST = $(man_MANS)
+EXTRA_DIST = \
+ $(man_MANS)
## Local variables:
## src/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.
##
DIST_SUBDIRS = \
cacao \
cacaoh \
+ classes \
fdlibm \
- lib \
mm \
native \
scripts \
vm \
vmcore
-if ENABLE_THREADS
-THREADS_DIR = \
- threads
-endif
-
if ENABLE_CACAOH
CACAOH_DIR = \
cacaoh
toolbox \
vmcore \
$(CACAOH_DIR) \
- lib \
+ classes \
native \
fdlibm \
mm \
- $(THREADS_DIR) \
+ threads \
vm \
cacao \
scripts
## src/cacao/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
-## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
-if ENABLE_THREADS
-THREAD_LIB = \
- $(top_builddir)/src/threads/libthreads.la
-endif
-
if ENABLE_STATICVM
cacao_LDFLAGS = \
-all-static
libjvm.la
libjvm_la_LDFLAGS = \
- -release $(PACKAGE_VERSION)
+ -version-info 1:0:0
if WITH_CLASSPATH_SUN
libjvm_la_LDFLAGS += \
cacao_LDFLAGS += -lrt
endif
+if ENABLE_PYTHON
+cacao_LDFLAGS += \
+ @PYTHON_LSPEC@
+endif
+
libjvm_la_SOURCES =
libjvm_la_LIBADD = \
$(top_builddir)/src/fdlibm/libfdlibm.la \
$(top_builddir)/src/mm/libmm.la \
$(top_builddir)/src/native/libnative.la \
+ $(top_builddir)/src/threads/libthreads.la \
$(top_builddir)/src/toolbox/libtoolbox.la \
$(top_builddir)/src/vm/libvm.la \
$(top_builddir)/src/vmcore/libvmcore.la \
- $(GC_LIB) \
- $(THREAD_LIB)
+ $(GC_LIB)
bin_PROGRAMS = \
cacao
/* src/cacao/cacao.c - contains main() of cacao
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
# include <ltdl.h>
#endif
-#if defined(WITH_JRE_LAYOUT)
+#if defined(ENABLE_JRE_LAYOUT)
# include <errno.h>
# include <libgen.h>
# include <unistd.h>
#if defined(ENABLE_JVMTI)
# include "native/jvmti/jvmti.h"
# include "native/jvmti/cacaodbg.h"
+# include "threads/mutex.h"
#endif
#include "vm/vm.h"
/* load and initialize a Java VM, return a JNI interface pointer in env */
#if defined(ENABLE_LIBJVM)
-# if defined(WITH_JRE_LAYOUT)
+# if defined(ENABLE_JRE_LAYOUT)
/* SUN also uses a buffer of 4096-bytes (strace is your friend). */
path = malloc(sizeof(char) * 4096);
(void) vm_createjvm(&vm, (void *) &env, vm_args);
#if defined(ENABLE_JVMTI)
- pthread_mutex_init(&dbgcomlock,NULL);
+ mutex_init(&dbgcomlock);
if (jvmti) jvmti_set_phase(JVMTI_PHASE_START);
#endif
## src/cacaoh/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.
##
log_println("Java - header-generator started");
}
- /* initialize the utf8 hashtable stuff: lock, often used utf8 strings
- (must be done _after_ threads_preinit) */
-
- if (!utf8_init())
- vm_abort("utf8_init failed\n");
+ utf8_init();
/* initialize the classcache hashtable stuff: lock, hashtable
(must be done _after_ threads_preinit) */
/* src/cacaoh/dummy.c - dummy functions for cacaoh
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include <assert.h>
+#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include "mm/gc-common.h"
#include "mm/memory.h"
#include "native/llni.h"
#include "toolbox/logging.h"
+#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/primitive.h"
#include "vm/vm.h"
+#include "vm/jit/code.h"
+
#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/utf8.h"
#include "vmcore/classcache.h"
+#include "vmcore/field.h"
#include "vmcore/loader.h"
+#include "vmcore/method.h"
+#include "vmcore/utf8.h"
+#include "vmcore/system.h"
/* global variables ***********************************************************/
abort();
}
-void asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
-{
- abort();
-}
-
-void intrp_asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
-{
- abort();
-}
-
/* builtin ********************************************************************/
java_handle_t *builtin_clone(void *env, java_handle_t *o)
{
- abort();
-
+ vm_abort("builtin_clone: Not implemented.");
return NULL;
}
-int32_t builtin_isanysubclass(classinfo *sub, classinfo *super)
+bool builtin_isanysubclass(classinfo *sub, classinfo *super)
{
- abort();
+ vm_abort("builtin_isanysubclass: Not implemented.");
+ return 0;
+}
+bool builtin_instanceof(java_handle_t *o, classinfo *class)
+{
+ vm_abort("builtin_instanceof: Not implemented.");
return 0;
}
java_handle_t *builtin_new(classinfo *c)
{
- abort();
-
+ vm_abort("builtin_new: Not implemented.");
return NULL;
}
}
-methodinfo *code_get_methodinfo_for_pv(u1 *pv)
+methodinfo *code_get_methodinfo_for_pv(void *pv)
{
return NULL;
}
abort();
}
-void exceptions_throw_incompatibleclasschangeerror(classinfo *c)
+void exceptions_throw_incompatibleclasschangeerror(classinfo *c, const char *message)
{
fprintf(stderr, "java.lang.IncompatibleClassChangeError: ");
abort();
}
-void exceptions_throw_verifyerror(methodinfo *m, const char *message)
+void exceptions_throw_verifyerror(methodinfo *m, const char *message, ...)
{
fprintf(stderr, "java.lang.VerifyError: ");
utf_fprint_printable_ascii(stderr, m->name);
abort();
}
-void exceptions_throw_unsupportedclassversionerror(classinfo *c,
- const char *message, ...)
+void exceptions_throw_unsupportedclassversionerror(classinfo *c, u4 ma, u4 mi)
{
- va_list ap;
-
fprintf(stderr, "java.lang.UnsupportedClassVersionError: " );
-
utf_display_printable_ascii(c->name);
- fprintf(stderr, ": ");
-
- va_start(ap, message);
- vfprintf(stderr, message, ap);
- va_end(ap);
-
- fputc('\n', stderr);
+ fprintf(stderr, " (Unsupported major.minor version %d.%d)\n", ma, mi);
abort();
}
/* heap ***********************************************************************/
-void *heap_alloc_uncollectable(uint32_t bytelength)
+void *heap_alloc_uncollectable(size_t bytelength)
{
return calloc(bytelength, 1);
}
free(m);
}
-void *dump_alloc(int32_t size)
+void *dumpmemory_get(size_t size)
{
return malloc(size);
}
-void dump_release(int32_t size)
+int32_t dumpmemory_marker(void)
{
+ return 0;
}
-int32_t dump_size(void)
+void dumpmemory_release(int32_t size)
{
- return 0;
}
}
+/* reflect ********************************************************************/
+
+java_handle_t *reflect_constructor_new(fieldinfo *f)
+{
+ vm_abort("reflect_constructor_new: Not implemented.");
+ return NULL;
+}
+
+java_handle_t *reflect_field_new(fieldinfo *f)
+{
+ vm_abort("reflect_field_new: Not implemented.");
+ return NULL;
+}
+
+java_handle_t *reflect_method_new(methodinfo *m)
+{
+ vm_abort("reflect_method_new: Not implemented.");
+ return NULL;
+}
+
+
/* resolve ********************************************************************/
+void resolve_handle_pending_exception(bool throwError)
+{
+ vm_abort("resolve_handle_pending_exception: Not implemented.");
+}
+
bool resolve_class_from_typedesc(typedesc *d, bool checkaccess, bool link, classinfo **result)
{
abort();
{
va_list ap;
- /* print the log message */
-
va_start(ap, text);
vfprintf(stderr, text, ap);
va_end(ap);
- /* now abort the VM */
+ system_abort();
+}
- abort();
+void vm_abort_errno(const char *text, ...)
+{
+ va_list ap;
+
+ va_start(ap, text);
+ vm_abort_errnum(errno, text, ap);
+ va_end(ap);
+}
+
+void vm_abort_errnum(int errnum, const char *text, ...)
+{
+ va_list ap;
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ log_print(": %s", system_strerror(errnum));
+ log_finish();
+
+ system_abort();
}
java_handle_t *vm_call_method(methodinfo *m, java_handle_t *o, ...)
}
+#if defined(ENABLE_VMLOG)
+void vmlog_cacao_set_prefix(const char *arg)
+{
+}
+
+void vmlog_cacao_set_stringprefix(const char *arg)
+{
+}
+
+void vmlog_cacao_set_ignoreprefix(const char *arg)
+{
+}
+#endif
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
/* src/cacaoh/headers.c - functions for header generation
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* create remarks */
fprintf(file, "\n/*\n * Class: ");
- utf_fprint_printable_ascii(file, m->class->name);
+ utf_fprint_printable_ascii(file, m->clazz->name);
fprintf(file, "\n * Method: ");
utf_fprint_printable_ascii(file, m->name);
fprintf(file, "\n * Signature: ");
fprintf(file, "JNIEXPORT ");
printtype(utf_ptr, "", "_handle");
fprintf(file, " JNICALL Java_");
- printID(m->class->name);
+ printID(m->clazz->name);
chain_addlast(ident_chain, m->name);
if (!(m->flags & ACC_STATIC)) {
fprintf(file, ", struct ");
- printID(m->class->name);
+ printID(m->clazz->name);
fprintf(file, "* this");
} else {
--- /dev/null
+## src/lib/Makefile.am
+##
+## Copyright (C) 1996-2005, 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+
+EXTRA_DIST = \
+ $(VM_JAVA_FILES_GNU) \
+ $(VM_JAVA_FILES_GNU_ANNOTATIONS) \
+ $(VM_JAVA_FILES_CLDC1_1)
+
+CLEANFILES = vm.zip
+
+VM_JAVA_FILES_GNU = \
+ $(top_srcdir)/src/classes/gnu/gnu/classpath/VMStackWalker.java \
+ $(top_srcdir)/src/classes/gnu/gnu/classpath/VMSystemProperties.java \
+ $(top_srcdir)/src/classes/gnu/gnu/java/lang/VMCPStringBuilder.java \
+ $(top_srcdir)/src/classes/gnu/gnu/java/lang/management/VMMemoryMXBeanImpl.java \
+ $(top_srcdir)/src/classes/gnu/gnu/java/lang/management/VMRuntimeMXBeanImpl.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/VMClassLoader.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/VMString.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/VMThread.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/reflect/VMConstructor.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/reflect/VMField.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/reflect/VMMethod.java \
+ $(top_srcdir)/src/classes/gnu/java/security/VMAccessController.java \
+ $(top_srcdir)/src/classes/gnu/sun/misc/Unsafe.java
+
+# Remove these files when a new GNU Classpath release (> 0.97.1) is
+# available.
+
+VM_JAVA_FILES_GNU += \
+ $(top_srcdir)/src/classes/gnu/java/lang/reflect/Constructor.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/reflect/Field.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/reflect/Method.java \
+ $(top_srcdir)/src/classes/gnu/java/lang/reflect/Modifier.java \
+ $(top_srcdir)/src/classes/gnu/gnu/java/lang/CPStringBuilder.java
+
+VM_JAVA_FILES_GNU_ANNOTATIONS = \
+ $(top_srcdir)/src/classes/gnu/sun/reflect/ConstantPool.java \
+ $(top_srcdir)/src/classes/gnu/sun/reflect/annotation/ExceptionProxy.java \
+ $(top_srcdir)/src/classes/gnu/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \
+ $(top_srcdir)/src/classes/gnu/sun/reflect/annotation/TypeNotPresentExceptionProxy.java \
+ $(top_srcdir)/src/classes/gnu/sun/reflect/annotation/AnnotationTypeMismatchExceptionProxy.java \
+ $(top_srcdir)/src/classes/gnu/sun/reflect/annotation/AnnotationType.java \
+ $(top_srcdir)/src/classes/gnu/sun/reflect/annotation/AnnotationParser.java
+
+VM_JAVA_FILES_CLDC1_1 = \
+ $(top_srcdir)/src/classes/cldc1.1/com/sun/cldchi/jvm/FileDescriptor.java
+
+BOOTCLASSPATH = $(top_builddir)/src/classes/classes:$(CLASSPATH_CLASSES)
+
+if WITH_CLASSPATH_GNU
+VM_JAVA_FILES = \
+ $(VM_JAVA_FILES_GNU)
+
+if ENABLE_ANNOTATIONS
+VM_JAVA_FILES += \
+ $(VM_JAVA_FILES_GNU_ANNOTATIONS)
+endif
+
+if ENABLE_ZLIB
+pkgdata_DATA = vm.zip
+else
+pkgdata_DATA = nozip
+endif
+endif
+
+if WITH_CLASSPATH_CLDC1_1
+VM_JAVA_FILES = \
+ $(VM_JAVA_FILES_CLDC1_1)
+
+if ENABLE_ZLIB
+pkgdata_DATA = vm.zip
+else
+pkgdata_DATA = nozip
+endif
+endif
+
+if ENABLE_ZLIB
+VM_ZIP = ../vm.zip
+
+vm.zip: $(VM_JAVA_FILES)
+ $(mkdir_p) classes
+ $(JAVAC) -bootclasspath $(BOOTCLASSPATH) -source 1.5 -target 1.5 -d classes $(VM_JAVA_FILES)
+ @if test "$(JAR)" = "zip" -o "$(JAR)" = "zip.exe"; then \
+ cd classes && $(JAR) -r -D $(VM_ZIP) .; \
+ else \
+ cd classes && $(JAR) cvf $(VM_ZIP) .; \
+ fi
+else
+nozip: $(VM_JAVA_FILES)
+ $(mkdir_p) classes
+ $(JAVAC) -bootclasspath $(BOOTCLASSPATH) -source 1.5 -target 1.5 -d classes $(VM_JAVA_FILES)
+endif
+
+clean-local:
+ -rm -rf classes
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+/* src/lib/com/sun/cldchi/jvm/FileDescriptor.java
+
+ Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+ C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+ Institut f. Computersprachen - TU Wien
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+package com.sun.cldchi.jvm;
+
+class FileDescriptor {
+ long pointer;
+ int position;
+ int length;
+}
--- /dev/null
+/* VMStackWalker.java -- Reference implementation of VM hooks for stack access
+ Copyright (C) 2005 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.classpath;
+
+/**
+ * This class provides access to the classes on the Java stack
+ * for reflection and security purposes.
+ *
+ * <p>
+ * This class is only available to privileged code (i.e., code loaded
+ * by the bootstrap loader).
+ *
+ * @author John Keiser
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @author Archie Cobbs
+ */
+public final class VMStackWalker
+{
+ /**
+ * Get a list of all the classes currently executing methods on the
+ * Java stack. <code>getClassContext()[0]</code> is the class associated
+ * with the currently executing method, i.e., the method that called
+ * <code>VMStackWalker.getClassContext()</code> (possibly through
+ * reflection). So you may need to pop off these stack frames from
+ * the top of the stack:
+ * <ul>
+ * <li><code>VMStackWalker.getClassContext()</code>
+ * <li><code>Method.invoke()</code>
+ * </ul>
+ *
+ * @return an array of the declaring classes of each stack frame
+ */
+ public static native Class[] getClassContext();
+
+ /**
+ * Get the class associated with the method invoking the method
+ * invoking this method, or <code>null</code> if the stack is not
+ * that deep (e.g., invoked via JNI invocation API). This method
+ * is an optimization for the expression <code>getClassContext()[1]</code>
+ * and should return the same result.
+ *
+ * <p>
+ * VM implementers are encouraged to provide a more efficient
+ * version of this method.
+ */
+// public static Class getCallingClass()
+// {
+// Class[] ctx = getClassContext();
+// if (ctx.length < 3)
+// return null;
+// return ctx[2];
+// }
+ public static native Class getCallingClass();
+
+ /**
+ * Get the class loader associated with the Class returned by
+ * <code>getCallingClass()</code>, or <code>null</code> if no such class
+ * exists or it is the boot loader. This method is an optimization for the
+ * expression <code>VMStackWalker.getClassLoader(getClassContext()[1])</code>
+ * and should return the same result.
+ *
+ * <p>
+ * VM implementers are encouraged to provide a more efficient
+ * version of this method.
+ */
+// public static ClassLoader getCallingClassLoader()
+// {
+// Class[] ctx = getClassContext();
+// if (ctx.length < 3)
+// return null;
+// return getClassLoader(ctx[2]);
+// }
+ public static native ClassLoader getCallingClassLoader();
+
+
+ /**
+ * Retrieve the class's ClassLoader, or <code>null</code> if loaded
+ * by the bootstrap loader. I.e., this should return the same thing
+ * as {@link java.lang.VMClass#getClassLoader}. This duplicate version
+ * is here to work around access permissions.
+ */
+// public static native ClassLoader getClassLoader(Class cl);
+
+ /**
+ * Walk up the stack and return the first non-null class loader.
+ * If there aren't any non-null class loaders on the stack, return null.
+ */
+// public static ClassLoader firstNonNullClassLoader()
+// {
+// Class[] stack = getClassContext();
+// for (int i = 0; i < stack.length; i++)
+// {
+// ClassLoader loader = getClassLoader(stack[i]);
+// if (loader != null)
+// return loader;
+// }
+// return null;
+// }
+ public static native ClassLoader firstNonNullClassLoader();
+}
--- /dev/null
+/* VMSystemProperties.java -- Allow the VM to set System properties.
+ Copyright (C) 2004 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.classpath;
+
+import java.util.Properties;
+
+class VMSystemProperties
+{
+ /**
+ * Get the system properties. This is done here, instead of in System,
+ * because of the bootstrap sequence. Note that the native code should
+ * not try to use the Java I/O classes yet, as they rely on the properties
+ * already existing. The only safe method to use to insert these default
+ * system properties is {@link Properties#setProperty(String, String)}.
+ *
+ * <p>These properties MUST include:
+ * <dl>
+ * <dt>java.version <dd>Java version number
+ * <dt>java.vendor <dd>Java vendor specific string
+ * <dt>java.vendor.url <dd>Java vendor URL
+ * <dt>java.home <dd>Java installation directory
+ * <dt>java.vm.specification.version <dd>VM Spec version
+ * <dt>java.vm.specification.vendor <dd>VM Spec vendor
+ * <dt>java.vm.specification.name <dd>VM Spec name
+ * <dt>java.vm.version <dd>VM implementation version
+ * <dt>java.vm.vendor <dd>VM implementation vendor
+ * <dt>java.vm.name <dd>VM implementation name
+ * <dt>java.specification.version <dd>Java Runtime Environment version
+ * <dt>java.specification.vendor <dd>Java Runtime Environment vendor
+ * <dt>java.specification.name <dd>Java Runtime Environment name
+ * <dt>java.class.version <dd>Java class version number
+ * <dt>java.class.path <dd>Java classpath
+ * <dt>java.library.path <dd>Path for finding Java libraries
+ * <dt>java.io.tmpdir <dd>Default temp file path
+ * <dt>java.compiler <dd>Name of JIT to use
+ * <dt>java.ext.dirs <dd>Java extension path
+ * <dt>os.name <dd>Operating System Name
+ * <dt>os.arch <dd>Operating System Architecture
+ * <dt>os.version <dd>Operating System Version
+ * <dt>file.separator <dd>File separator ("/" on Unix)
+ * <dt>path.separator <dd>Path separator (":" on Unix)
+ * <dt>line.separator <dd>Line separator ("\n" on Unix)
+ * <dt>user.name <dd>User account name
+ * <dt>user.home <dd>User home directory
+ * <dt>user.dir <dd>User's current working directory
+ * <dt>gnu.cpu.endian <dd>"big" or "little"
+ * </dl>
+ *
+ * @param properties the Properties object to insert the system properties into
+ */
+ static native void preInit(Properties properties);
+
+ /**
+ * Here you get a chance to overwrite some of the properties set by
+ * the common SystemProperties code. For example, it might be
+ * a good idea to process the properties specified on the command
+ * line here.
+ */
+// static void postInit(Properties properties)
+// {
+// }
+ static native void postInit(Properties properties);
+}
--- /dev/null
+/* ClasspathStringBuffer.java -- Growable strings without locking or copying
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+ Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.lang;
+
+import java.io.Serializable;
+
+/**
+ * This class is based on java.lang.AbstractStringBuffer but
+ * without the copying of the string by toString.
+ * If you modify this, please consider also modifying that code.
+ * This code is not thread-safe; limit its use to internal use within
+ * methods.
+ */
+public final class CPStringBuilder
+ implements Serializable, CharSequence, Appendable
+{
+
+ /**
+ * Index of next available character (and thus the size of the current
+ * string contents). Note that this has permissions set this way so that
+ * String can get the value.
+ *
+ * @serial the number of characters in the buffer
+ */
+ int count;
+
+ /**
+ * The buffer. Note that this has permissions set this way so that String
+ * can get the value.
+ *
+ * @serial the buffer
+ */
+ char[] value;
+
+ /**
+ * The default capacity of a buffer.
+ */
+ private static final int DEFAULT_CAPACITY = 16;
+
+ /**
+ * Create a new CPStringBuilder with default capacity 16.
+ */
+ public CPStringBuilder()
+ {
+ this(DEFAULT_CAPACITY);
+ }
+
+ /**
+ * Create an empty <code>StringBuffer</code> with the specified initial
+ * capacity.
+ *
+ * @param capacity the initial capacity
+ * @throws NegativeArraySizeException if capacity is negative
+ */
+ public CPStringBuilder(int capacity)
+ {
+ value = new char[capacity];
+ }
+
+ /**
+ * Create a new <code>StringBuffer</code> with the characters in the
+ * specified <code>String</code>. Initial capacity will be the size of the
+ * String plus 16.
+ *
+ * @param str the <code>String</code> to convert
+ * @throws NullPointerException if str is null
+ */
+ public CPStringBuilder(String str)
+ {
+ count = str.length();
+ value = new char[count + DEFAULT_CAPACITY];
+ str.getChars(0, count, value, 0);
+ }
+
+ /**
+ * Create a new <code>StringBuffer</code> with the characters in the
+ * specified <code>CharSequence</code>. Initial capacity will be the
+ * length of the sequence plus 16; if the sequence reports a length
+ * less than or equal to 0, then the initial capacity will be 16.
+ *
+ * @param seq the initializing <code>CharSequence</code>
+ * @throws NullPointerException if str is null
+ * @since 1.5
+ */
+ public CPStringBuilder(CharSequence seq)
+ {
+ int len = seq.length();
+ count = len <= 0 ? 0 : len;
+ value = new char[count + DEFAULT_CAPACITY];
+ for (int i = 0; i < len; ++i)
+ value[i] = seq.charAt(i);
+ }
+
+ /**
+ * Increase the capacity of this <code>StringBuffer</code>. This will
+ * ensure that an expensive growing operation will not occur until
+ * <code>minimumCapacity</code> is reached. The buffer is grown to the
+ * larger of <code>minimumCapacity</code> and
+ * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+ *
+ * @param minimumCapacity the new capacity
+ * @see #capacity()
+ */
+ public void ensureCapacity(int minimumCapacity)
+ {
+ ensureCapacity_unsynchronized(minimumCapacity);
+ }
+
+ /**
+ * Set the length of this StringBuffer. If the new length is greater than
+ * the current length, all the new characters are set to '\0'. If the new
+ * length is less than the current length, the first <code>newLength</code>
+ * characters of the old array will be preserved, and the remaining
+ * characters are truncated.
+ *
+ * @param newLength the new length
+ * @throws IndexOutOfBoundsException if the new length is negative
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ * @see #length()
+ */
+ public void setLength(int newLength)
+ {
+ if (newLength < 0)
+ throw new StringIndexOutOfBoundsException(newLength);
+
+ int valueLength = value.length;
+
+ /* Always call ensureCapacity_unsynchronized in order to preserve
+ copy-on-write semantics. */
+ ensureCapacity_unsynchronized(newLength);
+
+ if (newLength < valueLength)
+ {
+ /* If the StringBuffer's value just grew, then we know that
+ value is newly allocated and the region between count and
+ newLength is filled with '\0'. */
+ count = newLength;
+ }
+ else
+ {
+ /* The StringBuffer's value doesn't need to grow. However,
+ we should clear out any cruft that may exist. */
+ while (count < newLength)
+ value[count++] = '\0';
+ }
+ }
+
+ /**
+ * Get the character at the specified index.
+ *
+ * @param index the index of the character to get, starting at 0
+ * @return the character at the specified index
+ * @throws IndexOutOfBoundsException if index is negative or >= length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public char charAt(int index)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException(index);
+ return value[index];
+ }
+
+ /**
+ * Get the code point at the specified index. This is like #charAt(int),
+ * but if the character is the start of a surrogate pair, and the
+ * following character completes the pair, then the corresponding
+ * supplementary code point is returned.
+ * @param index the index of the codepoint to get, starting at 0
+ * @return the codepoint at the specified index
+ * @throws IndexOutOfBoundsException if index is negative or >= length()
+ * @since 1.5
+ */
+ public int codePointAt(int index)
+ {
+ return Character.codePointAt(value, index, count);
+ }
+
+ /**
+ * Get the code point before the specified index. This is like
+ * #codePointAt(int), but checks the characters at <code>index-1</code> and
+ * <code>index-2</code> to see if they form a supplementary code point.
+ * @param index the index just past the codepoint to get, starting at 0
+ * @return the codepoint at the specified index
+ * @throws IndexOutOfBoundsException if index is negative or >= length()
+ * @since 1.5
+ */
+ public int codePointBefore(int index)
+ {
+ // Character.codePointBefore() doesn't perform this check. We
+ // could use the CharSequence overload, but this is just as easy.
+ if (index >= count)
+ throw new IndexOutOfBoundsException();
+ return Character.codePointBefore(value, index, 1);
+ }
+
+ /**
+ * Get the specified array of characters. <code>srcOffset - srcEnd</code>
+ * characters will be copied into the array you pass in.
+ *
+ * @param srcOffset the index to start copying from (inclusive)
+ * @param srcEnd the index to stop copying from (exclusive)
+ * @param dst the array to copy into
+ * @param dstOffset the index to start copying into
+ * @throws NullPointerException if dst is null
+ * @throws IndexOutOfBoundsException if any source or target indices are
+ * out of range (while unspecified, source problems cause a
+ * StringIndexOutOfBoundsException, and dest problems cause an
+ * ArrayIndexOutOfBoundsException)
+ * @see System#arraycopy(Object, int, Object, int, int)
+ */
+ public void getChars(int srcOffset, int srcEnd,
+ char[] dst, int dstOffset)
+ {
+ if (srcOffset < 0 || srcEnd > count || srcEnd < srcOffset)
+ throw new StringIndexOutOfBoundsException();
+ System.arraycopy(value, srcOffset, dst, dstOffset, srcEnd - srcOffset);
+ }
+
+ /**
+ * Set the character at the specified index.
+ *
+ * @param index the index of the character to set starting at 0
+ * @param ch the value to set that character to
+ * @throws IndexOutOfBoundsException if index is negative or >= length()
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public void setCharAt(int index, char ch)
+ {
+ if (index < 0 || index >= count)
+ throw new StringIndexOutOfBoundsException(index);
+ // Call ensureCapacity to enforce copy-on-write.
+ ensureCapacity_unsynchronized(count);
+ value[index] = ch;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param obj the <code>Object</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(Object)
+ * @see #append(String)
+ */
+ public CPStringBuilder append(Object obj)
+ {
+ return append(String.valueOf(obj));
+ }
+
+ /**
+ * Append the <code>String</code> to this <code>StringBuffer</code>. If
+ * str is null, the String "null" is appended.
+ *
+ * @param str the <code>String</code> to append
+ * @return this <code>StringBuffer</code>
+ */
+ public CPStringBuilder append(String str)
+ {
+ if (str == null)
+ str = "null";
+ int len = str.length();
+ ensureCapacity_unsynchronized(count + len);
+ str.getChars(0, len, value, count);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Append the <code>StringBuilder</code> value of the argument to this
+ * <code>StringBuilder</code>. This behaves the same as
+ * <code>append((Object) stringBuffer)</code>, except it is more efficient.
+ *
+ * @param stringBuffer the <code>StringBuilder</code> to convert and append
+ * @return this <code>StringBuilder</code>
+ * @see #append(Object)
+ */
+ public CPStringBuilder append(StringBuffer stringBuffer)
+ {
+ if (stringBuffer == null)
+ return append("null");
+ synchronized (stringBuffer)
+ {
+ int len = stringBuffer.length();
+ ensureCapacity(count + len);
+ stringBuffer.getChars(0, len, value, count);
+ count += len;
+ }
+ return this;
+ }
+
+ /**
+ * Append the <code>char</code> array to this <code>StringBuffer</code>.
+ * This is similar (but more efficient) than
+ * <code>append(new String(data))</code>, except in the case of null.
+ *
+ * @param data the <code>char[]</code> to append
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @see #append(char[], int, int)
+ */
+ public CPStringBuilder append(char[] data)
+ {
+ return append(data, 0, data.length);
+ }
+
+ /**
+ * Append part of the <code>char</code> array to this
+ * <code>StringBuffer</code>. This is similar (but more efficient) than
+ * <code>append(new String(data, offset, count))</code>, except in the case
+ * of null.
+ *
+ * @param data the <code>char[]</code> to append
+ * @param offset the start location in <code>str</code>
+ * @param count the number of characters to get from <code>str</code>
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @throws IndexOutOfBoundsException if offset or count is out of range
+ * (while unspecified, this is a StringIndexOutOfBoundsException)
+ */
+ public CPStringBuilder append(char[] data, int offset, int count)
+ {
+ if (offset < 0 || count < 0 || offset > data.length - count)
+ throw new StringIndexOutOfBoundsException();
+ ensureCapacity_unsynchronized(this.count + count);
+ System.arraycopy(data, offset, value, this.count, count);
+ this.count += count;
+ return this;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param bool the <code>boolean</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(boolean)
+ */
+ public CPStringBuilder append(boolean bool)
+ {
+ return append(bool ? "true" : "false");
+ }
+
+ /**
+ * Append the <code>char</code> to this <code>StringBuffer</code>.
+ *
+ * @param ch the <code>char</code> to append
+ * @return this <code>StringBuffer</code>
+ */
+ public CPStringBuilder append(char ch)
+ {
+ ensureCapacity_unsynchronized(count + 1);
+ value[count++] = ch;
+ return this;
+ }
+
+ /**
+ * Append the characters in the <code>CharSequence</code> to this
+ * buffer.
+ *
+ * @param seq the <code>CharSequence</code> providing the characters
+ * @return this <code>StringBuffer</code>
+ * @since 1.5
+ */
+ public CPStringBuilder append(CharSequence seq)
+ {
+ return append(seq, 0, seq.length());
+ }
+
+ /**
+ * Append some characters from the <code>CharSequence</code> to this
+ * buffer. If the argument is null, the four characters "null" are
+ * appended.
+ *
+ * @param seq the <code>CharSequence</code> providing the characters
+ * @param start the starting index
+ * @param end one past the final index
+ * @return this <code>StringBuffer</code>
+ * @since 1.5
+ */
+ public CPStringBuilder append(CharSequence seq, int start, int end)
+ {
+ if (seq == null)
+ return append("null");
+ if (end - start > 0)
+ {
+ ensureCapacity_unsynchronized(count + end - start);
+ for (; start < end; ++start)
+ value[count++] = seq.charAt(start);
+ }
+ return this;
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param inum the <code>int</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(int)
+ */
+ // This is native in libgcj, for efficiency.
+ public CPStringBuilder append(int inum)
+ {
+ return append(String.valueOf(inum));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param lnum the <code>long</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(long)
+ */
+ public CPStringBuilder append(long lnum)
+ {
+ return append(Long.toString(lnum, 10));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param fnum the <code>float</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(float)
+ */
+ public CPStringBuilder append(float fnum)
+ {
+ return append(Float.toString(fnum));
+ }
+
+ /**
+ * Append the <code>String</code> value of the argument to this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param dnum the <code>double</code> to convert and append
+ * @return this <code>StringBuffer</code>
+ * @see String#valueOf(double)
+ */
+ public CPStringBuilder append(double dnum)
+ {
+ return append(Double.toString(dnum));
+ }
+
+ /**
+ * Append the code point to this <code>StringBuffer</code>.
+ * This is like #append(char), but will append two characters
+ * if a supplementary code point is given.
+ *
+ * @param code the code point to append
+ * @return this <code>StringBuffer</code>
+ * @see Character#toChars(int, char[], int)
+ * @since 1.5
+ */
+ public CPStringBuilder appendCodePoint(int code)
+ {
+ int len = Character.charCount(code);
+ ensureCapacity_unsynchronized(count + len);
+ Character.toChars(code, value, count);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Delete characters from this <code>StringBuffer</code>.
+ * <code>delete(10, 12)</code> will delete 10 and 11, but not 12. It is
+ * harmless for end to be larger than length().
+ *
+ * @param start the first character to delete
+ * @param end the index after the last character to delete
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+ * @since 1.2
+ */
+ public CPStringBuilder delete(int start, int end)
+ {
+ if (start < 0 || start > count || start > end)
+ throw new StringIndexOutOfBoundsException(start);
+ if (end > count)
+ end = count;
+ ensureCapacity_unsynchronized(count);
+ if (count - end != 0)
+ System.arraycopy(value, end, value, start, count - end);
+ count -= end - start;
+ return this;
+ }
+
+ /**
+ * Delete a character from this <code>StringBuffer</code>.
+ *
+ * @param index the index of the character to delete
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if index is out of bounds
+ * @since 1.2
+ */
+ public CPStringBuilder deleteCharAt(int index)
+ {
+ return delete(index, index + 1);
+ }
+
+ /**
+ * Replace characters between index <code>start</code> (inclusive) and
+ * <code>end</code> (exclusive) with <code>str</code>. If <code>end</code>
+ * is larger than the size of this StringBuffer, all characters after
+ * <code>start</code> are replaced.
+ *
+ * @param start the beginning index of characters to delete (inclusive)
+ * @param end the ending index of characters to delete (exclusive)
+ * @param str the new <code>String</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if start or end are out of bounds
+ * @throws NullPointerException if str is null
+ * @since 1.2
+ */
+ public CPStringBuilder replace(int start, int end, String str)
+ {
+ if (start < 0 || start > count || start > end)
+ throw new StringIndexOutOfBoundsException(start);
+
+ int len = str.length();
+ // Calculate the difference in 'count' after the replace.
+ int delta = len - (end > count ? count : end) + start;
+ ensureCapacity_unsynchronized(count + delta);
+
+ if (delta != 0 && end < count)
+ System.arraycopy(value, end, value, end + delta, count - end);
+
+ str.getChars(0, len, value, start);
+ count += delta;
+ return this;
+ }
+
+ /**
+ * Insert a subarray of the <code>char[]</code> argument into this
+ * <code>StringBuffer</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param str the <code>char[]</code> to insert
+ * @param str_offset the index in <code>str</code> to start inserting from
+ * @param len the number of characters to insert
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>str</code> is <code>null</code>
+ * @throws StringIndexOutOfBoundsException if any index is out of bounds
+ * @since 1.2
+ */
+ public CPStringBuilder insert(int offset, char[] str, int str_offset, int len)
+ {
+ if (offset < 0 || offset > count || len < 0
+ || str_offset < 0 || str_offset > str.length - len)
+ throw new StringIndexOutOfBoundsException();
+ ensureCapacity_unsynchronized(count + len);
+ System.arraycopy(value, offset, value, offset + len, count - offset);
+ System.arraycopy(str, str_offset, value, offset, len);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param obj the <code>Object</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @exception StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(Object)
+ */
+ public CPStringBuilder insert(int offset, Object obj)
+ {
+ return insert(offset, obj == null ? "null" : obj.toString());
+ }
+
+ /**
+ * Insert the <code>String</code> argument into this
+ * <code>StringBuffer</code>. If str is null, the String "null" is used
+ * instead.
+ *
+ * @param offset the place to insert in this buffer
+ * @param str the <code>String</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ */
+ public CPStringBuilder insert(int offset, String str)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException(offset);
+ if (str == null)
+ str = "null";
+ int len = str.length();
+ ensureCapacity_unsynchronized(count + len);
+ System.arraycopy(value, offset, value, offset + len, count - offset);
+ str.getChars(0, len, value, offset);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Insert the <code>CharSequence</code> argument into this
+ * <code>StringBuffer</code>. If the sequence is null, the String
+ * "null" is used instead.
+ *
+ * @param offset the place to insert in this buffer
+ * @param sequence the <code>CharSequence</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws IndexOutOfBoundsException if offset is out of bounds
+ * @since 1.5
+ */
+ public CPStringBuilder insert(int offset, CharSequence sequence)
+ {
+ if (sequence == null)
+ sequence = "null";
+ return insert(offset, sequence, 0, sequence.length());
+ }
+
+ /**
+ * Insert a subsequence of the <code>CharSequence</code> argument into this
+ * <code>StringBuffer</code>. If the sequence is null, the String
+ * "null" is used instead.
+ *
+ * @param offset the place to insert in this buffer
+ * @param sequence the <code>CharSequence</code> to insert
+ * @param start the starting index of the subsequence
+ * @param end one past the ending index of the subsequence
+ * @return this <code>StringBuffer</code>
+ * @throws IndexOutOfBoundsException if offset, start,
+ * or end are out of bounds
+ * @since 1.5
+ */
+ public CPStringBuilder insert(int offset, CharSequence sequence, int start, int end)
+ {
+ if (sequence == null)
+ sequence = "null";
+ if (start < 0 || end < 0 || start > end || end > sequence.length())
+ throw new IndexOutOfBoundsException();
+ int len = end - start;
+ ensureCapacity_unsynchronized(count + len);
+ System.arraycopy(value, offset, value, offset + len, count - offset);
+ for (int i = start; i < end; ++i)
+ value[offset++] = sequence.charAt(i);
+ count += len;
+ return this;
+ }
+
+ /**
+ * Insert the <code>char[]</code> argument into this
+ * <code>StringBuffer</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param data the <code>char[]</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws NullPointerException if <code>data</code> is <code>null</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see #insert(int, char[], int, int)
+ */
+ public CPStringBuilder insert(int offset, char[] data)
+ {
+ return insert(offset, data, 0, data.length);
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param bool the <code>boolean</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(boolean)
+ */
+ public CPStringBuilder insert(int offset, boolean bool)
+ {
+ return insert(offset, bool ? "true" : "false");
+ }
+
+ /**
+ * Insert the <code>char</code> argument into this <code>StringBuffer</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param ch the <code>char</code> to insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ */
+ public CPStringBuilder insert(int offset, char ch)
+ {
+ if (offset < 0 || offset > count)
+ throw new StringIndexOutOfBoundsException(offset);
+ ensureCapacity_unsynchronized(count + 1);
+ System.arraycopy(value, offset, value, offset + 1, count - offset);
+ value[offset] = ch;
+ count++;
+ return this;
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param inum the <code>int</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(int)
+ */
+ public CPStringBuilder insert(int offset, int inum)
+ {
+ return insert(offset, String.valueOf(inum));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param lnum the <code>long</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(long)
+ */
+ public CPStringBuilder insert(int offset, long lnum)
+ {
+ return insert(offset, Long.toString(lnum, 10));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param fnum the <code>float</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(float)
+ */
+ public CPStringBuilder insert(int offset, float fnum)
+ {
+ return insert(offset, Float.toString(fnum));
+ }
+
+ /**
+ * Insert the <code>String</code> value of the argument into this
+ * <code>StringBuffer</code>. Uses <code>String.valueOf()</code> to convert
+ * to <code>String</code>.
+ *
+ * @param offset the place to insert in this buffer
+ * @param dnum the <code>double</code> to convert and insert
+ * @return this <code>StringBuffer</code>
+ * @throws StringIndexOutOfBoundsException if offset is out of bounds
+ * @see String#valueOf(double)
+ */
+ public CPStringBuilder insert(int offset, double dnum)
+ {
+ return insert(offset, Double.toString(dnum));
+ }
+
+ /**
+ * Finds the first instance of a substring in this StringBuilder.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @see #indexOf(String, int)
+ */
+ public int indexOf(String str)
+ {
+ return indexOf(str, 0);
+ }
+
+ /**
+ * Finds the first instance of a String in this StringBuffer, starting at
+ * a given index. If starting index is less than 0, the search starts at
+ * the beginning of this String. If the starting index is greater than the
+ * length of this String, or the substring is not found, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @since 1.4
+ */
+ public int indexOf(String str, int fromIndex)
+ {
+ if (fromIndex < 0)
+ fromIndex = 0;
+ int olength = str.length();
+ int limit = count - olength;
+ String s = VMCPStringBuilder.toString(value, 0, count);
+ for (; fromIndex <= limit; ++fromIndex)
+ if (s.regionMatches(fromIndex, str, 0, olength))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Finds the last instance of a substring in this StringBuffer.
+ *
+ * @param str String to find
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @see #lastIndexOf(String, int)
+ * @since 1.4
+ */
+ public int lastIndexOf(String str)
+ {
+ return lastIndexOf(str, count - str.length());
+ }
+
+ /**
+ * Finds the last instance of a String in this StringBuffer, starting at a
+ * given index. If starting index is greater than the maximum valid index,
+ * then the search begins at the end of this String. If the starting index
+ * is less than zero, or the substring is not found, -1 is returned.
+ *
+ * @param str String to find
+ * @param fromIndex index to start the search
+ * @return location (base 0) of the String, or -1 if not found
+ * @throws NullPointerException if str is null
+ * @since 1.4
+ */
+ public int lastIndexOf(String str, int fromIndex)
+ {
+ fromIndex = Math.min(fromIndex, count - str.length());
+ String s = VMCPStringBuilder.toString(value, 0, count);
+ int olength = str.length();
+ for ( ; fromIndex >= 0; fromIndex--)
+ if (s.regionMatches(fromIndex, str, 0, olength))
+ return fromIndex;
+ return -1;
+ }
+
+ /**
+ * Reverse the characters in this StringBuffer. The same sequence of
+ * characters exists, but in the reverse index ordering.
+ *
+ * @return this <code>StringBuffer</code>
+ */
+ public CPStringBuilder reverse()
+ {
+ // Call ensureCapacity to enforce copy-on-write.
+ ensureCapacity_unsynchronized(count);
+ for (int i = count >> 1, j = count - i; --i >= 0; ++j)
+ {
+ char c = value[i];
+ value[i] = value[j];
+ value[j] = c;
+ }
+ return this;
+ }
+
+ /**
+ * This may reduce the amount of memory used by the StringBuffer,
+ * by resizing the internal array to remove unused space. However,
+ * this method is not required to resize, so this behavior cannot
+ * be relied upon.
+ * @since 1.5
+ */
+ public void trimToSize()
+ {
+ int wouldSave = value.length - count;
+ // Some random heuristics: if we save less than 20 characters, who
+ // cares.
+ if (wouldSave < 20)
+ return;
+ // If we save more than 200 characters, shrink.
+ // If we save more than 1/4 of the buffer, shrink.
+ if (wouldSave > 200 || wouldSave * 4 > value.length)
+ {
+ char[] newValue = new char[count];
+ System.arraycopy(value, 0, newValue, 0, count);
+ value = newValue;
+ }
+ }
+
+ /**
+ * Return the number of code points between two indices in the
+ * <code>StringBuffer</code>. An unpaired surrogate counts as a
+ * code point for this purpose. Characters outside the indicated
+ * range are not examined, even if the range ends in the middle of a
+ * surrogate pair.
+ *
+ * @param start the starting index
+ * @param end one past the ending index
+ * @return the number of code points
+ * @since 1.5
+ */
+ public int codePointCount(int start, int end)
+ {
+ if (start < 0 || end >= count || start > end)
+ throw new StringIndexOutOfBoundsException();
+
+ int count = 0;
+ while (start < end)
+ {
+ char base = value[start];
+ if (base < Character.MIN_HIGH_SURROGATE
+ || base > Character.MAX_HIGH_SURROGATE
+ || start == end
+ || start == count
+ || value[start + 1] < Character.MIN_LOW_SURROGATE
+ || value[start + 1] > Character.MAX_LOW_SURROGATE)
+ {
+ // Nothing.
+ }
+ else
+ {
+ // Surrogate pair.
+ ++start;
+ }
+ ++start;
+ ++count;
+ }
+ return count;
+ }
+
+ /**
+ * Starting at the given index, this counts forward by the indicated
+ * number of code points, and then returns the resulting index. An
+ * unpaired surrogate counts as a single code point for this
+ * purpose.
+ *
+ * @param start the starting index
+ * @param codePoints the number of code points
+ * @return the resulting index
+ * @since 1.5
+ */
+ public int offsetByCodePoints(int start, int codePoints)
+ {
+ while (codePoints > 0)
+ {
+ char base = value[start];
+ if (base < Character.MIN_HIGH_SURROGATE
+ || base > Character.MAX_HIGH_SURROGATE
+ || start == count
+ || value[start + 1] < Character.MIN_LOW_SURROGATE
+ || value[start + 1] > Character.MAX_LOW_SURROGATE)
+ {
+ // Nothing.
+ }
+ else
+ {
+ // Surrogate pair.
+ ++start;
+ }
+ ++start;
+ --codePoints;
+ }
+ return start;
+ }
+
+ /**
+ * Increase the capacity of this <code>StringBuilder</code>. This will
+ * ensure that an expensive growing operation will not occur until
+ * <code>minimumCapacity</code> is reached. The buffer is grown to the
+ * larger of <code>minimumCapacity</code> and
+ * <code>capacity() * 2 + 2</code>, if it is not already large enough.
+ *
+ * @param minimumCapacity the new capacity
+ * @see #capacity()
+ */
+ protected void ensureCapacity_unsynchronized(int minimumCapacity)
+ {
+ if (minimumCapacity > value.length)
+ {
+ int max = value.length * 2 + 2;
+ minimumCapacity = (minimumCapacity < max ? max : minimumCapacity);
+ char[] nb = new char[minimumCapacity];
+ System.arraycopy(value, 0, nb, 0, count);
+ value = nb;
+ }
+ }
+
+ /**
+ * Get the length of the <code>String</code> this <code>StringBuilder</code>
+ * would create. Not to be confused with the <em>capacity</em> of the
+ * <code>StringBuilder</code>.
+ *
+ * @return the length of this <code>StringBuilder</code>
+ * @see #capacity()
+ * @see #setLength(int)
+ */
+ public int length()
+ {
+ return count;
+ }
+
+ /**
+ * Creates a substring of this StringBuilder, starting at a specified index
+ * and ending at one character before a specified index. This is implemented
+ * the same as <code>substring(beginIndex, endIndex)</code>, to satisfy
+ * the CharSequence interface.
+ *
+ * @param beginIndex index to start at (inclusive, base 0)
+ * @param endIndex index to end at (exclusive)
+ * @return new String which is a substring of this StringBuilder
+ * @throws IndexOutOfBoundsException if beginIndex or endIndex is out of
+ * bounds
+ * @see #substring(int, int)
+ */
+ public CharSequence subSequence(int beginIndex, int endIndex)
+ {
+ return substring(beginIndex, endIndex);
+ }
+
+ /**
+ * Creates a substring of this StringBuilder, starting at a specified index
+ * and ending at one character before a specified index.
+ *
+ * @param beginIndex index to start at (inclusive, base 0)
+ * @param endIndex index to end at (exclusive)
+ * @return new String which is a substring of this StringBuilder
+ * @throws StringIndexOutOfBoundsException if beginIndex or endIndex is out
+ * of bounds
+ */
+ public String substring(int beginIndex, int endIndex)
+ {
+ if (beginIndex < 0 || endIndex > count || endIndex < beginIndex)
+ throw new StringIndexOutOfBoundsException();
+ int len = endIndex - beginIndex;
+ if (len == 0)
+ return "";
+ return VMCPStringBuilder.toString(value, beginIndex, len);
+ }
+
+ /**
+ * Convert this <code>StringBuilder</code> to a <code>String</code>. The
+ * String is composed of the characters currently in this StringBuilder. Note
+ * that the result is not a copy, so future modifications to this buffer
+ * do affect the String.
+ *
+ * @return the characters in this StringBuilder
+ */
+ public String toString()
+ {
+ return VMCPStringBuilder.toString(value, 0, count);
+ }
+
+}
--- /dev/null
+/* VMCPStringBuilder.java -- Growable strings without locking or copying
+ Copyright (C) 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.lang;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * This class provides VM support for CPStringBuilder
+ * by allowing the package-private constructor
+ * of java.lang.String to be invoked. The default
+ * implementation uses reflection. VMs may replace
+ * this class with a more efficient version.
+ */
+final class VMCPStringBuilder
+{
+
+ /**
+ * The package-private constructor for String objects without copying.
+ */
+// private static final Constructor<String> cons;
+
+// static
+// {
+// try
+// {
+// cons = String.class.getDeclaredConstructor(char[].class, Integer.TYPE,
+// Integer.TYPE, Boolean.TYPE);
+// cons.setAccessible(true);
+// }
+// catch (NoSuchMethodException e)
+// {
+// throw (Error)
+// new InternalError("Could not get no-copy String constructor").initCause(e);
+// }
+// }
+
+ /**
+ * Convert this <code>StringBuilder</code> to a <code>String</code>. The
+ * String is composed of the characters currently in this StringBuilder. Note
+ * that the result is not a copy, so future modifications to this buffer
+ * do affect the String.
+ *
+ * @param value the buffered characters.
+ * @param startIndex the index at which to start taking characters from the buffer.
+ * @param count the number of characters used in the buffer.
+ * @return the characters in this StringBuilder
+ */
+// public static String toString(char[] value, int startIndex, int count)
+// {
+// try
+// {
+// return cons.newInstance(value, startIndex, count, true);
+// }
+// catch (InstantiationException e)
+// {
+// throw (Error)
+// new InternalError("Could not instantiate no-copy String constructor").initCause(e);
+// }
+// catch (IllegalAccessException e)
+// {
+// throw (Error)
+// new InternalError("Could not access no-copy String constructor").initCause(e);
+// }
+// catch (InvocationTargetException e)
+// {
+// throw (Error)
+// new InternalError("Error calling no-copy String constructor").initCause(e);
+// }
+// }
+ public static native String toString(char[] value, int startIndex, int count);
+
+}
--- /dev/null
+/* VMMemoryMXBeanImpl.java - VM impl. of a memory bean
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.lang.management;
+
+import java.lang.management.MemoryUsage;
+
+/**
+ * Provides access to information about the memory
+ * management of the current invocation of the virtual
+ * machine. Instances of this bean are obtained by calling
+ * {@link ManagementFactory#getMemoryMXBean()}.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+final class VMMemoryMXBeanImpl
+{
+
+ /**
+ * Returns an instance of {@link java.lang.management.MemoryUsage}
+ * with appropriate initial, used, committed and maximum values
+ * for the heap. By default, this uses the methods of
+ * {@link java.lang.Runtime} to provide some of the values.
+ *
+ * @return an {@link java.lang.management.MemoryUsage} instance
+ * for the heap.
+ */
+// static MemoryUsage getHeapMemoryUsage()
+// {
+// Runtime runtime = Runtime.getRuntime();
+// long totalMem = runtime.totalMemory();
+// return new MemoryUsage(-1, totalMem - runtime.freeMemory(),
+// totalMem, runtime.maxMemory());
+// }
+ static native MemoryUsage getHeapMemoryUsage();
+
+ /**
+ * Returns an instance of {@link java.lang.management.MemoryUsage}
+ * with appropriate initial, used, committed and maximum values
+ * for non-heap memory.
+ *
+ * @return an {@link java.lang.management.MemoryUsage} instance
+ * for non-heap memory.
+ */
+ static native MemoryUsage getNonHeapMemoryUsage();
+
+ /**
+ * Returns the number of objects ready to be garbage collected.
+ *
+ * @return the number of finalizable objects.
+ */
+ static native int getObjectPendingFinalizationCount();
+
+ /**
+ * Returns true if the virtual machine will emit additional
+ * information when memory is allocated and deallocated. The
+ * format of the output is left up to the virtual machine.
+ *
+ * @return true if verbose class loading output is on.
+ */
+ static native boolean isVerbose();
+
+ /**
+ * Turns on or off the emission of additional information
+ * when memory is allocated and deallocated. The format of the
+ * output is left up to the virtual machine. This method
+ * may be called by multiple threads concurrently, but there
+ * is only one global setting of verbosity that is affected.
+ *
+ * @param verbose the new setting for verbose class loading
+ * output.
+ */
+ static native void setVerbose(boolean verbose);
+
+}
--- /dev/null
+/* VMRuntimeMXBeanImpl.java - VM implementation of an runtime bean
+ Copyright (C) 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.java.lang.management;
+
+import gnu.classpath.SystemProperties;
+
+/**
+ * Provides access to information about the virtual machine.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+final class VMRuntimeMXBeanImpl
+{
+
+ /**
+ * Returns the command-line arguments supplied
+ * to the virtual machine, excluding those supplied
+ * to <code>main()</code>.
+ *
+ * @return the command-line arguments.
+ */
+ static native String[] getInputArguments();
+
+ /**
+ * Returns a developer-chosen name for the virtual
+ * machine, which may differ over different running
+ * instances of the same virtual machine binary.
+ * For example, this may include the particular
+ * process identifier used by this instance or
+ * the host name of the machine on which it is
+ * running. The intention is that this name refers
+ * to the precise entity that the other data supplied
+ * by the bean refers to, rather than the VM in general.
+ *
+ * @return the custom name of the VM.
+ */
+ static String getName()
+ {
+ return SystemProperties.getProperty("java.vm.name") + " " +
+ SystemProperties.getProperty("java.vm.version");
+ }
+
+ /**
+ * The time in milliseconds at which the virtual
+ * machine was started. This method is only executed
+ * once (for efficency), as the value is not expected
+ * to change.
+ *
+ * @return the VM start time.
+ */
+ static native long getStartTime();
+
+}
--- /dev/null
+/* VMClassLoader.java -- Reference implementation of native interface
+ required by ClassLoader
+ Copyright (C) 1998, 2001, 2002, 2004, 2005, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang;
+
+import gnu.classpath.Configuration;
+import gnu.classpath.SystemProperties;
+import gnu.java.lang.InstrumentationImpl;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.instrument.Instrumentation;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.ProtectionDomain;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.zip.ZipFile;
+import java.util.Collections;
+import java.lang.Boolean;
+
+/**
+ * java.lang.VMClassLoader is a package-private helper for VMs to implement
+ * on behalf of java.lang.ClassLoader.
+ *
+ * @author John Keiser
+ * @author Mark Wielaard (mark@klomp.org)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ */
+final class VMClassLoader
+{
+
+
+ /** packages loaded by the bootstrap class loader */
+ static final HashMap definedPackages = new HashMap();
+
+ /** jars from property java.boot.class.path */
+ static final HashMap bootjars = new HashMap();
+
+
+ /**
+ * Converts the array string of native package names to
+ * Packages. The packages are then put into the
+ * definedPackages hashMap
+ */
+ static
+ {
+ String[] packages = getBootPackages();
+
+ if( packages != null)
+ {
+ String specName =
+ SystemProperties.getProperty("java.specification.name");
+ String vendor =
+ SystemProperties.getProperty("java.specification.vendor");
+ String version =
+ SystemProperties.getProperty("java.specification.version");
+
+ Package p;
+
+ for(int i = 0; i < packages.length; i++)
+ {
+ p = new Package(packages[i],
+ specName,
+ vendor,
+ version,
+ "GNU Classpath",
+ "GNU",
+ Configuration.CLASSPATH_VERSION,
+ null,
+ null);
+
+ definedPackages.put(packages[i], p);
+ }
+ }
+ }
+
+
+ /**
+ * Helper to define a class using a string of bytes. This assumes that
+ * the security checks have already been performed, if necessary.
+ *
+ * Implementations of this method are advised to consider the
+ * situation where user code modifies the byte array after it has
+ * been passed to defineClass. This can be handled by making a
+ * private copy of the array, or arranging to only read any given
+ * byte a single time.
+ *
+ * @param name the name to give the class, or null if unknown
+ * @param data the data representing the classfile, in classfile format
+ * @param offset the offset into the data where the classfile starts
+ * @param len the length of the classfile data in the array
+ * @param pd the protection domain
+ * @return the class that was defined
+ * @throws ClassFormatError if data is not in proper classfile format
+ */
+ static final native Class defineClass(ClassLoader cl, String name,
+ byte[] data, int offset, int len,
+ ProtectionDomain pd)
+ throws ClassFormatError;
+
+ /**
+ * Helper to resolve all references to other classes from this class.
+ *
+ * @param c the class to resolve
+ */
+ static final native void resolveClass(Class c);
+
+ /**
+ * Helper to load a class from the bootstrap class loader.
+ *
+ * @param name the class name to load
+ * @param resolve whether to resolve it
+ * @return the class, loaded by the bootstrap classloader or null
+ * if the class wasn't found. Returning null is equivalent to throwing
+ * a ClassNotFoundException (but a possible performance optimization).
+ */
+ static final native Class loadClass(String name, boolean resolve)
+ throws ClassNotFoundException;
+
+ /**
+ * Helper to load a resource from the bootstrap class loader.
+ *
+ * @param name the resource to find
+ * @return the URL to the resource
+ */
+ static URL getResource(String name)
+ {
+ Enumeration e = getResources(name);
+ if (e.hasMoreElements())
+ return (URL)e.nextElement();
+ return null;
+ }
+ /**
+ * Helper to get a list of resources from the bootstrap class loader.
+ *
+ * @param name the resource to find
+ * @return an enumeration of resources
+ */
+ static Enumeration getResources(String name)
+ {
+// StringTokenizer st = new StringTokenizer(
+// SystemProperties.getProperty("java.boot.class.path", "."),
+// File.pathSeparator);
+// Vector v = new Vector();
+// while (st.hasMoreTokens())
+// {
+// File file = new File(st.nextToken());
+// if (file.isDirectory())
+// {
+// try
+// {
+// File f = new File(file, name);
+// if (!f.exists()) continue;
+// v.add(new URL("file://" + f.getAbsolutePath()));
+// }
+// catch (MalformedURLException e)
+// {
+// throw new Error(e);
+// }
+// }
+// else if (file.isFile())
+// {
+// ZipFile zip;
+// synchronized(bootjars)
+// {
+// zip = (ZipFile) bootjars.get(file.getName());
+// }
+// if(zip == null)
+// {
+// try
+// {
+// zip = new ZipFile(file);
+// synchronized(bootjars)
+// {
+// bootjars.put(file.getName(), zip);
+// }
+// }
+// catch (IOException e)
+// {
+// continue;
+// }
+// }
+// String zname = name.startsWith("/") ? name.substring(1) : name;
+// if (zip.getEntry(zname) == null)
+// continue;
+// try
+// {
+// v.add(new URL("jar:file://"
+// + file.getAbsolutePath() + "!/" + zname));
+// }
+// catch (MalformedURLException e)
+// {
+// throw new Error(e);
+// }
+// }
+// }
+// return v.elements();
+// }
+ Vector urls = nativeGetResources(name);
+ Vector v = new Vector();
+ for (Enumeration en = urls.elements(); en.hasMoreElements();)
+ {
+ try
+ {
+ v.add(new URL((String) en.nextElement()));
+ }
+ catch (MalformedURLException e)
+ {
+ throw new Error(e);
+ }
+ }
+ return v.elements();
+ }
+
+ private native static final Vector nativeGetResources(String name);
+
+
+ /**
+ * Returns a String[] of native package names. The default
+ * implementation tries to load a list of package from
+ * the META-INF/INDEX.LIST file in the boot jar file.
+ * If not found or if any exception is raised, it returns
+ * an empty array. You may decide this needs native help.
+ */
+ private static String[] getBootPackages()
+ {
+ try
+ {
+ Enumeration indexListEnumeration = getResources("META-INF/INDEX.LIST");
+ Set packageSet = new HashSet();
+
+ while (indexListEnumeration.hasMoreElements())
+ {
+ try
+ {
+ String line;
+ int lineToSkip = 3;
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(
+ ((URL) indexListEnumeration.nextElement()).openStream()));
+ while ((line = reader.readLine()) != null)
+ {
+ if (lineToSkip == 0)
+ {
+ if (line.length() == 0)
+ lineToSkip = 1;
+ else
+ packageSet.add(line.replace('/', '.'));
+ }
+ else
+ lineToSkip--;
+ }
+ reader.close();
+ }
+ catch (IOException e)
+ {
+ // Empty catch block on purpose
+ }
+ }
+ return (String[]) packageSet.toArray(new String[packageSet.size()]);
+ }
+ catch (Exception e)
+ {
+ return new String[0];
+ }
+ }
+
+
+ /**
+ * Helper to get a package from the bootstrap class loader.
+ *
+ * @param name the name to find
+ * @return the named package, if it exists
+ */
+ static Package getPackage(String name)
+ {
+ return (Package)definedPackages.get(name);
+ }
+
+
+
+ /**
+ * Helper to get all packages from the bootstrap class loader.
+ *
+ * @return all named packages, if any exist
+ */
+ static Package[] getPackages()
+ {
+ Package[] packages = new Package[definedPackages.size()];
+ definedPackages.values().toArray(packages);
+ return packages;
+ }
+
+ /**
+ * Helper for java.lang.Integer, Byte, etc to get the TYPE class
+ * at initialization time. The type code is one of the chars that
+ * represents the primitive type as in JNI.
+ *
+ * <ul>
+ * <li>'Z' - boolean</li>
+ * <li>'B' - byte</li>
+ * <li>'C' - char</li>
+ * <li>'D' - double</li>
+ * <li>'F' - float</li>
+ * <li>'I' - int</li>
+ * <li>'J' - long</li>
+ * <li>'S' - short</li>
+ * <li>'V' - void</li>
+ * </ul>
+ *
+ * @param type the primitive type
+ * @return a "bogus" class representing the primitive type
+ */
+ static final native Class getPrimitiveClass(char type);
+
+ /**
+ * The system default for assertion status. This is used for all system
+ * classes (those with a null ClassLoader), as well as the initial value for
+ * every ClassLoader's default assertion status.
+ *
+ * @return the system-wide default assertion status
+ */
+ static native final boolean defaultAssertionStatus();
+
+ static native final boolean defaultUserAssertionStatus();
+
+
+ static final Map packageAssertionMap =
+ Collections.unmodifiableMap(packageAssertionStatus0(Boolean.TRUE, Boolean.FALSE));
+
+ static native final Map packageAssertionStatus0(Boolean jtrue, Boolean jfalse);
+ /**
+ * The system default for package assertion status. This is used for all
+ * ClassLoader's packageAssertionStatus defaults. It must be a map of
+ * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package
+ * represented as a null key.
+ *
+ * @return a (read-only) map for the default packageAssertionStatus
+ */
+
+ static final Map packageAssertionStatus() {
+ return packageAssertionMap;
+ }
+
+ static final Map classAssertionMap =
+ Collections.unmodifiableMap(classAssertionStatus0(Boolean.TRUE, Boolean.FALSE));
+
+ static native final Map classAssertionStatus0(Boolean jtrue, Boolean jfalse);
+
+ /**
+ * The system default for class assertion status. This is used for all
+ * ClassLoader's classAssertionStatus defaults. It must be a map of
+ * class names to Boolean.TRUE or Boolean.FALSE
+ *
+ * @return a (read-only) map for the default classAssertionStatus
+ */
+ static final Map classAssertionStatus() {
+ return classAssertionMap;
+ }
+
+ static ClassLoader getSystemClassLoader()
+ {
+ return ClassLoader.defaultGetSystemClassLoader();
+ }
+
+ /**
+ * Find the class if this class loader previously defined this class
+ * or if this class loader has been recorded as the initiating class loader
+ * for this class.
+ */
+ static native Class findLoadedClass(ClassLoader cl, String name);
+
+ /**
+ * The Instrumentation object created by the vm when agents are defined.
+ */
+ static final Instrumentation instrumenter = null;
+
+ /**
+ * Call the transformers of the possible Instrumentation object. This
+ * implementation assumes the instrumenter is a
+ * <code>InstrumentationImpl</code> object. VM implementors would
+ * have to redefine this method if they provide their own implementation
+ * of the <code>Instrumentation</code> interface.
+ *
+ * @param loader the initiating loader
+ * @param name the name of the class
+ * @param data the data representing the classfile, in classfile format
+ * @param offset the offset into the data where the classfile starts
+ * @param len the length of the classfile data in the array
+ * @param pd the protection domain
+ * @return the new data representing the classfile
+ */
+ static final Class defineClassWithTransformers(ClassLoader loader,
+ String name, byte[] data, int offset, int len, ProtectionDomain pd)
+ {
+
+ if (instrumenter != null)
+ {
+ byte[] modifiedData = new byte[len];
+ System.arraycopy(data, offset, modifiedData, 0, len);
+ modifiedData =
+ ((InstrumentationImpl)instrumenter).callTransformers(loader, name,
+ null, pd, modifiedData);
+
+ return defineClass(loader, name, modifiedData, 0, modifiedData.length,
+ pd);
+ }
+ else
+ {
+ return defineClass(loader, name, data, offset, len, pd);
+ }
+ }
+}
--- /dev/null
+/* VMString.java -- VM Specific String methods
+ Copyright (C) 2003 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+import java.lang.ref.WeakReference;
+import java.util.WeakHashMap;
+
+/*
+ * This class is a reference version, mainly for compiling a class library
+ * jar. It is likely that VM implementers replace this with their own
+ * version that can communicate effectively with the VM.
+ */
+
+/**
+ * Code relocated from java.lang.String by
+ * @author Dave Grove <groved@us.ibm.com>
+ */
+final class VMString
+{
+
+ /**
+ * Holds the references for each intern()'d String. If all references to
+ * the string disappear, and the VM properly supports weak references,
+ * the String will be GC'd.
+ */
+// private static final WeakHashMap internTable = new WeakHashMap();
+
+ /**
+ * Fetches this String from the intern hashtable. If two Strings are
+ * considered equal, by the equals() method, then intern() will return the
+ * same String instance. ie. if (s1.equals(s2)) then
+ * (s1.intern() == s2.intern()). All string literals and string-valued
+ * constant expressions are already interned.
+ *
+ * @param str the String to intern
+ * @return the interned String
+ */
+// static String intern(String str)
+// {
+// synchronized (internTable)
+// {
+// WeakReference ref = (WeakReference) internTable.get(str);
+// if (ref != null)
+// {
+// String s = (String) ref.get();
+// // If s is null, then no strong references exist to the String;
+// // the weak hash map will soon delete the key.
+// if (s != null)
+// return s;
+// }
+// internTable.put(str, new WeakReference(str));
+// }
+// return str;
+// }
+
+ /**
+ * this one is native in CACAO
+ */
+ static native String intern(String str);
+
+} // class VMString
--- /dev/null
+/* VMThread -- VM interface for Thread of executable code
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.lang;
+
+/**
+ * VM interface for Thread of executable code. Holds VM dependent state.
+ * It is deliberately package local and final and should only be accessed
+ * by the Thread class.
+ * <p>
+ * This is the GNU Classpath reference implementation, it should be adapted
+ * for a specific VM.
+ * <p>
+ * The following methods must be implemented:
+ * <ul>
+ * <li>native void start(long stacksize);
+ * <li>native void interrupt();
+ * <li>native boolean isInterrupted();
+ * <li>native void suspend();
+ * <li>native void resume();
+ * <li>native void nativeSetPriority(int priority);
+ * <li>native void nativeStop(Throwable t);
+ * <li>native static Thread currentThread();
+ * <li>static native void yield();
+ * <li>static native boolean interrupted();
+ * </ul>
+ * All other methods may be implemented to make Thread handling more efficient
+ * or to implement some optional (and sometimes deprecated) behaviour. Default
+ * implementations are provided but it is highly recommended to optimize them
+ * for a specific VM.
+ *
+ * @author Jeroen Frijters (jeroen@frijters.net)
+ * @author Dalibor Topic (robilad@kaffe.org)
+ */
+final class VMThread
+{
+ /**
+ * The Thread object that this VM state belongs to.
+ * Used in currentThread() and start().
+ * Note: when this thread dies, this reference is *not* cleared
+ */
+ volatile Thread thread;
+
+ /**
+ * Flag that is set when the thread runs, used by stop() to protect against
+ * stop's getting lost.
+ */
+ private volatile boolean running;
+
+ /**
+ * VM private data.
+ */
+ private transient Object vmdata;
+
+ /**
+ * Private constructor, create VMThreads with the static create method.
+ *
+ * @param thread The Thread object that was just created.
+ */
+ private VMThread(Thread thread)
+ {
+ this.thread = thread;
+ }
+
+ /**
+ * This method is the initial Java code that gets executed when a native
+ * thread starts. It's job is to coordinate with the rest of the VMThread
+ * logic and to start executing user code and afterwards handle clean up.
+ */
+ private void run()
+ {
+ try
+ {
+ try
+ {
+ running = true;
+ synchronized(thread)
+ {
+ Throwable t = thread.stillborn;
+ if(t != null)
+ {
+ thread.stillborn = null;
+ throw t;
+ }
+ }
+ thread.run();
+ }
+ catch(Throwable t)
+ {
+ try
+ {
+ Thread.UncaughtExceptionHandler handler;
+ handler = thread.getUncaughtExceptionHandler();
+ handler.uncaughtException(thread, t);
+ }
+ catch(Throwable ignore)
+ {
+ }
+ }
+ }
+ finally
+ {
+ // Setting runnable to false is partial protection against stop
+ // being called while we're cleaning up. To be safe all code in
+ // VMThread be unstoppable.
+ running = false;
+ thread.die();
+ synchronized(this)
+ {
+ // release the threads waiting to join us
+ notifyAll();
+ }
+ }
+ }
+
+ /**
+ * Creates a native Thread. This is called from the start method of Thread.
+ * The Thread is started.
+ *
+ * @param thread The newly created Thread object
+ * @param stacksize Indicates the requested stacksize. Normally zero,
+ * non-zero values indicate requested stack size in bytes but it is up
+ * to the specific VM implementation to interpret them and may be ignored.
+ */
+ static void create(Thread thread, long stacksize)
+ {
+ VMThread vmThread = new VMThread(thread);
+ thread.vmThread = vmThread;
+ vmThread.start(stacksize);
+ }
+
+ /**
+ * Gets the name of the thread. Usually this is the name field of the
+ * associated Thread object, but some implementation might choose to
+ * return the name of the underlying platform thread.
+ */
+ String getName()
+ {
+ return thread.name;
+ }
+
+ /**
+ * Set the name of the thread. Usually this sets the name field of the
+ * associated Thread object, but some implementations might choose to
+ * set the name of the underlying platform thread.
+ * @param name The new name
+ */
+ void setName(String name)
+ {
+ thread.name = name;
+ }
+
+ /**
+ * Set the thread priority field in the associated Thread object and
+ * calls the native method to set the priority of the underlying
+ * platform thread.
+ * @param priority The new priority
+ */
+ void setPriority(int priority)
+ {
+ thread.priority = priority;
+ nativeSetPriority(priority);
+ }
+
+ /**
+ * Returns the priority. Usually this is the priority field from the
+ * associated Thread object, but some implementation might choose to
+ * return the priority of the underlying platform thread.
+ * @return this Thread's priority
+ */
+ int getPriority()
+ {
+ return thread.priority;
+ }
+
+ /**
+ * Returns true if the thread is a daemon thread. Usually this is the
+ * daemon field from the associated Thread object, but some
+ * implementation might choose to return the daemon state of the underlying
+ * platform thread.
+ * @return whether this is a daemon Thread or not
+ */
+ boolean isDaemon()
+ {
+ return thread.daemon;
+ }
+
+ /**
+ * Returns the number of stack frames in this Thread.
+ * Will only be called when when a previous call to suspend() returned true.
+ *
+ * @deprecated unsafe operation
+ */
+ native int countStackFrames();
+
+ /**
+ * Wait the specified amount of time for the Thread in question to die.
+ *
+ * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
+ * not offer that fine a grain of timing resolution. Besides, there is
+ * no guarantee that this thread can start up immediately when time expires,
+ * because some other thread may be active. So don't expect real-time
+ * performance.
+ *
+ * @param ms the number of milliseconds to wait, or 0 for forever
+ * @param ns the number of extra nanoseconds to sleep (0-999999)
+ * @throws InterruptedException if the Thread is interrupted; it's
+ * <i>interrupted status</i> will be cleared
+ */
+ synchronized void join(long ms, int ns) throws InterruptedException
+ {
+ // Round up
+ ms += (ns != 0) ? 1 : 0;
+
+ // Compute end time, but don't overflow
+ long now = System.currentTimeMillis();
+ long end = now + ms;
+ if (end < now)
+ end = Long.MAX_VALUE;
+
+ // A VM is allowed to return from wait() without notify() having been
+ // called, so we loop to handle possible spurious wakeups.
+ while(thread.vmThread != null)
+ {
+ // We use the VMThread object to wait on, because this is a private
+ // object, so client code cannot call notify on us.
+ wait(ms);
+ if(ms != 0)
+ {
+ now = System.currentTimeMillis();
+ ms = end - now;
+ if(ms <= 0)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Cause this Thread to stop abnormally and throw the specified exception.
+ * If you stop a Thread that has not yet started, the stop is ignored
+ * (contrary to what the JDK documentation says).
+ * <b>WARNING</b>This bypasses Java security, and can throw a checked
+ * exception which the call stack is unprepared to handle. Do not abuse
+ * this power.
+ *
+ * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
+ * leave data in bad states.
+ *
+ * <p><b>NOTE</b> stop() should take care not to stop a thread if it is
+ * executing code in this class.
+ *
+ * @param t the Throwable to throw when the Thread dies
+ * @deprecated unsafe operation, try not to use
+ */
+ void stop(Throwable t)
+ {
+ // Note: we assume that we own the lock on thread
+ // (i.e. that Thread.stop() is synchronized)
+ if(running)
+ nativeStop(t);
+ else
+ thread.stillborn = t;
+ }
+
+ /**
+ * Create a native thread on the underlying platform and start it executing
+ * on the run method of this object.
+ * @param stacksize the requested size of the native thread stack
+ */
+ native void start(long stacksize);
+
+ /**
+ * Interrupt this thread.
+ */
+ native void interrupt();
+
+ /**
+ * Determine whether this Thread has been interrupted, but leave
+ * the <i>interrupted status</i> alone in the process.
+ *
+ * @return whether the Thread has been interrupted
+ */
+ native boolean isInterrupted();
+
+ /**
+ * Suspend this Thread. It will not come back, ever, unless it is resumed.
+ */
+ native void suspend();
+
+ /**
+ * Resume this Thread. If the thread is not suspended, this method does
+ * nothing.
+ */
+ native void resume();
+
+ /**
+ * Set the priority of the underlying platform thread.
+ *
+ * @param priority the new priority
+ */
+ native void nativeSetPriority(int priority);
+
+ /**
+ * Asynchronously throw the specified throwable in this Thread.
+ *
+ * @param t the exception to throw
+ */
+ native void nativeStop(Throwable t);
+
+ /**
+ * Return the Thread object associated with the currently executing
+ * thread.
+ *
+ * @return the currently executing Thread
+ */
+ static native Thread currentThread();
+
+ /**
+ * Yield to another thread. The Thread will not lose any locks it holds
+ * during this time. There are no guarantees which thread will be
+ * next to run, and it could even be this one, but most VMs will choose
+ * the highest priority thread that has been waiting longest.
+ */
+ static native void yield();
+
+ /**
+ * Suspend the current Thread's execution for the specified amount of
+ * time. The Thread will not lose any locks it has during this time. There
+ * are no guarantees which thread will be next to run, but most VMs will
+ * choose the highest priority thread that has been waiting longest.
+ *
+ * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
+ * not offer that fine a grain of timing resolution. Besides, there is
+ * no guarantee that this thread can start up immediately when time expires,
+ * because some other thread may be active. So don't expect real-time
+ * performance.
+ *
+ * @param ms the number of milliseconds to sleep.
+ * @param ns the number of extra nanoseconds to sleep (0-999999)
+ * @throws InterruptedException if the Thread is (or was) interrupted;
+ * it's <i>interrupted status</i> will be cleared
+ */
+ static void sleep(long ms, int ns) throws InterruptedException
+ {
+ // Note: JDK treats a zero length sleep is like Thread.yield(),
+ // without checking the interrupted status of the thread.
+ // It's unclear if this is a bug in the implementation or the spec.
+ // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203
+ if (ms == 0 && ns == 0)
+ {
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ return;
+ }
+
+ // Compute end time, but don't overflow
+ long now = System.currentTimeMillis();
+ long end = now + ms;
+ if (end < now)
+ end = Long.MAX_VALUE;
+
+ // A VM is allowed to return from wait() without notify() having been
+ // called, so we loop to handle possible spurious wakeups.
+ VMThread vt = Thread.currentThread().vmThread;
+ synchronized (vt)
+ {
+ while (true)
+ {
+ vt.wait(ms, ns);
+ now = System.currentTimeMillis();
+ if (now >= end)
+ break;
+ ms = end - now;
+ ns = 0;
+ }
+ }
+ }
+
+ /**
+ * Determine whether the current Thread has been interrupted, and clear
+ * the <i>interrupted status</i> in the process.
+ *
+ * @return whether the current Thread has been interrupted
+ */
+ static native boolean interrupted();
+
+ /**
+ * Checks whether the current thread holds the monitor on a given object.
+ * This allows you to do <code>assert Thread.holdsLock(obj)</code>.
+ *
+ * @param obj the object to check
+ * @return true if the current thread is currently synchronized on obj
+ * @throws NullPointerException if obj is null
+ */
+// static boolean holdsLock(Object obj)
+// {
+// /* Use obj.notify to check if the current thread holds
+// * the monitor of the object.
+// * If it doesn't, notify will throw an exception.
+// */
+// try
+// {
+// obj.notify();
+// // okay, current thread holds lock
+// return true;
+// }
+// catch (IllegalMonitorStateException e)
+// {
+// // it doesn't hold the lock
+// return false;
+// }
+// }
+ static native boolean holdsLock(Object obj);
+
+ /**
+ * Returns the current state of the thread.
+ * The value must be one of "BLOCKED", "NEW",
+ * "RUNNABLE", "TERMINATED", "TIMED_WAITING" or
+ * "WAITING".
+ *
+ * @return a string corresponding to one of the
+ * thread enumeration states specified above.
+ */
+ native String getState();
+
+}
--- /dev/null
+/* java.lang.reflect.Constructor - reflection of Java constructors
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
+
+import gnu.java.lang.reflect.MethodSignatureParser;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The Constructor class represents a constructor of a class. It also allows
+ * dynamic creation of an object, via reflection. Invocation on Constructor
+ * objects knows how to do widening conversions, but throws
+ * {@link IllegalArgumentException} if a narrowing conversion would be
+ * necessary. You can query for information on this Constructor regardless
+ * of location, but construction access may be limited by Java language
+ * access controls. If you can't do it in the compiler, you can't normally
+ * do it here either.<p>
+ *
+ * <B>Note:</B> This class returns and accepts types as Classes, even
+ * primitive types; there are Class types defined that represent each
+ * different primitive type. They are <code>java.lang.Boolean.TYPE,
+ * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
+ * byte.class</code>, etc. These are not to be confused with the
+ * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
+ * real classes.<p>
+ *
+ * Also note that this is not a serializable class. It is entirely feasible
+ * to make it serializable using the Externalizable interface, but this is
+ * on Sun, not me.
+ *
+ * @author John Keiser
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @see Member
+ * @see Class
+ * @see java.lang.Class#getConstructor(Class[])
+ * @see java.lang.Class#getDeclaredConstructor(Class[])
+ * @see java.lang.Class#getConstructors()
+ * @see java.lang.Class#getDeclaredConstructors()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Constructor<T>
+ extends AccessibleObject
+ implements GenericDeclaration, Member
+{
+ private static final int CONSTRUCTOR_MODIFIERS
+ = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
+
+ private MethodSignatureParser p;
+
+ VMConstructor cons;
+
+ /**
+ * This class is uninstantiable outside this package.
+ */
+ Constructor(VMConstructor cons)
+ {
+ this.cons = cons;
+ cons.cons = this;
+ }
+
+ private Constructor()
+ {
+ }
+
+ /**
+ * Gets the class that declared this constructor.
+ * @return the class that declared this member
+ */
+ @SuppressWarnings("unchecked")
+ public Class<T> getDeclaringClass()
+ {
+ return (Class<T>) cons.getDeclaringClass();
+ }
+
+ /**
+ * Gets the name of this constructor (the non-qualified name of the class
+ * it was declared in).
+ * @return the name of this constructor
+ */
+ public String getName()
+ {
+ return cons.getDeclaringClass().getName();
+ }
+
+ /**
+ * Gets the modifiers this constructor uses. Use the <code>Modifier</code>
+ * class to interpret the values. A constructor can only have a subset of the
+ * following modifiers: public, private, protected.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ public int getModifiers()
+ {
+ return cons.getModifiersInternal() & CONSTRUCTOR_MODIFIERS;
+ }
+
+ /**
+ * Return true if this constructor is synthetic, false otherwise.
+ * A synthetic member is one which is created by the compiler,
+ * and which does not appear in the user's source code.
+ * @since 1.5
+ */
+ public boolean isSynthetic()
+ {
+ return (cons.getModifiersInternal() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * Return true if this is a varargs constructor, that is if
+ * the constructor takes a variable number of arguments.
+ * @since 1.5
+ */
+ public boolean isVarArgs()
+ {
+ return (cons.getModifiersInternal() & Modifier.VARARGS) != 0;
+ }
+
+ /**
+ * Get the parameter list for this constructor, in declaration order. If the
+ * constructor takes no parameters, returns a 0-length array (not null).
+ *
+ * @return a list of the types of the constructor's parameters
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?>[] getParameterTypes()
+ {
+ return (Class<?>[]) cons.getParameterTypes();
+ }
+
+ /**
+ * Get the exception types this constructor says it throws, in no particular
+ * order. If the constructor has no throws clause, returns a 0-length array
+ * (not null).
+ *
+ * @return a list of the types in the constructor's throws clause
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?>[] getExceptionTypes()
+ {
+ return (Class<?>[]) cons.getExceptionTypes();
+ }
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Constructors are semantically equivalent if they have the same
+ * declaring class and the same parameter list. This ignores different
+ * exception clauses, but since you can't create a Method except through the
+ * VM, this is just the == relation.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not.
+ */
+ public boolean equals(Object o)
+ {
+ return cons.equals(o);
+ }
+
+ /**
+ * Get the hash code for the Constructor. The Constructor hash code is the
+ * hash code of the declaring class's name.
+ *
+ * @return the hash code for the object
+ */
+ public int hashCode()
+ {
+ return getName().hashCode();
+ }
+
+ /**
+ * Get a String representation of the Constructor. A Constructor's String
+ * representation is "<modifier> <classname>(<paramtypes>)
+ * throws <exceptions>", where everything after ')' is omitted if
+ * there are no exceptions.<br> Example:
+ * <code>public java.io.FileInputStream(java.lang.Runnable)
+ * throws java.io.FileNotFoundException</code>
+ *
+ * @return the String representation of the Constructor
+ */
+ public String toString()
+ {
+ // 128 is a reasonable buffer initial size for constructor
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(getDeclaringClass().getName()).append('(');
+ Class[] c = getParameterTypes();
+ if (c.length > 0)
+ {
+ sb.append(ClassHelper.getUserName(c[0]));
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(ClassHelper.getUserName(c[i]));
+ }
+ sb.append(')');
+ c = getExceptionTypes();
+ if (c.length > 0)
+ {
+ sb.append(" throws ").append(c[0].getName());
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(c[i].getName());
+ }
+ return sb.toString();
+ }
+
+ static <X extends GenericDeclaration>
+ void addTypeParameters(CPStringBuilder sb, TypeVariable<X>[] typeArgs)
+ {
+ if (typeArgs.length == 0)
+ return;
+ sb.append('<');
+ for (int i = 0; i < typeArgs.length; ++i)
+ {
+ if (i > 0)
+ sb.append(',');
+ sb.append(typeArgs[i]);
+ }
+ sb.append("> ");
+ }
+
+ public String toGenericString()
+ {
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ addTypeParameters(sb, getTypeParameters());
+ sb.append(getDeclaringClass().getName()).append('(');
+ Type[] types = getGenericParameterTypes();
+ if (types.length > 0)
+ {
+ sb.append(types[0]);
+ for (int i = 1; i < types.length; ++i)
+ sb.append(',').append(types[i]);
+ }
+ sb.append(')');
+ types = getGenericExceptionTypes();
+ if (types.length > 0)
+ {
+ sb.append(" throws ").append(types[0]);
+ for (int i = 1; i < types.length; i++)
+ sb.append(',').append(types[i]);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Create a new instance by invoking the constructor. Arguments are
+ * automatically unwrapped and widened, if needed.<p>
+ *
+ * If this class is abstract, you will get an
+ * <code>InstantiationException</code>. If the constructor takes 0
+ * arguments, you may use null or a 0-length array for <code>args</code>.<p>
+ *
+ * If this Constructor enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not create this object in similar compiled code. If the class
+ * is uninitialized, you trigger class initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Then, the constructor is invoked. If it completes normally, the return
+ * value will be the new object. If it completes abruptly, the exception is
+ * wrapped in an <code>InvocationTargetException</code>.
+ *
+ * @param args the arguments to the constructor
+ * @return the newly created object
+ * @throws IllegalAccessException if the constructor could not normally be
+ * called by the Java code (i.e. it is not public)
+ * @throws IllegalArgumentException if the number of arguments is incorrect;
+ * or if the arguments types are wrong even with a widening
+ * conversion
+ * @throws InstantiationException if the class is abstract
+ * @throws InvocationTargetException if the constructor throws an exception
+ * @throws ExceptionInInitializerError if construction triggered class
+ * initialization, which then failed
+ */
+ @SuppressWarnings("unchecked")
+ public T newInstance(Object... args)
+ throws InstantiationException, IllegalAccessException,
+ InvocationTargetException
+ {
+ return (T) cons.construct(args);
+ }
+
+ /**
+ * Returns an array of <code>TypeVariable</code> objects that represents
+ * the type variables declared by this constructor, in declaration order.
+ * An array of size zero is returned if this constructor has no type
+ * variables.
+ *
+ * @return the type variables associated with this constructor.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public TypeVariable<Constructor<T>>[] getTypeParameters()
+ {
+ if (p == null)
+ {
+ String sig = cons.getSignature();
+ if (sig == null)
+ return new TypeVariable[0];
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getTypeParameters();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the exception types declared by this constructor, in declaration order.
+ * An array of size zero is returned if this constructor declares no
+ * exceptions.
+ *
+ * @return the exception types declared by this constructor.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericExceptionTypes()
+ {
+ if (p == null)
+ {
+ String sig = cons.getSignature();
+ if (sig == null)
+ return getExceptionTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericExceptionTypes();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the parameter list for this constructor, in declaration order.
+ * An array of size zero is returned if this constructor takes no
+ * parameters.
+ *
+ * @return a list of the types of the constructor's parameters
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericParameterTypes()
+ {
+ if (p == null)
+ {
+ String sig = cons.getSignature();
+ if (sig == null)
+ return getParameterTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericParameterTypes();
+ }
+
+ /**
+ * <p>
+ * Return an array of arrays representing the annotations on each
+ * of the constructor's parameters. The outer array is aligned against
+ * the parameters of the constructors and is thus equal in length to
+ * the number of parameters (thus having a length zero if there are none).
+ * Each array element in the outer array contains an inner array which
+ * holds the annotations. This array has a length of zero if the parameter
+ * has no annotations.
+ * </p>
+ * <p>
+ * The returned annotations are serialized. Changing the annotations has
+ * no affect on the return value of future calls to this method.
+ * </p>
+ *
+ * @return an array of arrays which represents the annotations used on the
+ * parameters of this constructor. The order of the array elements
+ * matches the declaration order of the parameters.
+ * @since 1.5
+ */
+ public Annotation[][] getParameterAnnotations()
+ {
+ return cons.getParameterAnnotations();
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ return (T) cons.getAnnotation(annotationClass);
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations()
+ {
+ return cons.getDeclaredAnnotations();
+ }
+
+}
--- /dev/null
+/* java.lang.reflect.Field - reflection of Java fields
+ Copyright (C) 1998, 2001, 2005, 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
+
+import gnu.java.lang.reflect.FieldSignatureParser;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The Field class represents a member variable of a class. It also allows
+ * dynamic access to a member, via reflection. This works for both
+ * static and instance fields. Operations on Field objects know how to
+ * do widening conversions, but throw {@link IllegalArgumentException} if
+ * a narrowing conversion would be necessary. You can query for information
+ * on this Field regardless of location, but get and set access may be limited
+ * by Java language access controls. If you can't do it in the compiler, you
+ * can't normally do it here either.<p>
+ *
+ * <B>Note:</B> This class returns and accepts types as Classes, even
+ * primitive types; there are Class types defined that represent each
+ * different primitive type. They are <code>java.lang.Boolean.TYPE,
+ * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
+ * byte.class</code>, etc. These are not to be confused with the
+ * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
+ * real classes.<p>
+ *
+ * Also note that this is not a serializable class. It is entirely feasible
+ * to make it serializable using the Externalizable interface, but this is
+ * on Sun, not me.
+ *
+ * @author John Keiser
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @see Member
+ * @see Class
+ * @see Class#getField(String)
+ * @see Class#getDeclaredField(String)
+ * @see Class#getFields()
+ * @see Class#getDeclaredFields()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Field
+extends AccessibleObject implements Member
+{
+ static final int FIELD_MODIFIERS
+ = Modifier.FINAL | Modifier.PRIVATE | Modifier.PROTECTED
+ | Modifier.PUBLIC | Modifier.STATIC | Modifier.TRANSIENT
+ | Modifier.VOLATILE;
+
+ private FieldSignatureParser p;
+
+ VMField f;
+
+ /**
+ * This class is uninstantiable outside the package.
+ */
+ Field(VMField f)
+ {
+ this.f = f;
+ f.f = this;
+ }
+
+ /**
+ * Gets the class that declared this field, or the class where this field
+ * is a non-inherited member.
+ * @return the class that declared this member
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?> getDeclaringClass()
+ {
+ return (Class<?>) f.getDeclaringClass();
+ }
+
+ /**
+ * Gets the name of this field.
+ * @return the name of this field
+ */
+ public String getName()
+ {
+ return f.getName();
+ }
+
+ /**
+ * Gets the modifiers this field uses. Use the <code>Modifier</code>
+ * class to interpret the values. A field can only have a subset of the
+ * following modifiers: public, private, protected, static, final,
+ * transient, and volatile.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ public int getModifiers()
+ {
+ return f.getModifiersInternal() & FIELD_MODIFIERS;
+ }
+
+ /**
+ * Return true if this field is synthetic, false otherwise.
+ * @since 1.5
+ */
+ public boolean isSynthetic()
+ {
+ return (f.getModifiersInternal() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * Return true if this field represents an enum constant,
+ * false otherwise.
+ * @since 1.5
+ */
+ public boolean isEnumConstant()
+ {
+ return (f.getModifiersInternal() & Modifier.ENUM) != 0;
+ }
+
+ /**
+ * Gets the type of this field.
+ * @return the type of this field
+ */
+ public Class<?> getType()
+ {
+ return f.getType();
+ }
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Fields are semantically equivalent if they have the same declaring
+ * class, name, and type. Since you can't creat a Field except through
+ * the VM, this is just the == relation.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not
+ */
+ public boolean equals(Object o)
+ {
+ return f.equals(o);
+ }
+
+ /**
+ * Get the hash code for the Field. The Field hash code is the hash code
+ * of its name XOR'd with the hash code of its class name.
+ *
+ * @return the hash code for the object.
+ */
+ public int hashCode()
+ {
+ return f.getDeclaringClass().getName().hashCode() ^ f.getName().hashCode();
+ }
+
+ /**
+ * Get a String representation of the Field. A Field's String
+ * representation is "<modifiers> <type>
+ * <class>.<fieldname>".<br> Example:
+ * <code>public transient boolean gnu.parse.Parser.parseComplete</code>
+ *
+ * @return the String representation of the Field
+ */
+ public String toString()
+ {
+ // 64 is a reasonable buffer initial size for field
+ CPStringBuilder sb = new CPStringBuilder(64);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(ClassHelper.getUserName(getType())).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName());
+ return sb.toString();
+ }
+
+ public String toGenericString()
+ {
+ CPStringBuilder sb = new CPStringBuilder(64);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(getGenericType()).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName());
+ return sb.toString();
+ }
+
+ /**
+ * Get the value of this Field. If it is primitive, it will be wrapped
+ * in the appropriate wrapper type (boolean = java.lang.Boolean).<p>
+ *
+ * If the field is static, <code>o</code> will be ignored. Otherwise, if
+ * <code>o</code> is null, you get a <code>NullPointerException</code>,
+ * and if it is incompatible with the declaring class of the field, you
+ * get an <code>IllegalArgumentException</code>.<p>
+ *
+ * Next, if this Field enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not access this field in similar compiled code. If the field
+ * is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the field is accessed, and primitives are wrapped (but not
+ * necessarily in new objects). This method accesses the field of the
+ * declaring class, even if the instance passed in belongs to a subclass
+ * which declares another field to hide this one.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if <code>o</code> is not an instance of
+ * the class or interface declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #getBoolean(Object)
+ * @see #getByte(Object)
+ * @see #getChar(Object)
+ * @see #getShort(Object)
+ * @see #getInt(Object)
+ * @see #getLong(Object)
+ * @see #getFloat(Object)
+ * @see #getDouble(Object)
+ */
+ public Object get(Object o)
+ throws IllegalAccessException
+ {
+ return f.get(o);
+ }
+
+ /**
+ * Get the value of this boolean Field. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a boolean field of
+ * <code>o</code>, or if <code>o</code> is not an instance of the
+ * declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public boolean getBoolean(Object o)
+ throws IllegalAccessException
+ {
+ return f.getBoolean(o);
+ }
+
+ /**
+ * Get the value of this byte Field. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte field of
+ * <code>o</code>, or if <code>o</code> is not an instance of the
+ * declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public byte getByte(Object o)
+ throws IllegalAccessException
+ {
+ return f.getByte(o);
+ }
+
+ /**
+ * Get the value of this Field as a char. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a char field of
+ * <code>o</code>, or if <code>o</code> is not an instance
+ * of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public char getChar(Object o)
+ throws IllegalAccessException
+ {
+ return f.getChar(o);
+ }
+
+ /**
+ * Get the value of this Field as a short. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte or short
+ * field of <code>o</code>, or if <code>o</code> is not an instance
+ * of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public short getShort(Object o)
+ throws IllegalAccessException
+ {
+ return f.getShort(o);
+ }
+
+ /**
+ * Get the value of this Field as an int. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, or
+ * int field of <code>o</code>, or if <code>o</code> is not an
+ * instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public int getInt(Object o)
+ throws IllegalAccessException
+ {
+ return f.getInt(o);
+ }
+
+ /**
+ * Get the value of this Field as a long. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * or long field of <code>o</code>, or if <code>o</code> is not an
+ * instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public long getLong(Object o)
+ throws IllegalAccessException
+ {
+ return f.getLong(o);
+ }
+
+ /**
+ * Get the value of this Field as a float. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * long, or float field of <code>o</code>, or if <code>o</code> is
+ * not an instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public float getFloat(Object o)
+ throws IllegalAccessException
+ {
+ return f.getFloat(o);
+ }
+
+ /**
+ * Get the value of this Field as a double. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * long, float, or double field of <code>o</code>, or if
+ * <code>o</code> is not an instance of the declaring class of this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ public double getDouble(Object o)
+ throws IllegalAccessException
+ {
+ return f.getDouble(o);
+ }
+
+ /**
+ * Set the value of this Field. If it is a primitive field, the value
+ * will be unwrapped from the passed object (boolean = java.lang.Boolean).<p>
+ *
+ * If the field is static, <code>o</code> will be ignored. Otherwise, if
+ * <code>o</code> is null, you get a <code>NullPointerException</code>,
+ * and if it is incompatible with the declaring class of the field, you
+ * get an <code>IllegalArgumentException</code>.<p>
+ *
+ * Next, if this Field enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not access this field in similar compiled code. This also
+ * occurs whether or not there is access control if the field is final.
+ * If the field is primitive, and unwrapping your argument fails, you will
+ * get an <code>IllegalArgumentException</code>; likewise, this error
+ * happens if <code>value</code> cannot be cast to the correct object type.
+ * If the field is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the field is set with the widened value. This method accesses
+ * the field of the declaring class, even if the instance passed in belongs
+ * to a subclass which declares another field to hide this one.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if <code>value</code> cannot be
+ * converted by a widening conversion to the underlying type of
+ * the Field, or if <code>o</code> is not an instance of the class
+ * declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #setBoolean(Object, boolean)
+ * @see #setByte(Object, byte)
+ * @see #setChar(Object, char)
+ * @see #setShort(Object, short)
+ * @see #setInt(Object, int)
+ * @see #setLong(Object, long)
+ * @see #setFloat(Object, float)
+ * @see #setDouble(Object, double)
+ */
+ public void set(Object o, Object value)
+ throws IllegalAccessException
+ {
+ f.set(o, value);
+ }
+
+ /**
+ * Set this boolean Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a boolean field, or if
+ * <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setBoolean(Object o, boolean value)
+ throws IllegalAccessException
+ {
+ f.setBoolean(o, value);
+ }
+
+ /**
+ * Set this byte Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setByte(Object o, byte value)
+ throws IllegalAccessException
+ {
+ f.setByte(o, value);
+ }
+
+ /**
+ * Set this char Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a char, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setChar(Object o, char value)
+ throws IllegalAccessException
+ {
+ f.setChar(o, value);
+ }
+
+ /**
+ * Set this short Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a short, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setShort(Object o, short value)
+ throws IllegalAccessException
+ {
+ f.setShort(o, value);
+ }
+
+ /**
+ * Set this int Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not an int, long, float, or
+ * double field, or if <code>o</code> is not an instance of the
+ * class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setInt(Object o, int value)
+ throws IllegalAccessException
+ {
+ f.setInt(o, value);
+ }
+
+ /**
+ * Set this long Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a long, float, or double
+ * field, or if <code>o</code> is not an instance of the class
+ * declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setLong(Object o, long value)
+ throws IllegalAccessException
+ {
+ f.setLong(o, value);
+ }
+
+ /**
+ * Set this float Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a float or long field, or
+ * if <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setFloat(Object o, float value)
+ throws IllegalAccessException
+ {
+ f.setFloat(o, value);
+ }
+
+ /**
+ * Set this double Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a double field, or if
+ * <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ public void setDouble(Object o, double value)
+ throws IllegalAccessException
+ {
+ f.setDouble(o, value);
+ }
+
+ /**
+ * Return the generic type of the field. If the field type is not a generic
+ * type, the method returns the same as <code>getType()</code>.
+ *
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type getGenericType()
+ {
+ if (p == null)
+ {
+ String signature = f.getSignature();
+ if (signature == null)
+ return getType();
+ p = new FieldSignatureParser(getDeclaringClass(),
+ signature);
+ }
+ return p.getFieldType();
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ return (T) f.getAnnotation(annotationClass);
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations()
+ {
+ return f.getDeclaredAnnotations();
+ }
+
+}
--- /dev/null
+/* java.lang.reflect.Method - reflection of Java methods
+ Copyright (C) 1998, 2001, 2002, 2005, 2007, 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import gnu.java.lang.ClassHelper;
+import gnu.java.lang.CPStringBuilder;
+
+import gnu.java.lang.reflect.MethodSignatureParser;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * The Method class represents a member method of a class. It also allows
+ * dynamic invocation, via reflection. This works for both static and
+ * instance methods. Invocation on Method objects knows how to do
+ * widening conversions, but throws {@link IllegalArgumentException} if
+ * a narrowing conversion would be necessary. You can query for information
+ * on this Method regardless of location, but invocation access may be limited
+ * by Java language access controls. If you can't do it in the compiler, you
+ * can't normally do it here either.<p>
+ *
+ * <B>Note:</B> This class returns and accepts types as Classes, even
+ * primitive types; there are Class types defined that represent each
+ * different primitive type. They are <code>java.lang.Boolean.TYPE,
+ * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
+ * byte.class</code>, etc. These are not to be confused with the
+ * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
+ * real classes.<p>
+ *
+ * Also note that this is not a serializable class. It is entirely feasible
+ * to make it serializable using the Externalizable interface, but this is
+ * on Sun, not me.
+ *
+ * @author John Keiser
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @see Member
+ * @see Class
+ * @see java.lang.Class#getMethod(String,Class[])
+ * @see java.lang.Class#getDeclaredMethod(String,Class[])
+ * @see java.lang.Class#getMethods()
+ * @see java.lang.Class#getDeclaredMethods()
+ * @since 1.1
+ * @status updated to 1.4
+ */
+public final class Method
+extends AccessibleObject implements Member, GenericDeclaration
+{
+ private static final int METHOD_MODIFIERS
+ = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE
+ | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC
+ | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED;
+
+ private MethodSignatureParser p;
+
+ VMMethod m;
+
+ /**
+ * This class is uninstantiable outside this package.
+ */
+ Method(VMMethod m)
+ {
+ this.m = m;
+ m.m = this;
+ }
+
+ /**
+ * Gets the class that declared this method, or the class where this method
+ * is a non-inherited member.
+ * @return the class that declared this member
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?> getDeclaringClass()
+ {
+ return (Class<?>) m.getDeclaringClass();
+ }
+
+ /**
+ * Gets the name of this method.
+ * @return the name of this method
+ */
+ public String getName()
+ {
+ return m.getName();
+ }
+
+ /**
+ * Gets the modifiers this method uses. Use the <code>Modifier</code>
+ * class to interpret the values. A method can only have a subset of the
+ * following modifiers: public, private, protected, abstract, static,
+ * final, synchronized, native, and strictfp.
+ *
+ * @return an integer representing the modifiers to this Member
+ * @see Modifier
+ */
+ public int getModifiers()
+ {
+ return m.getModifiersInternal() & METHOD_MODIFIERS;
+ }
+
+ /**
+ * Return true if this method is a bridge method. A bridge method
+ * is generated by the compiler in some situations involving
+ * generics and inheritance.
+ * @since 1.5
+ */
+ public boolean isBridge()
+ {
+ return (m.getModifiersInternal() & Modifier.BRIDGE) != 0;
+ }
+
+ /**
+ * Return true if this method is synthetic, false otherwise.
+ * @since 1.5
+ */
+ public boolean isSynthetic()
+ {
+ return (m.getModifiersInternal() & Modifier.SYNTHETIC) != 0;
+ }
+
+ /**
+ * Return true if this is a varargs method, that is if
+ * the method takes a variable number of arguments.
+ * @since 1.5
+ */
+ public boolean isVarArgs()
+ {
+ return (m.getModifiersInternal() & Modifier.VARARGS) != 0;
+ }
+
+ /**
+ * Gets the return type of this method.
+ * @return the type of this method
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?> getReturnType()
+ {
+ return (Class<?>) m.getReturnType();
+ }
+
+ /**
+ * Get the parameter list for this method, in declaration order. If the
+ * method takes no parameters, returns a 0-length array (not null).
+ *
+ * @return a list of the types of the method's parameters
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?>[] getParameterTypes()
+ {
+ return (Class<?>[]) m.getParameterTypes();
+ }
+
+ /**
+ * Get the exception types this method says it throws, in no particular
+ * order. If the method has no throws clause, returns a 0-length array
+ * (not null).
+ *
+ * @return a list of the types in the method's throws clause
+ */
+ @SuppressWarnings("unchecked")
+ public Class<?>[] getExceptionTypes()
+ {
+ return (Class<?>[]) m.getExceptionTypes();
+ }
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Methods are semantically equivalent if they have the same declaring
+ * class, name, parameter list, and return type.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not
+ */
+ public boolean equals(Object o)
+ {
+ return m.equals(o);
+ }
+
+ /**
+ * Get the hash code for the Method. The Method hash code is the hash code
+ * of its name XOR'd with the hash code of its class name.
+ *
+ * @return the hash code for the object
+ */
+ public int hashCode()
+ {
+ return m.getDeclaringClass().getName().hashCode() ^ m.getName().hashCode();
+ }
+
+ /**
+ * Get a String representation of the Method. A Method's String
+ * representation is "<modifiers> <returntype>
+ * <methodname>(<paramtypes>) throws <exceptions>", where
+ * everything after ')' is omitted if there are no exceptions.<br> Example:
+ * <code>public static int run(java.lang.Runnable,int)</code>
+ *
+ * @return the String representation of the Method
+ */
+ public String toString()
+ {
+ // 128 is a reasonable buffer initial size for constructor
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ sb.append(ClassHelper.getUserName(getReturnType())).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName()).append('(');
+ Class[] c = getParameterTypes();
+ if (c.length > 0)
+ {
+ sb.append(ClassHelper.getUserName(c[0]));
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(ClassHelper.getUserName(c[i]));
+ }
+ sb.append(')');
+ c = getExceptionTypes();
+ if (c.length > 0)
+ {
+ sb.append(" throws ").append(c[0].getName());
+ for (int i = 1; i < c.length; i++)
+ sb.append(',').append(c[i].getName());
+ }
+ return sb.toString();
+ }
+
+ public String toGenericString()
+ {
+ // 128 is a reasonable buffer initial size for constructor
+ CPStringBuilder sb = new CPStringBuilder(128);
+ Modifier.toString(getModifiers(), sb).append(' ');
+ Constructor.addTypeParameters(sb, getTypeParameters());
+ sb.append(getGenericReturnType()).append(' ');
+ sb.append(getDeclaringClass().getName()).append('.');
+ sb.append(getName()).append('(');
+ Type[] types = getGenericParameterTypes();
+ if (types.length > 0)
+ {
+ sb.append(types[0]);
+ for (int i = 1; i < types.length; i++)
+ sb.append(',').append(types[i]);
+ }
+ sb.append(')');
+ types = getGenericExceptionTypes();
+ if (types.length > 0)
+ {
+ sb.append(" throws ").append(types[0]);
+ for (int i = 1; i < types.length; i++)
+ sb.append(',').append(types[i]);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Invoke the method. Arguments are automatically unwrapped and widened,
+ * and the result is automatically wrapped, if needed.<p>
+ *
+ * If the method is static, <code>o</code> will be ignored. Otherwise,
+ * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot
+ * mimic the behavior of nonvirtual lookup (as in super.foo()). This means
+ * you will get a <code>NullPointerException</code> if <code>o</code> is
+ * null, and an <code>IllegalArgumentException</code> if it is incompatible
+ * with the declaring class of the method. If the method takes 0 arguments,
+ * you may use null or a 0-length array for <code>args</code>.<p>
+ *
+ * Next, if this Method enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not acces this method in similar compiled code. If the method
+ * is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the method is invoked. If it completes normally, the return value
+ * will be null for a void method, a wrapped object for a primitive return
+ * method, or the actual return of an Object method. If it completes
+ * abruptly, the exception is wrapped in an
+ * <code>InvocationTargetException</code>.
+ *
+ * @param o the object to invoke the method on
+ * @param args the arguments to the method
+ * @return the return value of the method, wrapped in the appropriate
+ * wrapper if it is primitive
+ * @throws IllegalAccessException if the method could not normally be called
+ * by the Java code (i.e. it is not public)
+ * @throws IllegalArgumentException if the number of arguments is incorrect;
+ * if the arguments types are wrong even with a widening conversion;
+ * or if <code>o</code> is not an instance of the class or interface
+ * declaring this method
+ * @throws InvocationTargetException if the method throws an exception
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static method triggered
+ * class initialization, which then failed
+ */
+ public Object invoke(Object o, Object... args)
+ throws IllegalAccessException, InvocationTargetException
+ {
+ return m.invoke(o, args);
+ }
+
+ /**
+ * Returns an array of <code>TypeVariable</code> objects that represents
+ * the type variables declared by this constructor, in declaration order.
+ * An array of size zero is returned if this class has no type
+ * variables.
+ *
+ * @return the type variables associated with this class.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public TypeVariable<Method>[] getTypeParameters()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return (TypeVariable<Method>[]) new TypeVariable[0];
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getTypeParameters();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the exception types declared by this method, in declaration order.
+ * An array of size zero is returned if this method declares no
+ * exceptions.
+ *
+ * @return the exception types declared by this method.
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericExceptionTypes()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return getExceptionTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericExceptionTypes();
+ }
+
+ /**
+ * Returns an array of <code>Type</code> objects that represents
+ * the parameter list for this method, in declaration order.
+ * An array of size zero is returned if this method takes no
+ * parameters.
+ *
+ * @return a list of the types of the method's parameters
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type[] getGenericParameterTypes()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return getParameterTypes();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericParameterTypes();
+ }
+
+ /**
+ * Returns the return type of this method.
+ *
+ * @return the return type of this method
+ * @throws GenericSignatureFormatError if the generic signature does
+ * not conform to the format specified in the Virtual Machine
+ * specification, version 3.
+ * @since 1.5
+ */
+ public Type getGenericReturnType()
+ {
+ if (p == null)
+ {
+ String sig = m.getSignature();
+ if (sig == null)
+ return getReturnType();
+ p = new MethodSignatureParser(this, sig);
+ }
+ return p.getGenericReturnType();
+ }
+
+ /**
+ * If this method is an annotation method, returns the default
+ * value for the method. If there is no default value, or if the
+ * method is not a member of an annotation type, returns null.
+ * Primitive types are wrapped.
+ *
+ * @throws TypeNotPresentException if the method returns a Class,
+ * and the class cannot be found
+ *
+ * @since 1.5
+ */
+ public Object getDefaultValue()
+ {
+ return m.getDefaultValue();
+ }
+
+ /**
+ * <p>
+ * Return an array of arrays representing the annotations on each
+ * of the method's parameters. The outer array is aligned against
+ * the parameters of the method and is thus equal in length to
+ * the number of parameters (thus having a length zero if there are none).
+ * Each array element in the outer array contains an inner array which
+ * holds the annotations. This array has a length of zero if the parameter
+ * has no annotations.
+ * </p>
+ * <p>
+ * The returned annotations are serialized. Changing the annotations has
+ * no affect on the return value of future calls to this method.
+ * </p>
+ *
+ * @return an array of arrays which represents the annotations used on the
+ * parameters of this method. The order of the array elements
+ * matches the declaration order of the parameters.
+ * @since 1.5
+ */
+ public Annotation[][] getParameterAnnotations()
+ {
+ return m.getParameterAnnotations();
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+ @SuppressWarnings("unchecked")
+ public <T extends Annotation> T getAnnotation(Class<T> annotationClass)
+ {
+ return (T) m.getAnnotation(annotationClass);
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+ public Annotation[] getDeclaredAnnotations()
+ {
+ return m.getDeclaredAnnotations();
+ }
+
+}
--- /dev/null
+/* java.lang.reflect.Modifier
+ Copyright (C) 1998, 1999, 2001, 2002, 2005, 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import gnu.java.lang.CPStringBuilder;
+
+/**
+ * Modifier is a helper class with static methods to determine whether an
+ * int returned from getModifiers() represents static, public, protected,
+ * native, final, etc... and provides an additional method to print
+ * out all of the modifiers in an int in order.
+ * <p>
+ * The methods in this class use the bitmask values in the VM spec to
+ * determine the modifiers of an int. This means that a VM must return a
+ * standard mask, conformant with the VM spec. I don't know if this is how
+ * Sun does it, but I'm willing to bet money that it is.
+ *
+ * @author John Keiser
+ * @author Tom Tromey (tromey@cygnus.com)
+ * @author Eric Blake (ebb9@email.byu.edu)
+ * @see Member#getModifiers()
+ * @see Method#getModifiers()
+ * @see Field#getModifiers()
+ * @see Constructor#getModifiers()
+ * @see Class#getModifiers()
+ * @since 1.1
+ */
+public class Modifier
+{
+ /** <STRONG>This constructor really shouldn't be here ... there are no
+ * instance methods or variables of this class, so instantiation is
+ * worthless. However, this function is in the 1.1 spec, so it is added
+ * for completeness.</STRONG>
+ */
+ public Modifier()
+ {
+ }
+
+ /**
+ * Public: accessible from any other class.
+ */
+ public static final int PUBLIC = 0x0001;
+
+ /**
+ * Private: accessible only from the same enclosing class.
+ */
+ public static final int PRIVATE = 0x0002;
+
+ /**
+ * Protected: accessible only to subclasses, or within the package.
+ */
+ public static final int PROTECTED = 0x0004;
+
+ /**
+ * Static:<br><ul>
+ * <li>Class: no enclosing instance for nested class.</li>
+ * <li>Field or Method: can be accessed or invoked without an
+ * instance of the declaring class.</li>
+ * </ul>
+ */
+ public static final int STATIC = 0x0008;
+
+ /**
+ * Final:<br><ul>
+ * <li>Class: no subclasses allowed.</li>
+ * <li>Field: cannot be changed.</li>
+ * <li>Method: cannot be overriden.</li>
+ * </ul>
+ */
+ public static final int FINAL = 0x0010;
+
+ /**
+ * Synchronized: Method: lock the class while calling this method.
+ */
+ public static final int SYNCHRONIZED = 0x0020;
+
+ /**
+ * Volatile: Field: cannot be cached.
+ */
+ public static final int VOLATILE = 0x0040;
+
+ /**
+ * Transient: Field: not serialized or deserialized.
+ */
+ public static final int TRANSIENT = 0x0080;
+
+ /**
+ * Native: Method: use JNI to call this method.
+ */
+ public static final int NATIVE = 0x0100;
+
+ /**
+ * Interface: Class: is an interface.
+ */
+ public static final int INTERFACE = 0x0200;
+
+ /**
+ * Abstract:<br><ul>
+ * <li>Class: may not be instantiated.</li>
+ * <li>Method: may not be called.</li>
+ * </ul>
+ */
+ public static final int ABSTRACT = 0x0400;
+
+ /**
+ * Strictfp: Method: expressions are FP-strict.<p>
+ * Also used as a modifier for classes, to mean that all initializers
+ * and constructors are FP-strict, but does not show up in
+ * Class.getModifiers.
+ */
+ public static final int STRICT = 0x0800;
+
+
+ /**
+ * Super - treat invokespecial as polymorphic so that super.foo() works
+ * according to the JLS. This is a reuse of the synchronized constant
+ * to patch a hole in JDK 1.0. *shudder*.
+ */
+ static final int SUPER = 0x0020;
+
+ /**
+ * All the flags, only used by code in this package.
+ */
+ static final int ALL_FLAGS = 0xfff;
+
+ /**
+ * Flag indicating a bridge method.
+ */
+ static final int BRIDGE = 0x40;
+
+ /**
+ * Flag indicating a varargs method.
+ */
+ static final int VARARGS = 0x80;
+
+ /**
+ * Flag indicating a synthetic member.
+ */
+ static final int SYNTHETIC = 0x1000;
+
+ /**
+ * Flag indicating an enum constant or an enum class.
+ */
+ static final int ENUM = 0x4000;
+
+ /**
+ * Check whether the given modifier is abstract.
+ * @param mod the modifier.
+ * @return <code>true</code> if abstract, <code>false</code> otherwise.
+ */
+ public static boolean isAbstract(int mod)
+ {
+ return (mod & ABSTRACT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is final.
+ * @param mod the modifier.
+ * @return <code>true</code> if final, <code>false</code> otherwise.
+ */
+ public static boolean isFinal(int mod)
+ {
+ return (mod & FINAL) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is an interface.
+ * @param mod the modifier.
+ * @return <code>true</code> if an interface, <code>false</code> otherwise.
+ */
+ public static boolean isInterface(int mod)
+ {
+ return (mod & INTERFACE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is native.
+ * @param mod the modifier.
+ * @return <code>true</code> if native, <code>false</code> otherwise.
+ */
+ public static boolean isNative(int mod)
+ {
+ return (mod & NATIVE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is private.
+ * @param mod the modifier.
+ * @return <code>true</code> if private, <code>false</code> otherwise.
+ */
+ public static boolean isPrivate(int mod)
+ {
+ return (mod & PRIVATE) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is protected.
+ * @param mod the modifier.
+ * @return <code>true</code> if protected, <code>false</code> otherwise.
+ */
+ public static boolean isProtected(int mod)
+ {
+ return (mod & PROTECTED) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is public.
+ * @param mod the modifier.
+ * @return <code>true</code> if public, <code>false</code> otherwise.
+ */
+ public static boolean isPublic(int mod)
+ {
+ return (mod & PUBLIC) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is static.
+ * @param mod the modifier.
+ * @return <code>true</code> if static, <code>false</code> otherwise.
+ */
+ public static boolean isStatic(int mod)
+ {
+ return (mod & STATIC) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is strictfp.
+ * @param mod the modifier.
+ * @return <code>true</code> if strictfp, <code>false</code> otherwise.
+ */
+ public static boolean isStrict(int mod)
+ {
+ return (mod & STRICT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is synchronized.
+ * @param mod the modifier.
+ * @return <code>true</code> if synchronized, <code>false</code> otherwise.
+ */
+ public static boolean isSynchronized(int mod)
+ {
+ return (mod & SYNCHRONIZED) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is transient.
+ * @param mod the modifier.
+ * @return <code>true</code> if transient, <code>false</code> otherwise.
+ */
+ public static boolean isTransient(int mod)
+ {
+ return (mod & TRANSIENT) != 0;
+ }
+
+ /**
+ * Check whether the given modifier is volatile.
+ * @param mod the modifier.
+ * @return <code>true</code> if volatile, <code>false</code> otherwise.
+ */
+ public static boolean isVolatile(int mod)
+ {
+ return (mod & VOLATILE) != 0;
+ }
+
+ /**
+ * Get a string representation of all the modifiers represented by the
+ * given int. The keywords are printed in this order:
+ * <code><public|protected|private> abstract static final transient
+ * volatile synchronized native strictfp interface</code>.
+ *
+ * @param mod the modifier.
+ * @return the String representing the modifiers.
+ */
+ public static String toString(int mod)
+ {
+ return toString(mod, new CPStringBuilder()).toString();
+ }
+
+ /**
+ * Package helper method that can take a CPStringBuilder.
+ * @param mod the modifier
+ * @param r the CPStringBuilder to which the String representation is appended
+ * @return r, with information appended
+ */
+ static CPStringBuilder toString(int mod, CPStringBuilder r)
+ {
+ if (isPublic(mod))
+ r.append("public ");
+ if (isProtected(mod))
+ r.append("protected ");
+ if (isPrivate(mod))
+ r.append("private ");
+ if (isAbstract(mod))
+ r.append("abstract ");
+ if (isStatic(mod))
+ r.append("static ");
+ if (isFinal(mod))
+ r.append("final ");
+ if (isTransient(mod))
+ r.append("transient ");
+ if (isVolatile(mod))
+ r.append("volatile ");
+ if (isSynchronized(mod))
+ r.append("synchronized ");
+ if (isNative(mod))
+ r.append("native ");
+ if (isStrict(mod))
+ r.append("strictfp ");
+ if (isInterface(mod))
+ r.append("interface ");
+
+ // Trim trailing space.
+ if ((mod & ALL_FLAGS) != 0)
+ r.setLength(r.length() - 1);
+ return r;
+ }
+}
--- /dev/null
+/* java.lang.reflect.VMConstructor - VM interface for reflection of Java constructors
+ Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+
+import java.util.Arrays;
+import java.util.Map;
+
+final class VMConstructor
+{
+ Class clazz;
+ int slot;
+
+ /**
+ * Unparsed annotations.
+ */
+ private byte[] annotations = null;
+
+ /**
+ * Unparsed parameter annotations.
+ */
+ private byte[] parameterAnnotations = null;
+
+ /**
+ * Annotations get parsed the first time they are
+ * accessed and are then cached it this map.
+ */
+ private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
+
+ /**
+ * Helper array for creating a new array from a java.util.Container.
+ */
+ private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
+ new Annotation[0];
+
+ /**
+ * This field allows us to refer back to the main constructor instance.
+ * It is set by the constructor of Constructor.
+ */
+ Constructor cons;
+
+ VMConstructor(Class clazz, int slot)
+ {
+ this.clazz = clazz;
+ this.slot = slot;
+ }
+
+ public Class getDeclaringClass()
+ {
+ return clazz;
+ }
+
+ /**
+ * Return the raw modifiers for this constructor. In particular
+ * this will include the synthetic and varargs bits.
+ * @return the constructor's modifiers
+ */
+ native int getModifiersInternal();
+
+ /**
+ * Get the parameter list for this constructor, in declaration order. If the
+ * constructor takes no parameters, returns a 0-length array (not null).
+ *
+ * @return a list of the types of the constructor's parameters
+ */
+ native Class[] getParameterTypes();
+
+ /**
+ * Get the exception types this constructor says it throws, in no particular
+ * order. If the constructor has no throws clause, returns a 0-length array
+ * (not null).
+ *
+ * @return a list of the types in the constructor's throws clause
+ */
+ native Class[] getExceptionTypes();
+
+ native Object construct(Object[] args)
+ throws InstantiationException, IllegalAccessException,
+ InvocationTargetException;
+
+ /**
+ * Return the String in the Signature attribute for this constructor. If there
+ * is no Signature attribute, return null.
+ */
+ native String getSignature();
+
+ /**
+ * <p>
+ * Return an array of arrays representing the annotations on each
+ * of the constructor's parameters. The outer array is aligned against
+ * the parameters of the constructors and is thus equal in length to
+ * the number of parameters (thus having a length zero if there are none).
+ * Each array element in the outer array contains an inner array which
+ * holds the annotations. This array has a length of zero if the parameter
+ * has no annotations.
+ * </p>
+ * <p>
+ * The returned annotations are serialized. Changing the annotations has
+ * no affect on the return value of future calls to this method.
+ * </p>
+ *
+ * @return an array of arrays which represents the annotations used on the
+ * parameters of this constructor. The order of the array elements
+ * matches the declaration order of the parameters.
+ * @since 1.5
+ */
+ native Annotation[][] getParameterAnnotations();
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Constructors are semantically equivalent if they have the same
+ * declaring class and the same parameter list. This ignores different
+ * exception clauses, but since you can't create a Method except through the
+ * VM, this is just the == relation.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not.
+ */
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof Constructor))
+ return false;
+ Constructor that = (Constructor)o;
+ if (clazz != that.getDeclaringClass())
+ return false;
+ if (!Arrays.equals(getParameterTypes(), that.getParameterTypes()))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+// native Annotation getAnnotation(Class annotationClass);
+ Annotation getAnnotation(Class annotationClass) {
+ if (annotationClass == null)
+ throw new NullPointerException();
+
+ return declaredAnnotations().get(annotationClass);
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+// native Annotation[] getDeclaredAnnotations();
+ Annotation[] getDeclaredAnnotations() {
+ return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
+ }
+
+ /**
+ * Parses the annotations if they aren't parsed yet and stores them into
+ * the declaredAnnotations map and return this map.
+ */
+ private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
+
+}
--- /dev/null
+/* java.lang.reflect.Field - VM interface for reflection of Java fields
+ Copyright (C) 1998, 2001, 2005, 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+
+import java.util.Map;
+
+final class VMField
+{
+ Class clazz;
+ String name;
+ int slot;
+
+ /**
+ * Unparsed annotations.
+ */
+ private byte[] annotations = null;
+
+ /**
+ * Annotations get parsed the first time they are
+ * accessed and are then cached it this map.
+ */
+ private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
+
+ /**
+ * Helper array for creating a new array from a java.util.Container.
+ */
+ private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
+ new Annotation[0];
+
+ /**
+ * This field allows us to refer back to the main constructor instance.
+ * It is set by the constructor of Field.
+ */
+ Field f;
+
+ VMField(Class clazz, String name, int slot)
+ {
+ this.clazz = clazz;
+ this.name = name;
+ this.slot = slot;
+ }
+
+ public Class getDeclaringClass()
+ {
+ return clazz;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Return the raw modifiers for this field.
+ * @return the field's modifiers
+ */
+ native int getModifiersInternal();
+
+ /**
+ * Gets the type of this field.
+ * @return the type of this field
+ */
+ native Class getType();
+
+ /**
+ * Get the value of this Field. If it is primitive, it will be wrapped
+ * in the appropriate wrapper type (boolean = java.lang.Boolean).<p>
+ *
+ * If the field is static, <code>o</code> will be ignored. Otherwise, if
+ * <code>o</code> is null, you get a <code>NullPointerException</code>,
+ * and if it is incompatible with the declaring class of the field, you
+ * get an <code>IllegalArgumentException</code>.<p>
+ *
+ * Next, if this Field enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not access this field in similar compiled code. If the field
+ * is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the field is accessed, and primitives are wrapped (but not
+ * necessarily in new objects). This method accesses the field of the
+ * declaring class, even if the instance passed in belongs to a subclass
+ * which declares another field to hide this one.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if <code>o</code> is not an instance of
+ * the class or interface declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #getBoolean(Object)
+ * @see #getByte(Object)
+ * @see #getChar(Object)
+ * @see #getShort(Object)
+ * @see #getInt(Object)
+ * @see #getLong(Object)
+ * @see #getFloat(Object)
+ * @see #getDouble(Object)
+ */
+ native Object get(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this boolean Field. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a boolean field of
+ * <code>o</code>, or if <code>o</code> is not an instance of the
+ * declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native boolean getBoolean(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this byte Field. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte field of
+ * <code>o</code>, or if <code>o</code> is not an instance of the
+ * declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native byte getByte(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this Field as a char. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a char field of
+ * <code>o</code>, or if <code>o</code> is not an instance
+ * of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native char getChar(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this Field as a short. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte or short
+ * field of <code>o</code>, or if <code>o</code> is not an instance
+ * of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native short getShort(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this Field as an int. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, or
+ * int field of <code>o</code>, or if <code>o</code> is not an
+ * instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native int getInt(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this Field as a long. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * or long field of <code>o</code>, or if <code>o</code> is not an
+ * instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native long getLong(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this Field as a float. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * long, or float field of <code>o</code>, or if <code>o</code> is
+ * not an instance of the declaring class of this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native float getFloat(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Get the value of this Field as a double. If the field is static,
+ * <code>o</code> will be ignored.
+ *
+ * @param o the object to get the value of this Field from
+ * @return the value of the Field
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, char, int,
+ * long, float, or double field of <code>o</code>, or if
+ * <code>o</code> is not an instance of the declaring class of this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #get(Object)
+ */
+ native double getDouble(Object o)
+ throws IllegalAccessException;
+
+ /**
+ * Set the value of this Field. If it is a primitive field, the value
+ * will be unwrapped from the passed object (boolean = java.lang.Boolean).<p>
+ *
+ * If the field is static, <code>o</code> will be ignored. Otherwise, if
+ * <code>o</code> is null, you get a <code>NullPointerException</code>,
+ * and if it is incompatible with the declaring class of the field, you
+ * get an <code>IllegalArgumentException</code>.<p>
+ *
+ * Next, if this Field enforces access control, your runtime context is
+ * evaluated, and you may have an <code>IllegalAccessException</code> if
+ * you could not access this field in similar compiled code. This also
+ * occurs whether or not there is access control if the field is final.
+ * If the field is primitive, and unwrapping your argument fails, you will
+ * get an <code>IllegalArgumentException</code>; likewise, this error
+ * happens if <code>value</code> cannot be cast to the correct object type.
+ * If the field is static, and its class is uninitialized, you trigger class
+ * initialization, which may end in a
+ * <code>ExceptionInInitializerError</code>.<p>
+ *
+ * Finally, the field is set with the widened value. This method accesses
+ * the field of the declaring class, even if the instance passed in belongs
+ * to a subclass which declares another field to hide this one.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if <code>value</code> cannot be
+ * converted by a widening conversion to the underlying type of
+ * the Field, or if <code>o</code> is not an instance of the class
+ * declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #setBoolean(Object, boolean)
+ * @see #setByte(Object, byte)
+ * @see #setChar(Object, char)
+ * @see #setShort(Object, short)
+ * @see #setInt(Object, int)
+ * @see #setLong(Object, long)
+ * @see #setFloat(Object, float)
+ * @see #setDouble(Object, double)
+ */
+ native void set(Object o, Object value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this boolean Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a boolean field, or if
+ * <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setBoolean(Object o, boolean value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this byte Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a byte, short, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setByte(Object o, byte value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this char Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a char, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setChar(Object o, char value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this short Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a short, int, long,
+ * float, or double field, or if <code>o</code> is not an instance
+ * of the class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setShort(Object o, short value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this int Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not an int, long, float, or
+ * double field, or if <code>o</code> is not an instance of the
+ * class declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setInt(Object o, int value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this long Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a long, float, or double
+ * field, or if <code>o</code> is not an instance of the class
+ * declaring this field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setLong(Object o, long value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this float Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a float or long field, or
+ * if <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setFloat(Object o, float value)
+ throws IllegalAccessException;
+
+ /**
+ * Set this double Field. If the field is static, <code>o</code> will be
+ * ignored.
+ *
+ * @param o the object to set this Field on
+ * @param value the value to set this Field to
+ * @throws IllegalAccessException if you could not normally access this field
+ * (i.e. it is not public)
+ * @throws IllegalArgumentException if this is not a double field, or if
+ * <code>o</code> is not an instance of the class declaring this
+ * field
+ * @throws NullPointerException if <code>o</code> is null and this field
+ * requires an instance
+ * @throws ExceptionInInitializerError if accessing a static field triggered
+ * class initialization, which then failed
+ * @see #set(Object, Object)
+ */
+ native void setDouble(Object o, double value)
+ throws IllegalAccessException;
+
+ /**
+ * Return the String in the Signature attribute for this field. If there
+ * is no Signature attribute, return null.
+ *
+ */
+ native String getSignature();
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Fields are semantically equivalent if they have the same declaring
+ * class, name, and type. Since you can't create a Field except through
+ * the VM, this is just the == relation.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not
+ */
+ public boolean equals(Object o)
+ {
+ if (!(o instanceof Field))
+ return false;
+ Field that = (Field)o;
+ if (clazz != that.getDeclaringClass())
+ return false;
+ if (!name.equals(that.getName()))
+ return false;
+ if (getType() != that.getType())
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+// native Annotation getAnnotation(Class annotationClass);
+ Annotation getAnnotation(Class annotationClass){
+ if (annotationClass == null)
+ throw new NullPointerException();
+
+ return declaredAnnotations().get(annotationClass);
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+// native Annotation[] getDeclaredAnnotations();
+ Annotation[] getDeclaredAnnotations() {
+ return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
+ }
+
+ /**
+ * Parses the annotations if they aren't parsed yet and stores them into
+ * the declaredAnnotations map and return this map.
+ */
+ private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
+
+}
--- /dev/null
+/* java.lang.reflect.VMMethod - VM interface for reflection of Java methods
+ Copyright (C) 1998, 2001, 2002, 2005, 2007, 2008 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.lang.reflect;
+
+import java.lang.annotation.Annotation;
+
+import java.util.Arrays;
+import java.util.Map;
+
+final class VMMethod
+{
+ Class clazz;
+ String name;
+ int slot;
+
+ /**
+ * Unparsed annotations.
+ */
+ private byte[] annotations = null;
+
+ /**
+ * Unparsed parameter annotations.
+ */
+ private byte[] parameterAnnotations = null;
+
+ /**
+ * Unparsed annotation default value.
+ */
+ private byte[] annotationDefault = null;
+
+ /**
+ * Annotations get parsed the first time they are
+ * accessed and are then cached it this map.
+ */
+ private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
+
+ /**
+ * Helper array for creating a new array from a java.util.Container.
+ */
+ private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
+ new Annotation[0];
+
+ /**
+ * This field allows us to refer back to the main constructor instance.
+ * It is set by the constructor of Field.
+ */
+ Method m;
+
+ public Class getDeclaringClass()
+ {
+ return clazz;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ /**
+ * Return the raw modifiers for this method.
+ * @return the method's modifiers
+ */
+ native int getModifiersInternal();
+
+ /**
+ * Gets the return type of this method.
+ * @return the type of this method
+ */
+ native Class getReturnType();
+
+ /**
+ * Get the parameter list for this method, in declaration order. If the
+ * method takes no parameters, returns a 0-length array (not null).
+ *
+ * @return a list of the types of the method's parameters
+ */
+ native Class[] getParameterTypes();
+
+ /**
+ * Get the exception types this method says it throws, in no particular
+ * order. If the method has no throws clause, returns a 0-length array
+ * (not null).
+ *
+ * @return a list of the types in the method's throws clause
+ */
+ native Class[] getExceptionTypes();
+
+ native Object invoke(Object o, Object[] args)
+ throws IllegalAccessException, InvocationTargetException;
+
+ /**
+ * Return the String in the Signature attribute for this method. If there
+ * is no Signature attribute, return null.
+ */
+ native String getSignature();
+
+ /**
+ * If this method is an annotation method, returns the default
+ * value for the method. If there is no default value, or if the
+ * method is not a member of an annotation type, returns null.
+ * Primitive types are wrapped.
+ *
+ * @throws TypeNotPresentException if the method returns a Class,
+ * and the class cannot be found
+ *
+ * @since 1.5
+ */
+ native Object getDefaultValue();
+
+ /**
+ * <p>
+ * Return an array of arrays representing the annotations on each
+ * of the method's parameters. The outer array is aligned against
+ * the parameters of the method and is thus equal in length to
+ * the number of parameters (thus having a length zero if there are none).
+ * Each array element in the outer array contains an inner array which
+ * holds the annotations. This array has a length of zero if the parameter
+ * has no annotations.
+ * </p>
+ * <p>
+ * The returned annotations are serialized. Changing the annotations has
+ * no affect on the return value of future calls to this method.
+ * </p>
+ *
+ * @return an array of arrays which represents the annotations used on the
+ * parameters of this method. The order of the array elements
+ * matches the declaration order of the parameters.
+ * @since 1.5
+ */
+ native Annotation[][] getParameterAnnotations();
+
+ /**
+ * Compare two objects to see if they are semantically equivalent.
+ * Two Methods are semantically equivalent if they have the same declaring
+ * class, name, parameter list, and return type.
+ *
+ * @param o the object to compare to
+ * @return <code>true</code> if they are equal; <code>false</code> if not
+ */
+ public boolean equals(Object o)
+ {
+ // Implementation note:
+ // The following is a correct but possibly slow implementation.
+ //
+ // This class has a private field 'slot' that could be used by
+ // the VM implementation to "link" a particular method to a Class.
+ // In that case equals could be simply implemented as:
+ //
+ // if (o instanceof Method)
+ // {
+ // Method m = (Method)o;
+ // return m.declaringClass == this.declaringClass
+ // && m.slot == this.slot;
+ // }
+ // return false;
+ //
+ // If a VM uses the Method class as their native/internal representation
+ // then just using the following would be optimal:
+ //
+ // return this == o;
+ //
+ if (!(o instanceof Method))
+ return false;
+ Method that = (Method)o;
+ if (clazz != that.getDeclaringClass())
+ return false;
+ if (!name.equals(that.getName()))
+ return false;
+ if (getReturnType() != that.getReturnType())
+ return false;
+ if (!Arrays.equals(getParameterTypes(), that.getParameterTypes()))
+ return false;
+ return true;
+ }
+
+ /**
+ * Returns the element's annotation for the specified annotation type,
+ * or <code>null</code> if no such annotation exists.
+ *
+ * @param annotationClass the type of annotation to look for.
+ * @return this element's annotation for the specified type, or
+ * <code>null</code> if no such annotation exists.
+ * @throws NullPointerException if the annotation class is <code>null</code>.
+ */
+// native Annotation getAnnotation(Class annotationClass);
+ Annotation getAnnotation(Class annotationClass) {
+ if (annotationClass == null)
+ throw new NullPointerException();
+
+ return declaredAnnotations().get(annotationClass);
+ }
+
+ /**
+ * Returns all annotations directly defined by the element. If there are
+ * no annotations directly associated with the element, then a zero-length
+ * array will be returned. The returned array may be modified by the client
+ * code, but this will have no effect on the annotation content of this
+ * class, and hence no effect on the return value of this method for
+ * future callers.
+ *
+ * @return the annotations directly defined by the element.
+ * @since 1.5
+ */
+// native Annotation[] getDeclaredAnnotations();
+ Annotation[] getDeclaredAnnotations() {
+ return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
+ }
+
+ /**
+ * Parses the annotations if they aren't parsed yet and stores them into
+ * the declaredAnnotations map and return this map.
+ */
+ private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
+
+}
+
--- /dev/null
+/* VMAccessController.java -- VM-specific access controller methods.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+
+package java.security;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+
+final class VMAccessController
+{
+
+ // Fields.
+ // -------------------------------------------------------------------------
+
+ /**
+ * This is a per-thread stack of AccessControlContext objects (which can
+ * be null) for each call to AccessController.doPrivileged in each thread's
+ * call stack. We use this to remember which context object corresponds to
+ * which call.
+ */
+ private static final ThreadLocal contexts = new ThreadLocal();
+
+ /**
+ * This is a Boolean that, if set, tells getContext that it has already
+ * been called once, allowing us to handle recursive permission checks
+ * caused by methods getContext calls.
+ */
+ private static final ThreadLocal inGetContext = new ThreadLocal();
+
+ /**
+ * And we return this all-permissive context to ensure that privileged
+ * methods called from getContext succeed.
+ */
+ private static final AccessControlContext DEFAULT_CONTEXT;
+ static
+ {
+ CodeSource source = new CodeSource(null, null);
+ Permissions permissions = new Permissions();
+ permissions.add(new AllPermission());
+ ProtectionDomain[] domain = new ProtectionDomain[] {
+ new ProtectionDomain(source, permissions)
+ };
+ DEFAULT_CONTEXT = new AccessControlContext(domain);
+ }
+
+ private static final boolean DEBUG = gnu.classpath.Configuration.DEBUG;
+ private static void debug(String msg)
+ {
+ System.err.print(">>> VMAccessController: ");
+ System.err.println(msg);
+ }
+
+ // Constructors.
+ // -------------------------------------------------------------------------
+
+ private VMAccessController() { }
+
+ // Class methods.
+ // -------------------------------------------------------------------------
+
+ /**
+ * Relate a class (which should be an instance of {@link PrivilegedAction}
+ * with an access control context. This method is used by {@link
+ * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}
+ * to set up the context that will be returned by {@link #getContext()}.
+ * This method relates the class to the current thread, so contexts
+ * pushed from one thread will not be available to another.
+ *
+ * @param acc The access control context.
+ */
+ static void pushContext (AccessControlContext acc)
+ {
+ if (DEBUG)
+ debug("pushing " + acc);
+ LinkedList stack = (LinkedList) contexts.get();
+ if (stack == null)
+ {
+ if (DEBUG)
+ debug("no stack... creating ");
+ stack = new LinkedList();
+ contexts.set(stack);
+ }
+ stack.addFirst(acc);
+ }
+
+ /**
+ * Removes the relation of a class to an {@link AccessControlContext}.
+ * This method is used by {@link AccessController} when exiting from a
+ * call to {@link
+ * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}.
+ */
+ static void popContext()
+ {
+ if (DEBUG)
+ debug("popping context");
+
+ // Stack should never be null, nor should it be empty, if this method
+ // and its counterpart has been called properly.
+ LinkedList stack = (LinkedList) contexts.get();
+ if (stack != null)
+ {
+ stack.removeFirst();
+ if (stack.isEmpty())
+ contexts.set(null);
+ }
+ else if (DEBUG)
+ {
+ debug("no stack during pop?????");
+ }
+ }
+
+ /**
+ * Examine the method stack of the currently running thread, and create
+ * an {@link AccessControlContext} filled in with the appropriate {@link
+ * ProtectionDomain} objects given this stack.
+ *
+ * @return The context.
+ */
+ static AccessControlContext getContext()
+ {
+ // If we are already in getContext, but called a method that needs
+ // a permission check, return the all-permissive context so methods
+ // called from here succeed.
+ //
+ // XXX is this necessary? We should verify if there are any calls in
+ // the stack below this method that require permission checks.
+ Boolean inCall = (Boolean) inGetContext.get();
+ if (inCall != null && inCall.booleanValue())
+ {
+ if (DEBUG)
+ debug("already in getContext");
+ return DEFAULT_CONTEXT;
+ }
+
+ inGetContext.set(Boolean.TRUE);
+
+ Object[][] stack = getStack();
+ Class[] classes = (Class[]) stack[0];
+ String[] methods = (String[]) stack[1];
+
+ if (DEBUG)
+ debug("got trace of length " + classes.length);
+
+ HashSet domains = new HashSet();
+ HashSet seenDomains = new HashSet();
+ AccessControlContext context = null;
+ int privileged = 0;
+
+ // We walk down the stack, adding each ProtectionDomain for each
+ // class in the call stack. If we reach a call to doPrivileged,
+ // we don't add any more stack frames. We skip the first three stack
+ // frames, since they comprise the calls to getStack, getContext,
+ // and AccessController.getContext.
+ for (int i = 3; i < classes.length && privileged < 2; i++)
+ {
+ Class clazz = classes[i];
+ String method = methods[i];
+
+ if (DEBUG)
+ {
+ debug("checking " + clazz + "." + method);
+ // subject to getClassLoader RuntimePermission
+ debug("loader = " + clazz.getClassLoader());
+ }
+
+ // If the previous frame was a call to doPrivileged, then this is
+ // the last frame we look at.
+ if (privileged == 1)
+ privileged = 2;
+
+ if (clazz.equals (AccessController.class)
+ && method.equals ("doPrivileged"))
+ {
+ // If there was a call to doPrivileged with a supplied context,
+ // return that context. If using JAAS doAs*, it should be
+ // a context with a SubjectDomainCombiner
+ LinkedList l = (LinkedList) contexts.get();
+ if (l != null)
+ context = (AccessControlContext) l.getFirst();
+ privileged = 1;
+ }
+
+ // subject to getProtectionDomain RuntimePermission
+ ProtectionDomain domain = clazz.getProtectionDomain();
+
+ if (domain == null)
+ continue;
+ if (seenDomains.contains(domain))
+ continue;
+ seenDomains.add(domain);
+
+ // Create a static snapshot of this domain, which may change over time
+ // if the current policy changes.
+ domains.add(new ProtectionDomain(domain.getCodeSource(),
+ domain.getPermissions()));
+ }
+
+ if (DEBUG)
+ debug("created domains: " + domains);
+
+ ProtectionDomain[] result = (ProtectionDomain[])
+ domains.toArray(new ProtectionDomain[domains.size()]);
+
+ if (context != null)
+ {
+ DomainCombiner dc = context.getDomainCombiner ();
+ // If the supplied context had no explicit DomainCombiner, use
+ // our private version, which computes the intersection of the
+ // context's domains with the derived set.
+ if (dc == null)
+ context = new AccessControlContext
+ (IntersectingDomainCombiner.SINGLETON.combine
+ (result, context.getProtectionDomains ()));
+ // Use the supplied DomainCombiner. This should be secure,
+ // because only trusted code may create an
+ // AccessControlContext with a custom DomainCombiner.
+ else
+ context = new AccessControlContext (result, context, dc);
+ }
+ // No context was supplied. Return the derived one.
+ else
+ context = new AccessControlContext (result);
+
+ inGetContext.set(Boolean.FALSE);
+ return context;
+ }
+
+ /**
+ * Returns a snapshot of the current call stack as a pair of arrays:
+ * the first an array of classes in the call stack, the second an array
+ * of strings containing the method names in the call stack. The two
+ * arrays match up, meaning that method <i>i</i> is declared in class
+ * <i>i</i>. The arrays are clean; it will only contain Java methods,
+ * and no element of the list should be null.
+ *
+ * <p>The default implementation returns an empty stack, which will be
+ * interpreted as having no permissions whatsoever.
+ *
+ * @return A pair of arrays describing the current call stack. The first
+ * element is an array of Class objects, and the second is an array
+ * of Strings comprising the method names.
+ */
+// private static Object[][] getStack()
+// {
+// return new Object[][] { new Class[0], new String[0] };
+// }
+ private native static Object[][] getStack();
+}
--- /dev/null
+/*
+ * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.misc;
+
+import java.security.*;
+import java.lang.reflect.*;
+
+
+/**
+ * A collection of methods for performing low-level, unsafe operations.
+ * Although the class and all methods are public, use of this class is
+ * limited because only trusted code can obtain instances of it.
+ *
+ * @author John R. Rose
+ * @see #getUnsafe
+ */
+
+public final class Unsafe {
+
+ private static native void registerNatives();
+ static {
+ registerNatives();
+// sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
+ }
+
+ private Unsafe() {}
+
+ private static final Unsafe theUnsafe = new Unsafe();
+
+ /**
+ * Provides the caller with the capability of performing unsafe
+ * operations.
+ *
+ * <p> The returned <code>Unsafe</code> object should be carefully guarded
+ * by the caller, since it can be used to read and write data at arbitrary
+ * memory addresses. It must never be passed to untrusted code.
+ *
+ * <p> Most methods in this class are very low-level, and correspond to a
+ * small number of hardware instructions (on typical machines). Compilers
+ * are encouraged to optimize these methods accordingly.
+ *
+ * <p> Here is a suggested idiom for using unsafe operations:
+ *
+ * <blockquote><pre>
+ * class MyTrustedClass {
+ * private static final Unsafe unsafe = Unsafe.getUnsafe();
+ * ...
+ * private long myCountAddress = ...;
+ * public int getCount() { return unsafe.getByte(myCountAddress); }
+ * }
+ * </pre></blockquote>
+ *
+ * (It may assist compilers to make the local variable be
+ * <code>final</code>.)
+ *
+ * @exception SecurityException if a security manager exists and its
+ * <code>checkPropertiesAccess</code> method doesn't allow
+ * access to the system properties.
+ */
+ public static Unsafe getUnsafe() {
+ Class cc = sun.reflect.Reflection.getCallerClass(2);
+ if (cc.getClassLoader() != null)
+ throw new SecurityException("Unsafe");
+ return theUnsafe;
+ }
+
+ /// peek and poke operations
+ /// (compilers should optimize these to memory ops)
+
+ // These work on object fields in the Java heap.
+ // They will not work on elements of packed arrays.
+
+ /**
+ * Fetches a value from a given Java variable.
+ * More specifically, fetches a field or array element within the given
+ * object <code>o</code> at the given offset, or (if <code>o</code> is
+ * null) from the memory address whose numerical value is the given
+ * offset.
+ * <p>
+ * The results are undefined unless one of the following cases is true:
+ * <ul>
+ * <li>The offset was obtained from {@link #objectFieldOffset} on
+ * the {@link java.lang.reflect.Field} of some Java field and the object
+ * referred to by <code>o</code> is of a class compatible with that
+ * field's class.
+ *
+ * <li>The offset and object reference <code>o</code> (either null or
+ * non-null) were both obtained via {@link #staticFieldOffset}
+ * and {@link #staticFieldBase} (respectively) from the
+ * reflective {@link Field} representation of some Java field.
+ *
+ * <li>The object referred to by <code>o</code> is an array, and the offset
+ * is an integer of the form <code>B+N*S</code>, where <code>N</code> is
+ * a valid index into the array, and <code>B</code> and <code>S</code> are
+ * the values obtained by {@link #arrayBaseOffset} and {@link
+ * #arrayIndexScale} (respectively) from the array's class. The value
+ * referred to is the <code>N</code><em>th</em> element of the array.
+ *
+ * </ul>
+ * <p>
+ * If one of the above cases is true, the call references a specific Java
+ * variable (field or array element). However, the results are undefined
+ * if that variable is not in fact of the type returned by this method.
+ * <p>
+ * This method refers to a variable by means of two parameters, and so
+ * it provides (in effect) a <em>double-register</em> addressing mode
+ * for Java variables. When the object reference is null, this method
+ * uses its offset as an absolute address. This is similar in operation
+ * to methods such as {@link #getInt(long)}, which provide (in effect) a
+ * <em>single-register</em> addressing mode for non-Java variables.
+ * However, because Java variables may have a different layout in memory
+ * from non-Java variables, programmers should not assume that these
+ * two addressing modes are ever equivalent. Also, programmers should
+ * remember that offsets from the double-register addressing mode cannot
+ * be portably confused with longs used in the single-register addressing
+ * mode.
+ *
+ * @param o Java heap object in which the variable resides, if any, else
+ * null
+ * @param offset indication of where the variable resides in a Java heap
+ * object, if any, else a memory address locating the variable
+ * statically
+ * @return the value fetched from the indicated Java variable
+ * @throws RuntimeException No defined exceptions are thrown, not even
+ * {@link NullPointerException}
+ */
+ public native int getInt(Object o, long offset);
+
+ /**
+ * Stores a value into a given Java variable.
+ * <p>
+ * The first two parameters are interpreted exactly as with
+ * {@link #getInt(Object, long)} to refer to a specific
+ * Java variable (field or array element). The given value
+ * is stored into that variable.
+ * <p>
+ * The variable must be of the same type as the method
+ * parameter <code>x</code>.
+ *
+ * @param o Java heap object in which the variable resides, if any, else
+ * null
+ * @param offset indication of where the variable resides in a Java heap
+ * object, if any, else a memory address locating the variable
+ * statically
+ * @param x the value to store into the indicated Java variable
+ * @throws RuntimeException No defined exceptions are thrown, not even
+ * {@link NullPointerException}
+ */
+ public native void putInt(Object o, long offset, int x);
+
+ /**
+ * Fetches a reference value from a given Java variable.
+ * @see #getInt(Object, long)
+ */
+ public native Object getObject(Object o, long offset);
+
+ /**
+ * Stores a reference value into a given Java variable.
+ * <p>
+ * Unless the reference <code>x</code> being stored is either null
+ * or matches the field type, the results are undefined.
+ * If the reference <code>o</code> is non-null, car marks or
+ * other store barriers for that object (if the VM requires them)
+ * are updated.
+ * @see #putInt(Object, int, int)
+ */
+ public native void putObject(Object o, long offset, Object x);
+
+ /** @see #getInt(Object, long) */
+ public native boolean getBoolean(Object o, long offset);
+ /** @see #putInt(Object, int, int) */
+ public native void putBoolean(Object o, long offset, boolean x);
+ /** @see #getInt(Object, long) */
+ public native byte getByte(Object o, long offset);
+ /** @see #putInt(Object, int, int) */
+ public native void putByte(Object o, long offset, byte x);
+ /** @see #getInt(Object, long) */
+ public native short getShort(Object o, long offset);
+ /** @see #putInt(Object, int, int) */
+ public native void putShort(Object o, long offset, short x);
+ /** @see #getInt(Object, long) */
+ public native char getChar(Object o, long offset);
+ /** @see #putInt(Object, int, int) */
+ public native void putChar(Object o, long offset, char x);
+ /** @see #getInt(Object, long) */
+ public native long getLong(Object o, long offset);
+ /** @see #putInt(Object, int, int) */
+ public native void putLong(Object o, long offset, long x);
+ /** @see #getInt(Object, long) */
+ public native float getFloat(Object o, long offset);
+ /** @see #putInt(Object, int, int) */
+ public native void putFloat(Object o, long offset, float x);
+ /** @see #getInt(Object, long) */
+ public native double getDouble(Object o, long offset);
+ /** @see #putInt(Object, int, int) */
+ public native void putDouble(Object o, long offset, double x);
+
+ /**
+ * This method, like all others with 32-bit offsets, was native
+ * in a previous release but is now a wrapper which simply casts
+ * the offset to a long value. It provides backward compatibility
+ * with bytecodes compiled against 1.4.
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public int getInt(Object o, int offset) {
+ return getInt(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putInt(Object o, int offset, int x) {
+ putInt(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public Object getObject(Object o, int offset) {
+ return getObject(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putObject(Object o, int offset, Object x) {
+ putObject(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public boolean getBoolean(Object o, int offset) {
+ return getBoolean(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putBoolean(Object o, int offset, boolean x) {
+ putBoolean(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public byte getByte(Object o, int offset) {
+ return getByte(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putByte(Object o, int offset, byte x) {
+ putByte(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public short getShort(Object o, int offset) {
+ return getShort(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putShort(Object o, int offset, short x) {
+ putShort(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public char getChar(Object o, int offset) {
+ return getChar(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putChar(Object o, int offset, char x) {
+ putChar(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public long getLong(Object o, int offset) {
+ return getLong(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putLong(Object o, int offset, long x) {
+ putLong(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public float getFloat(Object o, int offset) {
+ return getFloat(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putFloat(Object o, int offset, float x) {
+ putFloat(o, (long)offset, x);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public double getDouble(Object o, int offset) {
+ return getDouble(o, (long)offset);
+ }
+
+ /**
+ * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
+ * See {@link #staticFieldOffset}.
+ */
+ @Deprecated
+ public void putDouble(Object o, int offset, double x) {
+ putDouble(o, (long)offset, x);
+ }
+
+ // These work on values in the C heap.
+
+ /**
+ * Fetches a value from a given memory address. If the address is zero, or
+ * does not point into a block obtained from {@link #allocateMemory}, the
+ * results are undefined.
+ *
+ * @see #allocateMemory
+ */
+ public native byte getByte(long address);
+
+ /**
+ * Stores a value into a given memory address. If the address is zero, or
+ * does not point into a block obtained from {@link #allocateMemory}, the
+ * results are undefined.
+ *
+ * @see #getByte(long)
+ */
+ public native void putByte(long address, byte x);
+
+ /** @see #getByte(long) */
+ public native short getShort(long address);
+ /** @see #putByte(long, byte) */
+ public native void putShort(long address, short x);
+ /** @see #getByte(long) */
+ public native char getChar(long address);
+ /** @see #putByte(long, byte) */
+ public native void putChar(long address, char x);
+ /** @see #getByte(long) */
+ public native int getInt(long address);
+ /** @see #putByte(long, byte) */
+ public native void putInt(long address, int x);
+ /** @see #getByte(long) */
+ public native long getLong(long address);
+ /** @see #putByte(long, byte) */
+ public native void putLong(long address, long x);
+ /** @see #getByte(long) */
+ public native float getFloat(long address);
+ /** @see #putByte(long, byte) */
+ public native void putFloat(long address, float x);
+ /** @see #getByte(long) */
+ public native double getDouble(long address);
+ /** @see #putByte(long, byte) */
+ public native void putDouble(long address, double x);
+
+ /**
+ * Fetches a native pointer from a given memory address. If the address is
+ * zero, or does not point into a block obtained from {@link
+ * #allocateMemory}, the results are undefined.
+ *
+ * <p> If the native pointer is less than 64 bits wide, it is extended as
+ * an unsigned number to a Java long. The pointer may be indexed by any
+ * given byte offset, simply by adding that offset (as a simple integer) to
+ * the long representing the pointer. The number of bytes actually read
+ * from the target address maybe determined by consulting {@link
+ * #addressSize}.
+ *
+ * @see #allocateMemory
+ */
+ public native long getAddress(long address);
+
+ /**
+ * Stores a native pointer into a given memory address. If the address is
+ * zero, or does not point into a block obtained from {@link
+ * #allocateMemory}, the results are undefined.
+ *
+ * <p> The number of bytes actually written at the target address maybe
+ * determined by consulting {@link #addressSize}.
+ *
+ * @see #getAddress(long)
+ */
+ public native void putAddress(long address, long x);
+
+ /// wrappers for malloc, realloc, free:
+
+ /**
+ * Allocates a new block of native memory, of the given size in bytes. The
+ * contents of the memory are uninitialized; they will generally be
+ * garbage. The resulting native pointer will never be zero, and will be
+ * aligned for all value types. Dispose of this memory by calling {@link
+ * #freeMemory}, or resize it with {@link #reallocateMemory}.
+ *
+ * @throws IllegalArgumentException if the size is negative or too large
+ * for the native size_t type
+ *
+ * @throws OutOfMemoryError if the allocation is refused by the system
+ *
+ * @see #getByte(long)
+ * @see #putByte(long, byte)
+ */
+ public native long allocateMemory(long bytes);
+
+ /**
+ * Resizes a new block of native memory, to the given size in bytes. The
+ * contents of the new block past the size of the old block are
+ * uninitialized; they will generally be garbage. The resulting native
+ * pointer will be zero if and only if the requested size is zero. The
+ * resulting native pointer will be aligned for all value types. Dispose
+ * of this memory by calling {@link #freeMemory}, or resize it with {@link
+ * #reallocateMemory}. The address passed to this method may be null, in
+ * which case an allocation will be performed.
+ *
+ * @throws IllegalArgumentException if the size is negative or too large
+ * for the native size_t type
+ *
+ * @throws OutOfMemoryError if the allocation is refused by the system
+ *
+ * @see #allocateMemory
+ */
+ public native long reallocateMemory(long address, long bytes);
+
+ /**
+ * Sets all bytes in a given block of memory to a fixed value
+ * (usually zero).
+ */
+ public native void setMemory(long address, long bytes, byte value);
+
+ /**
+ * Sets all bytes in a given block of memory to a copy of another
+ * block.
+ */
+ public native void copyMemory(long srcAddress, long destAddress,
+ long bytes);
+
+ /**
+ * Disposes of a block of native memory, as obtained from {@link
+ * #allocateMemory} or {@link #reallocateMemory}. The address passed to
+ * this method may be null, in which case no action is taken.
+ *
+ * @see #allocateMemory
+ */
+ public native void freeMemory(long address);
+
+ /// random queries
+
+ /**
+ * This constant differs from all results that will ever be returned from
+ * {@link #staticFieldOffset}, {@link #objectFieldOffset},
+ * or {@link #arrayBaseOffset}.
+ */
+ public static final int INVALID_FIELD_OFFSET = -1;
+
+ /**
+ * Returns the offset of a field, truncated to 32 bits.
+ * This method is implemented as follows:
+ * <blockquote><pre>
+ * public int fieldOffset(Field f) {
+ * if (Modifier.isStatic(f.getModifiers()))
+ * return (int) staticFieldOffset(f);
+ * else
+ * return (int) objectFieldOffset(f);
+ * }
+ * </pre></blockquote>
+ * @deprecated As of 1.4.1, use {@link #staticFieldOffset} for static
+ * fields and {@link #objectFieldOffset} for non-static fields.
+ */
+ @Deprecated
+ public int fieldOffset(Field f) {
+ if (Modifier.isStatic(f.getModifiers()))
+ return (int) staticFieldOffset(f);
+ else
+ return (int) objectFieldOffset(f);
+ }
+
+ /**
+ * Returns the base address for accessing some static field
+ * in the given class. This method is implemented as follows:
+ * <blockquote><pre>
+ * public Object staticFieldBase(Class c) {
+ * Field[] fields = c.getDeclaredFields();
+ * for (int i = 0; i < fields.length; i++) {
+ * if (Modifier.isStatic(fields[i].getModifiers())) {
+ * return staticFieldBase(fields[i]);
+ * }
+ * }
+ * return null;
+ * }
+ * </pre></blockquote>
+ * @deprecated As of 1.4.1, use {@link #staticFieldBase(Field)}
+ * to obtain the base pertaining to a specific {@link Field}.
+ * This method works only for JVMs which store all statics
+ * for a given class in one place.
+ */
+ @Deprecated
+ public Object staticFieldBase(Class c) {
+ Field[] fields = c.getDeclaredFields();
+ for (int i = 0; i < fields.length; i++) {
+ if (Modifier.isStatic(fields[i].getModifiers())) {
+ return staticFieldBase(fields[i]);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Report the location of a given field in the storage allocation of its
+ * class. Do not expect to perform any sort of arithmetic on this offset;
+ * it is just a cookie which is passed to the unsafe heap memory accessors.
+ *
+ * <p>Any given field will always have the same offset and base, and no
+ * two distinct fields of the same class will ever have the same offset
+ * and base.
+ *
+ * <p>As of 1.4.1, offsets for fields are represented as long values,
+ * although the Sun JVM does not use the most significant 32 bits.
+ * However, JVM implementations which store static fields at absolute
+ * addresses can use long offsets and null base pointers to express
+ * the field locations in a form usable by {@link #getInt(Object,long)}.
+ * Therefore, code which will be ported to such JVMs on 64-bit platforms
+ * must preserve all bits of static field offsets.
+ * @see #getInt(Object, long)
+ */
+ public native long staticFieldOffset(Field f);
+
+ /**
+ * Report the location of a given static field, in conjunction with {@link
+ * #staticFieldBase}.
+ * <p>Do not expect to perform any sort of arithmetic on this offset;
+ * it is just a cookie which is passed to the unsafe heap memory accessors.
+ *
+ * <p>Any given field will always have the same offset, and no two distinct
+ * fields of the same class will ever have the same offset.
+ *
+ * <p>As of 1.4.1, offsets for fields are represented as long values,
+ * although the Sun JVM does not use the most significant 32 bits.
+ * It is hard to imagine a JVM technology which needs more than
+ * a few bits to encode an offset within a non-array object,
+ * However, for consistency with other methods in this class,
+ * this method reports its result as a long value.
+ * @see #getInt(Object, long)
+ */
+ public native long objectFieldOffset(Field f);
+
+ /**
+ * Report the location of a given static field, in conjunction with {@link
+ * #staticFieldOffset}.
+ * <p>Fetch the base "Object", if any, with which static fields of the
+ * given class can be accessed via methods like {@link #getInt(Object,
+ * long)}. This value may be null. This value may refer to an object
+ * which is a "cookie", not guaranteed to be a real Object, and it should
+ * not be used in any way except as argument to the get and put routines in
+ * this class.
+ */
+ public native Object staticFieldBase(Field f);
+
+ /**
+ * Ensure the given class has been initialized. This is often
+ * needed in conjunction with obtaining the static field base of a
+ * class.
+ */
+ public native void ensureClassInitialized(Class c);
+
+ /**
+ * Report the offset of the first element in the storage allocation of a
+ * given array class. If {@link #arrayIndexScale} returns a non-zero value
+ * for the same class, you may use that scale factor, together with this
+ * base offset, to form new offsets to access elements of arrays of the
+ * given class.
+ *
+ * @see #getInt(Object, long)
+ * @see #putInt(Object, long, int)
+ */
+ public native int arrayBaseOffset(Class arrayClass);
+
+ /**
+ * Report the scale factor for addressing elements in the storage
+ * allocation of a given array class. However, arrays of "narrow" types
+ * will generally not work properly with accessors like {@link
+ * #getByte(Object, int)}, so the scale factor for such classes is reported
+ * as zero.
+ *
+ * @see #arrayBaseOffset
+ * @see #getInt(Object, long)
+ * @see #putInt(Object, long, int)
+ */
+ public native int arrayIndexScale(Class arrayClass);
+
+ /**
+ * Report the size in bytes of a native pointer, as stored via {@link
+ * #putAddress}. This value will be either 4 or 8. Note that the sizes of
+ * other primitive types (as stored in native memory blocks) is determined
+ * fully by their information content.
+ */
+ public native int addressSize();
+
+ /**
+ * Report the size in bytes of a native memory page (whatever that is).
+ * This value will always be a power of two.
+ */
+ public native int pageSize();
+
+
+ /// random trusted operations from JNI:
+
+ /**
+ * Tell the VM to define a class, without security checks. By default, the
+ * class loader and protection domain come from the caller's class.
+ */
+ public native Class defineClass(String name, byte[] b, int off, int len,
+ ClassLoader loader,
+ ProtectionDomain protectionDomain);
+
+ public native Class defineClass(String name, byte[] b, int off, int len);
+
+ /** Allocate an instance but do not run any constructor.
+ Initializes the class if it has not yet been. */
+ public native Object allocateInstance(Class cls)
+ throws InstantiationException;
+
+ /** Lock the object. It must get unlocked via {@link #monitorExit}. */
+ public native void monitorEnter(Object o);
+
+ /**
+ * Unlock the object. It must have been locked via {@link
+ * #monitorEnter}.
+ */
+ public native void monitorExit(Object o);
+
+ /**
+ * Tries to lock the object. Returns true or false to indicate
+ * whether the lock succeeded. If it did, the object must be
+ * unlocked via {@link #monitorExit}.
+ */
+ public native boolean tryMonitorEnter(Object o);
+
+ /** Throw the exception without telling the verifier. */
+ public native void throwException(Throwable ee);
+
+
+ /**
+ * Atomically update Java variable to <tt>x</tt> if it is currently
+ * holding <tt>expected</tt>.
+ * @return <tt>true</tt> if successful
+ */
+ public final native boolean compareAndSwapObject(Object o, long offset,
+ Object expected,
+ Object x);
+
+ /**
+ * Atomically update Java variable to <tt>x</tt> if it is currently
+ * holding <tt>expected</tt>.
+ * @return <tt>true</tt> if successful
+ */
+ public final native boolean compareAndSwapInt(Object o, long offset,
+ int expected,
+ int x);
+
+ /**
+ * Atomically update Java variable to <tt>x</tt> if it is currently
+ * holding <tt>expected</tt>.
+ * @return <tt>true</tt> if successful
+ */
+ public final native boolean compareAndSwapLong(Object o, long offset,
+ long expected,
+ long x);
+
+ /**
+ * Fetches a reference value from a given Java variable, with volatile
+ * load semantics. Otherwise identical to {@link #getObject(Object, long)}
+ */
+ public native Object getObjectVolatile(Object o, long offset);
+
+ /**
+ * Stores a reference value into a given Java variable, with
+ * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}
+ */
+ public native void putObjectVolatile(Object o, long offset, Object x);
+
+ /** Volatile version of {@link #getInt(Object, long)} */
+ public native int getIntVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putInt(Object, long, int)} */
+ public native void putIntVolatile(Object o, long offset, int x);
+
+ /** Volatile version of {@link #getBoolean(Object, long)} */
+ public native boolean getBooleanVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putBoolean(Object, long, boolean)} */
+ public native void putBooleanVolatile(Object o, long offset, boolean x);
+
+ /** Volatile version of {@link #getByte(Object, long)} */
+ public native byte getByteVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putByte(Object, long, byte)} */
+ public native void putByteVolatile(Object o, long offset, byte x);
+
+ /** Volatile version of {@link #getShort(Object, long)} */
+ public native short getShortVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putShort(Object, long, short)} */
+ public native void putShortVolatile(Object o, long offset, short x);
+
+ /** Volatile version of {@link #getChar(Object, long)} */
+ public native char getCharVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putChar(Object, long, char)} */
+ public native void putCharVolatile(Object o, long offset, char x);
+
+ /** Volatile version of {@link #getLong(Object, long)} */
+ public native long getLongVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putLong(Object, long, long)} */
+ public native void putLongVolatile(Object o, long offset, long x);
+
+ /** Volatile version of {@link #getFloat(Object, long)} */
+ public native float getFloatVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putFloat(Object, long, float)} */
+ public native void putFloatVolatile(Object o, long offset, float x);
+
+ /** Volatile version of {@link #getDouble(Object, long)} */
+ public native double getDoubleVolatile(Object o, long offset);
+
+ /** Volatile version of {@link #putDouble(Object, long, double)} */
+ public native void putDoubleVolatile(Object o, long offset, double x);
+
+ /**
+ * Version of {@link #putObjectVolatile(Object, long, Object)}
+ * that does not guarantee immediate visibility of the store to
+ * other threads. This method is generally only useful if the
+ * underlying field is a Java volatile (or if an array cell, one
+ * that is otherwise only accessed using volatile accesses).
+ */
+ public native void putOrderedObject(Object o, long offset, Object x);
+
+ /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
+ public native void putOrderedInt(Object o, long offset, int x);
+
+ /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
+ public native void putOrderedLong(Object o, long offset, long x);
+
+ /**
+ * Unblock the given thread blocked on <tt>park</tt>, or, if it is
+ * not blocked, cause the subsequent call to <tt>park</tt> not to
+ * block. Note: this operation is "unsafe" solely because the
+ * caller must somehow ensure that the thread has not been
+ * destroyed. Nothing special is usually required to ensure this
+ * when called from Java (in which there will ordinarily be a live
+ * reference to the thread) but this is not nearly-automatically
+ * so when calling from native code.
+ * @param thread the thread to unpark.
+ *
+ */
+ public native void unpark(Object thread);
+
+ /**
+ * Block current thread, returning when a balancing
+ * <tt>unpark</tt> occurs, or a balancing <tt>unpark</tt> has
+ * already occurred, or the thread is interrupted, or, if not
+ * absolute and time is not zero, the given time nanoseconds have
+ * elapsed, or if absolute, the given deadline in milliseconds
+ * since Epoch has passed, or spuriously (i.e., returning for no
+ * "reason"). Note: This operation is in the Unsafe class only
+ * because <tt>unpark</tt> is, so it would be strange to place it
+ * elsewhere.
+ */
+ public native void park(boolean isAbsolute, long time);
+
+ /**
+ * Gets the load average in the system run queue assigned
+ * to the available processors averaged over various periods of time.
+ * This method retrieves the given <tt>nelem</tt> samples and
+ * assigns to the elements of the given <tt>loadavg</tt> array.
+ * The system imposes a maximum of 3 samples, representing
+ * averages over the last 1, 5, and 15 minutes, respectively.
+ *
+ * @params loadavg an array of double of size nelems
+ * @params nelems the number of samples to be retrieved and
+ * must be 1 to 3.
+ *
+ * @return the number of samples actually retrieved; or -1
+ * if the load average is unobtainable.
+ */
+ public native int getLoadAverage(double[] loadavg, int nelems);
+}
--- /dev/null
+/*
+ * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.reflect;
+
+import java.lang.reflect.*;
+
+/** Provides reflective access to the constant pools of classes.
+ Currently this is needed to provide reflective access to annotations
+ but may be used by other internal subsystems in the future. */
+
+public class ConstantPool {
+ // Number of entries in this constant pool (= maximum valid constant pool index)
+ public int getSize() { return getSize0 (constantPoolOop); }
+ public Class getClassAt (int index) { return getClassAt0 (constantPoolOop, index); }
+ public Class getClassAtIfLoaded (int index) { return getClassAtIfLoaded0 (constantPoolOop, index); }
+ // Returns either a Method or Constructor.
+ // Static initializers are returned as Method objects.
+ public Member getMethodAt (int index) { return getMethodAt0 (constantPoolOop, index); }
+ public Member getMethodAtIfLoaded(int index) { return getMethodAtIfLoaded0(constantPoolOop, index); }
+ public Field getFieldAt (int index) { return getFieldAt0 (constantPoolOop, index); }
+ public Field getFieldAtIfLoaded (int index) { return getFieldAtIfLoaded0 (constantPoolOop, index); }
+ // Fetches the class name, member (field, method or interface
+ // method) name, and type descriptor as an array of three Strings
+ public String[] getMemberRefInfoAt (int index) { return getMemberRefInfoAt0 (constantPoolOop, index); }
+ public int getIntAt (int index) { return getIntAt0 (constantPoolOop, index); }
+ public long getLongAt (int index) { return getLongAt0 (constantPoolOop, index); }
+ public float getFloatAt (int index) { return getFloatAt0 (constantPoolOop, index); }
+ public double getDoubleAt (int index) { return getDoubleAt0 (constantPoolOop, index); }
+ public String getStringAt (int index) { return getStringAt0 (constantPoolOop, index); }
+ public String getUTF8At (int index) { return getUTF8At0 (constantPoolOop, index); }
+
+ //---------------------------------------------------------------------------
+ // Internals only below this point
+ //
+/* This hides this member from being visible through the reflection API in OpenJDK
+ * TODO: find out how to do this with GNU Classpath (if it's realy neccesary).
+
+ static {
+ Reflection.registerFieldsToFilter(ConstantPool.class, new String[] { "constantPoolOop" });
+ }
+*/
+ // HotSpot-internal constant pool object (set by the VM, name known to the VM)
+ private Object constantPoolOop;
+
+ private native int getSize0 (Object constantPoolOop);
+ private native Class getClassAt0 (Object constantPoolOop, int index);
+ private native Class getClassAtIfLoaded0 (Object constantPoolOop, int index);
+ private native Member getMethodAt0 (Object constantPoolOop, int index);
+ private native Member getMethodAtIfLoaded0(Object constantPoolOop, int index);
+ private native Field getFieldAt0 (Object constantPoolOop, int index);
+ private native Field getFieldAtIfLoaded0 (Object constantPoolOop, int index);
+ private native String[] getMemberRefInfoAt0 (Object constantPoolOop, int index);
+ private native int getIntAt0 (Object constantPoolOop, int index);
+ private native long getLongAt0 (Object constantPoolOop, int index);
+ private native float getFloatAt0 (Object constantPoolOop, int index);
+ private native double getDoubleAt0 (Object constantPoolOop, int index);
+ private native String getStringAt0 (Object constantPoolOop, int index);
+ private native String getUTF8At0 (Object constantPoolOop, int index);
+}
--- /dev/null
+/*
+ * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.reflect.annotation;
+
+import java.lang.annotation.*;
+import java.util.*;
+import java.nio.ByteBuffer;
+import java.nio.BufferUnderflowException;
+import java.lang.reflect.*;
+import sun.reflect.ConstantPool;
+
+import gnu.java.lang.reflect.FieldSignatureParser;
+
+
+/**
+ * Parser for Java programming language annotations. Translates
+ * annotation byte streams emitted by compiler into annotation objects.
+ *
+ * @author Josh Bloch
+ * @since 1.5
+ */
+public class AnnotationParser {
+ /**
+ * Parses the annotations described by the passed byte array,
+ * but returns Annotation[] so I don't have to do this in C.
+ *
+ * @author Mathias Panzenböck
+ *
+ * @param rawAnnotations are the unparsed annotations
+ * @param constPool is the constant pool of the declaring class
+ * @param container is the containing class
+ * @return the parsed annotations in an array
+ * @throws AnnotationFormatError if an annotation is found to be
+ * malformed.
+ */
+ public static Annotation[] parseAnnotationsIntoArray(
+ byte[] rawAnnotations,
+ ConstantPool constPool,
+ Class container) {
+ Map<Class, Annotation> annotations = parseAnnotations(rawAnnotations, constPool, container);
+ return annotations.values().toArray(EMPTY_ANNOTATIONS_ARRAY);
+ }
+
+ /**
+ * Parses parameter annotations.
+ *
+ * @author Mathias Panzenböck
+ *
+ * @param parameterAnnotations are the unparsed parameter annotations
+ * @param constPool is the constant pool of the declaring class
+ * @param container is the containing class
+ * @return the parsed parameter annotations in an array 2 dimensional array
+ * @throws AnnotationFormatError if an annotation is found to be
+ * malformed.
+ */
+ public static Annotation[][] parseParameterAnnotations(
+ byte[] parameterAnnotations,
+ ConstantPool constPool,
+ Class container,
+ int numParameters) {
+ if (parameterAnnotations == null)
+ return new Annotation[numParameters][0];
+
+ Annotation[][] result = parseParameterAnnotations(
+ parameterAnnotations, constPool, container);
+
+ if (result.length != numParameters)
+ throw new AnnotationFormatError(
+ "Parameter annotations don't match number of parameters (count was " +
+ result.length + " but should be " + numParameters + ").");
+ return result;
+ }
+
+ /**
+ * Parses the annotation default value of the supplied method.
+ * This method is basically copied from OpenJDKs
+ * java.lang.reflect.Method.getAnnotationDefault()
+ *
+ * @author Mathias Panzenböck
+ *
+ * @param method represents the method for which the annotation default value has to be parsed
+ * @param annotationDefault is the unparsed annotation default value
+ * @param constPool is the constant pool of the declaring class
+ * @return the parsed annotation default value (boxed, if it's a primitive type)
+ * @throws AnnotationFormatError if an annotation is found to be
+ * malformed.
+ */
+ public static Object parseAnnotationDefault(Method method,
+ byte[] annotationDefault,
+ ConstantPool constPool) {
+ if (annotationDefault == null)
+ return null;
+
+ Class memberType = AnnotationType.invocationHandlerReturnType(
+ method.getReturnType());
+
+ Object result = AnnotationParser.parseMemberValue(
+ memberType, ByteBuffer.wrap(annotationDefault),
+ constPool, method.getDeclaringClass());
+
+ if (result instanceof sun.reflect.annotation.ExceptionProxy)
+ throw new AnnotationFormatError("Invalid default: " + method);
+
+ return result;
+ }
+
+ /**
+ * Parses the annotations described by the specified byte array.
+ * resolving constant references in the specified constant pool.
+ * The array must contain an array of annotations as described
+ * in the RuntimeVisibleAnnotations_attribute:
+ *
+ * u2 num_annotations;
+ * annotation annotations[num_annotations];
+ *
+ * @throws AnnotationFormatError if an annotation is found to be
+ * malformed.
+ */
+ public static Map<Class, Annotation> parseAnnotations(
+ byte[] rawAnnotations,
+ ConstantPool constPool,
+ Class container) {
+ if (rawAnnotations == null)
+ return Collections.emptyMap();
+
+ try {
+ return parseAnnotations2(rawAnnotations, constPool, container);
+ } catch(BufferUnderflowException e) {
+ throw new AnnotationFormatError("Unexpected end of annotations.");
+ } catch(IllegalArgumentException e) {
+ // Type mismatch in constant pool
+ throw new AnnotationFormatError(e);
+ }
+ }
+
+ private static Map<Class, Annotation> parseAnnotations2(
+ byte[] rawAnnotations,
+ ConstantPool constPool,
+ Class container) {
+ Map<Class, Annotation> result = new LinkedHashMap<Class, Annotation>();
+ ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
+ int numAnnotations = buf.getShort() & 0xFFFF;
+ for (int i = 0; i < numAnnotations; i++) {
+ Annotation a = parseAnnotation(buf, constPool, container, false);
+ if (a != null) {
+ Class klass = a.annotationType();
+ AnnotationType type = AnnotationType.getInstance(klass);
+ if (type.retention() == RetentionPolicy.RUNTIME)
+ if (result.put(klass, a) != null)
+ throw new AnnotationFormatError(
+ "Duplicate annotation for class: "+klass+": " + a);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parses the parameter annotations described by the specified byte array.
+ * resolving constant references in the specified constant pool.
+ * The array must contain an array of annotations as described
+ * in the RuntimeVisibleParameterAnnotations_attribute:
+ *
+ * u1 num_parameters;
+ * {
+ * u2 num_annotations;
+ * annotation annotations[num_annotations];
+ * } parameter_annotations[num_parameters];
+ *
+ * Unlike parseAnnotations, rawAnnotations must not be null!
+ * A null value must be handled by the caller. This is so because
+ * we cannot determine the number of parameters if rawAnnotations
+ * is null. Also, the caller should check that the number
+ * of parameters indicated by the return value of this method
+ * matches the actual number of method parameters. A mismatch
+ * indicates that an AnnotationFormatError should be thrown.
+ *
+ * @throws AnnotationFormatError if an annotation is found to be
+ * malformed.
+ */
+ public static Annotation[][] parseParameterAnnotations(
+ byte[] rawAnnotations,
+ ConstantPool constPool,
+ Class container) {
+ try {
+ return parseParameterAnnotations2(rawAnnotations, constPool, container);
+ } catch(BufferUnderflowException e) {
+ throw new AnnotationFormatError(
+ "Unexpected end of parameter annotations.");
+ } catch(IllegalArgumentException e) {
+ // Type mismatch in constant pool
+ throw new AnnotationFormatError(e);
+ }
+ }
+
+ private static Annotation[][] parseParameterAnnotations2(
+ byte[] rawAnnotations,
+ ConstantPool constPool,
+ Class container) {
+ ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
+ int numParameters = buf.get() & 0xFF;
+ Annotation[][] result = new Annotation[numParameters][];
+
+ for (int i = 0; i < numParameters; i++) {
+ int numAnnotations = buf.getShort() & 0xFFFF;
+ List<Annotation> annotations =
+ new ArrayList<Annotation>(numAnnotations);
+ for (int j = 0; j < numAnnotations; j++) {
+ Annotation a = parseAnnotation(buf, constPool, container, false);
+ if (a != null) {
+ AnnotationType type = AnnotationType.getInstance(
+ a.annotationType());
+ if (type.retention() == RetentionPolicy.RUNTIME)
+ annotations.add(a);
+ }
+ }
+ result[i] = annotations.toArray(EMPTY_ANNOTATIONS_ARRAY);
+ }
+ return result;
+ }
+
+ private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
+ new Annotation[0];
+
+ /**
+ * Parses the annotation at the current position in the specified
+ * byte buffer, resolving constant references in the specified constant
+ * pool. The cursor of the byte buffer must point to an "annotation
+ * structure" as described in the RuntimeVisibleAnnotations_attribute:
+ *
+ * annotation {
+ * u2 type_index;
+ * u2 num_member_value_pairs;
+ * { u2 member_name_index;
+ * member_value value;
+ * } member_value_pairs[num_member_value_pairs];
+ * }
+ * }
+ *
+ * Returns the annotation, or null if the annotation's type cannot
+ * be found by the VM, or is not a valid annotation type.
+ *
+ * @param exceptionOnMissingAnnotationClass if true, throw
+ * TypeNotPresentException if a referenced annotation type is not
+ * available at runtime
+ */
+ private static Annotation parseAnnotation(ByteBuffer buf,
+ ConstantPool constPool,
+ Class container,
+ boolean exceptionOnMissingAnnotationClass) {
+ int typeIndex = buf.getShort() & 0xFFFF;
+ Class annotationClass = null;
+ String sig = "[unknown]";
+ try {
+ try {
+ sig = constPool.getUTF8At(typeIndex);
+ annotationClass = parseSig(sig, container);
+ } catch (IllegalArgumentException ex) {
+ // support obsolete early jsr175 format class files
+ annotationClass = constPool.getClassAt(typeIndex);
+ }
+ } catch (NoClassDefFoundError e) {
+ if (exceptionOnMissingAnnotationClass)
+ // note: at this point sig is "[unknown]" or VM-style
+ // name instead of a binary name
+ throw new TypeNotPresentException(sig, e);
+ skipAnnotation(buf, false);
+ return null;
+ }
+ catch (TypeNotPresentException e) {
+ if (exceptionOnMissingAnnotationClass)
+ throw e;
+ skipAnnotation(buf, false);
+ return null;
+ }
+ AnnotationType type = null;
+ try {
+ type = AnnotationType.getInstance(annotationClass);
+ } catch (IllegalArgumentException e) {
+ skipAnnotation(buf, false);
+ return null;
+ }
+
+ Map<String, Class> memberTypes = type.memberTypes();
+ Map<String, Object> memberValues =
+ new LinkedHashMap<String, Object>(type.memberDefaults());
+
+ int numMembers = buf.getShort() & 0xFFFF;
+ for (int i = 0; i < numMembers; i++) {
+ int memberNameIndex = buf.getShort() & 0xFFFF;
+ String memberName = constPool.getUTF8At(memberNameIndex);
+ Class memberType = memberTypes.get(memberName);
+
+ if (memberType == null) {
+ // Member is no longer present in annotation type; ignore it
+ skipMemberValue(buf);
+ } else {
+ Object value = parseMemberValue(memberType, buf, constPool, container);
+ if (value instanceof AnnotationTypeMismatchExceptionProxy)
+ ((AnnotationTypeMismatchExceptionProxy) value).
+ setMember(type.members().get(memberName));
+ memberValues.put(memberName, value);
+ }
+ }
+ return annotationForMap(annotationClass, memberValues);
+ }
+
+ /**
+ * Returns an annotation of the given type backed by the given
+ * member -> value map.
+ */
+ public static Annotation annotationForMap(
+ Class type, Map<String, Object> memberValues)
+ {
+ return (Annotation) Proxy.newProxyInstance(
+ type.getClassLoader(), new Class[] { type },
+ new AnnotationInvocationHandler(type, memberValues));
+ }
+
+ /**
+ * Parses the annotation member value at the current position in the
+ * specified byte buffer, resolving constant references in the specified
+ * constant pool. The cursor of the byte buffer must point to a
+ * "member_value structure" as described in the
+ * RuntimeVisibleAnnotations_attribute:
+ *
+ * member_value {
+ * u1 tag;
+ * union {
+ * u2 const_value_index;
+ * {
+ * u2 type_name_index;
+ * u2 const_name_index;
+ * } enum_const_value;
+ * u2 class_info_index;
+ * annotation annotation_value;
+ * {
+ * u2 num_values;
+ * member_value values[num_values];
+ * } array_value;
+ * } value;
+ * }
+ *
+ * The member must be of the indicated type. If it is not, this
+ * method returns an AnnotationTypeMismatchExceptionProxy.
+ */
+ public static Object parseMemberValue(Class memberType, ByteBuffer buf,
+ ConstantPool constPool,
+ Class container) {
+ Object result = null;
+ int tag = buf.get();
+ switch(tag) {
+ case 'e':
+ return parseEnumValue(memberType, buf, constPool, container);
+ case 'c':
+ result = parseClassValue(buf, constPool, container);
+ break;
+ case '@':
+ result = parseAnnotation(buf, constPool, container, true);
+ break;
+ case '[':
+ return parseArray(memberType, buf, constPool, container);
+ default:
+ result = parseConst(tag, buf, constPool);
+ }
+
+ if (!(result instanceof ExceptionProxy) &&
+ !memberType.isInstance(result))
+ result = new AnnotationTypeMismatchExceptionProxy(
+ result.getClass() + "[" + result + "]");
+ return result;
+ }
+
+ /**
+ * Parses the primitive or String annotation member value indicated by
+ * the specified tag byte at the current position in the specified byte
+ * buffer, resolving constant reference in the specified constant pool.
+ * The cursor of the byte buffer must point to an annotation member value
+ * of the type indicated by the specified tag, as described in the
+ * RuntimeVisibleAnnotations_attribute:
+ *
+ * u2 const_value_index;
+ */
+ private static Object parseConst(int tag,
+ ByteBuffer buf, ConstantPool constPool) {
+ int constIndex = buf.getShort() & 0xFFFF;
+ switch(tag) {
+ case 'B':
+ return Byte.valueOf((byte) constPool.getIntAt(constIndex));
+ case 'C':
+ return Character.valueOf((char) constPool.getIntAt(constIndex));
+ case 'D':
+ return Double.valueOf(constPool.getDoubleAt(constIndex));
+ case 'F':
+ return Float.valueOf(constPool.getFloatAt(constIndex));
+ case 'I':
+ return Integer.valueOf(constPool.getIntAt(constIndex));
+ case 'J':
+ return Long.valueOf(constPool.getLongAt(constIndex));
+ case 'S':
+ return Short.valueOf((short) constPool.getIntAt(constIndex));
+ case 'Z':
+ return Boolean.valueOf(constPool.getIntAt(constIndex) != 0);
+ case 's':
+ return constPool.getUTF8At(constIndex);
+ default:
+ throw new AnnotationFormatError(
+ "Invalid member-value tag in annotation: " + tag);
+ }
+ }
+
+ /**
+ * Parses the Class member value at the current position in the
+ * specified byte buffer, resolving constant references in the specified
+ * constant pool. The cursor of the byte buffer must point to a "class
+ * info index" as described in the RuntimeVisibleAnnotations_attribute:
+ *
+ * u2 class_info_index;
+ */
+ private static Object parseClassValue(ByteBuffer buf,
+ ConstantPool constPool,
+ Class container) {
+ int classIndex = buf.getShort() & 0xFFFF;
+ try {
+ try {
+ String sig = constPool.getUTF8At(classIndex);
+ return parseSig(sig, container);
+ } catch (IllegalArgumentException ex) {
+ // support obsolete early jsr175 format class files
+ return constPool.getClassAt(classIndex);
+ }
+ } catch (NoClassDefFoundError e) {
+ return new TypeNotPresentExceptionProxy("[unknown]", e);
+ }
+ catch (TypeNotPresentException e) {
+ return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
+ }
+ }
+
+ /**
+ * Parses a return type signature and returns the according Class object.
+ */
+ private static Class<?> parseSig(String sig, Class container) {
+ if (sig.equals("V")) {
+ return void.class;
+ }
+ else {
+ return toClass(new FieldSignatureParser(container, sig).getFieldType());
+ }
+ }
+
+ static Class<?> toClass(Type o) {
+ if (o instanceof GenericArrayType)
+ return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
+ 0)
+ .getClass();
+ return (Class<?>)o;
+ }
+
+ /**
+ * Parses the enum constant member value at the current position in the
+ * specified byte buffer, resolving constant references in the specified
+ * constant pool. The cursor of the byte buffer must point to a
+ * "enum_const_value structure" as described in the
+ * RuntimeVisibleAnnotations_attribute:
+ *
+ * {
+ * u2 type_name_index;
+ * u2 const_name_index;
+ * } enum_const_value;
+ */
+ private static Object parseEnumValue(Class enumType, ByteBuffer buf,
+ ConstantPool constPool,
+ Class container) {
+ int typeNameIndex = buf.getShort() & 0xFFFF;
+ String typeName = constPool.getUTF8At(typeNameIndex);
+ int constNameIndex = buf.getShort() & 0xFFFF;
+ String constName = constPool.getUTF8At(constNameIndex);
+
+ if (!typeName.endsWith(";")) {
+ // support now-obsolete early jsr175-format class files.
+ if (!enumType.getName().equals(typeName))
+ return new AnnotationTypeMismatchExceptionProxy(
+ typeName + "." + constName);
+ } else if (enumType != parseSig(typeName, container)) {
+ return new AnnotationTypeMismatchExceptionProxy(
+ typeName + "." + constName);
+ }
+
+ try {
+ return Enum.valueOf(enumType, constName);
+ } catch(IllegalArgumentException e) {
+ return new EnumConstantNotPresentExceptionProxy(
+ (Class<? extends Enum>)enumType, constName);
+ }
+ }
+
+ /**
+ * Parses the array value at the current position in the specified byte
+ * buffer, resolving constant references in the specified constant pool.
+ * The cursor of the byte buffer must point to an array value struct
+ * as specified in the RuntimeVisibleAnnotations_attribute:
+ *
+ * {
+ * u2 num_values;
+ * member_value values[num_values];
+ * } array_value;
+ *
+ * If the array values do not match arrayType, an
+ * AnnotationTypeMismatchExceptionProxy will be returned.
+ */
+ private static Object parseArray(Class arrayType,
+ ByteBuffer buf,
+ ConstantPool constPool,
+ Class container) {
+ int length = buf.getShort() & 0xFFFF; // Number of array components
+ Class componentType = arrayType.getComponentType();
+
+ if (componentType == byte.class) {
+ return parseByteArray(length, buf, constPool);
+ } else if (componentType == char.class) {
+ return parseCharArray(length, buf, constPool);
+ } else if (componentType == double.class) {
+ return parseDoubleArray(length, buf, constPool);
+ } else if (componentType == float.class) {
+ return parseFloatArray(length, buf, constPool);
+ } else if (componentType == int.class) {
+ return parseIntArray(length, buf, constPool);
+ } else if (componentType == long.class) {
+ return parseLongArray(length, buf, constPool);
+ } else if (componentType == short.class) {
+ return parseShortArray(length, buf, constPool);
+ } else if (componentType == boolean.class) {
+ return parseBooleanArray(length, buf, constPool);
+ } else if (componentType == String.class) {
+ return parseStringArray(length, buf, constPool);
+ } else if (componentType == Class.class) {
+ return parseClassArray(length, buf, constPool, container);
+ } else if (componentType.isEnum()) {
+ return parseEnumArray(length, componentType, buf,
+ constPool, container);
+ } else {
+ assert componentType.isAnnotation();
+ return parseAnnotationArray(length, componentType, buf,
+ constPool, container);
+ }
+ }
+
+ private static Object parseByteArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ byte[] result = new byte[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'B') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = (byte) constPool.getIntAt(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseCharArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ char[] result = new char[length];
+ boolean typeMismatch = false;
+ byte tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'C') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = (char) constPool.getIntAt(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseDoubleArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ double[] result = new double[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'D') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = constPool.getDoubleAt(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseFloatArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ float[] result = new float[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'F') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = constPool.getFloatAt(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseIntArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ int[] result = new int[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'I') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = constPool.getIntAt(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseLongArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ long[] result = new long[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'J') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = constPool.getLongAt(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseShortArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ short[] result = new short[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'S') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = (short) constPool.getIntAt(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseBooleanArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ boolean[] result = new boolean[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'Z') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = (constPool.getIntAt(index) != 0);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseStringArray(int length,
+ ByteBuffer buf, ConstantPool constPool) {
+ String[] result = new String[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 's') {
+ int index = buf.getShort() & 0xFFFF;
+ result[i] = constPool.getUTF8At(index);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseClassArray(int length,
+ ByteBuffer buf,
+ ConstantPool constPool,
+ Class container) {
+ Object[] result = new Class[length];
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'c') {
+ result[i] = parseClassValue(buf, constPool, container);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseEnumArray(int length, Class enumType,
+ ByteBuffer buf,
+ ConstantPool constPool,
+ Class container) {
+ Object[] result = (Object[]) Array.newInstance(enumType, length);
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == 'e') {
+ result[i] = parseEnumValue(enumType, buf, constPool, container);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ private static Object parseAnnotationArray(int length,
+ Class annotationType,
+ ByteBuffer buf,
+ ConstantPool constPool,
+ Class container) {
+ Object[] result = (Object[]) Array.newInstance(annotationType, length);
+ boolean typeMismatch = false;
+ int tag = 0;
+
+ for (int i = 0; i < length; i++) {
+ tag = buf.get();
+ if (tag == '@') {
+ result[i] = parseAnnotation(buf, constPool, container, true);
+ } else {
+ skipMemberValue(tag, buf);
+ typeMismatch = true;
+ }
+ }
+ return typeMismatch ? exceptionProxy(tag) : result;
+ }
+
+ /**
+ * Return an appropriate exception proxy for a mismatching array
+ * annotation where the erroneous array has the specified tag.
+ */
+ private static ExceptionProxy exceptionProxy(int tag) {
+ return new AnnotationTypeMismatchExceptionProxy(
+ "Array with component tag: " + tag);
+ }
+
+ /**
+ * Skips the annotation at the current position in the specified
+ * byte buffer. The cursor of the byte buffer must point to
+ * an "annotation structure" OR two bytes into an annotation
+ * structure (i.e., after the type index).
+ *
+ * @parameter complete true if the byte buffer points to the beginning
+ * of an annotation structure (rather than two bytes in).
+ */
+ private static void skipAnnotation(ByteBuffer buf, boolean complete) {
+ if (complete)
+ buf.getShort(); // Skip type index
+ int numMembers = buf.getShort() & 0xFFFF;
+ for (int i = 0; i < numMembers; i++) {
+ buf.getShort(); // Skip memberNameIndex
+ skipMemberValue(buf);
+ }
+ }
+
+ /**
+ * Skips the annotation member value at the current position in the
+ * specified byte buffer. The cursor of the byte buffer must point to a
+ * "member_value structure."
+ */
+ private static void skipMemberValue(ByteBuffer buf) {
+ int tag = buf.get();
+ skipMemberValue(tag, buf);
+ }
+
+ /**
+ * Skips the annotation member value at the current position in the
+ * specified byte buffer. The cursor of the byte buffer must point
+ * immediately after the tag in a "member_value structure."
+ */
+ private static void skipMemberValue(int tag, ByteBuffer buf) {
+ switch(tag) {
+ case 'e': // Enum value
+ buf.getInt(); // (Two shorts, actually.)
+ break;
+ case '@':
+ skipAnnotation(buf, true);
+ break;
+ case '[':
+ skipArray(buf);
+ break;
+ default:
+ // Class, primitive, or String
+ buf.getShort();
+ }
+ }
+
+ /**
+ * Skips the array value at the current position in the specified byte
+ * buffer. The cursor of the byte buffer must point to an array value
+ * struct.
+ */
+ private static void skipArray(ByteBuffer buf) {
+ int length = buf.getShort() & 0xFFFF;
+ for (int i = 0; i < length; i++)
+ skipMemberValue(buf);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.reflect.annotation;
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Represents an annotation type at run time. Used to type-check annotations
+ * and apply member defaults.
+ *
+ * @author Josh Bloch
+ * @since 1.5
+ */
+public class AnnotationType {
+ /**
+ * Annotation class -> AnnotationType mapping. This emulates
+ * sun.misc.SharedSecrets.getJavaLangAccess().getAnnotationType() and
+ * sun.misc.SharedSecrets.getJavaLangAccess().setAnnotationType() so
+ * this class can be used with gnu classpath.
+ *
+ * @author Mathias Panzenböck
+ */
+ private static Map<Class, AnnotationType> annotationTypes =
+ new HashMap<Class, AnnotationType>();
+
+ /**
+ * Member name -> type mapping. Note that primitive types
+ * are represented by the class objects for the corresponding wrapper
+ * types. This matches the return value that must be used for a
+ * dynamic proxy, allowing for a simple isInstance test.
+ */
+ private final Map<String, Class> memberTypes = new HashMap<String,Class>();
+
+ /**
+ * Member name -> default value mapping.
+ */
+ private final Map<String, Object> memberDefaults =
+ new HashMap<String, Object>();
+
+ /**
+ * Member name -> Method object mapping. This (and its assoicated
+ * accessor) are used only to generate AnnotationTypeMismatchExceptions.
+ */
+ private final Map<String, Method> members = new HashMap<String, Method>();
+
+ /**
+ * The retention policy for this annotation type.
+ */
+ private RetentionPolicy retention = RetentionPolicy.RUNTIME;;
+
+ /**
+ * Whether this annotation type is inherited.
+ */
+ private boolean inherited = false;
+
+ /**
+ * Returns an AnnotationType instance for the specified annotation type.
+ *
+ * @throw IllegalArgumentException if the specified class object for
+ * does not represent a valid annotation type
+ */
+ public static synchronized AnnotationType getInstance(
+ Class annotationClass)
+ {
+ /*
+ AnnotationType result = sun.misc.SharedSecrets.getJavaLangAccess().
+ getAnnotationType(annotationClass);
+ */
+ // emulating OpenJDKs SharedSecrets in GNU Classpath:
+ AnnotationType result = annotationTypes.get(annotationClass);
+ if (result == null)
+ result = new AnnotationType((Class<?>) annotationClass);
+
+ return result;
+ }
+
+ /**
+ * Sole constructor.
+ *
+ * @param annotationClass the class object for the annotation type
+ * @throw IllegalArgumentException if the specified class object for
+ * does not represent a valid annotation type
+ */
+ private AnnotationType(final Class<?> annotationClass) {
+ if (!annotationClass.isAnnotation())
+ throw new IllegalArgumentException("Not an annotation type");
+
+ Method[] methods =
+ AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+ public Method[] run() {
+ // Initialize memberTypes and defaultValues
+ return annotationClass.getDeclaredMethods();
+ }
+ });
+
+
+ for (Method method : methods) {
+ if (method.getParameterTypes().length != 0)
+ throw new IllegalArgumentException(method + " has params");
+ String name = method.getName();
+ Class type = method.getReturnType();
+ memberTypes.put(name, invocationHandlerReturnType(type));
+ members.put(name, method);
+
+ Object defaultValue = method.getDefaultValue();
+ if (defaultValue != null)
+ memberDefaults.put(name, defaultValue);
+
+ members.put(name, method);
+ }
+
+ /*
+ sun.misc.SharedSecrets.getJavaLangAccess().
+ setAnnotationType(annotationClass, this);
+ */
+ // emulating OpenJDKs SharedSecrets in GNU Classpath:
+ annotationTypes.put(annotationClass, this);
+
+ // Initialize retention, & inherited fields. Special treatment
+ // of the corresponding annotation types breaks infinite recursion.
+ if (annotationClass != Retention.class &&
+ annotationClass != Inherited.class) {
+ Retention ret = annotationClass.getAnnotation(Retention.class);
+ retention = (ret == null ? RetentionPolicy.CLASS : ret.value());
+ inherited = annotationClass.isAnnotationPresent(Inherited.class);
+ }
+ }
+
+ /**
+ * Returns the type that must be returned by the invocation handler
+ * of a dynamic proxy in order to have the dynamic proxy return
+ * the specified type (which is assumed to be a legal member type
+ * for an annotation).
+ */
+ public static Class invocationHandlerReturnType(Class type) {
+ // Translate primitives to wrappers
+ if (type == byte.class)
+ return Byte.class;
+ if (type == char.class)
+ return Character.class;
+ if (type == double.class)
+ return Double.class;
+ if (type == float.class)
+ return Float.class;
+ if (type == int.class)
+ return Integer.class;
+ if (type == long.class)
+ return Long.class;
+ if (type == short.class)
+ return Short.class;
+ if (type == boolean.class)
+ return Boolean.class;
+
+ // Otherwise, just return declared type
+ return type;
+ }
+
+ /**
+ * Returns member types for this annotation type
+ * (member name -> type mapping).
+ */
+ public Map<String, Class> memberTypes() {
+ return memberTypes;
+ }
+
+ /**
+ * Returns members of this annotation type
+ * (member name -> associated Method object mapping).
+ */
+ public Map<String, Method> members() {
+ return members;
+ }
+
+ /**
+ * Returns the default values for this annotation type
+ * (Member name -> default value mapping).
+ */
+ public Map<String, Object> memberDefaults() {
+ return memberDefaults;
+ }
+
+ /**
+ * Returns the retention policy for this annotation type.
+ */
+ public RetentionPolicy retention() {
+ return retention;
+ }
+
+ /**
+ * Returns true if this this annotation type is inherited.
+ */
+ public boolean isInherited() {
+ return inherited;
+ }
+
+ /**
+ * For debugging.
+ */
+ public String toString() {
+ StringBuffer s = new StringBuffer("Annotation Type:" + "\n");
+ s.append(" Member types: " + memberTypes + "\n");
+ s.append(" Member defaults: " + memberDefaults + "\n");
+ s.append(" Retention policy: " + retention + "\n");
+ s.append(" Inherited: " + inherited);
+ return s.toString();
+ }
+}
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.reflect.annotation;
+import java.lang.annotation.*;
+import java.lang.reflect.Method;
+
+/**
+ * ExceptionProxy for AnnotationTypeMismatchException.
+ *
+ * @author Josh Bloch
+ * @since 1.5
+ */
+class AnnotationTypeMismatchExceptionProxy extends ExceptionProxy {
+ private Method member;
+ private String foundType;
+
+ /**
+ * It turns out to be convenient to construct these proxies in
+ * two stages. Since this is a private implementation class, we
+ * permit ourselves this liberty even though it's normally a very
+ * bad idea.
+ */
+ AnnotationTypeMismatchExceptionProxy(String foundType) {
+ this.foundType = foundType;
+ }
+
+ AnnotationTypeMismatchExceptionProxy setMember(Method member) {
+ this.member = member;
+ return this;
+ }
+
+ protected RuntimeException generateException() {
+ return new AnnotationTypeMismatchException(member, foundType);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.reflect.annotation;
+import java.lang.annotation.*;
+
+/**
+ * ExceptionProxy for EnumConstantNotPresentException.
+ *
+ * @author Josh Bloch
+ * @since 1.5
+ */
+public class EnumConstantNotPresentExceptionProxy extends ExceptionProxy {
+ Class<? extends Enum> enumType;
+ String constName;
+
+ public EnumConstantNotPresentExceptionProxy(Class<? extends Enum> enumType,
+ String constName) {
+ this.enumType = enumType;
+ this.constName = constName;
+ }
+
+ protected RuntimeException generateException() {
+ return new EnumConstantNotPresentException(enumType, constName);
+ }
+}
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.reflect.annotation;
+
+/**
+ * An instance of this class is stored in an AnnotationInvocationHandler's
+ * "memberValues" map in lieu of a value for an annotation member that
+ * cannot be returned due to some exceptional condition (typically some
+ * form of illegal evolution of the annotation class). The ExceptionProxy
+ * instance describes the exception that the dynamic proxy should throw if
+ * it is queried for this member.
+ *
+ * @author Josh Bloch
+ * @since 1.5
+ */
+public abstract class ExceptionProxy implements java.io.Serializable {
+ protected abstract RuntimeException generateException();
+}
--- /dev/null
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.reflect.annotation;
+import java.lang.annotation.*;
+
+/**
+ * ExceptionProxy for TypeNotPresentException.
+ *
+ * @author Josh Bloch
+ * @since 1.5
+ */
+public class TypeNotPresentExceptionProxy extends ExceptionProxy {
+ String typeName;
+ Throwable cause;
+
+ public TypeNotPresentExceptionProxy(String typeName, Throwable cause) {
+ this.typeName = typeName;
+ this.cause = cause;
+ }
+
+ protected RuntimeException generateException() {
+ return new TypeNotPresentException(typeName, cause);
+ }
+}
+++ /dev/null
-## src/lib/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
-##
-## This file is part of CACAO.
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License as
-## published by the Free Software Foundation; either version 2, or (at
-## your option) any later version.
-##
-## This program is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-## 02110-1301, USA.
-
-
-EXTRA_DIST = \
- $(VM_JAVA_FILES)
-
-CLEANFILES = vm.zip
-
-if WITH_CLASSPATH_GNU
-VM_JAVA_FILES = \
- $(top_srcdir)/src/lib/gnu/gnu/classpath/VMStackWalker.java \
- $(top_srcdir)/src/lib/gnu/gnu/classpath/VMSystemProperties.java \
- $(top_srcdir)/src/lib/gnu/gnu/java/lang/management/VMMemoryMXBeanImpl.java \
- $(top_srcdir)/src/lib/gnu/gnu/java/lang/management/VMRuntimeMXBeanImpl.java \
- $(top_srcdir)/src/lib/gnu/java/lang/VMClassLoader.java \
- $(top_srcdir)/src/lib/gnu/java/lang/VMString.java \
- $(top_srcdir)/src/lib/gnu/java/lang/VMThread.java \
- $(top_srcdir)/src/lib/gnu/java/lang/VMThrowable.java \
- $(top_srcdir)/src/lib/gnu/java/lang/reflect/Constructor.java \
- $(top_srcdir)/src/lib/gnu/java/lang/reflect/Field.java \
- $(top_srcdir)/src/lib/gnu/java/lang/reflect/Method.java \
- $(top_srcdir)/src/lib/gnu/java/security/VMAccessController.java \
- $(top_srcdir)/src/lib/gnu/sun/misc/Unsafe.java
-
-VM_CLASS_FILES = \
- classes/gnu/classpath/VMStackWalker.class \
- classes/gnu/classpath/VMSystemProperties.class \
- classes/gnu/java/lang/management/VMMemoryMXBeanImpl.class \
- classes/gnu/java/lang/management/VMRuntimeMXBeanImpl.class \
- classes/java/lang/VMClassLoader.class \
- classes/java/lang/VMString.class \
- classes/java/lang/VMThread.class \
- classes/java/lang/VMThrowable.class \
- classes/java/lang/reflect/Constructor.class \
- classes/java/lang/reflect/Field.class \
- classes/java/lang/reflect/Method.class \
- classes/java/security/VMAccessController.class \
- classes/sun/misc/Unsafe.class
-
-if ENABLE_ANNOTATIONS
-VM_JAVA_FILES += \
- $(top_srcdir)/src/lib/gnu/sun/reflect/ConstantPool.java \
- $(top_srcdir)/src/lib/gnu/sun/reflect/annotation/ExceptionProxy.java \
- $(top_srcdir)/src/lib/gnu/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.java \
- $(top_srcdir)/src/lib/gnu/sun/reflect/annotation/TypeNotPresentExceptionProxy.java \
- $(top_srcdir)/src/lib/gnu/sun/reflect/annotation/AnnotationTypeMismatchExceptionProxy.java \
- $(top_srcdir)/src/lib/gnu/sun/reflect/annotation/AnnotationType.java \
- $(top_srcdir)/src/lib/gnu/sun/reflect/annotation/AnnotationParser.java
-
-VM_CLASS_FILES += \
- classes/sun/reflect/ConstantPool.class \
- classes/sun/reflect/annotation/ExceptionProxy.class \
- classes/sun/reflect/annotation/EnumConstantNotPresentExceptionProxy.class \
- classes/sun/reflect/annotation/TypeNotPresentExceptionProxy.class \
- classes/sun/reflect/annotation/AnnotationTypeMismatchExceptionProxy.class \
- classes/sun/reflect/annotation/AnnotationType.class \
- classes/sun/reflect/annotation/AnnotationParser.class
-endif
-
-if ENABLE_ZLIB
-pkgdata_DATA = vm.zip
-else
-pkgdata_DATA = nozip
-endif
-endif
-
-if WITH_CLASSPATH_CLDC1_1
-VM_JAVA_FILES = \
- $(top_srcdir)/src/lib/cldc1.1/com/sun/cldchi/jvm/FileDescriptor.java
-
-VM_CLASS_FILES = \
- classes/com/sun/cldchi/jvm/FileDescriptor.class
-
-if ENABLE_ZLIB
-pkgdata_DATA = vm.zip
-else
-pkgdata_DATA = nozip
-endif
-endif
-
-if ENABLE_ZLIB
-VM_ZIP = ../vm.zip
-
-vm.zip: $(VM_JAVA_FILES)
- $(mkdir_p) classes
- $(JAVAC) -source 1.5 -target 1.5 -d classes $(VM_JAVA_FILES)
- @if test "$(JAR)" = "zip" -o "$(JAR)" = "zip.exe"; then \
- cd classes && $(JAR) -r -D $(VM_ZIP) .; \
- else \
- cd classes && $(JAR) cvf $(VM_ZIP) .; \
- fi
-else
-nozip: $(VM_JAVA_FILES)
- $(mkdir_p) classes
- $(JAVAC) -source 1.5 -target 1.5 -d classes $(VM_JAVA_FILES)
-endif
-
-clean-local:
- -rm -rf classes
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
+++ /dev/null
-/* src/lib/com/sun/cldchi/jvm/FileDescriptor.java
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-package com.sun.cldchi.jvm;
-
-class FileDescriptor {
- long pointer;
- int position;
- int length;
-}
+++ /dev/null
-/* VMStackWalker.java -- Reference implementation of VM hooks for stack access
- Copyright (C) 2005 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package gnu.classpath;
-
-/**
- * This class provides access to the classes on the Java stack
- * for reflection and security purposes.
- *
- * <p>
- * This class is only available to privileged code (i.e., code loaded
- * by the bootstrap loader).
- *
- * @author John Keiser
- * @author Eric Blake <ebb9@email.byu.edu>
- * @author Archie Cobbs
- */
-public final class VMStackWalker
-{
- /**
- * Get a list of all the classes currently executing methods on the
- * Java stack. <code>getClassContext()[0]</code> is the class associated
- * with the currently executing method, i.e., the method that called
- * <code>VMStackWalker.getClassContext()</code> (possibly through
- * reflection). So you may need to pop off these stack frames from
- * the top of the stack:
- * <ul>
- * <li><code>VMStackWalker.getClassContext()</code>
- * <li><code>Method.invoke()</code>
- * </ul>
- *
- * @return an array of the declaring classes of each stack frame
- */
- public static native Class[] getClassContext();
-
- /**
- * Get the class associated with the method invoking the method
- * invoking this method, or <code>null</code> if the stack is not
- * that deep (e.g., invoked via JNI invocation API). This method
- * is an optimization for the expression <code>getClassContext()[1]</code>
- * and should return the same result.
- *
- * <p>
- * VM implementers are encouraged to provide a more efficient
- * version of this method.
- */
-// public static Class getCallingClass()
-// {
-// Class[] ctx = getClassContext();
-// if (ctx.length < 3)
-// return null;
-// return ctx[2];
-// }
- public static native Class getCallingClass();
-
- /**
- * Get the class loader associated with the Class returned by
- * <code>getCallingClass()</code>, or <code>null</code> if no such class
- * exists or it is the boot loader. This method is an optimization for the
- * expression <code>VMStackWalker.getClassLoader(getClassContext()[1])</code>
- * and should return the same result.
- *
- * <p>
- * VM implementers are encouraged to provide a more efficient
- * version of this method.
- */
-// public static ClassLoader getCallingClassLoader()
-// {
-// Class[] ctx = getClassContext();
-// if (ctx.length < 3)
-// return null;
-// return getClassLoader(ctx[2]);
-// }
- public static native ClassLoader getCallingClassLoader();
-
-
- /**
- * Retrieve the class's ClassLoader, or <code>null</code> if loaded
- * by the bootstrap loader. I.e., this should return the same thing
- * as {@link java.lang.VMClass#getClassLoader}. This duplicate version
- * is here to work around access permissions.
- */
-// public static native ClassLoader getClassLoader(Class cl);
-
- /**
- * Walk up the stack and return the first non-null class loader.
- * If there aren't any non-null class loaders on the stack, return null.
- */
-// public static ClassLoader firstNonNullClassLoader()
-// {
-// Class[] stack = getClassContext();
-// for (int i = 0; i < stack.length; i++)
-// {
-// ClassLoader loader = getClassLoader(stack[i]);
-// if (loader != null)
-// return loader;
-// }
-// return null;
-// }
- public static native ClassLoader firstNonNullClassLoader();
-}
+++ /dev/null
-/* VMSystemProperties.java -- Allow the VM to set System properties.
- Copyright (C) 2004 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package gnu.classpath;
-
-import java.util.Properties;
-
-class VMSystemProperties
-{
- /**
- * Get the system properties. This is done here, instead of in System,
- * because of the bootstrap sequence. Note that the native code should
- * not try to use the Java I/O classes yet, as they rely on the properties
- * already existing. The only safe method to use to insert these default
- * system properties is {@link Properties#setProperty(String, String)}.
- *
- * <p>These properties MUST include:
- * <dl>
- * <dt>java.version <dd>Java version number
- * <dt>java.vendor <dd>Java vendor specific string
- * <dt>java.vendor.url <dd>Java vendor URL
- * <dt>java.home <dd>Java installation directory
- * <dt>java.vm.specification.version <dd>VM Spec version
- * <dt>java.vm.specification.vendor <dd>VM Spec vendor
- * <dt>java.vm.specification.name <dd>VM Spec name
- * <dt>java.vm.version <dd>VM implementation version
- * <dt>java.vm.vendor <dd>VM implementation vendor
- * <dt>java.vm.name <dd>VM implementation name
- * <dt>java.specification.version <dd>Java Runtime Environment version
- * <dt>java.specification.vendor <dd>Java Runtime Environment vendor
- * <dt>java.specification.name <dd>Java Runtime Environment name
- * <dt>java.class.version <dd>Java class version number
- * <dt>java.class.path <dd>Java classpath
- * <dt>java.library.path <dd>Path for finding Java libraries
- * <dt>java.io.tmpdir <dd>Default temp file path
- * <dt>java.compiler <dd>Name of JIT to use
- * <dt>java.ext.dirs <dd>Java extension path
- * <dt>os.name <dd>Operating System Name
- * <dt>os.arch <dd>Operating System Architecture
- * <dt>os.version <dd>Operating System Version
- * <dt>file.separator <dd>File separator ("/" on Unix)
- * <dt>path.separator <dd>Path separator (":" on Unix)
- * <dt>line.separator <dd>Line separator ("\n" on Unix)
- * <dt>user.name <dd>User account name
- * <dt>user.home <dd>User home directory
- * <dt>user.dir <dd>User's current working directory
- * <dt>gnu.cpu.endian <dd>"big" or "little"
- * </dl>
- *
- * @param properties the Properties object to insert the system properties into
- */
- static native void preInit(Properties properties);
-
- /**
- * Here you get a chance to overwrite some of the properties set by
- * the common SystemProperties code. For example, it might be
- * a good idea to process the properties specified on the command
- * line here.
- */
-// static void postInit(Properties properties)
-// {
-// }
- static native void postInit(Properties properties);
-}
+++ /dev/null
-/* VMMemoryMXBeanImpl.java - VM impl. of a memory bean
- Copyright (C) 2006 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package gnu.java.lang.management;
-
-import java.lang.management.MemoryUsage;
-
-/**
- * Provides access to information about the memory
- * management of the current invocation of the virtual
- * machine. Instances of this bean are obtained by calling
- * {@link ManagementFactory#getMemoryMXBean()}.
- *
- * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
- * @since 1.5
- */
-final class VMMemoryMXBeanImpl
-{
-
- /**
- * Returns an instance of {@link java.lang.management.MemoryUsage}
- * with appropriate initial, used, committed and maximum values
- * for the heap. By default, this uses the methods of
- * {@link java.lang.Runtime} to provide some of the values.
- *
- * @return an {@link java.lang.management.MemoryUsage} instance
- * for the heap.
- */
-// static MemoryUsage getHeapMemoryUsage()
-// {
-// Runtime runtime = Runtime.getRuntime();
-// long totalMem = runtime.totalMemory();
-// return new MemoryUsage(-1, totalMem - runtime.freeMemory(),
-// totalMem, runtime.maxMemory());
-// }
- static native MemoryUsage getHeapMemoryUsage();
-
- /**
- * Returns an instance of {@link java.lang.management.MemoryUsage}
- * with appropriate initial, used, committed and maximum values
- * for non-heap memory.
- *
- * @return an {@link java.lang.management.MemoryUsage} instance
- * for non-heap memory.
- */
- static native MemoryUsage getNonHeapMemoryUsage();
-
- /**
- * Returns the number of objects ready to be garbage collected.
- *
- * @return the number of finalizable objects.
- */
- static native int getObjectPendingFinalizationCount();
-
- /**
- * Returns true if the virtual machine will emit additional
- * information when memory is allocated and deallocated. The
- * format of the output is left up to the virtual machine.
- *
- * @return true if verbose class loading output is on.
- */
- static native boolean isVerbose();
-
- /**
- * Turns on or off the emission of additional information
- * when memory is allocated and deallocated. The format of the
- * output is left up to the virtual machine. This method
- * may be called by multiple threads concurrently, but there
- * is only one global setting of verbosity that is affected.
- *
- * @param verbose the new setting for verbose class loading
- * output.
- */
- static native void setVerbose(boolean verbose);
-
-}
+++ /dev/null
-/* VMRuntimeMXBeanImpl.java - VM implementation of an runtime bean
- Copyright (C) 2006 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package gnu.java.lang.management;
-
-import gnu.classpath.SystemProperties;
-
-/**
- * Provides access to information about the virtual machine.
- *
- * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
- * @since 1.5
- */
-final class VMRuntimeMXBeanImpl
-{
-
- /**
- * Returns the command-line arguments supplied
- * to the virtual machine, excluding those supplied
- * to <code>main()</code>.
- *
- * @return the command-line arguments.
- */
- static native String[] getInputArguments();
-
- /**
- * Returns a developer-chosen name for the virtual
- * machine, which may differ over different running
- * instances of the same virtual machine binary.
- * For example, this may include the particular
- * process identifier used by this instance or
- * the host name of the machine on which it is
- * running. The intention is that this name refers
- * to the precise entity that the other data supplied
- * by the bean refers to, rather than the VM in general.
- *
- * @return the custom name of the VM.
- */
- static String getName()
- {
- return SystemProperties.getProperty("java.vm.name") + " " +
- SystemProperties.getProperty("java.vm.version");
- }
-
- /**
- * The time in milliseconds at which the virtual
- * machine was started. This method is only executed
- * once (for efficency), as the value is not expected
- * to change.
- *
- * @return the VM start time.
- */
- static native long getStartTime();
-
-}
+++ /dev/null
-/* VMClassLoader.java -- Reference implementation of native interface
- required by ClassLoader
- Copyright (C) 1998, 2001, 2002, 2004, 2005, 2006 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.lang;
-
-import gnu.classpath.Configuration;
-import gnu.classpath.SystemProperties;
-import gnu.java.lang.InstrumentationImpl;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.lang.instrument.Instrumentation;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.zip.ZipFile;
-import java.util.Collections;
-import java.lang.Boolean;
-
-/**
- * java.lang.VMClassLoader is a package-private helper for VMs to implement
- * on behalf of java.lang.ClassLoader.
- *
- * @author John Keiser
- * @author Mark Wielaard (mark@klomp.org)
- * @author Eric Blake (ebb9@email.byu.edu)
- */
-final class VMClassLoader
-{
-
-
- /** packages loaded by the bootstrap class loader */
- static final HashMap definedPackages = new HashMap();
-
- /** jars from property java.boot.class.path */
- static final HashMap bootjars = new HashMap();
-
-
- /**
- * Converts the array string of native package names to
- * Packages. The packages are then put into the
- * definedPackages hashMap
- */
- static
- {
- String[] packages = getBootPackages();
-
- if( packages != null)
- {
- String specName =
- SystemProperties.getProperty("java.specification.name");
- String vendor =
- SystemProperties.getProperty("java.specification.vendor");
- String version =
- SystemProperties.getProperty("java.specification.version");
-
- Package p;
-
- for(int i = 0; i < packages.length; i++)
- {
- p = new Package(packages[i],
- specName,
- vendor,
- version,
- "GNU Classpath",
- "GNU",
- Configuration.CLASSPATH_VERSION,
- null,
- null);
-
- definedPackages.put(packages[i], p);
- }
- }
- }
-
-
- /**
- * Helper to define a class using a string of bytes. This assumes that
- * the security checks have already been performed, if necessary.
- *
- * Implementations of this method are advised to consider the
- * situation where user code modifies the byte array after it has
- * been passed to defineClass. This can be handled by making a
- * private copy of the array, or arranging to only read any given
- * byte a single time.
- *
- * @param name the name to give the class, or null if unknown
- * @param data the data representing the classfile, in classfile format
- * @param offset the offset into the data where the classfile starts
- * @param len the length of the classfile data in the array
- * @param pd the protection domain
- * @return the class that was defined
- * @throws ClassFormatError if data is not in proper classfile format
- */
- static final native Class defineClass(ClassLoader cl, String name,
- byte[] data, int offset, int len,
- ProtectionDomain pd)
- throws ClassFormatError;
-
- /**
- * Helper to resolve all references to other classes from this class.
- *
- * @param c the class to resolve
- */
- static final native void resolveClass(Class c);
-
- /**
- * Helper to load a class from the bootstrap class loader.
- *
- * @param name the class name to load
- * @param resolve whether to resolve it
- * @return the class, loaded by the bootstrap classloader or null
- * if the class wasn't found. Returning null is equivalent to throwing
- * a ClassNotFoundException (but a possible performance optimization).
- */
- static final native Class loadClass(String name, boolean resolve)
- throws ClassNotFoundException;
-
- /**
- * Helper to load a resource from the bootstrap class loader.
- *
- * @param name the resource to find
- * @return the URL to the resource
- */
- static URL getResource(String name)
- {
- Enumeration e = getResources(name);
- if (e.hasMoreElements())
- return (URL)e.nextElement();
- return null;
- }
- /**
- * Helper to get a list of resources from the bootstrap class loader.
- *
- * @param name the resource to find
- * @return an enumeration of resources
- */
- static Enumeration getResources(String name)
- {
-// StringTokenizer st = new StringTokenizer(
-// SystemProperties.getProperty("java.boot.class.path", "."),
-// File.pathSeparator);
-// Vector v = new Vector();
-// while (st.hasMoreTokens())
-// {
-// File file = new File(st.nextToken());
-// if (file.isDirectory())
-// {
-// try
-// {
-// File f = new File(file, name);
-// if (!f.exists()) continue;
-// v.add(new URL("file://" + f.getAbsolutePath()));
-// }
-// catch (MalformedURLException e)
-// {
-// throw new Error(e);
-// }
-// }
-// else if (file.isFile())
-// {
-// ZipFile zip;
-// synchronized(bootjars)
-// {
-// zip = (ZipFile) bootjars.get(file.getName());
-// }
-// if(zip == null)
-// {
-// try
-// {
-// zip = new ZipFile(file);
-// synchronized(bootjars)
-// {
-// bootjars.put(file.getName(), zip);
-// }
-// }
-// catch (IOException e)
-// {
-// continue;
-// }
-// }
-// String zname = name.startsWith("/") ? name.substring(1) : name;
-// if (zip.getEntry(zname) == null)
-// continue;
-// try
-// {
-// v.add(new URL("jar:file://"
-// + file.getAbsolutePath() + "!/" + zname));
-// }
-// catch (MalformedURLException e)
-// {
-// throw new Error(e);
-// }
-// }
-// }
-// return v.elements();
-// }
- Vector urls = nativeGetResources(name);
- Vector v = new Vector();
- for (Enumeration en = urls.elements(); en.hasMoreElements();)
- {
- try
- {
- v.add(new URL((String) en.nextElement()));
- }
- catch (MalformedURLException e)
- {
- throw new Error(e);
- }
- }
- return v.elements();
- }
-
- private native static final Vector nativeGetResources(String name);
-
-
- /**
- * Returns a String[] of native package names. The default
- * implementation tries to load a list of package from
- * the META-INF/INDEX.LIST file in the boot jar file.
- * If not found or if any exception is raised, it returns
- * an empty array. You may decide this needs native help.
- */
- private static String[] getBootPackages()
- {
- try
- {
- Enumeration indexListEnumeration = getResources("META-INF/INDEX.LIST");
- Set packageSet = new HashSet();
-
- while (indexListEnumeration.hasMoreElements())
- {
- try
- {
- String line;
- int lineToSkip = 3;
- BufferedReader reader = new BufferedReader(
- new InputStreamReader(
- ((URL) indexListEnumeration.nextElement()).openStream()));
- while ((line = reader.readLine()) != null)
- {
- if (lineToSkip == 0)
- {
- if (line.length() == 0)
- lineToSkip = 1;
- else
- packageSet.add(line.replace('/', '.'));
- }
- else
- lineToSkip--;
- }
- reader.close();
- }
- catch (IOException e)
- {
- // Empty catch block on purpose
- }
- }
- return (String[]) packageSet.toArray(new String[packageSet.size()]);
- }
- catch (Exception e)
- {
- return new String[0];
- }
- }
-
-
- /**
- * Helper to get a package from the bootstrap class loader.
- *
- * @param name the name to find
- * @return the named package, if it exists
- */
- static Package getPackage(String name)
- {
- return (Package)definedPackages.get(name);
- }
-
-
-
- /**
- * Helper to get all packages from the bootstrap class loader.
- *
- * @return all named packages, if any exist
- */
- static Package[] getPackages()
- {
- Package[] packages = new Package[definedPackages.size()];
- definedPackages.values().toArray(packages);
- return packages;
- }
-
- /**
- * Helper for java.lang.Integer, Byte, etc to get the TYPE class
- * at initialization time. The type code is one of the chars that
- * represents the primitive type as in JNI.
- *
- * <ul>
- * <li>'Z' - boolean</li>
- * <li>'B' - byte</li>
- * <li>'C' - char</li>
- * <li>'D' - double</li>
- * <li>'F' - float</li>
- * <li>'I' - int</li>
- * <li>'J' - long</li>
- * <li>'S' - short</li>
- * <li>'V' - void</li>
- * </ul>
- *
- * @param type the primitive type
- * @return a "bogus" class representing the primitive type
- */
- static final native Class getPrimitiveClass(char type);
-
- /**
- * The system default for assertion status. This is used for all system
- * classes (those with a null ClassLoader), as well as the initial value for
- * every ClassLoader's default assertion status.
- *
- * @return the system-wide default assertion status
- */
- static native final boolean defaultAssertionStatus();
-
- static native final boolean defaultUserAssertionStatus();
-
-
- static final Map packageAssertionMap =
- Collections.unmodifiableMap(packageAssertionStatus0(Boolean.TRUE, Boolean.FALSE));
-
- static native final Map packageAssertionStatus0(Boolean jtrue, Boolean jfalse);
- /**
- * The system default for package assertion status. This is used for all
- * ClassLoader's packageAssertionStatus defaults. It must be a map of
- * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package
- * represented as a null key.
- *
- * @return a (read-only) map for the default packageAssertionStatus
- */
-
- static final Map packageAssertionStatus() {
- return packageAssertionMap;
- }
-
- static final Map classAssertionMap =
- Collections.unmodifiableMap(classAssertionStatus0(Boolean.TRUE, Boolean.FALSE));
-
- static native final Map classAssertionStatus0(Boolean jtrue, Boolean jfalse);
-
- /**
- * The system default for class assertion status. This is used for all
- * ClassLoader's classAssertionStatus defaults. It must be a map of
- * class names to Boolean.TRUE or Boolean.FALSE
- *
- * @return a (read-only) map for the default classAssertionStatus
- */
- static final Map classAssertionStatus() {
- return classAssertionMap;
- }
-
- static ClassLoader getSystemClassLoader()
- {
- return ClassLoader.defaultGetSystemClassLoader();
- }
-
- /**
- * Find the class if this class loader previously defined this class
- * or if this class loader has been recorded as the initiating class loader
- * for this class.
- */
- static native Class findLoadedClass(ClassLoader cl, String name);
-
- /**
- * The Instrumentation object created by the vm when agents are defined.
- */
- static final Instrumentation instrumenter = null;
-
- /**
- * Call the transformers of the possible Instrumentation object. This
- * implementation assumes the instrumenter is a
- * <code>InstrumentationImpl</code> object. VM implementors would
- * have to redefine this method if they provide their own implementation
- * of the <code>Instrumentation</code> interface.
- *
- * @param loader the initiating loader
- * @param name the name of the class
- * @param data the data representing the classfile, in classfile format
- * @param offset the offset into the data where the classfile starts
- * @param len the length of the classfile data in the array
- * @param pd the protection domain
- * @return the new data representing the classfile
- */
- static final Class defineClassWithTransformers(ClassLoader loader,
- String name, byte[] data, int offset, int len, ProtectionDomain pd)
- {
-
- if (instrumenter != null)
- {
- byte[] modifiedData = new byte[len];
- System.arraycopy(data, offset, modifiedData, 0, len);
- modifiedData =
- ((InstrumentationImpl)instrumenter).callTransformers(loader, name,
- null, pd, modifiedData);
-
- return defineClass(loader, name, modifiedData, 0, modifiedData.length,
- pd);
- }
- else
- {
- return defineClass(loader, name, data, offset, len, pd);
- }
- }
-}
+++ /dev/null
-/* VMString.java -- VM Specific String methods
- Copyright (C) 2003 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java.lang;
-
-import java.lang.ref.WeakReference;
-import java.util.WeakHashMap;
-
-/*
- * This class is a reference version, mainly for compiling a class library
- * jar. It is likely that VM implementers replace this with their own
- * version that can communicate effectively with the VM.
- */
-
-/**
- * Code relocated from java.lang.String by
- * @author Dave Grove <groved@us.ibm.com>
- */
-final class VMString
-{
-
- /**
- * Holds the references for each intern()'d String. If all references to
- * the string disappear, and the VM properly supports weak references,
- * the String will be GC'd.
- */
-// private static final WeakHashMap internTable = new WeakHashMap();
-
- /**
- * Fetches this String from the intern hashtable. If two Strings are
- * considered equal, by the equals() method, then intern() will return the
- * same String instance. ie. if (s1.equals(s2)) then
- * (s1.intern() == s2.intern()). All string literals and string-valued
- * constant expressions are already interned.
- *
- * @param str the String to intern
- * @return the interned String
- */
-// static String intern(String str)
-// {
-// synchronized (internTable)
-// {
-// WeakReference ref = (WeakReference) internTable.get(str);
-// if (ref != null)
-// {
-// String s = (String) ref.get();
-// // If s is null, then no strong references exist to the String;
-// // the weak hash map will soon delete the key.
-// if (s != null)
-// return s;
-// }
-// internTable.put(str, new WeakReference(str));
-// }
-// return str;
-// }
-
- /**
- * this one is native in CACAO
- */
- static native String intern(String str);
-
-} // class VMString
+++ /dev/null
-/* VMThread -- VM interface for Thread of executable code
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java.lang;
-
-/**
- * VM interface for Thread of executable code. Holds VM dependent state.
- * It is deliberately package local and final and should only be accessed
- * by the Thread class.
- * <p>
- * This is the GNU Classpath reference implementation, it should be adapted
- * for a specific VM.
- * <p>
- * The following methods must be implemented:
- * <ul>
- * <li>native void start(long stacksize);
- * <li>native void interrupt();
- * <li>native boolean isInterrupted();
- * <li>native void suspend();
- * <li>native void resume();
- * <li>native void nativeSetPriority(int priority);
- * <li>native void nativeStop(Throwable t);
- * <li>native static Thread currentThread();
- * <li>static native void yield();
- * <li>static native boolean interrupted();
- * </ul>
- * All other methods may be implemented to make Thread handling more efficient
- * or to implement some optional (and sometimes deprecated) behaviour. Default
- * implementations are provided but it is highly recommended to optimize them
- * for a specific VM.
- *
- * @author Jeroen Frijters (jeroen@frijters.net)
- * @author Dalibor Topic (robilad@kaffe.org)
- */
-final class VMThread
-{
- /**
- * The Thread object that this VM state belongs to.
- * Used in currentThread() and start().
- * Note: when this thread dies, this reference is *not* cleared
- */
- volatile Thread thread;
-
- /**
- * Flag that is set when the thread runs, used by stop() to protect against
- * stop's getting lost.
- */
- private volatile boolean running;
-
- /**
- * VM private data.
- */
- private transient Object vmdata;
-
- /**
- * Private constructor, create VMThreads with the static create method.
- *
- * @param thread The Thread object that was just created.
- */
- private VMThread(Thread thread)
- {
- this.thread = thread;
- }
-
- /**
- * This method is the initial Java code that gets executed when a native
- * thread starts. It's job is to coordinate with the rest of the VMThread
- * logic and to start executing user code and afterwards handle clean up.
- */
- private void run()
- {
- try
- {
- try
- {
- running = true;
- synchronized(thread)
- {
- Throwable t = thread.stillborn;
- if(t != null)
- {
- thread.stillborn = null;
- throw t;
- }
- }
- thread.run();
- }
- catch(Throwable t)
- {
- try
- {
- Thread.UncaughtExceptionHandler handler;
- handler = thread.getUncaughtExceptionHandler();
- handler.uncaughtException(thread, t);
- }
- catch(Throwable ignore)
- {
- }
- }
- }
- finally
- {
- // Setting runnable to false is partial protection against stop
- // being called while we're cleaning up. To be safe all code in
- // VMThread be unstoppable.
- running = false;
- thread.die();
- synchronized(this)
- {
- // release the threads waiting to join us
- notifyAll();
- }
- }
- }
-
- /**
- * Creates a native Thread. This is called from the start method of Thread.
- * The Thread is started.
- *
- * @param thread The newly created Thread object
- * @param stacksize Indicates the requested stacksize. Normally zero,
- * non-zero values indicate requested stack size in bytes but it is up
- * to the specific VM implementation to interpret them and may be ignored.
- */
- static void create(Thread thread, long stacksize)
- {
- VMThread vmThread = new VMThread(thread);
- thread.vmThread = vmThread;
- vmThread.start(stacksize);
- }
-
- /**
- * Gets the name of the thread. Usually this is the name field of the
- * associated Thread object, but some implementation might choose to
- * return the name of the underlying platform thread.
- */
- String getName()
- {
- return thread.name;
- }
-
- /**
- * Set the name of the thread. Usually this sets the name field of the
- * associated Thread object, but some implementations might choose to
- * set the name of the underlying platform thread.
- * @param name The new name
- */
- void setName(String name)
- {
- thread.name = name;
- }
-
- /**
- * Set the thread priority field in the associated Thread object and
- * calls the native method to set the priority of the underlying
- * platform thread.
- * @param priority The new priority
- */
- void setPriority(int priority)
- {
- thread.priority = priority;
- nativeSetPriority(priority);
- }
-
- /**
- * Returns the priority. Usually this is the priority field from the
- * associated Thread object, but some implementation might choose to
- * return the priority of the underlying platform thread.
- * @return this Thread's priority
- */
- int getPriority()
- {
- return thread.priority;
- }
-
- /**
- * Returns true if the thread is a daemon thread. Usually this is the
- * daemon field from the associated Thread object, but some
- * implementation might choose to return the daemon state of the underlying
- * platform thread.
- * @return whether this is a daemon Thread or not
- */
- boolean isDaemon()
- {
- return thread.daemon;
- }
-
- /**
- * Returns the number of stack frames in this Thread.
- * Will only be called when when a previous call to suspend() returned true.
- *
- * @deprecated unsafe operation
- */
- native int countStackFrames();
-
- /**
- * Wait the specified amount of time for the Thread in question to die.
- *
- * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
- * not offer that fine a grain of timing resolution. Besides, there is
- * no guarantee that this thread can start up immediately when time expires,
- * because some other thread may be active. So don't expect real-time
- * performance.
- *
- * @param ms the number of milliseconds to wait, or 0 for forever
- * @param ns the number of extra nanoseconds to sleep (0-999999)
- * @throws InterruptedException if the Thread is interrupted; it's
- * <i>interrupted status</i> will be cleared
- */
- synchronized void join(long ms, int ns) throws InterruptedException
- {
- // Round up
- ms += (ns != 0) ? 1 : 0;
-
- // Compute end time, but don't overflow
- long now = System.currentTimeMillis();
- long end = now + ms;
- if (end < now)
- end = Long.MAX_VALUE;
-
- // A VM is allowed to return from wait() without notify() having been
- // called, so we loop to handle possible spurious wakeups.
- while(thread.vmThread != null)
- {
- // We use the VMThread object to wait on, because this is a private
- // object, so client code cannot call notify on us.
- wait(ms);
- if(ms != 0)
- {
- now = System.currentTimeMillis();
- ms = end - now;
- if(ms <= 0)
- {
- break;
- }
- }
- }
- }
-
- /**
- * Cause this Thread to stop abnormally and throw the specified exception.
- * If you stop a Thread that has not yet started, the stop is ignored
- * (contrary to what the JDK documentation says).
- * <b>WARNING</b>This bypasses Java security, and can throw a checked
- * exception which the call stack is unprepared to handle. Do not abuse
- * this power.
- *
- * <p>This is inherently unsafe, as it can interrupt synchronized blocks and
- * leave data in bad states.
- *
- * <p><b>NOTE</b> stop() should take care not to stop a thread if it is
- * executing code in this class.
- *
- * @param t the Throwable to throw when the Thread dies
- * @deprecated unsafe operation, try not to use
- */
- void stop(Throwable t)
- {
- // Note: we assume that we own the lock on thread
- // (i.e. that Thread.stop() is synchronized)
- if(running)
- nativeStop(t);
- else
- thread.stillborn = t;
- }
-
- /**
- * Create a native thread on the underlying platform and start it executing
- * on the run method of this object.
- * @param stacksize the requested size of the native thread stack
- */
- native void start(long stacksize);
-
- /**
- * Interrupt this thread.
- */
- native void interrupt();
-
- /**
- * Determine whether this Thread has been interrupted, but leave
- * the <i>interrupted status</i> alone in the process.
- *
- * @return whether the Thread has been interrupted
- */
- native boolean isInterrupted();
-
- /**
- * Suspend this Thread. It will not come back, ever, unless it is resumed.
- */
- native void suspend();
-
- /**
- * Resume this Thread. If the thread is not suspended, this method does
- * nothing.
- */
- native void resume();
-
- /**
- * Set the priority of the underlying platform thread.
- *
- * @param priority the new priority
- */
- native void nativeSetPriority(int priority);
-
- /**
- * Asynchronously throw the specified throwable in this Thread.
- *
- * @param t the exception to throw
- */
- native void nativeStop(Throwable t);
-
- /**
- * Return the Thread object associated with the currently executing
- * thread.
- *
- * @return the currently executing Thread
- */
- static native Thread currentThread();
-
- /**
- * Yield to another thread. The Thread will not lose any locks it holds
- * during this time. There are no guarantees which thread will be
- * next to run, and it could even be this one, but most VMs will choose
- * the highest priority thread that has been waiting longest.
- */
- static native void yield();
-
- /**
- * Suspend the current Thread's execution for the specified amount of
- * time. The Thread will not lose any locks it has during this time. There
- * are no guarantees which thread will be next to run, but most VMs will
- * choose the highest priority thread that has been waiting longest.
- *
- * <p>Note that 1,000,000 nanoseconds == 1 millisecond, but most VMs do
- * not offer that fine a grain of timing resolution. Besides, there is
- * no guarantee that this thread can start up immediately when time expires,
- * because some other thread may be active. So don't expect real-time
- * performance.
- *
- * @param ms the number of milliseconds to sleep.
- * @param ns the number of extra nanoseconds to sleep (0-999999)
- * @throws InterruptedException if the Thread is (or was) interrupted;
- * it's <i>interrupted status</i> will be cleared
- */
- static void sleep(long ms, int ns) throws InterruptedException
- {
- // Note: JDK treats a zero length sleep is like Thread.yield(),
- // without checking the interrupted status of the thread.
- // It's unclear if this is a bug in the implementation or the spec.
- // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6213203
- if (ms == 0 && ns == 0)
- {
- if (Thread.interrupted())
- throw new InterruptedException();
- return;
- }
-
- // Compute end time, but don't overflow
- long now = System.currentTimeMillis();
- long end = now + ms;
- if (end < now)
- end = Long.MAX_VALUE;
-
- // A VM is allowed to return from wait() without notify() having been
- // called, so we loop to handle possible spurious wakeups.
- VMThread vt = Thread.currentThread().vmThread;
- synchronized (vt)
- {
- while (true)
- {
- vt.wait(ms, ns);
- now = System.currentTimeMillis();
- if (now >= end)
- break;
- ms = end - now;
- ns = 0;
- }
- }
- }
-
- /**
- * Determine whether the current Thread has been interrupted, and clear
- * the <i>interrupted status</i> in the process.
- *
- * @return whether the current Thread has been interrupted
- */
- static native boolean interrupted();
-
- /**
- * Checks whether the current thread holds the monitor on a given object.
- * This allows you to do <code>assert Thread.holdsLock(obj)</code>.
- *
- * @param obj the object to check
- * @return true if the current thread is currently synchronized on obj
- * @throws NullPointerException if obj is null
- */
-// static boolean holdsLock(Object obj)
-// {
-// /* Use obj.notify to check if the current thread holds
-// * the monitor of the object.
-// * If it doesn't, notify will throw an exception.
-// */
-// try
-// {
-// obj.notify();
-// // okay, current thread holds lock
-// return true;
-// }
-// catch (IllegalMonitorStateException e)
-// {
-// // it doesn't hold the lock
-// return false;
-// }
-// }
- static native boolean holdsLock(Object obj);
-
- /**
- * Returns the current state of the thread.
- * The value must be one of "BLOCKED", "NEW",
- * "RUNNABLE", "TERMINATED", "TIMED_WAITING" or
- * "WAITING".
- *
- * @return a string corresponding to one of the
- * thread enumeration states specified above.
- */
- native String getState();
-
-}
+++ /dev/null
-/* java.lang.VMThrowable -- VM support methods for Throwable.
- Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-package java.lang;
-
-import gnu.classpath.Pointer;
-
-/**
- * VM dependant state and support methods for Throwable.
- * It is deliberately package local and final and should only be accessed
- * by the Throwable class.
- * <p>
- * This is the GNU Classpath reference implementation, it should be adapted
- * for a specific VM. The reference implementation does nothing.
- *
- * @author Mark Wielaard (mark@klomp.org)
- */
-final class VMThrowable
-{
- /* IMPORTANT: the rawdata field is not a java object */
- private final Pointer vmData;
-
- /**
- * VM private data.
- */
- private transient Object vmdata;
-
- /**
- * Private contructor, create VMThrowables with fillInStackTrace();
- */
-// private VMThrowable() { }
- private VMThrowable()
- {
- vmData = null;
- }
-
- /**
- * Fill in the stack trace with the current execution stack.
- * Called by <code>Throwable.fillInStackTrace()</code> to get the state of
- * the VM. Can return null when the VM does not support caputing the VM
- * execution state.
- *
- * @return a new VMThrowable containing the current execution stack trace.
- * @see Throwable#fillInStackTrace()
- */
- static native VMThrowable fillInStackTrace(Throwable t);
-
- /**
- * Returns an <code>StackTraceElement</code> array based on the execution
- * state of the VM as captured by <code>fillInStackTrace</code>.
- * Called by <code>Throwable.getStackTrace()</code>.
- *
- * @return a non-null but possible zero length array of StackTraceElement.
- * @see Throwable#getStackTrace()
- */
- native StackTraceElement[] getStackTrace(Throwable t);
-}
+++ /dev/null
-/* java.lang.reflect.Constructor - reflection of Java constructors
- Copyright (C) 1998, 2001, 2004, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.lang.reflect;
-
-import gnu.java.lang.ClassHelper;
-
-import gnu.java.lang.reflect.MethodSignatureParser;
-
-import java.lang.annotation.Annotation;
-import java.util.Map;
-import java.util.Arrays;
-
-/**
- * The Constructor class represents a constructor of a class. It also allows
- * dynamic creation of an object, via reflection. Invocation on Constructor
- * objects knows how to do widening conversions, but throws
- * {@link IllegalArgumentException} if a narrowing conversion would be
- * necessary. You can query for information on this Constructor regardless
- * of location, but construction access may be limited by Java language
- * access controls. If you can't do it in the compiler, you can't normally
- * do it here either.<p>
- *
- * <B>Note:</B> This class returns and accepts types as Classes, even
- * primitive types; there are Class types defined that represent each
- * different primitive type. They are <code>java.lang.Boolean.TYPE,
- * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
- * byte.class</code>, etc. These are not to be confused with the
- * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
- * real classes.<p>
- *
- * Also note that this is not a serializable class. It is entirely feasible
- * to make it serializable using the Externalizable interface, but this is
- * on Sun, not me.
- *
- * @author John Keiser
- * @author Eric Blake <ebb9@email.byu.edu>
- * @see Member
- * @see Class
- * @see java.lang.Class#getConstructor(Class[])
- * @see java.lang.Class#getDeclaredConstructor(Class[])
- * @see java.lang.Class#getConstructors()
- * @see java.lang.Class#getDeclaredConstructors()
- * @since 1.1
- * @status updated to 1.4
- */
-public final class Constructor<T>
- extends AccessibleObject
- implements GenericDeclaration, Member
-{
- private Class<T> clazz;
- private int slot;
-
- /**
- * Unparsed annotations.
- */
- private byte[] annotations = null;
-
- /**
- * Unparsed parameter annotations.
- */
- private byte[] parameterAnnotations = null;
-
- /**
- * Annotations get parsed the first time they are
- * accessed and are then cached it this map.
- */
- private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
-
- private static final int CONSTRUCTOR_MODIFIERS
- = Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC;
-
- /**
- * Helper array for creating a new array from a java.util.Container.
- */
- private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
- new Annotation[0];
-
- /**
- * This class is uninstantiable except from native code.
- */
- private Constructor(Class declaringClass,int slot)
- {
- this.clazz = declaringClass;
- this.slot = slot;
- }
-
- private Constructor()
- {
- }
-
- /**
- * Gets the class that declared this constructor.
- * @return the class that declared this member
- */
- public Class<T> getDeclaringClass()
- {
- return clazz;
- }
-
- /**
- * Gets the name of this constructor (the non-qualified name of the class
- * it was declared in).
- * @return the name of this constructor
- */
- public String getName()
- {
- return getDeclaringClass().getName();
- }
-
- /**
- * Return the raw modifiers for this constructor. In particular
- * this will include the synthetic and varargs bits.
- * @return the constructor's modifiers
- */
- private native int getModifiersInternal();
-
- /**
- * Gets the modifiers this constructor uses. Use the <code>Modifier</code>
- * class to interpret the values. A constructor can only have a subset of the
- * following modifiers: public, private, protected.
- *
- * @return an integer representing the modifiers to this Member
- * @see Modifier
- */
- public int getModifiers()
- {
- return getModifiersInternal() & CONSTRUCTOR_MODIFIERS;
- }
-
- /**
- * Return true if this constructor is synthetic, false otherwise.
- * A synthetic member is one which is created by the compiler,
- * and which does not appear in the user's source code.
- * @since 1.5
- */
- public boolean isSynthetic()
- {
- return (getModifiersInternal() & Modifier.SYNTHETIC) != 0;
- }
-
- /**
- * Return true if this is a varargs constructor, that is if
- * the constructor takes a variable number of arguments.
- * @since 1.5
- */
- public boolean isVarArgs()
- {
- return (getModifiersInternal() & Modifier.VARARGS) != 0;
- }
-
- /**
- * Get the parameter list for this constructor, in declaration order. If the
- * constructor takes no parameters, returns a 0-length array (not null).
- *
- * @return a list of the types of the constructor's parameters
- */
- public native Class<?>[] getParameterTypes();
-
- /**
- * Get the exception types this constructor says it throws, in no particular
- * order. If the constructor has no throws clause, returns a 0-length array
- * (not null).
- *
- * @return a list of the types in the constructor's throws clause
- */
- public native Class<?>[] getExceptionTypes();
-
- /**
- * Compare two objects to see if they are semantically equivalent.
- * Two Constructors are semantically equivalent if they have the same
- * declaring class and the same parameter list. This ignores different
- * exception clauses, but since you can't create a Method except through the
- * VM, this is just the == relation.
- *
- * @param o the object to compare to
- * @return <code>true</code> if they are equal; <code>false</code> if not.
- */
- public boolean equals(Object o)
- {
- if (!(o instanceof Constructor))
- return false;
- Constructor that = (Constructor)o;
- if (this.getDeclaringClass() != that.getDeclaringClass())
- return false;
- if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes()))
- return false;
- return true;
- }
-
- /**
- * Get the hash code for the Constructor. The Constructor hash code is the
- * hash code of the declaring class's name.
- *
- * @return the hash code for the object
- */
- public int hashCode()
- {
- return getDeclaringClass().getName().hashCode();
- }
-
- /**
- * Get a String representation of the Constructor. A Constructor's String
- * representation is "<modifier> <classname>(<paramtypes>)
- * throws <exceptions>", where everything after ')' is omitted if
- * there are no exceptions.<br> Example:
- * <code>public java.io.FileInputStream(java.lang.Runnable)
- * throws java.io.FileNotFoundException</code>
- *
- * @return the String representation of the Constructor
- */
- public String toString()
- {
- // 128 is a reasonable buffer initial size for constructor
- StringBuilder sb = new StringBuilder(128);
- Modifier.toString(getModifiers(), sb).append(' ');
- sb.append(getDeclaringClass().getName()).append('(');
- Class[] c = getParameterTypes();
- if (c.length > 0)
- {
- sb.append(ClassHelper.getUserName(c[0]));
- for (int i = 1; i < c.length; i++)
- sb.append(',').append(ClassHelper.getUserName(c[i]));
- }
- sb.append(')');
- c = getExceptionTypes();
- if (c.length > 0)
- {
- sb.append(" throws ").append(c[0].getName());
- for (int i = 1; i < c.length; i++)
- sb.append(',').append(c[i].getName());
- }
- return sb.toString();
- }
-
- static <X extends GenericDeclaration>
- void addTypeParameters(StringBuilder sb, TypeVariable<X>[] typeArgs)
- {
- if (typeArgs.length == 0)
- return;
- sb.append('<');
- for (int i = 0; i < typeArgs.length; ++i)
- {
- if (i > 0)
- sb.append(',');
- sb.append(typeArgs[i]);
- }
- sb.append("> ");
- }
-
- public String toGenericString()
- {
- StringBuilder sb = new StringBuilder(128);
- Modifier.toString(getModifiers(), sb).append(' ');
- addTypeParameters(sb, getTypeParameters());
- sb.append(getDeclaringClass().getName()).append('(');
- Type[] types = getGenericParameterTypes();
- if (types.length > 0)
- {
- sb.append(types[0]);
- for (int i = 1; i < types.length; ++i)
- sb.append(',').append(types[i]);
- }
- sb.append(')');
- types = getGenericExceptionTypes();
- if (types.length > 0)
- {
- sb.append(" throws ").append(types[0]);
- for (int i = 1; i < types.length; i++)
- sb.append(',').append(types[i]);
- }
- return sb.toString();
- }
-
- /**
- * Create a new instance by invoking the constructor. Arguments are
- * automatically unwrapped and widened, if needed.<p>
- *
- * If this class is abstract, you will get an
- * <code>InstantiationException</code>. If the constructor takes 0
- * arguments, you may use null or a 0-length array for <code>args</code>.<p>
- *
- * If this Constructor enforces access control, your runtime context is
- * evaluated, and you may have an <code>IllegalAccessException</code> if
- * you could not create this object in similar compiled code. If the class
- * is uninitialized, you trigger class initialization, which may end in a
- * <code>ExceptionInInitializerError</code>.<p>
- *
- * Then, the constructor is invoked. If it completes normally, the return
- * value will be the new object. If it completes abruptly, the exception is
- * wrapped in an <code>InvocationTargetException</code>.
- *
- * @param args the arguments to the constructor
- * @return the newly created object
- * @throws IllegalAccessException if the constructor could not normally be
- * called by the Java code (i.e. it is not public)
- * @throws IllegalArgumentException if the number of arguments is incorrect;
- * or if the arguments types are wrong even with a widening
- * conversion
- * @throws InstantiationException if the class is abstract
- * @throws InvocationTargetException if the constructor throws an exception
- * @throws ExceptionInInitializerError if construction triggered class
- * initialization, which then failed
- */
- public T newInstance(Object... args)
- throws InstantiationException, IllegalAccessException,
- InvocationTargetException
- {
- return constructNative(args, clazz, slot);
- }
-
- private native T constructNative(Object[] args, Class declaringClass,
- int slot)
- throws InstantiationException, IllegalAccessException,
- InvocationTargetException;
-
- /**
- * Returns an array of <code>TypeVariable</code> objects that represents
- * the type variables declared by this constructor, in declaration order.
- * An array of size zero is returned if this constructor has no type
- * variables.
- *
- * @return the type variables associated with this constructor.
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public TypeVariable<Constructor<T>>[] getTypeParameters()
- {
- String sig = getSignature();
- if (sig == null)
- return new TypeVariable[0];
- MethodSignatureParser p = new MethodSignatureParser(this, sig);
- return p.getTypeParameters();
- }
-
- /**
- * Return the String in the Signature attribute for this constructor. If there
- * is no Signature attribute, return null.
- */
- private native String getSignature();
-
- /**
- * Returns an array of <code>Type</code> objects that represents
- * the exception types declared by this constructor, in declaration order.
- * An array of size zero is returned if this constructor declares no
- * exceptions.
- *
- * @return the exception types declared by this constructor.
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public Type[] getGenericExceptionTypes()
- {
- String sig = getSignature();
- if (sig == null)
- return getExceptionTypes();
- MethodSignatureParser p = new MethodSignatureParser(this, sig);
- return p.getGenericExceptionTypes();
- }
-
- /**
- * Returns an array of <code>Type</code> objects that represents
- * the parameter list for this constructor, in declaration order.
- * An array of size zero is returned if this constructor takes no
- * parameters.
- *
- * @return a list of the types of the constructor's parameters
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public Type[] getGenericParameterTypes()
- {
- String sig = getSignature();
- if (sig == null)
- return getParameterTypes();
- MethodSignatureParser p = new MethodSignatureParser(this, sig);
- return p.getGenericParameterTypes();
- }
-
- /**
- * @throws NullPointerException {@inheritDoc}
- * @since 1.5
- */
- public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
-
- return (T)declaredAnnotations().get(annotationClass);
- }
-
- /**
- * @since 1.5
- */
- public Annotation[] getDeclaredAnnotations() {
- return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
- }
-
- /**
- * Parses the annotations if they aren't parsed yet and stores them into
- * the declaredAnnotations map and return this map.
- */
- private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
-
- /**
- * Returns an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by
- * this <tt>Method</tt> object. (Returns an array of length zero if the
- * underlying method is parameterless. If the method has one or more
- * parameters, a nested array of length zero is returned for each parameter
- * with no annotations.) The annotation objects contained in the returned
- * arrays are serializable. The caller of this method is free to modify
- * the returned arrays; it will have no effect on the arrays returned to
- * other callers.
- *
- * @return an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by this
- * Method object
- * @since 1.5
- */
- public native Annotation[][] getParameterAnnotations();
-}
+++ /dev/null
-/* java.lang.reflect.Field - reflection of Java fields
- Copyright (C) 1998, 2001, 2005 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.lang.reflect;
-
-import gnu.java.lang.ClassHelper;
-
-import gnu.java.lang.reflect.FieldSignatureParser;
-
-import java.lang.annotation.Annotation;
-import java.util.Map;
-
-
-/**
- * The Field class represents a member variable of a class. It also allows
- * dynamic access to a member, via reflection. This works for both
- * static and instance fields. Operations on Field objects know how to
- * do widening conversions, but throw {@link IllegalArgumentException} if
- * a narrowing conversion would be necessary. You can query for information
- * on this Field regardless of location, but get and set access may be limited
- * by Java language access controls. If you can't do it in the compiler, you
- * can't normally do it here either.<p>
- *
- * <B>Note:</B> This class returns and accepts types as Classes, even
- * primitive types; there are Class types defined that represent each
- * different primitive type. They are <code>java.lang.Boolean.TYPE,
- * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
- * byte.class</code>, etc. These are not to be confused with the
- * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
- * real classes.<p>
- *
- * Also note that this is not a serializable class. It is entirely feasible
- * to make it serializable using the Externalizable interface, but this is
- * on Sun, not me.
- *
- * @author John Keiser
- * @author Eric Blake <ebb9@email.byu.edu>
- * @see Member
- * @see Class
- * @see Class#getField(String)
- * @see Class#getDeclaredField(String)
- * @see Class#getFields()
- * @see Class#getDeclaredFields()
- * @since 1.1
- * @status updated to 1.4
- */
-public final class Field
-extends AccessibleObject implements Member
-{
- private Class clazz;
- private String name;
- private int slot;
-
- /**
- * Unparsed annotations.
- */
- private byte[] annotations = null;
-
- /**
- * Annotations get parsed the first time they are
- * accessed and are then cached it this map.
- */
- private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
-
- private static final int FIELD_MODIFIERS
- = Modifier.FINAL | Modifier.PRIVATE | Modifier.PROTECTED
- | Modifier.PUBLIC | Modifier.STATIC | Modifier.TRANSIENT
- | Modifier.VOLATILE;
-
- /**
- * Helper array for creating a new array from a java.util.Container.
- */
- private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
- new Annotation[0];
-
- /**
- * This class is uninstantiable except natively.
- */
- private Field(Class declaringClass, String name, int slot)
- {
- this.clazz = declaringClass;
- this.name = name;
- this.slot = slot;
- }
-
- /**
- * Gets the class that declared this field, or the class where this field
- * is a non-inherited member.
- * @return the class that declared this member
- */
- public Class<?> getDeclaringClass()
- {
- return clazz;
- }
-
- /**
- * Gets the name of this field.
- * @return the name of this field
- */
- public String getName()
- {
- return name;
- }
-
- /**
- * Return the raw modifiers for this field.
- * @return the field's modifiers
- */
- private native int getModifiersInternal();
-
- /**
- * Gets the modifiers this field uses. Use the <code>Modifier</code>
- * class to interpret the values. A field can only have a subset of the
- * following modifiers: public, private, protected, static, final,
- * transient, and volatile.
- *
- * @return an integer representing the modifiers to this Member
- * @see Modifier
- */
- public int getModifiers()
- {
- return getModifiersInternal() & FIELD_MODIFIERS;
- }
-
- /**
- * Return true if this field is synthetic, false otherwise.
- * @since 1.5
- */
- public boolean isSynthetic()
- {
- return (getModifiersInternal() & Modifier.SYNTHETIC) != 0;
- }
-
- /**
- * Return true if this field represents an enum constant,
- * false otherwise.
- * @since 1.5
- */
- public boolean isEnumConstant()
- {
- return (getModifiersInternal() & Modifier.ENUM) != 0;
- }
-
- /**
- * Gets the type of this field.
- * @return the type of this field
- */
- public native Class<?> getType();
-
- /**
- * Compare two objects to see if they are semantically equivalent.
- * Two Fields are semantically equivalent if they have the same declaring
- * class, name, and type. Since you can't creat a Field except through
- * the VM, this is just the == relation.
- *
- * @param o the object to compare to
- * @return <code>true</code> if they are equal; <code>false</code> if not
- */
- public boolean equals(Object o)
- {
- if (!(o instanceof Field))
- return false;
- Field that = (Field)o;
- if (this.getDeclaringClass() != that.getDeclaringClass())
- return false;
- if (!this.getName().equals(that.getName()))
- return false;
- if (this.getType() != that.getType())
- return false;
- return true;
- }
-
- /**
- * Get the hash code for the Field. The Field hash code is the hash code
- * of its name XOR'd with the hash code of its class name.
- *
- * @return the hash code for the object.
- */
- public int hashCode()
- {
- return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
- }
-
- /**
- * Get a String representation of the Field. A Field's String
- * representation is "<modifiers> <type>
- * <class>.<fieldname>".<br> Example:
- * <code>public transient boolean gnu.parse.Parser.parseComplete</code>
- *
- * @return the String representation of the Field
- */
- public String toString()
- {
- // 64 is a reasonable buffer initial size for field
- StringBuilder sb = new StringBuilder(64);
- Modifier.toString(getModifiers(), sb).append(' ');
- sb.append(ClassHelper.getUserName(getType())).append(' ');
- sb.append(getDeclaringClass().getName()).append('.');
- sb.append(getName());
- return sb.toString();
- }
-
- public String toGenericString()
- {
- StringBuilder sb = new StringBuilder(64);
- Modifier.toString(getModifiers(), sb).append(' ');
- sb.append(getGenericType()).append(' ');
- sb.append(getDeclaringClass().getName()).append('.');
- sb.append(getName());
- return sb.toString();
- }
-
- /**
- * Get the value of this Field. If it is primitive, it will be wrapped
- * in the appropriate wrapper type (boolean = java.lang.Boolean).<p>
- *
- * If the field is static, <code>o</code> will be ignored. Otherwise, if
- * <code>o</code> is null, you get a <code>NullPointerException</code>,
- * and if it is incompatible with the declaring class of the field, you
- * get an <code>IllegalArgumentException</code>.<p>
- *
- * Next, if this Field enforces access control, your runtime context is
- * evaluated, and you may have an <code>IllegalAccessException</code> if
- * you could not access this field in similar compiled code. If the field
- * is static, and its class is uninitialized, you trigger class
- * initialization, which may end in a
- * <code>ExceptionInInitializerError</code>.<p>
- *
- * Finally, the field is accessed, and primitives are wrapped (but not
- * necessarily in new objects). This method accesses the field of the
- * declaring class, even if the instance passed in belongs to a subclass
- * which declares another field to hide this one.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if <code>o</code> is not an instance of
- * the class or interface declaring this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #getBoolean(Object)
- * @see #getByte(Object)
- * @see #getChar(Object)
- * @see #getShort(Object)
- * @see #getInt(Object)
- * @see #getLong(Object)
- * @see #getFloat(Object)
- * @see #getDouble(Object)
- */
- public native Object get(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this boolean Field. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a boolean field of
- * <code>o</code>, or if <code>o</code> is not an instance of the
- * declaring class of this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native boolean getBoolean(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this byte Field. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a byte field of
- * <code>o</code>, or if <code>o</code> is not an instance of the
- * declaring class of this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native byte getByte(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this Field as a char. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a char field of
- * <code>o</code>, or if <code>o</code> is not an instance
- * of the declaring class of this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native char getChar(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this Field as a short. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a byte or short
- * field of <code>o</code>, or if <code>o</code> is not an instance
- * of the declaring class of this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native short getShort(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this Field as an int. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a byte, short, char, or
- * int field of <code>o</code>, or if <code>o</code> is not an
- * instance of the declaring class of this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native int getInt(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this Field as a long. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a byte, short, char, int,
- * or long field of <code>o</code>, or if <code>o</code> is not an
- * instance of the declaring class of this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native long getLong(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this Field as a float. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a byte, short, char, int,
- * long, or float field of <code>o</code>, or if <code>o</code> is
- * not an instance of the declaring class of this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native float getFloat(Object o)
- throws IllegalAccessException;
-
- /**
- * Get the value of this Field as a double. If the field is static,
- * <code>o</code> will be ignored.
- *
- * @param o the object to get the value of this Field from
- * @return the value of the Field
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a byte, short, char, int,
- * long, float, or double field of <code>o</code>, or if
- * <code>o</code> is not an instance of the declaring class of this
- * field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #get(Object)
- */
- public native double getDouble(Object o)
- throws IllegalAccessException;
-
- /**
- * Set the value of this Field. If it is a primitive field, the value
- * will be unwrapped from the passed object (boolean = java.lang.Boolean).<p>
- *
- * If the field is static, <code>o</code> will be ignored. Otherwise, if
- * <code>o</code> is null, you get a <code>NullPointerException</code>,
- * and if it is incompatible with the declaring class of the field, you
- * get an <code>IllegalArgumentException</code>.<p>
- *
- * Next, if this Field enforces access control, your runtime context is
- * evaluated, and you may have an <code>IllegalAccessException</code> if
- * you could not access this field in similar compiled code. This also
- * occurs whether or not there is access control if the field is final.
- * If the field is primitive, and unwrapping your argument fails, you will
- * get an <code>IllegalArgumentException</code>; likewise, this error
- * happens if <code>value</code> cannot be cast to the correct object type.
- * If the field is static, and its class is uninitialized, you trigger class
- * initialization, which may end in a
- * <code>ExceptionInInitializerError</code>.<p>
- *
- * Finally, the field is set with the widened value. This method accesses
- * the field of the declaring class, even if the instance passed in belongs
- * to a subclass which declares another field to hide this one.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if <code>value</code> cannot be
- * converted by a widening conversion to the underlying type of
- * the Field, or if <code>o</code> is not an instance of the class
- * declaring this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #setBoolean(Object, boolean)
- * @see #setByte(Object, byte)
- * @see #setChar(Object, char)
- * @see #setShort(Object, short)
- * @see #setInt(Object, int)
- * @see #setLong(Object, long)
- * @see #setFloat(Object, float)
- * @see #setDouble(Object, double)
- */
- public native void set(Object o, Object value)
- throws IllegalAccessException;
-
- /**
- * Set this boolean Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a boolean field, or if
- * <code>o</code> is not an instance of the class declaring this
- * field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setBoolean(Object o, boolean value)
- throws IllegalAccessException;
-
- /**
- * Set this byte Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a byte, short, int, long,
- * float, or double field, or if <code>o</code> is not an instance
- * of the class declaring this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setByte(Object o, byte value)
- throws IllegalAccessException;
-
- /**
- * Set this char Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a char, int, long,
- * float, or double field, or if <code>o</code> is not an instance
- * of the class declaring this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setChar(Object o, char value)
- throws IllegalAccessException;
-
- /**
- * Set this short Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a short, int, long,
- * float, or double field, or if <code>o</code> is not an instance
- * of the class declaring this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setShort(Object o, short value)
- throws IllegalAccessException;
-
- /**
- * Set this int Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not an int, long, float, or
- * double field, or if <code>o</code> is not an instance of the
- * class declaring this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setInt(Object o, int value)
- throws IllegalAccessException;
-
- /**
- * Set this long Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a long, float, or double
- * field, or if <code>o</code> is not an instance of the class
- * declaring this field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setLong(Object o, long value)
- throws IllegalAccessException;
-
- /**
- * Set this float Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a float or long field, or
- * if <code>o</code> is not an instance of the class declaring this
- * field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setFloat(Object o, float value)
- throws IllegalAccessException;
-
- /**
- * Set this double Field. If the field is static, <code>o</code> will be
- * ignored.
- *
- * @param o the object to set this Field on
- * @param value the value to set this Field to
- * @throws IllegalAccessException if you could not normally access this field
- * (i.e. it is not public)
- * @throws IllegalArgumentException if this is not a double field, or if
- * <code>o</code> is not an instance of the class declaring this
- * field
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static field triggered
- * class initialization, which then failed
- * @see #set(Object, Object)
- */
- public native void setDouble(Object o, double value)
- throws IllegalAccessException;
-
- /**
- * Return the generic type of the field. If the field type is not a generic
- * type, the method returns the same as <code>getType()</code>.
- *
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public Type getGenericType()
- {
- String signature = getSignature();
- if (signature == null)
- return getType();
- FieldSignatureParser p = new FieldSignatureParser(getDeclaringClass(),
- signature);
- return p.getFieldType();
- }
-
- /**
- * Return the String in the Signature attribute for this field. If there
- * is no Signature attribute, return null.
- */
- private native String getSignature();
-
- /**
- * @throws NullPointerException {@inheritDoc}
- * @since 1.5
- */
- public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
-
- return (T)declaredAnnotations().get(annotationClass);
- }
-
- /**
- * @since 1.5
- */
- public Annotation[] getDeclaredAnnotations() {
- return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
- }
-
- /**
- * Parses the annotations if they aren't parsed yet and stores them into
- * the declaredAnnotations map and return this map.
- */
- private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
-}
+++ /dev/null
-/* java.lang.reflect.Method - reflection of Java methods
- Copyright (C) 1998, 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.lang.reflect;
-
-import gnu.java.lang.ClassHelper;
-
-import gnu.java.lang.reflect.MethodSignatureParser;
-
-import java.lang.annotation.Annotation;
-import java.util.Map;
-import java.util.Arrays;
-
-/**
- * The Method class represents a member method of a class. It also allows
- * dynamic invocation, via reflection. This works for both static and
- * instance methods. Invocation on Method objects knows how to do
- * widening conversions, but throws {@link IllegalArgumentException} if
- * a narrowing conversion would be necessary. You can query for information
- * on this Method regardless of location, but invocation access may be limited
- * by Java language access controls. If you can't do it in the compiler, you
- * can't normally do it here either.<p>
- *
- * <B>Note:</B> This class returns and accepts types as Classes, even
- * primitive types; there are Class types defined that represent each
- * different primitive type. They are <code>java.lang.Boolean.TYPE,
- * java.lang.Byte.TYPE,</code>, also available as <code>boolean.class,
- * byte.class</code>, etc. These are not to be confused with the
- * classes <code>java.lang.Boolean, java.lang.Byte</code>, etc., which are
- * real classes.<p>
- *
- * Also note that this is not a serializable class. It is entirely feasible
- * to make it serializable using the Externalizable interface, but this is
- * on Sun, not me.
- *
- * @author John Keiser
- * @author Eric Blake <ebb9@email.byu.edu>
- * @see Member
- * @see Class
- * @see java.lang.Class#getMethod(String,Class[])
- * @see java.lang.Class#getDeclaredMethod(String,Class[])
- * @see java.lang.Class#getMethods()
- * @see java.lang.Class#getDeclaredMethods()
- * @since 1.1
- * @status updated to 1.4
- */
-public final class Method
-extends AccessibleObject implements Member, GenericDeclaration
-{
- Class clazz;
- String name;
- int slot;
-
- /**
- * Unparsed annotations.
- */
- private byte[] annotations = null;
-
- /**
- * Unparsed parameter annotations.
- */
- private byte[] parameterAnnotations = null;
-
- /**
- * Unparsed annotation default value.
- */
- private byte[] annotationDefault = null;
-
- /**
- * Annotations get parsed the first time they are
- * accessed and are then cached it this map.
- */
- private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations = null;
-
- private static final int METHOD_MODIFIERS
- = Modifier.ABSTRACT | Modifier.FINAL | Modifier.NATIVE
- | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.PUBLIC
- | Modifier.STATIC | Modifier.STRICT | Modifier.SYNCHRONIZED;
-
- /**
- * Helper array for creating a new array from a java.util.Container.
- */
- private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
- new Annotation[0];
-
- /**
- * This class is uninstantiable.
- */
- private Method(Class declaringClass, String name, int slot)
- {
- this.clazz = declaringClass;
- this.name = name;
- this.slot = slot;
- }
-
- /**
- * Gets the class that declared this method, or the class where this method
- * is a non-inherited member.
- * @return the class that declared this member
- */
- public Class<?> getDeclaringClass()
- {
- return clazz;
- }
-
- /**
- * Gets the name of this method.
- * @return the name of this method
- */
- public String getName()
- {
- return name;
- }
-
- /**
- * Return the raw modifiers for this method.
- * @return the method's modifiers
- */
- private native int getModifiersInternal();
-
- /**
- * Gets the modifiers this method uses. Use the <code>Modifier</code>
- * class to interpret the values. A method can only have a subset of the
- * following modifiers: public, private, protected, abstract, static,
- * final, synchronized, native, and strictfp.
- *
- * @return an integer representing the modifiers to this Member
- * @see Modifier
- */
- public int getModifiers()
- {
- return getModifiersInternal() & METHOD_MODIFIERS;
- }
-
- /**
- * Return true if this method is a bridge method. A bridge method
- * is generated by the compiler in some situations involving
- * generics and inheritance.
- * @since 1.5
- */
- public boolean isBridge()
- {
- return (getModifiersInternal() & Modifier.BRIDGE) != 0;
- }
-
- /**
- * Return true if this method is synthetic, false otherwise.
- * @since 1.5
- */
- public boolean isSynthetic()
- {
- return (getModifiersInternal() & Modifier.SYNTHETIC) != 0;
- }
-
- /**
- * Return true if this is a varargs method, that is if
- * the method takes a variable number of arguments.
- * @since 1.5
- */
- public boolean isVarArgs()
- {
- return (getModifiersInternal() & Modifier.VARARGS) != 0;
- }
-
- /**
- * Gets the return type of this method.
- * @return the type of this method
- */
- public native Class<?> getReturnType();
-
- /**
- * Get the parameter list for this method, in declaration order. If the
- * method takes no parameters, returns a 0-length array (not null).
- *
- * @return a list of the types of the method's parameters
- */
- public native Class<?>[] getParameterTypes();
-
- /**
- * Get the exception types this method says it throws, in no particular
- * order. If the method has no throws clause, returns a 0-length array
- * (not null).
- *
- * @return a list of the types in the method's throws clause
- */
- public native Class<?>[] getExceptionTypes();
-
- /**
- * Compare two objects to see if they are semantically equivalent.
- * Two Methods are semantically equivalent if they have the same declaring
- * class, name, parameter list, and return type.
- *
- * @param o the object to compare to
- * @return <code>true</code> if they are equal; <code>false</code> if not
- */
- public boolean equals(Object o)
- {
- // Implementation note:
- // The following is a correct but possibly slow implementation.
- //
- // This class has a private field 'slot' that could be used by
- // the VM implementation to "link" a particular method to a Class.
- // In that case equals could be simply implemented as:
- //
- // if (o instanceof Method)
- // {
- // Method m = (Method)o;
- // return m.clazz == this.clazz
- // && m.slot == this.slot;
- // }
- // return false;
- //
- // If a VM uses the Method class as their native/internal representation
- // then just using the following would be optimal:
- //
- // return this == o;
- //
- if (!(o instanceof Method))
- return false;
- Method that = (Method)o;
- if (this.getDeclaringClass() != that.getDeclaringClass())
- return false;
- if (!this.getName().equals(that.getName()))
- return false;
- if (this.getReturnType() != that.getReturnType())
- return false;
- if (!Arrays.equals(this.getParameterTypes(), that.getParameterTypes()))
- return false;
- return true;
- }
-
- /**
- * Get the hash code for the Method. The Method hash code is the hash code
- * of its name XOR'd with the hash code of its class name.
- *
- * @return the hash code for the object
- */
- public int hashCode()
- {
- return getDeclaringClass().getName().hashCode() ^ getName().hashCode();
- }
-
- /**
- * Get a String representation of the Method. A Method's String
- * representation is "<modifiers> <returntype>
- * <methodname>(<paramtypes>) throws <exceptions>", where
- * everything after ')' is omitted if there are no exceptions.<br> Example:
- * <code>public static int run(java.lang.Runnable,int)</code>
- *
- * @return the String representation of the Method
- */
- public String toString()
- {
- // 128 is a reasonable buffer initial size for constructor
- StringBuilder sb = new StringBuilder(128);
- Modifier.toString(getModifiers(), sb).append(' ');
- sb.append(ClassHelper.getUserName(getReturnType())).append(' ');
- sb.append(getDeclaringClass().getName()).append('.');
- sb.append(getName()).append('(');
- Class[] c = getParameterTypes();
- if (c.length > 0)
- {
- sb.append(ClassHelper.getUserName(c[0]));
- for (int i = 1; i < c.length; i++)
- sb.append(',').append(ClassHelper.getUserName(c[i]));
- }
- sb.append(')');
- c = getExceptionTypes();
- if (c.length > 0)
- {
- sb.append(" throws ").append(c[0].getName());
- for (int i = 1; i < c.length; i++)
- sb.append(',').append(c[i].getName());
- }
- return sb.toString();
- }
-
- public String toGenericString()
- {
- // 128 is a reasonable buffer initial size for constructor
- StringBuilder sb = new StringBuilder(128);
- Modifier.toString(getModifiers(), sb).append(' ');
- Constructor.addTypeParameters(sb, getTypeParameters());
- sb.append(getGenericReturnType()).append(' ');
- sb.append(getDeclaringClass().getName()).append('.');
- sb.append(getName()).append('(');
- Type[] types = getGenericParameterTypes();
- if (types.length > 0)
- {
- sb.append(types[0]);
- for (int i = 1; i < types.length; i++)
- sb.append(',').append(types[i]);
- }
- sb.append(')');
- types = getGenericExceptionTypes();
- if (types.length > 0)
- {
- sb.append(" throws ").append(types[0]);
- for (int i = 1; i < types.length; i++)
- sb.append(',').append(types[i]);
- }
- return sb.toString();
- }
-
- /**
- * Invoke the method. Arguments are automatically unwrapped and widened,
- * and the result is automatically wrapped, if needed.<p>
- *
- * If the method is static, <code>o</code> will be ignored. Otherwise,
- * the method uses dynamic lookup as described in JLS 15.12.4.4. You cannot
- * mimic the behavior of nonvirtual lookup (as in super.foo()). This means
- * you will get a <code>NullPointerException</code> if <code>o</code> is
- * null, and an <code>IllegalArgumentException</code> if it is incompatible
- * with the declaring class of the method. If the method takes 0 arguments,
- * you may use null or a 0-length array for <code>args</code>.<p>
- *
- * Next, if this Method enforces access control, your runtime context is
- * evaluated, and you may have an <code>IllegalAccessException</code> if
- * you could not acces this method in similar compiled code. If the method
- * is static, and its class is uninitialized, you trigger class
- * initialization, which may end in a
- * <code>ExceptionInInitializerError</code>.<p>
- *
- * Finally, the method is invoked. If it completes normally, the return value
- * will be null for a void method, a wrapped object for a primitive return
- * method, or the actual return of an Object method. If it completes
- * abruptly, the exception is wrapped in an
- * <code>InvocationTargetException</code>.
- *
- * @param o the object to invoke the method on
- * @param args the arguments to the method
- * @return the return value of the method, wrapped in the appropriate
- * wrapper if it is primitive
- * @throws IllegalAccessException if the method could not normally be called
- * by the Java code (i.e. it is not public)
- * @throws IllegalArgumentException if the number of arguments is incorrect;
- * if the arguments types are wrong even with a widening conversion;
- * or if <code>o</code> is not an instance of the class or interface
- * declaring this method
- * @throws InvocationTargetException if the method throws an exception
- * @throws NullPointerException if <code>o</code> is null and this field
- * requires an instance
- * @throws ExceptionInInitializerError if accessing a static method triggered
- * class initialization, which then failed
- */
- public Object invoke(Object o, Object... args)
- throws IllegalAccessException, InvocationTargetException
- {
- return invokeNative(o, args, clazz, slot);
- }
-
- /*
- * NATIVE HELPERS
- */
-
- private native Object invokeNative(Object o, Object[] args,
- Class declaringClass, int slot)
- throws IllegalAccessException, InvocationTargetException;
-
- /**
- * Returns an array of <code>TypeVariable</code> objects that represents
- * the type variables declared by this constructor, in declaration order.
- * An array of size zero is returned if this class has no type
- * variables.
- *
- * @return the type variables associated with this class.
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public TypeVariable<Method>[] getTypeParameters()
- {
- String sig = getSignature();
- if (sig == null)
- return new TypeVariable[0];
- MethodSignatureParser p = new MethodSignatureParser(this, sig);
- return p.getTypeParameters();
- }
-
- /**
- * Return the String in the Signature attribute for this method. If there
- * is no Signature attribute, return null.
- */
- private native String getSignature();
-
- /**
- * Returns an array of <code>Type</code> objects that represents
- * the exception types declared by this method, in declaration order.
- * An array of size zero is returned if this method declares no
- * exceptions.
- *
- * @return the exception types declared by this method.
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public Type[] getGenericExceptionTypes()
- {
- String sig = getSignature();
- if (sig == null)
- return getExceptionTypes();
- MethodSignatureParser p = new MethodSignatureParser(this, sig);
- return p.getGenericExceptionTypes();
- }
-
- /**
- * Returns an array of <code>Type</code> objects that represents
- * the parameter list for this method, in declaration order.
- * An array of size zero is returned if this method takes no
- * parameters.
- *
- * @return a list of the types of the method's parameters
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public Type[] getGenericParameterTypes()
- {
- String sig = getSignature();
- if (sig == null)
- return getParameterTypes();
- MethodSignatureParser p = new MethodSignatureParser(this, sig);
- return p.getGenericParameterTypes();
- }
-
- /**
- * Returns the return type of this method.
- *
- * @return the return type of this method
- * @throws GenericSignatureFormatError if the generic signature does
- * not conform to the format specified in the Virtual Machine
- * specification, version 3.
- * @since 1.5
- */
- public Type getGenericReturnType()
- {
- String sig = getSignature();
- if (sig == null)
- return getReturnType();
- MethodSignatureParser p = new MethodSignatureParser(this, sig);
- return p.getGenericReturnType();
- }
-
- /**
- * If this method is an annotation method, returns the default
- * value for the method. If there is no default value, or if the
- * method is not a member of an annotation type, returns null.
- * Primitive types are wrapped.
- *
- * @throws TypeNotPresentException if the method returns a Class,
- * and the class cannot be found
- *
- * @since 1.5
- */
- public native Object getDefaultValue();
-
- /**
- * @throws NullPointerException {@inheritDoc}
- * @since 1.5
- */
- public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
- if (annotationClass == null)
- throw new NullPointerException();
-
- return (T)declaredAnnotations().get(annotationClass);
- }
-
- /**
- * @since 1.5
- */
- public Annotation[] getDeclaredAnnotations() {
- return declaredAnnotations().values().toArray(EMPTY_ANNOTATIONS_ARRAY);
- }
-
- /**
- * Parses the annotations if they aren't parsed yet and stores them into
- * the declaredAnnotations map and return this map.
- */
- private synchronized native Map<Class<? extends Annotation>, Annotation> declaredAnnotations();
-
- /**
- * Returns an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by
- * this <tt>Method</tt> object. (Returns an array of length zero if the
- * underlying method is parameterless. If the method has one or more
- * parameters, a nested array of length zero is returned for each parameter
- * with no annotations.) The annotation objects contained in the returned
- * arrays are serializable. The caller of this method is free to modify
- * the returned arrays; it will have no effect on the arrays returned to
- * other callers.
- *
- * @return an array of arrays that represent the annotations on the formal
- * parameters, in declaration order, of the method represented by this
- * Method object
- * @since 1.5
- */
- public native Annotation[][] getParameterAnnotations();
-}
+++ /dev/null
-/* VMAccessController.java -- VM-specific access controller methods.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
-
-package java.security;
-
-import java.util.HashSet;
-import java.util.LinkedList;
-
-final class VMAccessController
-{
-
- // Fields.
- // -------------------------------------------------------------------------
-
- /**
- * This is a per-thread stack of AccessControlContext objects (which can
- * be null) for each call to AccessController.doPrivileged in each thread's
- * call stack. We use this to remember which context object corresponds to
- * which call.
- */
- private static final ThreadLocal contexts = new ThreadLocal();
-
- /**
- * This is a Boolean that, if set, tells getContext that it has already
- * been called once, allowing us to handle recursive permission checks
- * caused by methods getContext calls.
- */
- private static final ThreadLocal inGetContext = new ThreadLocal();
-
- /**
- * And we return this all-permissive context to ensure that privileged
- * methods called from getContext succeed.
- */
- private static final AccessControlContext DEFAULT_CONTEXT;
- static
- {
- CodeSource source = new CodeSource(null, null);
- Permissions permissions = new Permissions();
- permissions.add(new AllPermission());
- ProtectionDomain[] domain = new ProtectionDomain[] {
- new ProtectionDomain(source, permissions)
- };
- DEFAULT_CONTEXT = new AccessControlContext(domain);
- }
-
- private static final boolean DEBUG = gnu.classpath.Configuration.DEBUG;
- private static void debug(String msg)
- {
- System.err.print(">>> VMAccessController: ");
- System.err.println(msg);
- }
-
- // Constructors.
- // -------------------------------------------------------------------------
-
- private VMAccessController() { }
-
- // Class methods.
- // -------------------------------------------------------------------------
-
- /**
- * Relate a class (which should be an instance of {@link PrivilegedAction}
- * with an access control context. This method is used by {@link
- * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}
- * to set up the context that will be returned by {@link #getContext()}.
- * This method relates the class to the current thread, so contexts
- * pushed from one thread will not be available to another.
- *
- * @param acc The access control context.
- */
- static void pushContext (AccessControlContext acc)
- {
- if (DEBUG)
- debug("pushing " + acc);
- LinkedList stack = (LinkedList) contexts.get();
- if (stack == null)
- {
- if (DEBUG)
- debug("no stack... creating ");
- stack = new LinkedList();
- contexts.set(stack);
- }
- stack.addFirst(acc);
- }
-
- /**
- * Removes the relation of a class to an {@link AccessControlContext}.
- * This method is used by {@link AccessController} when exiting from a
- * call to {@link
- * AccessController#doPrivileged(java.security.PrivilegedAction,java.security.AccessControlContext)}.
- */
- static void popContext()
- {
- if (DEBUG)
- debug("popping context");
-
- // Stack should never be null, nor should it be empty, if this method
- // and its counterpart has been called properly.
- LinkedList stack = (LinkedList) contexts.get();
- if (stack != null)
- {
- stack.removeFirst();
- if (stack.isEmpty())
- contexts.set(null);
- }
- else if (DEBUG)
- {
- debug("no stack during pop?????");
- }
- }
-
- /**
- * Examine the method stack of the currently running thread, and create
- * an {@link AccessControlContext} filled in with the appropriate {@link
- * ProtectionDomain} objects given this stack.
- *
- * @return The context.
- */
- static AccessControlContext getContext()
- {
- // If we are already in getContext, but called a method that needs
- // a permission check, return the all-permissive context so methods
- // called from here succeed.
- //
- // XXX is this necessary? We should verify if there are any calls in
- // the stack below this method that require permission checks.
- Boolean inCall = (Boolean) inGetContext.get();
- if (inCall != null && inCall.booleanValue())
- {
- if (DEBUG)
- debug("already in getContext");
- return DEFAULT_CONTEXT;
- }
-
- inGetContext.set(Boolean.TRUE);
-
- Object[][] stack = getStack();
- Class[] classes = (Class[]) stack[0];
- String[] methods = (String[]) stack[1];
-
- if (DEBUG)
- debug("got trace of length " + classes.length);
-
- HashSet domains = new HashSet();
- HashSet seenDomains = new HashSet();
- AccessControlContext context = null;
- int privileged = 0;
-
- // We walk down the stack, adding each ProtectionDomain for each
- // class in the call stack. If we reach a call to doPrivileged,
- // we don't add any more stack frames. We skip the first three stack
- // frames, since they comprise the calls to getStack, getContext,
- // and AccessController.getContext.
- for (int i = 3; i < classes.length && privileged < 2; i++)
- {
- Class clazz = classes[i];
- String method = methods[i];
-
- if (DEBUG)
- {
- debug("checking " + clazz + "." + method);
- // subject to getClassLoader RuntimePermission
- debug("loader = " + clazz.getClassLoader());
- }
-
- // If the previous frame was a call to doPrivileged, then this is
- // the last frame we look at.
- if (privileged == 1)
- privileged = 2;
-
- if (clazz.equals (AccessController.class)
- && method.equals ("doPrivileged"))
- {
- // If there was a call to doPrivileged with a supplied context,
- // return that context. If using JAAS doAs*, it should be
- // a context with a SubjectDomainCombiner
- LinkedList l = (LinkedList) contexts.get();
- if (l != null)
- context = (AccessControlContext) l.getFirst();
- privileged = 1;
- }
-
- // subject to getProtectionDomain RuntimePermission
- ProtectionDomain domain = clazz.getProtectionDomain();
-
- if (domain == null)
- continue;
- if (seenDomains.contains(domain))
- continue;
- seenDomains.add(domain);
-
- // Create a static snapshot of this domain, which may change over time
- // if the current policy changes.
- domains.add(new ProtectionDomain(domain.getCodeSource(),
- domain.getPermissions()));
- }
-
- if (DEBUG)
- debug("created domains: " + domains);
-
- ProtectionDomain[] result = (ProtectionDomain[])
- domains.toArray(new ProtectionDomain[domains.size()]);
-
- if (context != null)
- {
- DomainCombiner dc = context.getDomainCombiner ();
- // If the supplied context had no explicit DomainCombiner, use
- // our private version, which computes the intersection of the
- // context's domains with the derived set.
- if (dc == null)
- context = new AccessControlContext
- (IntersectingDomainCombiner.SINGLETON.combine
- (result, context.getProtectionDomains ()));
- // Use the supplied DomainCombiner. This should be secure,
- // because only trusted code may create an
- // AccessControlContext with a custom DomainCombiner.
- else
- context = new AccessControlContext (result, context, dc);
- }
- // No context was supplied. Return the derived one.
- else
- context = new AccessControlContext (result);
-
- inGetContext.set(Boolean.FALSE);
- return context;
- }
-
- /**
- * Returns a snapshot of the current call stack as a pair of arrays:
- * the first an array of classes in the call stack, the second an array
- * of strings containing the method names in the call stack. The two
- * arrays match up, meaning that method <i>i</i> is declared in class
- * <i>i</i>. The arrays are clean; it will only contain Java methods,
- * and no element of the list should be null.
- *
- * <p>The default implementation returns an empty stack, which will be
- * interpreted as having no permissions whatsoever.
- *
- * @return A pair of arrays describing the current call stack. The first
- * element is an array of Class objects, and the second is an array
- * of Strings comprising the method names.
- */
-// private static Object[][] getStack()
-// {
-// return new Object[][] { new Class[0], new String[0] };
-// }
- private native static Object[][] getStack();
-}
+++ /dev/null
-/*
- * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.misc;
-
-import java.security.*;
-import java.lang.reflect.*;
-
-
-/**
- * A collection of methods for performing low-level, unsafe operations.
- * Although the class and all methods are public, use of this class is
- * limited because only trusted code can obtain instances of it.
- *
- * @author John R. Rose
- * @version 1.28, 07/06/04
- * @see #getUnsafe
- */
-
-public final class Unsafe {
-
- private static native void registerNatives();
- static {
- registerNatives();
-// sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
- }
-
- private Unsafe() {}
-
- private static final Unsafe theUnsafe = new Unsafe();
-
- /**
- * Provides the caller with the capability of performing unsafe
- * operations.
- *
- * <p> The returned <code>Unsafe</code> object should be carefully guarded
- * by the caller, since it can be used to read and write data at arbitrary
- * memory addresses. It must never be passed to untrusted code.
- *
- * <p> Most methods in this class are very low-level, and correspond to a
- * small number of hardware instructions (on typical machines). Compilers
- * are encouraged to optimize these methods accordingly.
- *
- * <p> Here is a suggested idiom for using unsafe operations:
- *
- * <blockquote><pre>
- * class MyTrustedClass {
- * private static final Unsafe unsafe = Unsafe.getUnsafe();
- * ...
- * private long myCountAddress = ...;
- * public int getCount() { return unsafe.getByte(myCountAddress); }
- * }
- * </pre></blockquote>
- *
- * (It may assist compilers to make the local variable be
- * <code>final</code>.)
- *
- * @exception SecurityException if a security manager exists and its
- * <code>checkPropertiesAccess</code> method doesn't allow
- * access to the system properties.
- */
- public static Unsafe getUnsafe() {
- Class cc = sun.reflect.Reflection.getCallerClass(2);
- if (cc.getClassLoader() != null)
- throw new SecurityException("Unsafe");
- return theUnsafe;
- }
-
- /// peek and poke operations
- /// (compilers should optimize these to memory ops)
-
- // These work on object fields in the Java heap.
- // They will not work on elements of packed arrays.
-
- /**
- * Fetches a value from a given Java variable.
- * More specifically, fetches a field or array element within the given
- * object <code>o</code> at the given offset, or (if <code>o</code> is
- * null) from the memory address whose numerical value is the given
- * offset.
- * <p>
- * The results are undefined unless one of the following cases is true:
- * <ul>
- * <li>The offset was obtained from {@link #objectFieldOffset} on
- * the {@link java.lang.reflect.Field} of some Java field and the object
- * referred to by <code>o</code> is of a class compatible with that
- * field's class.
- *
- * <li>The offset and object reference <code>o</code> (either null or
- * non-null) were both obtained via {@link #staticFieldOffset}
- * and {@link #staticFieldBase} (respectively) from the
- * reflective {@link Field} representation of some Java field.
- *
- * <li>The object referred to by <code>o</code> is an array, and the offset
- * is an integer of the form <code>B+N*S</code>, where <code>N</code> is
- * a valid index into the array, and <code>B</code> and <code>S</code> are
- * the values obtained by {@link #arrayBaseOffset} and {@link
- * #arrayIndexScale} (respectively) from the array's class. The value
- * referred to is the <code>N</code><em>th</em> element of the array.
- *
- * </ul>
- * <p>
- * If one of the above cases is true, the call references a specific Java
- * variable (field or array element). However, the results are undefined
- * if that variable is not in fact of the type returned by this method.
- * <p>
- * This method refers to a variable by means of two parameters, and so
- * it provides (in effect) a <em>double-register</em> addressing mode
- * for Java variables. When the object reference is null, this method
- * uses its offset as an absolute address. This is similar in operation
- * to methods such as {@link #getInt(long)}, which provide (in effect) a
- * <em>single-register</em> addressing mode for non-Java variables.
- * However, because Java variables may have a different layout in memory
- * from non-Java variables, programmers should not assume that these
- * two addressing modes are ever equivalent. Also, programmers should
- * remember that offsets from the double-register addressing mode cannot
- * be portably confused with longs used in the single-register addressing
- * mode.
- *
- * @param o Java heap object in which the variable resides, if any, else
- * null
- * @param offset indication of where the variable resides in a Java heap
- * object, if any, else a memory address locating the variable
- * statically
- * @return the value fetched from the indicated Java variable
- * @throws RuntimeException No defined exceptions are thrown, not even
- * {@link NullPointerException}
- */
- public native int getInt(Object o, long offset);
-
- /**
- * Stores a value into a given Java variable.
- * <p>
- * The first two parameters are interpreted exactly as with
- * {@link #getInt(Object, long)} to refer to a specific
- * Java variable (field or array element). The given value
- * is stored into that variable.
- * <p>
- * The variable must be of the same type as the method
- * parameter <code>x</code>.
- *
- * @param o Java heap object in which the variable resides, if any, else
- * null
- * @param offset indication of where the variable resides in a Java heap
- * object, if any, else a memory address locating the variable
- * statically
- * @param x the value to store into the indicated Java variable
- * @throws RuntimeException No defined exceptions are thrown, not even
- * {@link NullPointerException}
- */
- public native void putInt(Object o, long offset, int x);
-
- /**
- * Fetches a reference value from a given Java variable.
- * @see #getInt(Object, long)
- */
- public native Object getObject(Object o, long offset);
-
- /**
- * Stores a reference value into a given Java variable.
- * <p>
- * Unless the reference <code>x</code> being stored is either null
- * or matches the field type, the results are undefined.
- * If the reference <code>o</code> is non-null, car marks or
- * other store barriers for that object (if the VM requires them)
- * are updated.
- * @see #putInt(Object, int, int)
- */
- public native void putObject(Object o, long offset, Object x);
-
- /** @see #getInt(Object, long) */
- public native boolean getBoolean(Object o, long offset);
- /** @see #putInt(Object, int, int) */
- public native void putBoolean(Object o, long offset, boolean x);
- /** @see #getInt(Object, long) */
- public native byte getByte(Object o, long offset);
- /** @see #putInt(Object, int, int) */
- public native void putByte(Object o, long offset, byte x);
- /** @see #getInt(Object, long) */
- public native short getShort(Object o, long offset);
- /** @see #putInt(Object, int, int) */
- public native void putShort(Object o, long offset, short x);
- /** @see #getInt(Object, long) */
- public native char getChar(Object o, long offset);
- /** @see #putInt(Object, int, int) */
- public native void putChar(Object o, long offset, char x);
- /** @see #getInt(Object, long) */
- public native long getLong(Object o, long offset);
- /** @see #putInt(Object, int, int) */
- public native void putLong(Object o, long offset, long x);
- /** @see #getInt(Object, long) */
- public native float getFloat(Object o, long offset);
- /** @see #putInt(Object, int, int) */
- public native void putFloat(Object o, long offset, float x);
- /** @see #getInt(Object, long) */
- public native double getDouble(Object o, long offset);
- /** @see #putInt(Object, int, int) */
- public native void putDouble(Object o, long offset, double x);
-
- /**
- * This method, like all others with 32-bit offsets, was native
- * in a previous release but is now a wrapper which simply casts
- * the offset to a long value. It provides backward compatibility
- * with bytecodes compiled against 1.4.
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public int getInt(Object o, int offset) {
- return getInt(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putInt(Object o, int offset, int x) {
- putInt(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public Object getObject(Object o, int offset) {
- return getObject(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putObject(Object o, int offset, Object x) {
- putObject(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public boolean getBoolean(Object o, int offset) {
- return getBoolean(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putBoolean(Object o, int offset, boolean x) {
- putBoolean(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public byte getByte(Object o, int offset) {
- return getByte(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putByte(Object o, int offset, byte x) {
- putByte(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public short getShort(Object o, int offset) {
- return getShort(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putShort(Object o, int offset, short x) {
- putShort(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public char getChar(Object o, int offset) {
- return getChar(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putChar(Object o, int offset, char x) {
- putChar(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public long getLong(Object o, int offset) {
- return getLong(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putLong(Object o, int offset, long x) {
- putLong(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public float getFloat(Object o, int offset) {
- return getFloat(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putFloat(Object o, int offset, float x) {
- putFloat(o, (long)offset, x);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public double getDouble(Object o, int offset) {
- return getDouble(o, (long)offset);
- }
-
- /**
- * @deprecated As of 1.4.1, cast the 32-bit offset argument to a long.
- * See {@link #staticFieldOffset}.
- */
- @Deprecated
- public void putDouble(Object o, int offset, double x) {
- putDouble(o, (long)offset, x);
- }
-
- // These work on values in the C heap.
-
- /**
- * Fetches a value from a given memory address. If the address is zero, or
- * does not point into a block obtained from {@link #allocateMemory}, the
- * results are undefined.
- *
- * @see #allocateMemory
- */
- public native byte getByte(long address);
-
- /**
- * Stores a value into a given memory address. If the address is zero, or
- * does not point into a block obtained from {@link #allocateMemory}, the
- * results are undefined.
- *
- * @see #getByte(long)
- */
- public native void putByte(long address, byte x);
-
- /** @see #getByte(long) */
- public native short getShort(long address);
- /** @see #putByte(long, byte) */
- public native void putShort(long address, short x);
- /** @see #getByte(long) */
- public native char getChar(long address);
- /** @see #putByte(long, byte) */
- public native void putChar(long address, char x);
- /** @see #getByte(long) */
- public native int getInt(long address);
- /** @see #putByte(long, byte) */
- public native void putInt(long address, int x);
- /** @see #getByte(long) */
- public native long getLong(long address);
- /** @see #putByte(long, byte) */
- public native void putLong(long address, long x);
- /** @see #getByte(long) */
- public native float getFloat(long address);
- /** @see #putByte(long, byte) */
- public native void putFloat(long address, float x);
- /** @see #getByte(long) */
- public native double getDouble(long address);
- /** @see #putByte(long, byte) */
- public native void putDouble(long address, double x);
-
- /**
- * Fetches a native pointer from a given memory address. If the address is
- * zero, or does not point into a block obtained from {@link
- * #allocateMemory}, the results are undefined.
- *
- * <p> If the native pointer is less than 64 bits wide, it is extended as
- * an unsigned number to a Java long. The pointer may be indexed by any
- * given byte offset, simply by adding that offset (as a simple integer) to
- * the long representing the pointer. The number of bytes actually read
- * from the target address maybe determined by consulting {@link
- * #addressSize}.
- *
- * @see #allocateMemory
- */
- public native long getAddress(long address);
-
- /**
- * Stores a native pointer into a given memory address. If the address is
- * zero, or does not point into a block obtained from {@link
- * #allocateMemory}, the results are undefined.
- *
- * <p> The number of bytes actually written at the target address maybe
- * determined by consulting {@link #addressSize}.
- *
- * @see #getAddress(long)
- */
- public native void putAddress(long address, long x);
-
- /// wrappers for malloc, realloc, free:
-
- /**
- * Allocates a new block of native memory, of the given size in bytes. The
- * contents of the memory are uninitialized; they will generally be
- * garbage. The resulting native pointer will never be zero, and will be
- * aligned for all value types. Dispose of this memory by calling {@link
- * #freeMemory}, or resize it with {@link #reallocateMemory}.
- *
- * @throws IllegalArgumentException if the size is negative or too large
- * for the native size_t type
- *
- * @throws OutOfMemoryError if the allocation is refused by the system
- *
- * @see #getByte(long)
- * @see #putByte(long, byte)
- */
- public native long allocateMemory(long bytes);
-
- /**
- * Resizes a new block of native memory, to the given size in bytes. The
- * contents of the new block past the size of the old block are
- * uninitialized; they will generally be garbage. The resulting native
- * pointer will be zero if and only if the requested size is zero. The
- * resulting native pointer will be aligned for all value types. Dispose
- * of this memory by calling {@link #freeMemory}, or resize it with {@link
- * #reallocateMemory}. The address passed to this method may be null, in
- * which case an allocation will be performed.
- *
- * @throws IllegalArgumentException if the size is negative or too large
- * for the native size_t type
- *
- * @throws OutOfMemoryError if the allocation is refused by the system
- *
- * @see #allocateMemory
- */
- public native long reallocateMemory(long address, long bytes);
-
- /**
- * Sets all bytes in a given block of memory to a fixed value
- * (usually zero).
- *
- * <p>This method determines a block's base address by means of two parameters,
- * and so it provides (in effect) a <em>double-register</em> addressing mode,
- * as discussed in {@link #getInt(Object,long)}. When the object reference is null,
- * the offset supplies an absolute base address.
- *
- * <p>The stores are in coherent (atomic) units of a size determined
- * by the address and length parameters. If the effective address and
- * length are all even modulo 8, the stores take place in 'long' units.
- * If the effective address and length are (resp.) even modulo 4 or 2,
- * the stores take place in units of 'int' or 'short'.
- *
- * @since 1.7
- */
- public native void setMemory(Object o, long offset, long bytes, byte value);
-
- /**
- * Sets all bytes in a given block of memory to a fixed value
- * (usually zero). This provides a <em>single-register</em> addressing mode,
- * as discussed in {@link #getInt(Object,long)}.
- *
- * <p>Equivalent to <code>setMemory(null, address, bytes, value)</code>.
- */
- public void setMemory(long address, long bytes, byte value) {
- setMemory(null, address, bytes, value);
- }
-
- /**
- * Sets all bytes in a given block of memory to a copy of another
- * block.
- *
- * <p>This method determines each block's base address by means of two parameters,
- * and so it provides (in effect) a <em>double-register</em> addressing mode,
- * as discussed in {@link #getInt(Object,long)}. When the object reference is null,
- * the offset supplies an absolute base address.
- *
- * <p>The transfers are in coherent (atomic) units of a size determined
- * by the address and length parameters. If the effective addresses and
- * length are all even modulo 8, the transfer takes place in 'long' units.
- * If the effective addresses and length are (resp.) even modulo 4 or 2,
- * the transfer takes place in units of 'int' or 'short'.
- *
- * @since 1.7
- */
- public native void copyMemory(Object srcBase, long srcOffset,
- Object destBase, long destOffset,
- long bytes);
- /**
- * Sets all bytes in a given block of memory to a copy of another
- * block. This provides a <em>single-register</em> addressing mode,
- * as discussed in {@link #getInt(Object,long)}.
- *
- * Equivalent to <code>copyMemory(null, srcAddress, null, destAddress, bytes)</code>.
- */
- public void copyMemory(long srcAddress, long destAddress, long bytes) {
- copyMemory(null, srcAddress, null, destAddress, bytes);
- }
-
- /**
- * Disposes of a block of native memory, as obtained from {@link
- * #allocateMemory} or {@link #reallocateMemory}. The address passed to
- * this method may be null, in which case no action is taken.
- *
- * @see #allocateMemory
- */
- public native void freeMemory(long address);
-
- /// random queries
-
- /**
- * This constant differs from all results that will ever be returned from
- * {@link #staticFieldOffset}, {@link #objectFieldOffset},
- * or {@link #arrayBaseOffset}.
- */
- public static final int INVALID_FIELD_OFFSET = -1;
-
- /**
- * Returns the offset of a field, truncated to 32 bits.
- * This method is implemented as follows:
- * <blockquote><pre>
- * public int fieldOffset(Field f) {
- * if (Modifier.isStatic(f.getModifiers()))
- * return (int) staticFieldOffset(f);
- * else
- * return (int) objectFieldOffset(f);
- * }
- * </pre></blockquote>
- * @deprecated As of 1.4.1, use {@link #staticFieldOffset} for static
- * fields and {@link #objectFieldOffset} for non-static fields.
- */
- @Deprecated
- public int fieldOffset(Field f) {
- if (Modifier.isStatic(f.getModifiers()))
- return (int) staticFieldOffset(f);
- else
- return (int) objectFieldOffset(f);
- }
-
- /**
- * Returns the base address for accessing some static field
- * in the given class. This method is implemented as follows:
- * <blockquote><pre>
- * public Object staticFieldBase(Class c) {
- * Field[] fields = c.getDeclaredFields();
- * for (int i = 0; i < fields.length; i++) {
- * if (Modifier.isStatic(fields[i].getModifiers())) {
- * return staticFieldBase(fields[i]);
- * }
- * }
- * return null;
- * }
- * </pre></blockquote>
- * @deprecated As of 1.4.1, use {@link #staticFieldBase(Field)}
- * to obtain the base pertaining to a specific {@link Field}.
- * This method works only for JVMs which store all statics
- * for a given class in one place.
- */
- @Deprecated
- public Object staticFieldBase(Class c) {
- Field[] fields = c.getDeclaredFields();
- for (int i = 0; i < fields.length; i++) {
- if (Modifier.isStatic(fields[i].getModifiers())) {
- return staticFieldBase(fields[i]);
- }
- }
- return null;
- }
-
- /**
- * Report the location of a given field in the storage allocation of its
- * class. Do not expect to perform any sort of arithmetic on this offset;
- * it is just a cookie which is passed to the unsafe heap memory accessors.
- *
- * <p>Any given field will always have the same offset and base, and no
- * two distinct fields of the same class will ever have the same offset
- * and base.
- *
- * <p>As of 1.4.1, offsets for fields are represented as long values,
- * although the Sun JVM does not use the most significant 32 bits.
- * However, JVM implementations which store static fields at absolute
- * addresses can use long offsets and null base pointers to express
- * the field locations in a form usable by {@link #getInt(Object,long)}.
- * Therefore, code which will be ported to such JVMs on 64-bit platforms
- * must preserve all bits of static field offsets.
- * @see #getInt(Object, long)
- */
- public native long staticFieldOffset(Field f);
-
- /**
- * Report the location of a given static field, in conjunction with {@link
- * #staticFieldBase}.
- * <p>Do not expect to perform any sort of arithmetic on this offset;
- * it is just a cookie which is passed to the unsafe heap memory accessors.
- *
- * <p>Any given field will always have the same offset, and no two distinct
- * fields of the same class will ever have the same offset.
- *
- * <p>As of 1.4.1, offsets for fields are represented as long values,
- * although the Sun JVM does not use the most significant 32 bits.
- * It is hard to imagine a JVM technology which needs more than
- * a few bits to encode an offset within a non-array object,
- * However, for consistency with other methods in this class,
- * this method reports its result as a long value.
- * @see #getInt(Object, long)
- */
- public native long objectFieldOffset(Field f);
-
- /**
- * Report the location of a given static field, in conjunction with {@link
- * #staticFieldOffset}.
- * <p>Fetch the base "Object", if any, with which static fields of the
- * given class can be accessed via methods like {@link #getInt(Object,
- * long)}. This value may be null. This value may refer to an object
- * which is a "cookie", not guaranteed to be a real Object, and it should
- * not be used in any way except as argument to the get and put routines in
- * this class.
- */
- public native Object staticFieldBase(Field f);
-
- /**
- * Ensure the given class has been initialized. This is often
- * needed in conjunction with obtaining the static field base of a
- * class.
- */
- public native void ensureClassInitialized(Class c);
-
- /**
- * Report the offset of the first element in the storage allocation of a
- * given array class. If {@link #arrayIndexScale} returns a non-zero value
- * for the same class, you may use that scale factor, together with this
- * base offset, to form new offsets to access elements of arrays of the
- * given class.
- *
- * @see #getInt(Object, long)
- * @see #putInt(Object, long, int)
- */
- public native int arrayBaseOffset(Class arrayClass);
-
- /** The value of {@code arrayBaseOffset(boolean[].class)} */
- public static final int ARRAY_BOOLEAN_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(boolean[].class);
-
- /** The value of {@code arrayBaseOffset(byte[].class)} */
- public static final int ARRAY_BYTE_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(byte[].class);
-
- /** The value of {@code arrayBaseOffset(short[].class)} */
- public static final int ARRAY_SHORT_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(short[].class);
-
- /** The value of {@code arrayBaseOffset(char[].class)} */
- public static final int ARRAY_CHAR_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(char[].class);
-
- /** The value of {@code arrayBaseOffset(int[].class)} */
- public static final int ARRAY_INT_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(int[].class);
-
- /** The value of {@code arrayBaseOffset(long[].class)} */
- public static final int ARRAY_LONG_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(long[].class);
-
- /** The value of {@code arrayBaseOffset(float[].class)} */
- public static final int ARRAY_FLOAT_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(float[].class);
-
- /** The value of {@code arrayBaseOffset(double[].class)} */
- public static final int ARRAY_DOUBLE_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(double[].class);
-
- /** The value of {@code arrayBaseOffset(Object[].class)} */
- public static final int ARRAY_OBJECT_BASE_OFFSET
- = theUnsafe.arrayBaseOffset(Object[].class);
-
- /**
- * Report the scale factor for addressing elements in the storage
- * allocation of a given array class. However, arrays of "narrow" types
- * will generally not work properly with accessors like {@link
- * #getByte(Object, int)}, so the scale factor for such classes is reported
- * as zero.
- *
- * @see #arrayBaseOffset
- * @see #getInt(Object, long)
- * @see #putInt(Object, long, int)
- */
- public native int arrayIndexScale(Class arrayClass);
-
- /** The value of {@code arrayIndexScale(boolean[].class)} */
- public static final int ARRAY_BOOLEAN_INDEX_SCALE
- = theUnsafe.arrayIndexScale(boolean[].class);
-
- /** The value of {@code arrayIndexScale(byte[].class)} */
- public static final int ARRAY_BYTE_INDEX_SCALE
- = theUnsafe.arrayIndexScale(byte[].class);
-
- /** The value of {@code arrayIndexScale(short[].class)} */
- public static final int ARRAY_SHORT_INDEX_SCALE
- = theUnsafe.arrayIndexScale(short[].class);
-
- /** The value of {@code arrayIndexScale(char[].class)} */
- public static final int ARRAY_CHAR_INDEX_SCALE
- = theUnsafe.arrayIndexScale(char[].class);
-
- /** The value of {@code arrayIndexScale(int[].class)} */
- public static final int ARRAY_INT_INDEX_SCALE
- = theUnsafe.arrayIndexScale(int[].class);
-
- /** The value of {@code arrayIndexScale(long[].class)} */
- public static final int ARRAY_LONG_INDEX_SCALE
- = theUnsafe.arrayIndexScale(long[].class);
-
- /** The value of {@code arrayIndexScale(float[].class)} */
- public static final int ARRAY_FLOAT_INDEX_SCALE
- = theUnsafe.arrayIndexScale(float[].class);
-
- /** The value of {@code arrayIndexScale(double[].class)} */
- public static final int ARRAY_DOUBLE_INDEX_SCALE
- = theUnsafe.arrayIndexScale(double[].class);
-
- /** The value of {@code arrayIndexScale(Object[].class)} */
- public static final int ARRAY_OBJECT_INDEX_SCALE
- = theUnsafe.arrayIndexScale(Object[].class);
-
- /**
- * Report the size in bytes of a native pointer, as stored via {@link
- * #putAddress}. This value will be either 4 or 8. Note that the sizes of
- * other primitive types (as stored in native memory blocks) is determined
- * fully by their information content.
- */
- public native int addressSize();
-
- /** The value of {@code addressSize()} */
- public static final int ADDRESS_SIZE = theUnsafe.addressSize();
-
- /**
- * Report the size in bytes of a native memory page (whatever that is).
- * This value will always be a power of two.
- */
- public native int pageSize();
-
-
- /// random trusted operations from JNI:
-
- /**
- * Tell the VM to define a class, without security checks. By default, the
- * class loader and protection domain come from the caller's class.
- */
- public native Class defineClass(String name, byte[] b, int off, int len,
- ClassLoader loader,
- ProtectionDomain protectionDomain);
-
- public native Class defineClass(String name, byte[] b, int off, int len);
-
- /** Allocate an instance but do not run any constructor.
- Initializes the class if it has not yet been. */
- public native Object allocateInstance(Class cls)
- throws InstantiationException;
-
- /** Lock the object. It must get unlocked via {@link #monitorExit}. */
- public native void monitorEnter(Object o);
-
- /**
- * Unlock the object. It must have been locked via {@link
- * #monitorEnter}.
- */
- public native void monitorExit(Object o);
-
- /**
- * Tries to lock the object. Returns true or false to indicate
- * whether the lock succeeded. If it did, the object must be
- * unlocked via {@link #monitorExit}.
- */
- public native boolean tryMonitorEnter(Object o);
-
- /** Throw the exception without telling the verifier. */
- public native void throwException(Throwable ee);
-
-
- /**
- * Atomically update Java variable to <tt>x</tt> if it is currently
- * holding <tt>expected</tt>.
- * @return <tt>true</tt> if successful
- */
- public final native boolean compareAndSwapObject(Object o, long offset,
- Object expected,
- Object x);
-
- /**
- * Atomically update Java variable to <tt>x</tt> if it is currently
- * holding <tt>expected</tt>.
- * @return <tt>true</tt> if successful
- */
- public final native boolean compareAndSwapInt(Object o, long offset,
- int expected,
- int x);
-
- /**
- * Atomically update Java variable to <tt>x</tt> if it is currently
- * holding <tt>expected</tt>.
- * @return <tt>true</tt> if successful
- */
- public final native boolean compareAndSwapLong(Object o, long offset,
- long expected,
- long x);
-
- /**
- * Fetches a reference value from a given Java variable, with volatile
- * load semantics. Otherwise identical to {@link #getObject(Object, long)}
- */
- public native Object getObjectVolatile(Object o, long offset);
-
- /**
- * Stores a reference value into a given Java variable, with
- * volatile store semantics. Otherwise identical to {@link #putObject(Object, long, Object)}
- */
- public native void putObjectVolatile(Object o, long offset, Object x);
-
- /** Volatile version of {@link #getInt(Object, long)} */
- public native int getIntVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putInt(Object, long, int)} */
- public native void putIntVolatile(Object o, long offset, int x);
-
- /** Volatile version of {@link #getBoolean(Object, long)} */
- public native boolean getBooleanVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putBoolean(Object, long, boolean)} */
- public native void putBooleanVolatile(Object o, long offset, boolean x);
-
- /** Volatile version of {@link #getByte(Object, long)} */
- public native byte getByteVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putByte(Object, long, byte)} */
- public native void putByteVolatile(Object o, long offset, byte x);
-
- /** Volatile version of {@link #getShort(Object, long)} */
- public native short getShortVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putShort(Object, long, short)} */
- public native void putShortVolatile(Object o, long offset, short x);
-
- /** Volatile version of {@link #getChar(Object, long)} */
- public native char getCharVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putChar(Object, long, char)} */
- public native void putCharVolatile(Object o, long offset, char x);
-
- /** Volatile version of {@link #getLong(Object, long)} */
- public native long getLongVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putLong(Object, long, long)} */
- public native void putLongVolatile(Object o, long offset, long x);
-
- /** Volatile version of {@link #getFloat(Object, long)} */
- public native float getFloatVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putFloat(Object, long, float)} */
- public native void putFloatVolatile(Object o, long offset, float x);
-
- /** Volatile version of {@link #getDouble(Object, long)} */
- public native double getDoubleVolatile(Object o, long offset);
-
- /** Volatile version of {@link #putDouble(Object, long, double)} */
- public native void putDoubleVolatile(Object o, long offset, double x);
-
- /**
- * Version of {@link #putObjectVolatile(Object, long, Object)}
- * that does not guarantee immediate visibility of the store to
- * other threads. This method is generally only useful if the
- * underlying field is a Java volatile (or if an array cell, one
- * that is otherwise only accessed using volatile accesses).
- */
- public native void putOrderedObject(Object o, long offset, Object x);
-
- /** Ordered/Lazy version of {@link #putIntVolatile(Object, long, int)} */
- public native void putOrderedInt(Object o, long offset, int x);
-
- /** Ordered/Lazy version of {@link #putLongVolatile(Object, long, long)} */
- public native void putOrderedLong(Object o, long offset, long x);
-
- /**
- * Unblock the given thread blocked on <tt>park</tt>, or, if it is
- * not blocked, cause the subsequent call to <tt>park</tt> not to
- * block. Note: this operation is "unsafe" solely because the
- * caller must somehow ensure that the thread has not been
- * destroyed. Nothing special is usually required to ensure this
- * when called from Java (in which there will ordinarily be a live
- * reference to the thread) but this is not nearly-automatically
- * so when calling from native code.
- * @param thread the thread to unpark.
- *
- */
- public native void unpark(Object thread);
-
- /**
- * Block current thread, returning when a balancing
- * <tt>unpark</tt> occurs, or a balancing <tt>unpark</tt> has
- * already occurred, or the thread is interrupted, or, if not
- * absolute and time is not zero, the given time nanoseconds have
- * elapsed, or if absolute, the given deadline in milliseconds
- * since Epoch has passed, or spuriously (i.e., returning for no
- * "reason"). Note: This operation is in the Unsafe class only
- * because <tt>unpark</tt> is, so it would be strange to place it
- * elsewhere.
- */
- public native void park(boolean isAbsolute, long time);
-
- /**
- * Gets the load average in the system run queue assigned
- * to the available processors averaged over various periods of time.
- * This method retrieves the given <tt>nelem</tt> samples and
- * assigns to the elements of the given <tt>loadavg</tt> array.
- * The system imposes a maximum of 3 samples, representing
- * averages over the last 1, 5, and 15 minutes, respectively.
- *
- * @params loadavg an array of double of size nelems
- * @params nelems the number of samples to be retrieved and
- * must be 1 to 3.
- *
- * @return the number of samples actually retrieved; or -1
- * if the load average is unobtainable.
- */
- public native int getLoadAverage(double[] loadavg, int nelems);
-}
+++ /dev/null
-/*
- * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.reflect;
-
-import java.lang.reflect.*;
-
-/** Provides reflective access to the constant pools of classes.
- Currently this is needed to provide reflective access to annotations
- but may be used by other internal subsystems in the future. */
-
-public class ConstantPool {
- // Number of entries in this constant pool (= maximum valid constant pool index)
- public int getSize() { return getSize0 (constantPoolOop); }
- public Class getClassAt (int index) { return getClassAt0 (constantPoolOop, index); }
- public Class getClassAtIfLoaded (int index) { return getClassAtIfLoaded0 (constantPoolOop, index); }
- // Returns either a Method or Constructor.
- // Static initializers are returned as Method objects.
- public Member getMethodAt (int index) { return getMethodAt0 (constantPoolOop, index); }
- public Member getMethodAtIfLoaded(int index) { return getMethodAtIfLoaded0(constantPoolOop, index); }
- public Field getFieldAt (int index) { return getFieldAt0 (constantPoolOop, index); }
- public Field getFieldAtIfLoaded (int index) { return getFieldAtIfLoaded0 (constantPoolOop, index); }
- // Fetches the class name, member (field, method or interface
- // method) name, and type descriptor as an array of three Strings
- public String[] getMemberRefInfoAt (int index) { return getMemberRefInfoAt0 (constantPoolOop, index); }
- public int getIntAt (int index) { return getIntAt0 (constantPoolOop, index); }
- public long getLongAt (int index) { return getLongAt0 (constantPoolOop, index); }
- public float getFloatAt (int index) { return getFloatAt0 (constantPoolOop, index); }
- public double getDoubleAt (int index) { return getDoubleAt0 (constantPoolOop, index); }
- public String getStringAt (int index) { return getStringAt0 (constantPoolOop, index); }
- public String getUTF8At (int index) { return getUTF8At0 (constantPoolOop, index); }
-
- //---------------------------------------------------------------------------
- // Internals only below this point
- //
-/* This hides this member from being visible through the reflection API in OpenJDK
- * TODO: find out how to do this with GNU Classpath (if it's realy neccesary).
-
- static {
- Reflection.registerFieldsToFilter(ConstantPool.class, new String[] { "constantPoolOop" });
- }
-*/
- // HotSpot-internal constant pool object (set by the VM, name known to the VM)
- private Object constantPoolOop;
-
- private native int getSize0 (Object constantPoolOop);
- private native Class getClassAt0 (Object constantPoolOop, int index);
- private native Class getClassAtIfLoaded0 (Object constantPoolOop, int index);
- private native Member getMethodAt0 (Object constantPoolOop, int index);
- private native Member getMethodAtIfLoaded0(Object constantPoolOop, int index);
- private native Field getFieldAt0 (Object constantPoolOop, int index);
- private native Field getFieldAtIfLoaded0 (Object constantPoolOop, int index);
- private native String[] getMemberRefInfoAt0 (Object constantPoolOop, int index);
- private native int getIntAt0 (Object constantPoolOop, int index);
- private native long getLongAt0 (Object constantPoolOop, int index);
- private native float getFloatAt0 (Object constantPoolOop, int index);
- private native double getDoubleAt0 (Object constantPoolOop, int index);
- private native String getStringAt0 (Object constantPoolOop, int index);
- private native String getUTF8At0 (Object constantPoolOop, int index);
-}
+++ /dev/null
-/*
- * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.reflect.annotation;
-
-import java.lang.annotation.*;
-import java.util.*;
-import java.nio.ByteBuffer;
-import java.nio.BufferUnderflowException;
-import java.lang.reflect.*;
-import sun.reflect.ConstantPool;
-
-import gnu.java.lang.reflect.FieldSignatureParser;
-
-
-/**
- * Parser for Java programming language annotations. Translates
- * annotation byte streams emitted by compiler into annotation objects.
- *
- * @author Josh Bloch
- * @since 1.5
- */
-public class AnnotationParser {
- /**
- * Parses the annotations described by the passed byte array,
- * but returns Annotation[] so I don't have to do this in C.
- *
- * @author Mathias Panzenböck
- *
- * @param rawAnnotations are the unparsed annotations
- * @param constPool is the constant pool of the declaring class
- * @param container is the containing class
- * @return the parsed annotations in an array
- * @throws AnnotationFormatError if an annotation is found to be
- * malformed.
- */
- public static Annotation[] parseAnnotationsIntoArray(
- byte[] rawAnnotations,
- ConstantPool constPool,
- Class container) {
- Map<Class, Annotation> annotations = parseAnnotations(rawAnnotations, constPool, container);
- return annotations.values().toArray(EMPTY_ANNOTATIONS_ARRAY);
- }
-
- /**
- * Parses parameter annotations.
- *
- * @author Mathias Panzenböck
- *
- * @param parameterAnnotations are the unparsed parameter annotations
- * @param constPool is the constant pool of the declaring class
- * @param container is the containing class
- * @return the parsed parameter annotations in an array 2 dimensional array
- * @throws AnnotationFormatError if an annotation is found to be
- * malformed.
- */
- public static Annotation[][] parseParameterAnnotations(
- byte[] parameterAnnotations,
- ConstantPool constPool,
- Class container,
- int numParameters) {
- if (parameterAnnotations == null)
- return new Annotation[numParameters][0];
-
- Annotation[][] result = parseParameterAnnotations(
- parameterAnnotations, constPool, container);
-
- if (result.length != numParameters)
- throw new AnnotationFormatError(
- "Parameter annotations don't match number of parameters (count was " +
- result.length + " but should be " + numParameters + ").");
- return result;
- }
-
- /**
- * Parses the annotation default value of the supplied method.
- * This method is basically copied from OpenJDKs
- * java.lang.reflect.Method.getAnnotationDefault()
- *
- * @author Mathias Panzenböck
- *
- * @param method represents the method for which the annotation default value has to be parsed
- * @param annotationDefault is the unparsed annotation default value
- * @param constPool is the constant pool of the declaring class
- * @return the parsed annotation default value (boxed, if it's a primitive type)
- * @throws AnnotationFormatError if an annotation is found to be
- * malformed.
- */
- public static Object parseAnnotationDefault(Method method,
- byte[] annotationDefault,
- ConstantPool constPool) {
- if (annotationDefault == null)
- return null;
-
- Class memberType = AnnotationType.invocationHandlerReturnType(
- method.getReturnType());
-
- Object result = AnnotationParser.parseMemberValue(
- memberType, ByteBuffer.wrap(annotationDefault),
- constPool, method.getDeclaringClass());
-
- if (result instanceof sun.reflect.annotation.ExceptionProxy)
- throw new AnnotationFormatError("Invalid default: " + method);
-
- return result;
- }
-
- /**
- * Parses the annotations described by the specified byte array.
- * resolving constant references in the specified constant pool.
- * The array must contain an array of annotations as described
- * in the RuntimeVisibleAnnotations_attribute:
- *
- * u2 num_annotations;
- * annotation annotations[num_annotations];
- *
- * @throws AnnotationFormatError if an annotation is found to be
- * malformed.
- */
- public static Map<Class, Annotation> parseAnnotations(
- byte[] rawAnnotations,
- ConstantPool constPool,
- Class container) {
- if (rawAnnotations == null)
- return Collections.emptyMap();
-
- try {
- return parseAnnotations2(rawAnnotations, constPool, container);
- } catch(BufferUnderflowException e) {
- throw new AnnotationFormatError("Unexpected end of annotations.");
- } catch(IllegalArgumentException e) {
- // Type mismatch in constant pool
- throw new AnnotationFormatError(e);
- }
- }
-
- private static Map<Class, Annotation> parseAnnotations2(
- byte[] rawAnnotations,
- ConstantPool constPool,
- Class container) {
- Map<Class, Annotation> result = new LinkedHashMap<Class, Annotation>();
- ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
- int numAnnotations = buf.getShort() & 0xFFFF;
- for (int i = 0; i < numAnnotations; i++) {
- Annotation a = parseAnnotation(buf, constPool, container, false);
- if (a != null) {
- Class klass = a.annotationType();
- AnnotationType type = AnnotationType.getInstance(klass);
- if (type.retention() == RetentionPolicy.RUNTIME)
- if (result.put(klass, a) != null)
- throw new AnnotationFormatError(
- "Duplicate annotation for class: "+klass+": " + a);
- }
- }
- return result;
- }
-
- /**
- * Parses the parameter annotations described by the specified byte array.
- * resolving constant references in the specified constant pool.
- * The array must contain an array of annotations as described
- * in the RuntimeVisibleParameterAnnotations_attribute:
- *
- * u1 num_parameters;
- * {
- * u2 num_annotations;
- * annotation annotations[num_annotations];
- * } parameter_annotations[num_parameters];
- *
- * Unlike parseAnnotations, rawAnnotations must not be null!
- * A null value must be handled by the caller. This is so because
- * we cannot determine the number of parameters if rawAnnotations
- * is null. Also, the caller should check that the number
- * of parameters indicated by the return value of this method
- * matches the actual number of method parameters. A mismatch
- * indicates that an AnnotationFormatError should be thrown.
- *
- * @throws AnnotationFormatError if an annotation is found to be
- * malformed.
- */
- public static Annotation[][] parseParameterAnnotations(
- byte[] rawAnnotations,
- ConstantPool constPool,
- Class container) {
- try {
- return parseParameterAnnotations2(rawAnnotations, constPool, container);
- } catch(BufferUnderflowException e) {
- throw new AnnotationFormatError(
- "Unexpected end of parameter annotations.");
- } catch(IllegalArgumentException e) {
- // Type mismatch in constant pool
- throw new AnnotationFormatError(e);
- }
- }
-
- private static Annotation[][] parseParameterAnnotations2(
- byte[] rawAnnotations,
- ConstantPool constPool,
- Class container) {
- ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
- int numParameters = buf.get() & 0xFF;
- Annotation[][] result = new Annotation[numParameters][];
-
- for (int i = 0; i < numParameters; i++) {
- int numAnnotations = buf.getShort() & 0xFFFF;
- List<Annotation> annotations =
- new ArrayList<Annotation>(numAnnotations);
- for (int j = 0; j < numAnnotations; j++) {
- Annotation a = parseAnnotation(buf, constPool, container, false);
- if (a != null) {
- AnnotationType type = AnnotationType.getInstance(
- a.annotationType());
- if (type.retention() == RetentionPolicy.RUNTIME)
- annotations.add(a);
- }
- }
- result[i] = annotations.toArray(EMPTY_ANNOTATIONS_ARRAY);
- }
- return result;
- }
-
- private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
- new Annotation[0];
-
- /**
- * Parses the annotation at the current position in the specified
- * byte buffer, resolving constant references in the specified constant
- * pool. The cursor of the byte buffer must point to an "annotation
- * structure" as described in the RuntimeVisibleAnnotations_attribute:
- *
- * annotation {
- * u2 type_index;
- * u2 num_member_value_pairs;
- * { u2 member_name_index;
- * member_value value;
- * } member_value_pairs[num_member_value_pairs];
- * }
- * }
- *
- * Returns the annotation, or null if the annotation's type cannot
- * be found by the VM, or is not a valid annotation type.
- *
- * @param exceptionOnMissingAnnotationClass if true, throw
- * TypeNotPresentException if a referenced annotation type is not
- * available at runtime
- */
- private static Annotation parseAnnotation(ByteBuffer buf,
- ConstantPool constPool,
- Class container,
- boolean exceptionOnMissingAnnotationClass) {
- int typeIndex = buf.getShort() & 0xFFFF;
- Class annotationClass = null;
- String sig = "[unknown]";
- try {
- try {
- sig = constPool.getUTF8At(typeIndex);
- annotationClass = parseSig(sig, container);
- } catch (IllegalArgumentException ex) {
- // support obsolete early jsr175 format class files
- annotationClass = constPool.getClassAt(typeIndex);
- }
- } catch (NoClassDefFoundError e) {
- if (exceptionOnMissingAnnotationClass)
- // note: at this point sig is "[unknown]" or VM-style
- // name instead of a binary name
- throw new TypeNotPresentException(sig, e);
- skipAnnotation(buf, false);
- return null;
- }
- catch (TypeNotPresentException e) {
- if (exceptionOnMissingAnnotationClass)
- throw e;
- skipAnnotation(buf, false);
- return null;
- }
- AnnotationType type = null;
- try {
- type = AnnotationType.getInstance(annotationClass);
- } catch (IllegalArgumentException e) {
- skipAnnotation(buf, false);
- return null;
- }
-
- Map<String, Class> memberTypes = type.memberTypes();
- Map<String, Object> memberValues =
- new LinkedHashMap<String, Object>(type.memberDefaults());
-
- int numMembers = buf.getShort() & 0xFFFF;
- for (int i = 0; i < numMembers; i++) {
- int memberNameIndex = buf.getShort() & 0xFFFF;
- String memberName = constPool.getUTF8At(memberNameIndex);
- Class memberType = memberTypes.get(memberName);
-
- if (memberType == null) {
- // Member is no longer present in annotation type; ignore it
- skipMemberValue(buf);
- } else {
- Object value = parseMemberValue(memberType, buf, constPool, container);
- if (value instanceof AnnotationTypeMismatchExceptionProxy)
- ((AnnotationTypeMismatchExceptionProxy) value).
- setMember(type.members().get(memberName));
- memberValues.put(memberName, value);
- }
- }
- return annotationForMap(annotationClass, memberValues);
- }
-
- /**
- * Returns an annotation of the given type backed by the given
- * member -> value map.
- */
- public static Annotation annotationForMap(
- Class type, Map<String, Object> memberValues)
- {
- return (Annotation) Proxy.newProxyInstance(
- type.getClassLoader(), new Class[] { type },
- new AnnotationInvocationHandler(type, memberValues));
- }
-
- /**
- * Parses the annotation member value at the current position in the
- * specified byte buffer, resolving constant references in the specified
- * constant pool. The cursor of the byte buffer must point to a
- * "member_value structure" as described in the
- * RuntimeVisibleAnnotations_attribute:
- *
- * member_value {
- * u1 tag;
- * union {
- * u2 const_value_index;
- * {
- * u2 type_name_index;
- * u2 const_name_index;
- * } enum_const_value;
- * u2 class_info_index;
- * annotation annotation_value;
- * {
- * u2 num_values;
- * member_value values[num_values];
- * } array_value;
- * } value;
- * }
- *
- * The member must be of the indicated type. If it is not, this
- * method returns an AnnotationTypeMismatchExceptionProxy.
- */
- public static Object parseMemberValue(Class memberType, ByteBuffer buf,
- ConstantPool constPool,
- Class container) {
- Object result = null;
- int tag = buf.get();
- switch(tag) {
- case 'e':
- return parseEnumValue(memberType, buf, constPool, container);
- case 'c':
- result = parseClassValue(buf, constPool, container);
- break;
- case '@':
- result = parseAnnotation(buf, constPool, container, true);
- break;
- case '[':
- return parseArray(memberType, buf, constPool, container);
- default:
- result = parseConst(tag, buf, constPool);
- }
-
- if (!(result instanceof ExceptionProxy) &&
- !memberType.isInstance(result))
- result = new AnnotationTypeMismatchExceptionProxy(
- result.getClass() + "[" + result + "]");
- return result;
- }
-
- /**
- * Parses the primitive or String annotation member value indicated by
- * the specified tag byte at the current position in the specified byte
- * buffer, resolving constant reference in the specified constant pool.
- * The cursor of the byte buffer must point to an annotation member value
- * of the type indicated by the specified tag, as described in the
- * RuntimeVisibleAnnotations_attribute:
- *
- * u2 const_value_index;
- */
- private static Object parseConst(int tag,
- ByteBuffer buf, ConstantPool constPool) {
- int constIndex = buf.getShort() & 0xFFFF;
- switch(tag) {
- case 'B':
- return Byte.valueOf((byte) constPool.getIntAt(constIndex));
- case 'C':
- return Character.valueOf((char) constPool.getIntAt(constIndex));
- case 'D':
- return Double.valueOf(constPool.getDoubleAt(constIndex));
- case 'F':
- return Float.valueOf(constPool.getFloatAt(constIndex));
- case 'I':
- return Integer.valueOf(constPool.getIntAt(constIndex));
- case 'J':
- return Long.valueOf(constPool.getLongAt(constIndex));
- case 'S':
- return Short.valueOf((short) constPool.getIntAt(constIndex));
- case 'Z':
- return Boolean.valueOf(constPool.getIntAt(constIndex) != 0);
- case 's':
- return constPool.getUTF8At(constIndex);
- default:
- throw new AnnotationFormatError(
- "Invalid member-value tag in annotation: " + tag);
- }
- }
-
- /**
- * Parses the Class member value at the current position in the
- * specified byte buffer, resolving constant references in the specified
- * constant pool. The cursor of the byte buffer must point to a "class
- * info index" as described in the RuntimeVisibleAnnotations_attribute:
- *
- * u2 class_info_index;
- */
- private static Object parseClassValue(ByteBuffer buf,
- ConstantPool constPool,
- Class container) {
- int classIndex = buf.getShort() & 0xFFFF;
- try {
- try {
- String sig = constPool.getUTF8At(classIndex);
- return parseSig(sig, container);
- } catch (IllegalArgumentException ex) {
- // support obsolete early jsr175 format class files
- return constPool.getClassAt(classIndex);
- }
- } catch (NoClassDefFoundError e) {
- return new TypeNotPresentExceptionProxy("[unknown]", e);
- }
- catch (TypeNotPresentException e) {
- return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
- }
- }
-
- /**
- * Parses a return type signature and returns the according Class object.
- */
- private static Class<?> parseSig(String sig, Class container) {
- if (sig.equals("V")) {
- return void.class;
- }
- else {
- return toClass(new FieldSignatureParser(container, sig).getFieldType());
- }
- }
-
- static Class<?> toClass(Type o) {
- if (o instanceof GenericArrayType)
- return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
- 0)
- .getClass();
- return (Class<?>)o;
- }
-
- /**
- * Parses the enum constant member value at the current position in the
- * specified byte buffer, resolving constant references in the specified
- * constant pool. The cursor of the byte buffer must point to a
- * "enum_const_value structure" as described in the
- * RuntimeVisibleAnnotations_attribute:
- *
- * {
- * u2 type_name_index;
- * u2 const_name_index;
- * } enum_const_value;
- */
- private static Object parseEnumValue(Class enumType, ByteBuffer buf,
- ConstantPool constPool,
- Class container) {
- int typeNameIndex = buf.getShort() & 0xFFFF;
- String typeName = constPool.getUTF8At(typeNameIndex);
- int constNameIndex = buf.getShort() & 0xFFFF;
- String constName = constPool.getUTF8At(constNameIndex);
-
- if (!typeName.endsWith(";")) {
- // support now-obsolete early jsr175-format class files.
- if (!enumType.getName().equals(typeName))
- return new AnnotationTypeMismatchExceptionProxy(
- typeName + "." + constName);
- } else if (enumType != parseSig(typeName, container)) {
- return new AnnotationTypeMismatchExceptionProxy(
- typeName + "." + constName);
- }
-
- try {
- return Enum.valueOf(enumType, constName);
- } catch(IllegalArgumentException e) {
- return new EnumConstantNotPresentExceptionProxy(
- (Class<? extends Enum>)enumType, constName);
- }
- }
-
- /**
- * Parses the array value at the current position in the specified byte
- * buffer, resolving constant references in the specified constant pool.
- * The cursor of the byte buffer must point to an array value struct
- * as specified in the RuntimeVisibleAnnotations_attribute:
- *
- * {
- * u2 num_values;
- * member_value values[num_values];
- * } array_value;
- *
- * If the array values do not match arrayType, an
- * AnnotationTypeMismatchExceptionProxy will be returned.
- */
- private static Object parseArray(Class arrayType,
- ByteBuffer buf,
- ConstantPool constPool,
- Class container) {
- int length = buf.getShort() & 0xFFFF; // Number of array components
- Class componentType = arrayType.getComponentType();
-
- if (componentType == byte.class) {
- return parseByteArray(length, buf, constPool);
- } else if (componentType == char.class) {
- return parseCharArray(length, buf, constPool);
- } else if (componentType == double.class) {
- return parseDoubleArray(length, buf, constPool);
- } else if (componentType == float.class) {
- return parseFloatArray(length, buf, constPool);
- } else if (componentType == int.class) {
- return parseIntArray(length, buf, constPool);
- } else if (componentType == long.class) {
- return parseLongArray(length, buf, constPool);
- } else if (componentType == short.class) {
- return parseShortArray(length, buf, constPool);
- } else if (componentType == boolean.class) {
- return parseBooleanArray(length, buf, constPool);
- } else if (componentType == String.class) {
- return parseStringArray(length, buf, constPool);
- } else if (componentType == Class.class) {
- return parseClassArray(length, buf, constPool, container);
- } else if (componentType.isEnum()) {
- return parseEnumArray(length, componentType, buf,
- constPool, container);
- } else {
- assert componentType.isAnnotation();
- return parseAnnotationArray(length, componentType, buf,
- constPool, container);
- }
- }
-
- private static Object parseByteArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- byte[] result = new byte[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'B') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = (byte) constPool.getIntAt(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseCharArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- char[] result = new char[length];
- boolean typeMismatch = false;
- byte tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'C') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = (char) constPool.getIntAt(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseDoubleArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- double[] result = new double[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'D') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = constPool.getDoubleAt(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseFloatArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- float[] result = new float[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'F') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = constPool.getFloatAt(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseIntArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- int[] result = new int[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'I') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = constPool.getIntAt(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseLongArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- long[] result = new long[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'J') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = constPool.getLongAt(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseShortArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- short[] result = new short[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'S') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = (short) constPool.getIntAt(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseBooleanArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- boolean[] result = new boolean[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'Z') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = (constPool.getIntAt(index) != 0);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseStringArray(int length,
- ByteBuffer buf, ConstantPool constPool) {
- String[] result = new String[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 's') {
- int index = buf.getShort() & 0xFFFF;
- result[i] = constPool.getUTF8At(index);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseClassArray(int length,
- ByteBuffer buf,
- ConstantPool constPool,
- Class container) {
- Object[] result = new Class[length];
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'c') {
- result[i] = parseClassValue(buf, constPool, container);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseEnumArray(int length, Class enumType,
- ByteBuffer buf,
- ConstantPool constPool,
- Class container) {
- Object[] result = (Object[]) Array.newInstance(enumType, length);
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == 'e') {
- result[i] = parseEnumValue(enumType, buf, constPool, container);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- private static Object parseAnnotationArray(int length,
- Class annotationType,
- ByteBuffer buf,
- ConstantPool constPool,
- Class container) {
- Object[] result = (Object[]) Array.newInstance(annotationType, length);
- boolean typeMismatch = false;
- int tag = 0;
-
- for (int i = 0; i < length; i++) {
- tag = buf.get();
- if (tag == '@') {
- result[i] = parseAnnotation(buf, constPool, container, true);
- } else {
- skipMemberValue(tag, buf);
- typeMismatch = true;
- }
- }
- return typeMismatch ? exceptionProxy(tag) : result;
- }
-
- /**
- * Return an appropriate exception proxy for a mismatching array
- * annotation where the erroneous array has the specified tag.
- */
- private static ExceptionProxy exceptionProxy(int tag) {
- return new AnnotationTypeMismatchExceptionProxy(
- "Array with component tag: " + tag);
- }
-
- /**
- * Skips the annotation at the current position in the specified
- * byte buffer. The cursor of the byte buffer must point to
- * an "annotation structure" OR two bytes into an annotation
- * structure (i.e., after the type index).
- *
- * @parameter complete true if the byte buffer points to the beginning
- * of an annotation structure (rather than two bytes in).
- */
- private static void skipAnnotation(ByteBuffer buf, boolean complete) {
- if (complete)
- buf.getShort(); // Skip type index
- int numMembers = buf.getShort() & 0xFFFF;
- for (int i = 0; i < numMembers; i++) {
- buf.getShort(); // Skip memberNameIndex
- skipMemberValue(buf);
- }
- }
-
- /**
- * Skips the annotation member value at the current position in the
- * specified byte buffer. The cursor of the byte buffer must point to a
- * "member_value structure."
- */
- private static void skipMemberValue(ByteBuffer buf) {
- int tag = buf.get();
- skipMemberValue(tag, buf);
- }
-
- /**
- * Skips the annotation member value at the current position in the
- * specified byte buffer. The cursor of the byte buffer must point
- * immediately after the tag in a "member_value structure."
- */
- private static void skipMemberValue(int tag, ByteBuffer buf) {
- switch(tag) {
- case 'e': // Enum value
- buf.getInt(); // (Two shorts, actually.)
- break;
- case '@':
- skipAnnotation(buf, true);
- break;
- case '[':
- skipArray(buf);
- break;
- default:
- // Class, primitive, or String
- buf.getShort();
- }
- }
-
- /**
- * Skips the array value at the current position in the specified byte
- * buffer. The cursor of the byte buffer must point to an array value
- * struct.
- */
- private static void skipArray(ByteBuffer buf) {
- int length = buf.getShort() & 0xFFFF;
- for (int i = 0; i < length; i++)
- skipMemberValue(buf);
- }
-}
+++ /dev/null
-/*
- * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.reflect.annotation;
-
-import java.lang.annotation.*;
-import java.lang.reflect.*;
-import java.util.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * Represents an annotation type at run time. Used to type-check annotations
- * and apply member defaults.
- *
- * @author Josh Bloch
- * @since 1.5
- */
-public class AnnotationType {
- /**
- * Annotation class -> AnnotationType mapping. This emulates
- * sun.misc.SharedSecrets.getJavaLangAccess().getAnnotationType() and
- * sun.misc.SharedSecrets.getJavaLangAccess().setAnnotationType() so
- * this class can be used with gnu classpath.
- *
- * @author Mathias Panzenböck
- */
- private static Map<Class, AnnotationType> annotationTypes =
- new HashMap<Class, AnnotationType>();
-
- /**
- * Member name -> type mapping. Note that primitive types
- * are represented by the class objects for the corresponding wrapper
- * types. This matches the return value that must be used for a
- * dynamic proxy, allowing for a simple isInstance test.
- */
- private final Map<String, Class> memberTypes = new HashMap<String,Class>();
-
- /**
- * Member name -> default value mapping.
- */
- private final Map<String, Object> memberDefaults =
- new HashMap<String, Object>();
-
- /**
- * Member name -> Method object mapping. This (and its assoicated
- * accessor) are used only to generate AnnotationTypeMismatchExceptions.
- */
- private final Map<String, Method> members = new HashMap<String, Method>();
-
- /**
- * The retention policy for this annotation type.
- */
- private RetentionPolicy retention = RetentionPolicy.RUNTIME;;
-
- /**
- * Whether this annotation type is inherited.
- */
- private boolean inherited = false;
-
- /**
- * Returns an AnnotationType instance for the specified annotation type.
- *
- * @throw IllegalArgumentException if the specified class object for
- * does not represent a valid annotation type
- */
- public static synchronized AnnotationType getInstance(
- Class annotationClass)
- {
- /*
- AnnotationType result = sun.misc.SharedSecrets.getJavaLangAccess().
- getAnnotationType(annotationClass);
- */
- // emulating OpenJDKs SharedSecrets in GNU Classpath:
- AnnotationType result = annotationTypes.get(annotationClass);
- if (result == null)
- result = new AnnotationType((Class<?>) annotationClass);
-
- return result;
- }
-
- /**
- * Sole constructor.
- *
- * @param annotationClass the class object for the annotation type
- * @throw IllegalArgumentException if the specified class object for
- * does not represent a valid annotation type
- */
- private AnnotationType(final Class<?> annotationClass) {
- if (!annotationClass.isAnnotation())
- throw new IllegalArgumentException("Not an annotation type");
-
- Method[] methods =
- AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
- public Method[] run() {
- // Initialize memberTypes and defaultValues
- return annotationClass.getDeclaredMethods();
- }
- });
-
-
- for (Method method : methods) {
- if (method.getParameterTypes().length != 0)
- throw new IllegalArgumentException(method + " has params");
- String name = method.getName();
- Class type = method.getReturnType();
- memberTypes.put(name, invocationHandlerReturnType(type));
- members.put(name, method);
-
- Object defaultValue = method.getDefaultValue();
- if (defaultValue != null)
- memberDefaults.put(name, defaultValue);
-
- members.put(name, method);
- }
-
- /*
- sun.misc.SharedSecrets.getJavaLangAccess().
- setAnnotationType(annotationClass, this);
- */
- // emulating OpenJDKs SharedSecrets in GNU Classpath:
- annotationTypes.put(annotationClass, this);
-
- // Initialize retention, & inherited fields. Special treatment
- // of the corresponding annotation types breaks infinite recursion.
- if (annotationClass != Retention.class &&
- annotationClass != Inherited.class) {
- Retention ret = annotationClass.getAnnotation(Retention.class);
- retention = (ret == null ? RetentionPolicy.CLASS : ret.value());
- inherited = annotationClass.isAnnotationPresent(Inherited.class);
- }
- }
-
- /**
- * Returns the type that must be returned by the invocation handler
- * of a dynamic proxy in order to have the dynamic proxy return
- * the specified type (which is assumed to be a legal member type
- * for an annotation).
- */
- public static Class invocationHandlerReturnType(Class type) {
- // Translate primitives to wrappers
- if (type == byte.class)
- return Byte.class;
- if (type == char.class)
- return Character.class;
- if (type == double.class)
- return Double.class;
- if (type == float.class)
- return Float.class;
- if (type == int.class)
- return Integer.class;
- if (type == long.class)
- return Long.class;
- if (type == short.class)
- return Short.class;
- if (type == boolean.class)
- return Boolean.class;
-
- // Otherwise, just return declared type
- return type;
- }
-
- /**
- * Returns member types for this annotation type
- * (member name -> type mapping).
- */
- public Map<String, Class> memberTypes() {
- return memberTypes;
- }
-
- /**
- * Returns members of this annotation type
- * (member name -> associated Method object mapping).
- */
- public Map<String, Method> members() {
- return members;
- }
-
- /**
- * Returns the default values for this annotation type
- * (Member name -> default value mapping).
- */
- public Map<String, Object> memberDefaults() {
- return memberDefaults;
- }
-
- /**
- * Returns the retention policy for this annotation type.
- */
- public RetentionPolicy retention() {
- return retention;
- }
-
- /**
- * Returns true if this this annotation type is inherited.
- */
- public boolean isInherited() {
- return inherited;
- }
-
- /**
- * For debugging.
- */
- public String toString() {
- StringBuffer s = new StringBuffer("Annotation Type:" + "\n");
- s.append(" Member types: " + memberTypes + "\n");
- s.append(" Member defaults: " + memberDefaults + "\n");
- s.append(" Retention policy: " + retention + "\n");
- s.append(" Inherited: " + inherited);
- return s.toString();
- }
-}
+++ /dev/null
-/*
- * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.reflect.annotation;
-import java.lang.annotation.*;
-import java.lang.reflect.Method;
-
-/**
- * ExceptionProxy for AnnotationTypeMismatchException.
- *
- * @author Josh Bloch
- * @since 1.5
- */
-class AnnotationTypeMismatchExceptionProxy extends ExceptionProxy {
- private Method member;
- private String foundType;
-
- /**
- * It turns out to be convenient to construct these proxies in
- * two stages. Since this is a private implementation class, we
- * permit ourselves this liberty even though it's normally a very
- * bad idea.
- */
- AnnotationTypeMismatchExceptionProxy(String foundType) {
- this.foundType = foundType;
- }
-
- AnnotationTypeMismatchExceptionProxy setMember(Method member) {
- this.member = member;
- return this;
- }
-
- protected RuntimeException generateException() {
- return new AnnotationTypeMismatchException(member, foundType);
- }
-}
+++ /dev/null
-/*
- * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.reflect.annotation;
-import java.lang.annotation.*;
-
-/**
- * ExceptionProxy for EnumConstantNotPresentException.
- *
- * @author Josh Bloch
- * @since 1.5
- */
-public class EnumConstantNotPresentExceptionProxy extends ExceptionProxy {
- Class<? extends Enum> enumType;
- String constName;
-
- public EnumConstantNotPresentExceptionProxy(Class<? extends Enum> enumType,
- String constName) {
- this.enumType = enumType;
- this.constName = constName;
- }
-
- protected RuntimeException generateException() {
- return new EnumConstantNotPresentException(enumType, constName);
- }
-}
+++ /dev/null
-/*
- * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.reflect.annotation;
-
-/**
- * An instance of this class is stored in an AnnotationInvocationHandler's
- * "memberValues" map in lieu of a value for an annotation member that
- * cannot be returned due to some exceptional condition (typically some
- * form of illegal evolution of the annotation class). The ExceptionProxy
- * instance describes the exception that the dynamic proxy should throw if
- * it is queried for this member.
- *
- * @author Josh Bloch
- * @since 1.5
- */
-public abstract class ExceptionProxy implements java.io.Serializable {
- protected abstract RuntimeException generateException();
-}
+++ /dev/null
-/*
- * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
- */
-
-package sun.reflect.annotation;
-import java.lang.annotation.*;
-
-/**
- * ExceptionProxy for TypeNotPresentException.
- *
- * @author Josh Bloch
- * @since 1.5
- */
-public class TypeNotPresentExceptionProxy extends ExceptionProxy {
- String typeName;
- Throwable cause;
-
- public TypeNotPresentExceptionProxy(String typeName, Throwable cause) {
- this.typeName = typeName;
- this.cause = cause;
- }
-
- protected RuntimeException generateException() {
- return new TypeNotPresentException(typeName, cause);
- }
-}
## src/mm/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.
##
libmm.la
libmm_la_SOURCES = \
+ codememory.c \
+ codememory.h \
+ dumpmemory.c \
+ dumpmemory.h \
$(GC_FILE) \
gc-common.h \
memory.c \
-# Makefile for Borland C++ 5.5 on NT
-# If you have the Borland assembler, remove "-DUSE_GENERIC"
-#
-bc= c:\Borland\BCC55
-bcbin= $(bc)\bin
-bclib= $(bc)\lib
-bcinclude= $(bc)\include
-
-gcinclude1 = $(bc)\gc6.2\include
-gcinclude2 = $(bc)\gc6.2\cord
-
-cc= $(bcbin)\bcc32
-rc= $(bcbin)\brc32
-lib= $(bcbin)\tlib
-link= $(bcbin)\ilink32
-cflags= -O2 -R -v- -vi -H -H=gc.csm -I$(bcinclude);$(gcinclude1);$(gcinclude2) -L$(bclib) \
- -w-pro -w-aus -w-par -w-ccc -w-rch -a4 -D__STDC__=0
-#defines= -DSILENT
-defines= -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY
-
-.c.obj:
- $(cc) @&&|
- $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.c
-|
-
-.cpp.obj:
- $(cc) @&&|
- $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.cpp
-|
-
-.rc.res:
- $(rc) -i$(bcinclude) -r -fo$* $*.rc
-
-XXXOBJS= XXXalloc.obj XXXreclaim.obj XXXallchblk.obj XXXmisc.obj \
- XXXmach_dep.obj XXXos_dep.obj XXXmark_rts.obj XXXheaders.obj XXXmark.obj \
- XXXobj_map.obj XXXblacklst.obj XXXfinalize.obj XXXnew_hblk.obj \
- XXXdbg_mlc.obj XXXmalloc.obj XXXstubborn.obj XXXdyn_load.obj \
- XXXtypd_mlc.obj XXXptr_chck.obj XXXgc_cpp.obj XXXmallocx.obj
-
-OBJS= $(XXXOBJS:XXX=)
-
-all: gctest.exe cord\de.exe test_cpp.exe
-
-$(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h MAKEFILE
-
-gc.lib: $(OBJS)
- del gc.lib
- $(lib) $* @&&|
- $(XXXOBJS:XXX=+)
-|
-
-gctest.exe: tests\test.obj gc.lib
- $(cc) @&&|
- $(cflags) -W -e$* tests\test.obj gc.lib
-|
-
-cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h \
- cord\de_cmds.h
-
-cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \
- cord\de_win.res gc.lib
- $(cc) @&&|
- $(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \
- cord\de.obj cord\de_win.obj gc.lib
-|
- $(rc) cord\de_win.res cord\de.exe
-
-gc_cpp.obj: include\gc_cpp.h include\gc.h
-
-gc_cpp.cpp: gc_cpp.cc
- copy gc_cpp.cc gc_cpp.cpp
-
-test_cpp.cpp: tests\test_cpp.cc
- copy tests\test_cpp.cc test_cpp.cpp
-
-test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib
- $(cc) @&&|
- $(cflags) -W -e$* test_cpp.obj gc.lib
-|
-
-scratch:
- -del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm
-
-clean:
- del gc.lib
- del *.obj
- del tests\test.obj
-
+# Makefile for Borland C++ 5.5 on NT\r
+# If you have the Borland assembler, remove "-DUSE_GENERIC"\r
+#\r
+bc= c:\Borland\BCC55\r
+bcbin= $(bc)\bin\r
+bclib= $(bc)\lib\r
+bcinclude= $(bc)\include\r
+\r
+gcinclude1 = $(bc)\gc6.2\include\r
+gcinclude2 = $(bc)\gc6.2\cord\r
+\r
+cc= $(bcbin)\bcc32\r
+rc= $(bcbin)\brc32\r
+lib= $(bcbin)\tlib\r
+link= $(bcbin)\ilink32\r
+cflags= -O2 -R -v- -vi -H -H=gc.csm -I$(bcinclude);$(gcinclude1);$(gcinclude2) -L$(bclib) \\r
+ -w-pro -w-aus -w-par -w-ccc -w-rch -a4 -D__STDC__=0\r
+#defines= -DSILENT\r
+defines= -DSILENT -DALL_INTERIOR_POINTERS -DUSE_GENERIC -DNO_GETENV -DJAVA_FINALIZATION -DGC_OPERATOR_NEW_ARRAY\r
+\r
+.c.obj:\r
+ $(cc) @&&|\r
+ $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.c\r
+|\r
+\r
+.cpp.obj:\r
+ $(cc) @&&|\r
+ $(cdebug) $(cflags) $(cvars) $(defines) -o$* -c $*.cpp\r
+|\r
+\r
+.rc.res:\r
+ $(rc) -i$(bcinclude) -r -fo$* $*.rc\r
+\r
+XXXOBJS= XXXalloc.obj XXXreclaim.obj XXXallchblk.obj XXXmisc.obj \\r
+ XXXmach_dep.obj XXXos_dep.obj XXXmark_rts.obj XXXheaders.obj XXXmark.obj \\r
+ XXXobj_map.obj XXXblacklst.obj XXXfinalize.obj XXXnew_hblk.obj \\r
+ XXXdbg_mlc.obj XXXmalloc.obj XXXstubborn.obj XXXdyn_load.obj \\r
+ XXXtypd_mlc.obj XXXptr_chck.obj XXXgc_cpp.obj XXXmallocx.obj\r
+\r
+OBJS= $(XXXOBJS:XXX=)\r
+\r
+all: gctest.exe cord\de.exe test_cpp.exe\r
+\r
+$(OBJS) test.obj: include\private\gc_priv.h include\private\gc_hdrs.h include\gc.h include\private\gcconfig.h MAKEFILE\r
+\r
+gc.lib: $(OBJS)\r
+ del gc.lib\r
+ $(lib) $* @&&|\r
+ $(XXXOBJS:XXX=+)\r
+|\r
+\r
+gctest.exe: tests\test.obj gc.lib\r
+ $(cc) @&&|\r
+ $(cflags) -W -e$* tests\test.obj gc.lib\r
+|\r
+\r
+cord\de.obj cord\de_win.obj: include\cord.h include\private\cord_pos.h cord\de_win.h \\r
+ cord\de_cmds.h\r
+\r
+cord\de.exe: cord\cordbscs.obj cord\cordxtra.obj cord\de.obj cord\de_win.obj \\r
+ cord\de_win.res gc.lib\r
+ $(cc) @&&|\r
+ $(cflags) -W -e$* cord\cordbscs.obj cord\cordxtra.obj \\r
+ cord\de.obj cord\de_win.obj gc.lib\r
+|\r
+ $(rc) cord\de_win.res cord\de.exe\r
+\r
+gc_cpp.obj: include\gc_cpp.h include\gc.h\r
+\r
+gc_cpp.cpp: gc_cpp.cc\r
+ copy gc_cpp.cc gc_cpp.cpp\r
+\r
+test_cpp.cpp: tests\test_cpp.cc\r
+ copy tests\test_cpp.cc test_cpp.cpp\r
+\r
+test_cpp.exe: test_cpp.obj include\gc_cpp.h include\gc.h gc.lib\r
+ $(cc) @&&|\r
+ $(cflags) -W -e$* test_cpp.obj gc.lib\r
+|\r
+\r
+scratch:\r
+ -del *.obj *.res *.exe *.csm cord\*.obj cord\*.res cord\*.exe cord\*.csm\r
+\r
+clean:\r
+ del gc.lib\r
+ del *.obj\r
+ del tests\test.obj\r
+\r
-# Makefile to build Hans Boehm garbage collector using the Digital Mars
-# compiler from www.digitalmars.com
-# Written by Walter Bright
-
-
-DEFINES=-DNDEBUG -DSILENT -DGC_BUILD -D_WINDOWS -DGC_DLL -DALL_INTERIOR_POINTERS -D__STDC__ -DWIN32_THREADS
-CFLAGS=-Iinclude $(DEFINES) -wx -g
-LFLAGS=/ma/implib/co
-CC=sc
-
-.c.obj:
- $(CC) -c $(CFLAGS) $*
-
-.cpp.obj:
- $(CC) -c $(CFLAGS) -Aa $*
-
-OBJS= \
- allchblk.obj\
- alloc.obj\
- blacklst.obj\
- checksums.obj\
- dbg_mlc.obj\
- dyn_load.obj\
- finalize.obj\
- gc_cpp.obj\
- headers.obj\
- mach_dep.obj\
- malloc.obj\
- mallocx.obj\
- mark.obj\
- mark_rts.obj\
- misc.obj\
- new_hblk.obj\
- obj_map.obj\
- os_dep.obj\
- ptr_chck.obj\
- reclaim.obj\
- stubborn.obj\
- typd_mlc.obj\
- win32_threads.obj
-
-targets: gc.dll gc.lib gctest.exe
-
-gc.dll: $(OBJS) gc.def digimars.mak
- sc -ogc.dll $(OBJS) -L$(LFLAGS) gc.def kernel32.lib user32.lib
-
-gc.def: digimars.mak
- echo LIBRARY GC >gc.def
- echo DESCRIPTION "Hans Boehm Garbage Collector" >>gc.def
- echo EXETYPE NT >>gc.def
- echo EXPORTS >>gc.def
- echo GC_is_visible_print_proc >>gc.def
- echo GC_is_valid_displacement_print_proc >>gc.def
-
-clean:
- del gc.def
- del $(OBJS)
-
-
-gctest.exe : gc.lib tests\test.obj
- sc -ogctest.exe tests\test.obj gc.lib
-
-tests\test.obj : tests\test.c
- $(CC) -c -g -DNDEBUG -DSILENT -DGC_BUILD -D_WINDOWS -DGC_DLL \
- -DALL_INTERIOR_POINTERS -DWIN32_THREADS \
- -Iinclude tests\test.c -otests\test.obj
-
-allchblk.obj: allchblk.c
-alloc.obj: alloc.c
-blacklst.obj: blacklst.c
-checksums.obj: checksums.c
-dbg_mlc.obj: dbg_mlc.c
-dyn_load.obj: dyn_load.c
-finalize.obj: finalize.c
-gc_cpp.obj: gc_cpp.cpp
-headers.obj: headers.c
-mach_dep.obj: mach_dep.c
-malloc.obj: malloc.c
-mallocx.obj: mallocx.c
-mark.obj: mark.c
-mark_rts.obj: mark_rts.c
-misc.obj: misc.c
-new_hblk.obj: new_hblk.c
-obj_map.obj: obj_map.c
-os_dep.obj: os_dep.c
-ptr_chck.obj: ptr_chck.c
-reclaim.obj: reclaim.c
-stubborn.obj: stubborn.c
-typd_mlc.obj: typd_mlc.c
-win32_threads.obj: win32_threads.c
+# Makefile to build Hans Boehm garbage collector using the Digital Mars\r
+# compiler from www.digitalmars.com\r
+# Written by Walter Bright\r
+\r
+\r
+DEFINES=-DNDEBUG -DSILENT -DGC_BUILD -D_WINDOWS -DGC_DLL -DALL_INTERIOR_POINTERS -D__STDC__ -DWIN32_THREADS\r
+CFLAGS=-Iinclude $(DEFINES) -wx -g\r
+LFLAGS=/ma/implib/co\r
+CC=sc\r
+\r
+.c.obj:\r
+ $(CC) -c $(CFLAGS) $*\r
+\r
+.cpp.obj:\r
+ $(CC) -c $(CFLAGS) -Aa $*\r
+\r
+OBJS= \\r
+ allchblk.obj\\r
+ alloc.obj\\r
+ blacklst.obj\\r
+ checksums.obj\\r
+ dbg_mlc.obj\\r
+ dyn_load.obj\\r
+ finalize.obj\\r
+ gc_cpp.obj\\r
+ headers.obj\\r
+ mach_dep.obj\\r
+ malloc.obj\\r
+ mallocx.obj\\r
+ mark.obj\\r
+ mark_rts.obj\\r
+ misc.obj\\r
+ new_hblk.obj\\r
+ obj_map.obj\\r
+ os_dep.obj\\r
+ ptr_chck.obj\\r
+ reclaim.obj\\r
+ stubborn.obj\\r
+ typd_mlc.obj\\r
+ win32_threads.obj\r
+\r
+targets: gc.dll gc.lib gctest.exe\r
+\r
+gc.dll: $(OBJS) gc.def digimars.mak\r
+ sc -ogc.dll $(OBJS) -L$(LFLAGS) gc.def kernel32.lib user32.lib\r
+\r
+gc.def: digimars.mak\r
+ echo LIBRARY GC >gc.def\r
+ echo DESCRIPTION "Hans Boehm Garbage Collector" >>gc.def\r
+ echo EXETYPE NT >>gc.def\r
+ echo EXPORTS >>gc.def\r
+ echo GC_is_visible_print_proc >>gc.def\r
+ echo GC_is_valid_displacement_print_proc >>gc.def\r
+\r
+clean:\r
+ del gc.def\r
+ del $(OBJS)\r
+\r
+\r
+gctest.exe : gc.lib tests\test.obj\r
+ sc -ogctest.exe tests\test.obj gc.lib\r
+\r
+tests\test.obj : tests\test.c\r
+ $(CC) -c -g -DNDEBUG -DSILENT -DGC_BUILD -D_WINDOWS -DGC_DLL \\r
+ -DALL_INTERIOR_POINTERS -DWIN32_THREADS \\r
+ -Iinclude tests\test.c -otests\test.obj\r
+\r
+allchblk.obj: allchblk.c\r
+alloc.obj: alloc.c\r
+blacklst.obj: blacklst.c\r
+checksums.obj: checksums.c\r
+dbg_mlc.obj: dbg_mlc.c\r
+dyn_load.obj: dyn_load.c\r
+finalize.obj: finalize.c\r
+gc_cpp.obj: gc_cpp.cpp\r
+headers.obj: headers.c\r
+mach_dep.obj: mach_dep.c\r
+malloc.obj: malloc.c\r
+mallocx.obj: mallocx.c\r
+mark.obj: mark.c\r
+mark_rts.obj: mark_rts.c\r
+misc.obj: misc.c\r
+new_hblk.obj: new_hblk.c\r
+obj_map.obj: obj_map.c\r
+os_dep.obj: os_dep.c\r
+ptr_chck.obj: ptr_chck.c\r
+reclaim.obj: reclaim.c\r
+stubborn.obj: stubborn.c\r
+typd_mlc.obj: typd_mlc.c\r
+win32_threads.obj: win32_threads.c\r
/* src/mm/boehm.c - interface for boehm gc
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#if defined(ENABLE_THREADS) && defined(__IRIX__)
#define GC_IRIX_THREADS
#endif
+#if defined(ENABLE_THREADS) && defined(__DARWIN__)
+#define GC_DARWIN_THREADS
+#endif
#include "boehm-gc/include/gc.h"
#include "mm/gc-common.h"
{
size_t heapcurrentsize;
+ TRACESUBSYSTEMINITIALIZATION("gc_init");
+
/* just to be sure (should be set to 1 by JAVA_FINALIZATION macro) */
GC_java_finalization = 1;
}
-void *heap_alloc_uncollectable(u4 size)
+void *heap_alloc_uncollectable(size_t size)
{
void *p;
/* src/mm/cacao-gc/gc.c - main garbage collector methods
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
+
#include <signal.h>
+#include <stdint.h>
+
#include "vm/types.h"
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "compact.h"
#include "copy.h"
#if !defined(NDEBUG)
/* check if this reference is already registered */
- for (re = list_first_unsynced(list); re != NULL; re = list_next_unsynced(list, re)) {
+ for (re = list_first(list); re != NULL; re = list_next(list, re)) {
if (re->ref == ref)
vm_abort("gc_reference_register_intern: reference already registered");
}
#endif
/* add the entry to the given list */
- list_add_last_unsynced(list, re);
+ list_add_last(list, re);
/* the global GC lock also guards the reference lists */
GC_MUTEX_UNLOCK;
GC_LOG2( printf("Un-Registering Reference at %p\n", (void *) ref); );
/* search for the appropriate reference entry */
- for (re = list_first_unsynced(list); re != NULL; re = list_next_unsynced(list, re)) {
+ for (re = list_first(list); re != NULL; re = list_next(list, re)) {
if (re->ref == ref) {
/* remove the entry from the given list */
- list_remove_unsynced(list, re);
+ list_remove(list, re);
/* free the reference entry */
FREE(re, list_gcref_entry_t);
void gc_collect(s4 level)
{
rootset_t *rs;
- s4 dumpsize;
+ int32_t dumpmarker;
#if !defined(NDEBUG)
- stackframeinfo_t *sfi;
- stacktracebuffer *stb;
+ stacktrace_t *st;
#endif
#if defined(ENABLE_RT_TIMING)
struct timespec time_start, time_suspend, time_rootset, time_mark, time_compact, time_end;
GC_MUTEX_LOCK;
/* remember start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
GCSTAT_COUNT(gcstat_collections);
#if !defined(NDEBUG)
/* get the stacktrace of the current thread and make sure it is non-empty */
GC_LOG( printf("Stacktrace of current thread:\n"); );
- sfi = STACKFRAMEINFO;
- stb = stacktrace_create(sfi);
- if (stb == NULL)
+ st = stacktrace_get_current();
+ if (st == NULL)
vm_abort("gc_collect: no stacktrace available for current thread!");
- GC_LOG( stacktrace_print_trace_from_buffer(stb); );
+ GC_LOG( stacktrace_print(st); );
#endif
/* sourcestate of the current thread, assuming we are in the native world */
RT_TIMING_TIME_DIFF(time_start , time_end , RT_TIMING_GC_TOTAL);
/* free dump memory area */
- dump_release(dumpsize);
+ DRELEASE;
/* leave the global gc lock */
GC_MUTEX_UNLOCK;
/* src/mm/cacao-gc/gc.h - main garbage collector header
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include "vm/types.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "toolbox/list.h"
#include "vm/jit/replace.h"
-/* mm/cacao-gc/mark.c - GC module for marking heap objects
+/* src/mm/cacao-gc/mark.c - GC module for marking heap objects
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#if defined(GCCONF_FINALIZER)
/* objects with finalizers will also be marked here. if they have not been
marked before the finalization is triggered */
- /* REMEMBER: all threads are stopped, so we can use unsynced access here */
- fe = list_first_unsynced(final_list);
+
+ /* REMEMBER: All threads are stopped, so we don't have to lock the
+ list here. */
+
+ fe = list_first(final_list);
+
while (fe) {
f_type = fe->type;
ref = fe->o;
}
}
- fe = list_next_unsynced(final_list, fe);
+ fe = list_next(final_list, fe);
}
#endif /*defined(GCCONF_FINALIZER)*/
/* mm/cacao-gc/rootset.c - GC module for root set management
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "final.h"
#include "heap.h"
#include "mark.h"
+
#include "mm/memory.h"
-#include "threads/threads-common.h"
+
+#include "threads/threadlist.h"
+#include "threads/thread.h"
+
#include "toolbox/logging.h"
+
#include "vm/global.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
Searches global variables to compile the global root set out of references
contained in them.
- REMEMBER: All threads are stopped, so we can use unsynced access
- in this function.
+ REMEMBER: All threads are stopped, so we don't have to lock the
+ lists in this function.
SEARCHES IN:
- thread objects (threads.c)
refcount = rs->refcount;
/* walk through all registered strong references */
- for (re = list_first_unsynced(gc_reflist_strong); re != NULL; re = list_next_unsynced(gc_reflist_strong, re)) {
+ for (re = list_first(gc_reflist_strong); re != NULL; re = list_next(gc_reflist_strong, re)) {
GC_LOG2( printf("Found Registered Reference: %p at %p of type %d\n", *(re->ref), re->ref, ref->reftype); );
/* add this registered reference to the root set */
}
/* walk through all registered weak references */
- for (re = list_first_unsynced(gc_reflist_weak); re != NULL; re = list_next_unsynced(gc_reflist_weak, re)) {
+ for (re = list_first(gc_reflist_weak); re != NULL; re = list_next(gc_reflist_weak, re)) {
GC_LOG2( printf("Found Registered Weak Reference: %p at %p of type %d\n", *(re->ref), re->ref, ref->reftype); );
/* add this registered reference to the root set */
}
/* walk through all finalizer entries */
- for (fe = list_first_unsynced(final_list); fe != NULL; fe = list_next_unsynced(final_list, fe)) {
+ for (fe = list_first(final_list); fe != NULL; fe = list_next(final_list, fe)) {
GC_LOG2( printf("Found Finalizer Entry: %p\n", (void *) fe->o); );
/* add this object with finalizer to the root set */
{
rootset_t *rs_top;
rootset_t *rs;
- threadobject *thread;
+ threadobject *t;
/* find the global rootset ... */
rs_top = rootset_create();
/* ... and the rootsets for the threads */
rs = rs_top;
#if defined(ENABLE_THREADS)
- for (thread = threads_list_first(); thread != NULL; thread = threads_list_next(thread)) {
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
/* ignore threads which are in state NEW */
- if (thread->state == THREAD_STATE_NEW)
+ if (t->state == THREAD_STATE_NEW)
continue;
rs->next = rootset_create();
- rs->next = rootset_from_thread(thread, rs->next);
+ rs->next = rootset_from_thread(t, rs->next);
rs = rs->next;
}
#else
- thread = THREADOBJECT;
+ t = THREADOBJECT;
rs->next = rootset_create();
- rs->next = rootset_from_thread(thread, rs->next);
+ rs->next = rootset_from_thread(t, rs->next);
#endif
return rs_top;
-/* mm/cacao-gc/rootset.h - GC header for root set management
+/* src/mm/cacao-gc/rootset.h - GC header for root set management
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include "vm/types.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#else
-# include "threads/none/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/jit/replace.h"
#include "vmcore/method.h"
--- /dev/null
+/* src/mm/codememory.c - code 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 <stdlib.h>
+#include <sys/mman.h> /* REMOVEME */
+
+#include "threads/lock-common.h"
+#include "threads/thread.h"
+
+#include "mm/codememory.h"
+#include "mm/memory.h"
+
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
+#include "vmcore/system.h"
+
+#include "vm/global.h"
+
+
+/* global code memory variables ***********************************************/
+
+#define DEFAULT_CODE_MEMORY_SIZE 128 * 1024 /* defaulting to 128kB */
+
+#if defined(ENABLE_THREADS)
+static java_object_t *lock_code_memory = NULL;
+#endif
+static void *code_memory = NULL;
+static int code_memory_size = 0;
+static int pagesize = 0;
+
+
+/* codememory_init *************************************************************
+
+ Initialize the code memory subsystem.
+
+*******************************************************************************/
+
+void codememory_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("codememory_init");
+
+#if defined(ENABLE_THREADS)
+ /* create lock for code memory */
+
+ lock_code_memory = NEW(java_object_t);
+
+ lock_init_object_lock(lock_code_memory);
+#endif
+
+ /* Get the pagesize of this architecture. */
+
+ pagesize = system_getpagesize();
+}
+
+
+/* codememory_get **************************************************************
+
+ Allocates memory from the heap via mmap and make the memory read-,
+ write-, and executeable.
+
+*******************************************************************************/
+
+void *codememory_get(size_t size)
+{
+ void *p;
+
+ LOCK_MONITOR_ENTER(lock_code_memory);
+
+ size = MEMORY_ALIGN(size, ALIGNSIZE);
+
+ /* check if enough memory is available */
+
+ if (size > code_memory_size) {
+ /* set default code size */
+
+ code_memory_size = DEFAULT_CODE_MEMORY_SIZE;
+
+ /* do we need more? */
+
+ if (size > code_memory_size)
+ code_memory_size = size;
+
+ /* align the size of the memory to be allocated */
+
+ code_memory_size = MEMORY_ALIGN(code_memory_size, pagesize);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ codememusage += code_memory_size;
+
+ if (codememusage > maxcodememusage)
+ maxcodememusage = codememusage;
+ }
+#endif
+
+ /* allocate the memory */
+
+ p = system_mmap_anonymous(NULL, code_memory_size,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE);
+
+ /* set global code memory pointer */
+
+ code_memory = p;
+ }
+
+ /* get a memory chunk of the allocated memory */
+
+ p = code_memory;
+
+ code_memory = (void *) ((ptrint) code_memory + size);
+ code_memory_size -= size;
+
+ LOCK_MONITOR_EXIT(lock_code_memory);
+
+ return p;
+}
+
+
+/* codememory_release **********************************************************
+
+ Release the code memory and return it to the code memory
+ management.
+
+ IN:
+ p ...... pointer to the code memory
+ size ... size of the code memory
+
+*******************************************************************************/
+
+void codememory_release(void *p, size_t size)
+{
+ /* do nothing */
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically 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/codememory.h - code memory management
+
+ 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 _CODEMEMORY_H
+#define _CODEMEMORY_H
+
+#include "config.h"
+
+#include <stdint.h>
+#include <sys/types.h>
+
+
+/* convenience macros *********************************************************/
+
+#define CNEW(type,num) ((type *) codememory_get(sizeof(type) * (num)))
+#define CFREE(ptr,num) codememory_release((ptr),(num))
+
+
+/* function prototypes ********************************************************/
+
+void codememory_init(void);
+
+void *codememory_get(size_t size);
+void codememory_release(void *p, size_t size);
+
+#endif /* _CODEMEMORY_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.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.h"
+
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
+#include "vmcore/system.h"
+
+#include "vm/vm.h"
+
+
+/*******************************************************************************
+
+ 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) system_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) system_memcpy(dst, src, len1);
+
+#if defined(ENABLE_MEMCHECK)
+ /* destroy the source */
+
+ (void) system_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) system_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. */
+
+ system_free(tmp->dumpmem);
+ system_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.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
+
+/* 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) 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);
+
+#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:
+ */
/* src/mm/gc-common.h - gc independant interface for heap managment
- 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.
void gc_init(u4 heapmaxsize, u4 heapstartsize);
-void *heap_alloc_uncollectable(u4 size);
+void *heap_alloc_uncollectable(size_t size);
void *heap_alloc(u4 size, u4 references, methodinfo *finalizer, bool collect);
void heap_free(void *p);
/* src/mm/memory.c - memory management
- 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 <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <sys/mman.h>
#if defined(__DARWIN__)
/* If we compile with -ansi on darwin, <sys/types.h> is not
#include "native/native.h"
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
# include "vmcore/statistics.h"
#endif
-
-/*******************************************************************************
-
- 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
-
-
-/* global code memory variables ***********************************************/
-
-#define DEFAULT_CODE_MEMORY_SIZE 128 * 1024 /* defaulting to 128kB */
-
-#if defined(ENABLE_THREADS)
-static java_object_t *lock_code_memory = NULL;
-#endif
-static void *code_memory = NULL;
-static int code_memory_size = 0;
-static int pagesize = 0;
-
-
-/* memory_init *****************************************************************
-
- Initialize the memory subsystem.
-
-*******************************************************************************/
-
-bool memory_init(void)
-{
-#if defined(ENABLE_THREADS)
- /* create lock for code memory */
-
- lock_code_memory = NEW(java_object_t);
-
- lock_init_object_lock(lock_code_memory);
-#endif
-
- /* get the pagesize of this architecture */
-
- pagesize = getpagesize();
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* memory_mmap_anon ************************************************************
-
- Maps anonymous memory, even on systems not defining
- MAP_ANON(YMOUS).
-
-*******************************************************************************/
-
-void *memory_mmap_anon(void *addr, size_t len, int prot, int flags)
-{
- void *p;
-
-#if defined(MAP_ANON) || defined(MAP_ANONYMOUS)
- p = mmap(addr, len, prot,
-# if defined(MAP_ANON)
- MAP_ANON | flags,
-# else
- MAP_ANONYMOUS | flags,
-# endif
- -1, 0);
-#else
- int fd;
-
- fd = open("/dev/zero", O_RDONLY, 0);
-
- if (fd == -1)
- vm_abort("memory_mmap_anon: open failed: %s", strerror(errno));
-
- p = mmap(addr, len, prot, flags, fd, 0);
-#endif
-
-#if defined(MAP_FAILED)
- if (p == MAP_FAILED)
-#else
- if (p == (void *) -1)
-#endif
- vm_abort("memory_mmap_anon: mmap failed: %s", strerror(errno));
-
- return p;
-}
+#include "vmcore/system.h"
/* memory_mprotect *************************************************************
void memory_mprotect(void *addr, size_t len, int prot)
{
- if (mprotect(addr, len, prot) != 0)
- vm_abort("memory_mprotect: mprotect failed: %s", strerror(errno));
+ if (system_mprotect(addr, len, prot) != 0)
+ vm_abort("memory_mprotect: system_mprotect failed: %s",
+ strerror(errno));
}
*******************************************************************************/
-static void *memory_checked_alloc(s4 size)
+void *memory_checked_alloc(size_t size)
{
/* always allocate memory zeroed out */
}
-/* memory_cnew *****************************************************************
-
- Allocates memory from the heap via mmap and make the memory read-,
- write-, and executeable.
-
-*******************************************************************************/
-
-void *memory_cnew(s4 size)
-{
- void *p;
-
- LOCK_MONITOR_ENTER(lock_code_memory);
-
- size = MEMORY_ALIGN(size, ALIGNSIZE);
-
- /* check if enough memory is available */
-
- if (size > code_memory_size) {
- /* set default code size */
-
- code_memory_size = DEFAULT_CODE_MEMORY_SIZE;
-
- /* do we need more? */
-
- if (size > code_memory_size)
- code_memory_size = size;
-
- /* align the size of the memory to be allocated */
-
- code_memory_size = MEMORY_ALIGN(code_memory_size, pagesize);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- codememusage += code_memory_size;
-
- if (codememusage > maxcodememusage)
- maxcodememusage = codememusage;
- }
-#endif
-
- /* allocate the memory */
-
- p = memory_mmap_anon(NULL, code_memory_size,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE);
-
- /* set global code memory pointer */
-
- code_memory = p;
- }
-
- /* get a memory chunk of the allocated memory */
-
- p = code_memory;
-
- code_memory = (void *) ((ptrint) code_memory + size);
- code_memory_size -= size;
-
- LOCK_MONITOR_EXIT(lock_code_memory);
-
- return p;
-}
-
-
-/* memory_cfree ****************************************************************
-
- Frees the code memory pointed to.
-
- ATTENTION: This function currently does NOTHING! Because we don't
- have a memory management for code memory.
-
-*******************************************************************************/
-
-void memory_cfree(void *p, s4 size)
-{
- /* do nothing */
-}
-
-
-void *mem_alloc(s4 size)
+void *mem_alloc(int32_t size)
{
void *m;
}
-void *mem_realloc(void *src, s4 len1, s4 len2)
+void *mem_realloc(void *src, int32_t len1, int32_t len2)
{
void *dst;
}
-void mem_free(void *m, s4 size)
+void mem_free(void *m, int32_t size)
{
if (!m) {
if (size == 0)
{
int32_t seconds;
+ /* Prevent compiler warning. */
+
+ seconds = 1;
+
/* If both arguments are specified, use the value of
ProfileMemoryUsage. */
#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)
-void dump_check_canaries(dumpinfo_t *di, s4 bottomsize)
-{
- dump_allocation_t *da;
- u1 *pm;
- s4 i, j;
-
- /* iterate over all dump memory allocations above bottomsize */
-
- da = di->allocations;
- while (da && da->useddumpsize >= bottomsize) {
- /* check canaries */
-
- pm = 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 = 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) */
-
-
-/* dump_alloc ******************************************************************
-
- 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:
- dump_alloc is thread safe. Each thread has its own dump memory area.
-
- dump_alloc 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 `dump_size`. Later, when you no
- longer need the memory, call `dump_release` with the remembered size and
- all dump memory allocated since the call to `dump_size` will be freed.
-
-*******************************************************************************/
-
-void *dump_alloc(s4 size)
-{
-#if defined(DISABLE_DUMP)
-
- /* use malloc memory for dump memory (for debugging only!) */
-
- return mem_alloc(size);
-
-#else /* !defined(DISABLE_DUMP) */
-
- void *m;
- dumpinfo_t *di;
-#if defined(ENABLE_MEMCHECK)
- s4 origsize = size; /* needed for the canary system */
-#endif
-
- /* If no threads are used, the dumpinfo structure is a static structure */
- /* defined at the top of this file. */
-
- di = DUMPINFO;
-
- if (size == 0)
- return NULL;
-
-#if defined(ENABLE_MEMCHECK)
- size += 2*MEMORY_CANARY_SIZE;
-#endif
-
- size = MEMORY_ALIGN(size, ALIGNSIZE);
-
- if (di->useddumpsize + size > di->allocateddumpsize) {
- dumpblock_t *newdumpblock;
- s4 newdumpblocksize;
-
- /* allocate a new dumplist structure */
-
- newdumpblock = 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) {
- newdumpblocksize = size;
-
- } else {
- newdumpblocksize = DUMPBLOCKSIZE;
- }
-
- /* allocate dumpblock memory */
-
- newdumpblock->dumpmem = memory_checked_alloc(newdumpblocksize);
-
- newdumpblock->prev = di->currentdumpblock;
- newdumpblock->size = newdumpblocksize;
- di->currentdumpblock = newdumpblock;
-
- /* Used dump size is previously allocated dump size, because the */
- /* remaining free memory of the previous dump block cannot be used. */
-
- di->useddumpsize = di->allocateddumpsize;
-
- /* increase the allocated dump size by the size of the new dump block */
-
- di->allocateddumpsize += newdumpblocksize;
-
-#if defined(ENABLE_STATISTICS)
- /* the amount of globally allocated dump memory (thread save) */
-
- if (opt_stat)
- globalallocateddumpsize += newdumpblocksize;
-#endif
- }
-
- /* current dump block base address + the size of the current dump block - */
- /* the size of the unused memory = new start address */
-
- m = di->currentdumpblock->dumpmem + di->currentdumpblock->size -
- (di->allocateddumpsize - di->useddumpsize);
-
-#if defined(ENABLE_MEMCHECK)
- {
- dump_allocation_t *da = NEW(dump_allocation_t);
- s4 i;
- u1 *pm;
-
- /* add the allocation to our linked list of allocations */
-
- da->next = di->allocations;
- da->mem = (u1*) m + MEMORY_CANARY_SIZE;
- da->size = origsize;
- da->useddumpsize = di->useddumpsize;
-
- di->allocations = da;
-
- /* write the canaries */
-
- pm = (u1*)m;
- for (i=0; i<MEMORY_CANARY_SIZE; ++i)
- pm[i] = i + MEMORY_CANARY_FIRST_BYTE;
- pm = 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 */
-
- m = (u1*)m + MEMORY_CANARY_SIZE;
-
- /* clear the memory */
-
- memset(m, MEMORY_CLEAR_BYTE, da->size);
- }
-#endif /* defined(ENABLE_MEMCHECK) */
-
- /* increase used dump size by the allocated memory size */
-
- di->useddumpsize += size;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- if (di->useddumpsize > maxdumpsize)
- maxdumpsize = di->useddumpsize;
-#endif
-
- return m;
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/* dump_realloc ****************************************************************
-
- Stupid realloc implementation for dump memory. Avoid, if possible.
-
-*******************************************************************************/
-
-void *dump_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 = dump_alloc(len2);
-
- memcpy(dst, src, len1);
-
-#if defined(ENABLE_MEMCHECK)
- /* destroy the source */
- memset(src, MEMORY_CLEAR_BYTE, len1);
-#endif
-
- return dst;
-#endif
-}
-
-
-/* dump_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 `dump_size` call
- made earlier.
-
- ERROR HANDLING:
- XXX If the given size is invalid, this function *exits* with an
- error message.
-
- See `dump_alloc`.
-
-*******************************************************************************/
-
-void dump_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;
-
- /* If no threads are used, the dumpinfo structure is a static structure */
- /* defined at the top of this file. */
-
- di = DUMPINFO;
-
- if ((size < 0) || (size > di->useddumpsize))
- vm_abort("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 && da->useddumpsize >= size) {
- next = da->next;
-
- /* invalidate the freed memory */
-
- 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->useddumpsize = size;
-
- while (di->currentdumpblock && di->allocateddumpsize - di->currentdumpblock->size >= di->useddumpsize) {
- dumpblock_t *tmp = di->currentdumpblock;
-
- di->allocateddumpsize -= tmp->size;
- di->currentdumpblock = 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 */
-
- free(tmp->dumpmem);
- free(tmp);
- }
-
-#endif /* defined(DISABLE_DUMP) */
-}
-
-
-/* dump_size *******************************************************************
-
- Return the current size of the dump memory area. See `dump_alloc`.
-
-*******************************************************************************/
-
-s4 dump_size(void)
-{
-#if defined(DISABLE_DUMP)
- /* use malloc memory for dump memory (for debugging only!) */
-
- return 0;
-
-#else /* !defined(DISABLE_DUMP) */
-
- dumpinfo_t *di;
-
- /* If no threads are used, the dumpinfo structure is a static structure */
- /* defined at the top of this file. */
-
- di = DUMPINFO;
-
- if (di == NULL)
- return 0;
-
- return di->useddumpsize;
-
-#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
/* src/mm/memory.h - macros for memory management
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#ifndef _MEMORY_H
#define _MEMORY_H
-/* forward typedefs ***********************************************************/
-
-typedef struct dumpblock_t dumpblock_t;
-typedef struct dumpinfo_t dumpinfo_t;
#include "config.h"
#include "vm/types.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;
- u1 *dumpmem;
- s4 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;
- u1 *mem;
- s4 useddumpsize;
- s4 size;
-};
-#endif
-
-
-/* dumpinfo *******************************************************************/
-
-struct dumpinfo_t {
- dumpblock_t *currentdumpblock; /* the current top-most block */
- s4 allocateddumpsize; /* allocated bytes in this area */
- s4 useddumpsize; /* used bytes in this dump area */
-#if defined(ENABLE_MEMCHECK)
- dump_allocation_t *allocations; /* list of allocations in this area */
-#endif
-};
+#include "mm/codememory.h"
+#include "mm/dumpmemory.h"
/* constants for ENABLE_MEMCHECK **********************************************/
mem_realloc ... change size of a memory block (position may change)
mem_usage ..... amount of allocated memory
-
- 2. explicit allocating, automatic deallocating
-
- dump_alloc .... allocate a memory block in the dump area
- dump_realloc .. change size of a memory block (position may change)
- dump_size ..... marks the current top of dump
- dump_release .. free all memory requested after the mark
-
-
There are some useful macros:
NEW (type) ....... allocate memory for an element of type `type`
MREALLOC (ptr,type,num1,num2) .. enlarge the array to size num2
-These macros do the same except they operate on the dump area:
-
- DNEW, DMNEW, DMREALLOC (there is no DFREE)
-
-
-------------------------------------------------------------------------------
Some more macros:
#define MEMORY_ALIGN(pos,size) ((((pos) + (size) - 1) / (size)) * (size))
#define PADDING(pos,size) (MEMORY_ALIGN((pos),(size)) - (pos))
-#define OFFSET(s,el) ((s4) ((ptrint) &(((s*) 0)->el)))
+#define OFFSET(s,el) ((int32_t) ((ptrint) &(((s*) 0)->el)))
#define NEW(type) ((type *) mem_alloc(sizeof(type)))
sizeof(type) * (num2))
-#define DNEW(type) ((type *) dump_alloc(sizeof(type)))
-#define DMNEW(type,num) ((type *) dump_alloc(sizeof(type) * (num)))
-#define DMREALLOC(ptr,type,num1,num2) dump_realloc((ptr), sizeof(type) * (num1), \
- sizeof(type) * (num2))
-
#define MCOPY(dest,src,type,num) memcpy((dest), (src), sizeof(type) * (num))
#define MSET(ptr,byte,type,num) memset((ptr), (byte), sizeof(type) * (num))
#define MZERO(ptr,type,num) MSET(ptr,0,type,num)
#define MMOVE(dest,src,type,num) memmove((dest), (src), sizeof(type) * (num))
-#define CNEW(type,num) ((type *) memory_cnew(sizeof(type) * (num)))
-#define CFREE(ptr,num) memory_cfree((ptr),(num))
-
/* GC macros (boehm only) *****************************************************/
/* function prototypes ********************************************************/
-/* initializes the memory subsystem */
-bool memory_init(void);
+bool memory_init(void);
-void *memory_mmap_anon(void *addr, size_t len, int prot, int flags);
void memory_mprotect(void *addr, size_t len, int prot);
-void *memory_cnew(s4 size);
-void memory_cfree(void *p, s4 size);
+void *memory_checked_alloc(size_t size);
+
+void *memory_cnew(int32_t size);
+void memory_cfree(void *p, int32_t size);
-void *mem_alloc(s4 size);
-void mem_free(void *m, s4 size);
-void *mem_realloc(void *src, s4 len1, s4 len2);
+void *mem_alloc(int32_t size);
+void mem_free(void *m, int32_t size);
+void *mem_realloc(void *src, int32_t len1, int32_t len2);
#if defined(ENABLE_THREADS)
bool memory_start_thread(void);
#endif
-void *dump_alloc(s4 size);
-void *dump_realloc(void *src, s4 len1, s4 len2);
-s4 dump_size(void);
-void dump_release(s4 size);
-
#endif /* _MEMORY_H */
## src/native/include/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.
##
## 02110-1301, USA.
+JAVAH = $(CACAOH)
+JAVAHCMD = $(JAVAH) -bootclasspath $(BOOTCLASSPATH)
+
COMMON_HEADER_FILES = \
java_lang_Class.h \
java_lang_Object.h \
gnu_classpath_Pointer.h \
gnu_classpath_Pointer32.h \
gnu_classpath_Pointer64.h \
+ gnu_java_lang_VMCPStringBuilder.h \
java_lang_VMObject.h \
+ java_lang_reflect_VMConstructor.h \
+ java_lang_reflect_VMField.h \
+ java_lang_reflect_VMMethod.h \
java_nio_DirectByteBufferImpl.h
if ENABLE_ANNOTATIONS
endif
if WITH_CLASSPATH_GNU
-CLASSPATH = $(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
-VM_ZIP = $(top_builddir)/src/lib/vm.zip
-endif
-
-if WITH_CLASSPATH_SUN
-CLASSPATH = $(CLASSPATH_CLASSES)
+VM_ZIP = $(top_builddir)/src/classes/vm.zip
endif
if WITH_CLASSPATH_CLDC1_1
-CLASSPATH = $(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
-VM_ZIP = $(top_builddir)/src/lib/vm.zip
+VM_ZIP = $(top_builddir)/src/classes/vm.zip
endif
noinst_DATA = $(DO_HEADER_FILES)
$(DO_HEADER_FILES): $(CACAOH) $(VM_ZIP) $(CLASSPATH_CLASSES)
@class=`echo $@ | sed -e 's/\.h$$//' -e 's/_/\./g'`; \
- echo "$(CACAOH) -bootclasspath $(CLASSPATH) -d . $$class"; \
- $(CACAOH) -bootclasspath $(CLASSPATH) -d . $$class
+ echo "$(JAVAHCMD) -d . $$class"; \
+ $(JAVAHCMD) -d . $$class
## Local variables:
/* src/native/jni.c - implementation of the Java Native Interface functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/java_lang_Throwable.h"
#if defined(ENABLE_JAVASE)
+
# if defined(WITH_CLASSPATH_SUN)
# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
# endif
+/* java_lang_ClassLoader is used in java_lang_Class and vice versa, so
+ we pre-define it here to prevent a compiler warning for Sun
+ configurations. */
+
+struct java_lang_ClassLoader;
+
# include "native/include/java_lang_Class.h"
# include "native/include/java_lang_ClassLoader.h"
# include "native/include/java_nio_Buffer.h"
# if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_reflect_VMConstructor.h"
+# include "native/include/java_lang_reflect_VMField.h"
+# include "native/include/java_lang_reflect_VMMethod.h"
+
# include "native/include/java_nio_DirectByteBufferImpl.h"
# endif
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+# include "native/include/java_lang_Class.h"
#endif
#if defined(ENABLE_JVMTI)
# include "native/jvmti/cacaodbg.h"
#endif
-#include "native/vm/java_lang_Class.h"
-
#if defined(ENABLE_JAVASE)
-# include "native/vm/java_lang_ClassLoader.h"
# include "native/vm/reflect.h"
#endif
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
/* debug **********************************************************************/
#if !defined(NDEBUG)
-# define TRACEJNICALLS(format, ...) \
- do { \
- if (opt_TraceJNICalls) { \
- log_println((format), __VA_ARGS__); \
- } \
+# define TRACEJNICALLS(text) \
+ do { \
+ if (opt_TraceJNICalls) { \
+ log_println text; \
+ } \
} while (0)
#else
-# define TRACEJNICALLS(format, ...)
+# define TRACEJNICALLS(text)
#endif
bool jni_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("jni_init");
+
/* create global ref hashtable */
hashtable_global_ref = NEW(hashtable);
}
-/* _Jv_jni_invokeNative ********************************************************
-
- Invoke a method on the given object with the given arguments.
-
- For instance methods OBJ must be != NULL and the method is looked up
- in the vftbl of the object.
-
- For static methods, OBJ is ignored.
-
-*******************************************************************************/
-
-java_handle_t *_Jv_jni_invokeNative(methodinfo *m, java_handle_t *o,
- java_handle_objectarray_t *params)
-{
- methodinfo *resm;
- java_handle_t *ro;
- s4 argcount;
- s4 paramcount;
-
- if (m == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- argcount = m->parseddesc->paramcount;
- paramcount = argcount;
-
- /* if method is non-static, remove the `this' pointer */
-
- if (!(m->flags & ACC_STATIC))
- paramcount--;
-
- /* For instance methods the object has to be an instance of the
- class the method belongs to. For static methods the obj
- parameter is ignored. */
-
- if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->class))) {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* check if we got the right number of arguments */
-
- if (((params == NULL) && (paramcount != 0)) ||
- (params && (LLNI_array_size(params) != paramcount)))
- {
- exceptions_throw_illegalargumentexception();
- return NULL;
- }
-
- /* for instance methods we need an object */
-
- if (!(m->flags & ACC_STATIC) && (o == NULL)) {
- /* XXX not sure if that is the correct exception */
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* for static methods, zero object to make subsequent code simpler */
- if (m->flags & ACC_STATIC)
- o = NULL;
-
- if (o != NULL) {
- /* for instance methods we must do a vftbl lookup */
- resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
- }
- else {
- /* for static methods, just for convenience */
- resm = m;
- }
-
- ro = vm_call_method_objectarray(resm, o, params);
-
- return ro;
-}
-
-
/* GetVersion ******************************************************************
Returns the major version number in the higher 16 bits and the
jint _Jv_JNI_GetVersion(JNIEnv *env)
{
- TRACEJNICALLS("_Jv_JNI_GetVersion(env=%p)", env);
+ TRACEJNICALLS(("_Jv_JNI_GetVersion(env=%p)", env));
/* We support JNI 1.6. */
{
#if defined(ENABLE_JAVASE)
utf *u;
- classloader *cl;
+ classloader_t *cl;
classinfo *c;
java_lang_Class *co;
- TRACEJNICALLS("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen);
+ TRACEJNICALLS(("_Jv_JNI_DefineClass(env=%p, name=%s, loader=%p, buf=%p, bufLen=%d)", env, name, loader, buf, bufLen));
u = utf_new_char(name);
cl = loader_hashtable_classloader_add((java_handle_t *) loader);
- c = class_define(u, cl, bufLen, (const uint8_t *) buf, NULL);
+ c = class_define(u, cl, bufLen, (uint8_t *) buf, NULL);
co = LLNI_classinfo_wrap(c);
*******************************************************************************/
-jclass _Jv_JNI_FindClass(JNIEnv *env, const char *name)
+jclass jni_FindClass(JNIEnv *env, const char *name)
{
#if defined(ENABLE_JAVASE)
classinfo *c;
java_lang_Class *co;
- TRACEJNICALLS("_Jv_JNI_FindClass(env=%p, name=%s)", env, name);
+ TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
+
+ /* FIXME If name is NULL we have a problem here. */
u = utf_new_char_classname((char *) name);
+ if ((u == NULL) /*|| (int)strlen(name) > symbolOopDesc::max_length() */) {
+ exceptions_throw_noclassdeffounderror(u);
+ return NULL;
+ }
+
/* Check stacktrace for classloader, if one found use it,
otherwise use the system classloader. */
else
c = load_class_from_classloader(u, cc->classloader);
- if (c == NULL)
+ if (c == NULL) {
+ resolve_handle_pending_exception(true);
return NULL;
+ }
if (!link_class(c))
return NULL;
utf *u;
classinfo *c;
- TRACEJNICALLS("_Jv_JNI_FindClass(env=%p, name=%s)", env, name);
+ TRACEJNICALLS(("jni_FindClass(env=%p, name=%s)", env, name));
u = utf_new_char_classname((char *) name);
c = load_class_bootstrap(u);
- if (c == NULL)
+ if (c == NULL) {
+ resolve_handle_pending_exception(true);
return NULL;
+ }
if (!link_class(c))
return NULL;
return (jclass) _Jv_JNI_NewLocalRef(env, (jobject) c);
#else
- vm_abort("_Jv_JNI_FindClass: not implemented in this configuration");
+ vm_abort("jni_FindClass: not implemented in this configuration");
/* keep compiler happy */
classinfo *super;
java_lang_Class *co;
- TRACEJNICALLS("_Jv_JNI_GetSuperclass(env=%p, sub=%p)", env, sub);
+ TRACEJNICALLS(("_Jv_JNI_GetSuperclass(env=%p, sub=%p)", env, sub));
c = LLNI_classinfo_unwrap(sub);
jboolean _Jv_JNI_IsAssignableFrom(JNIEnv *env, jclass sub, jclass sup)
{
- java_lang_Class *csup;
- java_lang_Class *csub;
+ classinfo *to;
+ classinfo *from;
- csup = (java_lang_Class *) sup;
- csub = (java_lang_Class *) sub;
+ TRACEJNICALLS(("_Jv_JNI_IsAssignableFrom(env=%p, sub=%p, sup=%p)", env, sub, sup));
- STATISTICS(jniinvokation());
+ to = (classinfo *) sup;
+ from = (classinfo *) sub;
- return _Jv_java_lang_Class_isAssignableFrom(csup, csub);
+ return class_is_assignable_from(to, from);
}
{
java_handle_t *o;
- TRACEJNICALLS("_Jv_JNI_ExceptionOccurred(env=%p)", env);
+ TRACEJNICALLS(("_Jv_JNI_ExceptionOccurred(env=%p)", env));
o = exceptions_get_exception();
*******************************************************************************/
-void _Jv_JNI_ExceptionDescribe(JNIEnv *env)
+void jni_ExceptionDescribe(JNIEnv *env)
{
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
-
- TRACEJNICALLS("_Jv_JNI_ExceptionDescribe(env=%p)", env);
-
- /* Clear exception, because we are probably calling Java code
- again. */
-
- o = exceptions_get_and_clear_exception();
+ TRACEJNICALLS(("jni_ExceptionDescribe(env=%p)", env));
- if (o != NULL) {
- /* get printStackTrace method from exception class */
-
- LLNI_class_get(o, c);
-
- m = class_resolveclassmethod(c,
- utf_printStackTrace,
- utf_void__void,
- NULL,
- true);
-
- if (m == NULL)
- vm_abort("_Jv_JNI_ExceptionDescribe: could not find printStackTrace");
-
- /* Print the stacktrace. */
-
- (void) vm_call_method(m, o);
- }
+ exceptions_print_stacktrace();
}
*******************************************************************************/
-void _Jv_JNI_ExceptionClear(JNIEnv *env)
+void jni_ExceptionClear(JNIEnv *env)
{
- STATISTICS(jniinvokation());
+ TRACEJNICALLS(("jni_ExceptionClear(env=%p)", env));
exceptions_clear_exception();
}
localref = localref_add(LLNI_DIRECT(o));
- return localref;
+ return (jobject) localref;
}
jboolean _Jv_JNI_IsInstanceOf(JNIEnv *env, jobject obj, jclass clazz)
{
- java_lang_Class *c;
- java_lang_Object *o;
+ classinfo *c;
+ java_handle_t *h;
- STATISTICS(jniinvokation());
+ TRACEJNICALLS(("_Jv_JNI_IsInstanceOf(env=%p, obj=%p, clazz=%p)", env, obj, clazz));
- c = (java_lang_Class *) clazz;
- o = (java_lang_Object *) obj;
+ /* XXX Is this correct? */
+ c = LLNI_classinfo_unwrap(clazz);
+ h = (java_handle_t *) obj;
- return _Jv_java_lang_Class_isInstance(c, o);
+ return class_is_instance(c, h);
}
*******************************************************************************/
-jmethodID _Jv_JNI_FromReflectedMethod(JNIEnv *env, jobject method)
+jmethodID jni_FromReflectedMethod(JNIEnv *env, jobject method)
{
#if defined(ENABLE_JAVASE)
- java_handle_t *o;
- classinfo *c;
- methodinfo *m;
- s4 slot;
+ java_handle_t *o;
+ java_lang_reflect_Method *rm;
+ java_lang_reflect_Constructor *rc;
+ classinfo *c;
+ methodinfo *m;
+ int32_t slot;
+
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_reflect_VMMethod *rvmm;
+ java_lang_reflect_VMConstructor *rvmc;
+#endif
- STATISTICS(jniinvokation());
+ TRACEJNICALLS(("jni_FromReflectedMethod(env=%p, method=%p)", env, method));
o = (java_handle_t *) method;
if (o == NULL)
return NULL;
-
- if (builtin_instanceof(o, class_java_lang_reflect_Method)) {
- java_lang_reflect_Method *rm;
- rm = (java_lang_reflect_Method *) method;
- LLNI_field_get_cls(rm, clazz, c);
- LLNI_field_get_val(rm, slot , slot);
- }
- else if (builtin_instanceof(o, class_java_lang_reflect_Constructor)) {
- java_lang_reflect_Constructor *rc;
+ if (o->vftbl->clazz == class_java_lang_reflect_Constructor) {
+ rc = (java_lang_reflect_Constructor *) method;
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ LLNI_field_get_ref(rc, cons , rvmc);
+ LLNI_field_get_cls(rvmc, clazz, c);
+ LLNI_field_get_val(rvmc, slot , slot);
+
+#elif defined(WITH_CLASSPATH_SUN)
- rc = (java_lang_reflect_Constructor *) method;
LLNI_field_get_cls(rc, clazz, c);
LLNI_field_get_val(rc, slot , slot);
+
+#else
+# error unknown configuration
+#endif
+ }
+ else {
+ assert(o->vftbl->clazz == class_java_lang_reflect_Method);
+
+ rm = (java_lang_reflect_Method *) method;
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ LLNI_field_get_ref(rm, m , rvmm);
+ LLNI_field_get_cls(rvmm, clazz, c);
+ LLNI_field_get_val(rvmm, slot , slot);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
+ LLNI_field_get_cls(rm, clazz, c);
+ LLNI_field_get_val(rm, slot , slot);
+
+#else
+# error unknown configuration
+#endif
}
- else
- return NULL;
m = &(c->methods[slot]);
return (jmethodID) m;
#else
- vm_abort("_Jv_JNI_FromReflectedMethod: not implemented in this configuration");
+ vm_abort("jni_FromReflectedMethod: Not implemented in this configuration.");
- /* keep compiler happy */
+ /* Keep compiler happy. */
return NULL;
#endif
*******************************************************************************/
-jfieldID _Jv_JNI_FromReflectedField(JNIEnv* env, jobject field)
+jfieldID jni_FromReflectedField(JNIEnv* env, jobject field)
{
#if defined(ENABLE_JAVASE)
- java_lang_reflect_Field *rf;
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
+ java_lang_reflect_Field *rf;
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
- STATISTICS(jniinvokation());
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_reflect_VMField *rvmf;
+#endif
+
+ TRACEJNICALLS(("jni_FromReflectedField(env=%p, field=%p)", env, field));
rf = (java_lang_reflect_Field *) field;
if (rf == NULL)
return NULL;
+#if defined(WITH_CLASSPATH_GNU)
+
+ LLNI_field_get_ref(rf, f, rvmf);
+ LLNI_field_get_cls(rvmf, clazz, c);
+ LLNI_field_get_val(rvmf, slot , slot);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
LLNI_field_get_cls(rf, clazz, c);
LLNI_field_get_val(rf, slot , slot);
+
+#else
+# error unknown configuration
+#endif
+
f = &(c->fields[slot]);
return (jfieldID) f;
#else
- vm_abort("_Jv_JNI_FromReflectedField: not implemented in this configuration");
+ vm_abort("jni_FromReflectedField: Not implemented in this configuration.");
- /* keep compiler happy */
+ /* Keep compiler happy. */
return NULL;
#endif
java_lang_reflect_Constructor *rc;
java_lang_reflect_Method *rm;
- TRACEJNICALLS("_Jv_JNI_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic);
+ TRACEJNICALLS(("_Jv_JNI_ToReflectedMethod(env=%p, cls=%p, methodID=%p, isStatic=%d)", env, cls, methodID, isStatic));
m = (methodinfo *) methodID;
{ \
intern ret; \
\
- STATISTICS(jniinvokation()); \
+ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "Field(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID)); \
\
LLNI_CRITICAL_START; \
\
{
java_handle_t *o;
- TRACEJNICALLS("_Jv_JNI_GetObjectField(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID);
+ TRACEJNICALLS(("_Jv_JNI_GetObjectField(env=%p, obj=%p, fieldId=%p)", env, obj, fieldID));
LLNI_CRITICAL_START;
LLNI_CRITICAL_END;
- return _Jv_JNI_NewLocalRef(env, o);
+ return _Jv_JNI_NewLocalRef(env, (jobject) o);
}
void _Jv_JNI_Set##name##Field(JNIEnv *env, jobject obj, jfieldID fieldID, \
type value) \
{ \
- STATISTICS(jniinvokation()); \
+ TRACEJNICALLS(("_Jv_JNI_Set" STR(name) "Field(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value)); \
\
LLNI_CRITICAL_START; \
\
void _Jv_JNI_SetObjectField(JNIEnv *env, jobject obj, jfieldID fieldID,
jobject value)
{
- TRACEJNICALLS("_Jv_JNI_SetObjectField(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value);
+ TRACEJNICALLS(("_Jv_JNI_SetObjectField(env=%p, obj=%p, fieldId=%p, value=%p)", env, obj, fieldID, value));
LLNI_CRITICAL_START;
utf *udesc;
methodinfo *m;
- TRACEJNICALLS("_Jv_JNI_GetStaticMethodID(env=%p, clazz=%p, name=%s, sig=%s)", env, clazz, name, sig);
+ TRACEJNICALLS(("_Jv_JNI_GetStaticMethodID(env=%p, clazz=%p, name=%s, sig=%s)", env, clazz, name, sig));
c = LLNI_classinfo_unwrap(clazz);
java_handle_t *o;
va_list ap;
+ TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
+
m = (methodinfo *) methodID;
va_start(ap, methodID);
methodinfo *m;
java_handle_t *o;
+ TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
m = (methodinfo *) methodID;
o = _Jv_jni_CallObjectMethod(NULL, NULL, m, args);
methodinfo *m;
java_handle_t *o;
+ TRACEJNICALLS(("_Jv_JNI_CallStaticObjectMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
m = (methodinfo *) methodID;
o = _Jv_jni_CallObjectMethodA(NULL, NULL, m, args);
methodinfo *m;
va_list ap;
+ TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethod(env=%p, clazz=%p, methodID=%p, ...)", env, clazz, methodID));
+
m = (methodinfo *) methodID;
va_start(ap, methodID);
{
methodinfo *m;
+ TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodV(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
m = (methodinfo *) methodID;
_Jv_jni_CallVoidMethod(NULL, NULL, m, args);
{
methodinfo *m;
+ TRACEJNICALLS(("_Jv_JNI_CallStaticVoidMethodA(env=%p, clazz=%p, methodID=%p, args=%p)", env, clazz, methodID, args));
+
m = (methodinfo *) methodID;
_Jv_jni_CallVoidMethodA(NULL, NULL, m, args);
h = LLNI_WRAP(f->value->a);
- return _Jv_JNI_NewLocalRef(env, h);
+ return _Jv_JNI_NewLocalRef(env, (jobject) h);
}
java_lang_String *s;
jsize len;
- TRACEJNICALLS("_Jv_JNI_GetStringLength(env=%p, str=%p)", env, str);
+ TRACEJNICALLS(("_Jv_JNI_GetStringLength(env=%p, str=%p)", env, str));
s = (java_lang_String *) str;
{
java_lang_String *s;
- TRACEJNICALLS("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes);
+ TRACEJNICALLS(("_Jv_JNI_NewStringUTF(env=%p, bytes=%s)", env, bytes));
s = (java_lang_String *) javastring_safe_new_from_utf8(bytes);
java_lang_String *s;
s4 length;
- TRACEJNICALLS("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string);
+ TRACEJNICALLS(("_Jv_JNI_GetStringUTFLength(env=%p, string=%p)", env, string));
s = (java_lang_String *) string;
java_handle_t *a;
jsize size;
- STATISTICS(jniinvokation());
+ TRACEJNICALLS(("_Jv_JNI_GetArrayLength(env=%p, array=%p)", env, array));
a = (java_handle_t *) array;
JNI_NEW_ARRAY(Boolean, jbooleanArray, boolean)
JNI_NEW_ARRAY(Byte, jbyteArray, byte)
JNI_NEW_ARRAY(Char, jcharArray, char)
-JNI_NEW_ARRAY(Short, jshortArray, byte)
+JNI_NEW_ARRAY(Short, jshortArray, short)
JNI_NEW_ARRAY(Int, jintArray, int)
JNI_NEW_ARRAY(Long, jlongArray, long)
JNI_NEW_ARRAY(Float, jfloatArray, float)
{ \
java_handle_##intern##array_t *a; \
\
- STATISTICS(jniinvokation()); \
+ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayElements(env=%p, array=%p, isCopy=%d)", env, array, isCopy)); \
\
a = (java_handle_##intern##array_t *) array; \
\
{ \
java_handle_##intern##array_t *a; \
\
- STATISTICS(jniinvokation()); \
+ TRACEJNICALLS(("_Jv_JNI_Get" STR(name) "ArrayRegion(env=%p, array=%p, start=%d, len=%d, buf=%p)", env, array, start, len, buf)); \
\
a = (java_handle_##intern##array_t *) array; \
\
int32_t count;
int32_t offset;
- TRACEJNICALLS("_Jv_JNI_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf);
+ TRACEJNICALLS(("_Jv_JNI_GetStringUTFRegion(env=%p, str=%p, start=%d, len=%d, buf=%p)", env, str, start, len, buf));
s = (java_lang_String *) str;
LLNI_field_get_ref(s, value, ca);
Obtain a direct pointer to array elements.
+ ATTENTION: Critical section keeps open when this function returns!
+ See ReleasePrimitiveArrayCritical.
+
*******************************************************************************/
-void *_Jv_JNI_GetPrimitiveArrayCritical(JNIEnv *env, jarray array,
- jboolean *isCopy)
+void* jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy)
{
- java_handle_bytearray_t *ba;
- jbyte *bp;
+ java_handle_t* h;
+ java_array_t* a;
+ arraydescriptor* ad;
+ void* data;
- ba = (java_handle_bytearray_t *) array;
+ TRACEJNICALLS(("jni_GetPrimitiveArrayCritical(env=%p, array=%p, isCopy=%d)", env, array, isCopy));
- /* do the same as Kaffe does */
+ if (isCopy != NULL) {
+ *isCopy = JNI_FALSE;
+ }
- bp = _Jv_JNI_GetByteArrayElements(env, (jbyteArray) ba, isCopy);
+ LLNI_CRITICAL_START;
+
+ h = (java_handle_t*) array;
+ a = (java_array_t*) LLNI_UNWRAP(h);
+ ad = a->objheader.vftbl->arraydesc;
+
+ /* Sanity check. */
- return (void *) bp;
+ assert(ad != NULL);
+
+ data = (void*) (((intptr_t) a) + ad->dataoffset);
+
+ return data;
}
No specific documentation.
+ ATTENTION: This function closes the critical section opened in
+ GetPrimitiveArrayCritical!
+
*******************************************************************************/
-void _Jv_JNI_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array,
- void *carray, jint mode)
+void jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode)
{
- STATISTICS(jniinvokation());
-
- /* do the same as Kaffe does */
+ TRACEJNICALLS(("jni_ReleasePrimitiveArrayCritical(env=%p, array=%p, carray=%p, mode=%d)", env, array, carray, mode));
- _Jv_JNI_ReleaseByteArrayElements(env, (jbyteArray) array, (jbyte *) carray,
- mode);
+ LLNI_CRITICAL_END;
}
jweak _Jv_JNI_NewWeakGlobalRef(JNIEnv* env, jobject obj)
{
- TRACEJNICALLS("_Jv_JNI_NewWeakGlobalRef(env=%p, obj=%p): IMPLEMENT ME!", env, obj);
+ TRACEJNICALLS(("_Jv_JNI_NewWeakGlobalRef(env=%p, obj=%p): IMPLEMENT ME!", env, obj));
return obj;
}
void _Jv_JNI_DeleteWeakGlobalRef(JNIEnv* env, jweak ref)
{
- TRACEJNICALLS("_Jv_JNI_DeleteWeakGlobalRef(env=%p, ref=%p): IMPLEMENT ME", env, ref);
+ TRACEJNICALLS(("_Jv_JNI_DeleteWeakGlobalRef(env=%p, ref=%p): IMPLEMENT ME", env, ref));
}
gnu_classpath_Pointer32 *paddress;
# endif
- TRACEJNICALLS("_Jv_JNI_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld", env, address, capacity);
+ TRACEJNICALLS(("_Jv_JNI_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld", env, address, capacity));
/* alocate a gnu.classpath.Pointer{32,64} object */
int64_t addr;
int32_t cap;
- TRACEJNICALLS("_Jv_JNI_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld", env, address, capacity);
+ TRACEJNICALLS(("_Jv_JNI_NewDirectByteBuffer(env=%p, address=%p, capacity=%ld", env, address, capacity));
/* Be paranoid about address sign-extension. */
void *_Jv_JNI_GetDirectBufferAddress(JNIEnv *env, jobject buf)
{
#if defined(ENABLE_JAVASE)
+ java_handle_t *h;
+
# if defined(WITH_CLASSPATH_GNU)
java_nio_DirectByteBufferImpl *nbuf;
+ gnu_classpath_Pointer *po;
# if SIZEOF_VOID_P == 8
gnu_classpath_Pointer64 *paddress;
+ int64_t address;
# else
gnu_classpath_Pointer32 *paddress;
+ int32_t address;
# endif
- void *address;
+ void *p;
+
+ TRACEJNICALLS(("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
- TRACEJNICALLS("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf);
+ /* Prevent compiler warning. */
- if ((buf != NULL) && !builtin_instanceof(buf, class_java_nio_Buffer))
+ h = (java_handle_t *) buf;
+
+ if ((h != NULL) && !builtin_instanceof(h, class_java_nio_Buffer))
return NULL;
nbuf = (java_nio_DirectByteBufferImpl *) buf;
- LLNI_field_get_ref(nbuf, address, paddress);
+ LLNI_field_get_ref(nbuf, address, po);
+
+# if SIZEOF_VOID_P == 8
+ paddress = (gnu_classpath_Pointer64 *) po;
+# else
+ paddress = (gnu_classpath_Pointer32 *) po;
+# endif
if (paddress == NULL)
return NULL;
LLNI_field_get_val(paddress, data, address);
- /* this was the cast to avaoid warning: (void *) paddress->data */
- return address;
+ p = (void *) (intptr_t) address;
+
+ return p;
# elif defined(WITH_CLASSPATH_SUN)
int64_t address;
void *p;
- TRACEJNICALLS("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf);
+ TRACEJNICALLS(("_Jv_JNI_GetDirectBufferAddress(env=%p, buf=%p)", env, buf));
+
+ /* Prevent compiler warning. */
- if ((buf != NULL) && !builtin_instanceof(buf, class_sun_nio_ch_DirectBuffer))
+ h = (java_handle_t *) buf;
+
+ if ((h != NULL) && !builtin_instanceof(h, class_sun_nio_ch_DirectBuffer))
return NULL;
o = (java_nio_Buffer *) buf;
jint _Jv_JNI_DestroyJavaVM(JavaVM *vm)
{
- int32_t status;
+ int status;
+
+ TRACEJNICALLS(("_Jv_JNI_DestroyJavaVM(vm=%p)", vm));
- TRACEJNICALLS("_Jv_JNI_DestroyJavaVM(vm=%p)", vm);
+ if (vm_created == false)
+ return JNI_ERR;
status = vm_destroy(vm);
*******************************************************************************/
-static s4 jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
+static int jni_attach_current_thread(void **p_env, void *thr_args, bool isdaemon)
{
+#if defined(ENABLE_THREADS)
JavaVMAttachArgs *vm_aargs;
+ bool result;
-#if defined(ENABLE_THREADS)
- if (threads_get_current_threadobject() == NULL) {
- vm_aargs = (JavaVMAttachArgs *) thr_args;
+ /* If the current thread has already been attached, this operation
+ is a no-op. */
- if (vm_aargs != NULL) {
- if ((vm_aargs->version != JNI_VERSION_1_2) &&
- (vm_aargs->version != JNI_VERSION_1_4))
- return JNI_EVERSION;
- }
+ result = thread_current_is_attached();
- if (!threads_attach_current_thread(vm_aargs, false))
- return JNI_ERR;
+ if (result == true) {
+ *p_env = _Jv_env;
- if (!localref_table_init())
- return JNI_ERR;
+ return JNI_OK;
}
+
+ vm_aargs = (JavaVMAttachArgs *) thr_args;
+
+ if (vm_aargs != NULL) {
+ if ((vm_aargs->version != JNI_VERSION_1_2) &&
+ (vm_aargs->version != JNI_VERSION_1_4))
+ return JNI_EVERSION;
+ }
+
+ if (!threads_attach_current_thread(vm_aargs, false))
+ return JNI_ERR;
+
+ if (!localref_table_init())
+ return JNI_ERR;
#endif
*p_env = _Jv_env;
jint _Jv_JNI_AttachCurrentThread(JavaVM *vm, void **p_env, void *thr_args)
{
- STATISTICS(jniinvokation());
+ int result;
+
+ TRACEJNICALLS(("_Jv_JNI_AttachCurrentThread(vm=%p, p_env=%p, thr_args=%p)", vm, p_env, thr_args));
+
+ if (vm_created == false)
+ return JNI_ERR;
+
+ result = jni_attach_current_thread(p_env, thr_args, false);
- return jni_attach_current_thread(p_env, thr_args, false);
+ return result;
}
jint _Jv_JNI_DetachCurrentThread(JavaVM *vm)
{
#if defined(ENABLE_THREADS)
- threadobject *thread;
+ threadobject *t;
+ bool result;
- STATISTICS(jniinvokation());
+ TRACEJNICALLS(("_Jv_JNI_DetachCurrentThread(vm=%p)", vm));
- thread = threads_get_current_threadobject();
+ t = thread_get_current();
- if (thread == NULL)
- return JNI_ERR;
+ /* Sanity check. */
+
+ assert(t != NULL);
+
+ /* If the given thread has already been detached, this operation
+ is a no-op. */
+
+ result = thread_is_attached(t);
+
+ if (result == false)
+ return true;
/* We need to pop all frames before we can destroy the table. */
if (!localref_table_destroy())
return JNI_ERR;
- if (!threads_detach_thread(thread))
+ if (!threads_detach_thread(t))
return JNI_ERR;
#endif
jint _Jv_JNI_GetEnv(JavaVM *vm, void **env, jint version)
{
- TRACEJNICALLS("_Jv_JNI_GetEnv(vm=%p, env=%p, %d=version)", vm, env, version);
+ TRACEJNICALLS(("_Jv_JNI_GetEnv(vm=%p, env=%p, %d=version)", vm, env, version));
+
+ if (vm_created == false) {
+ *env = NULL;
+ return JNI_EDETACHED;
+ }
#if defined(ENABLE_THREADS)
- if (threads_get_current_threadobject() == NULL) {
+ if (thread_get_current() == NULL) {
*env = NULL;
return JNI_EDETACHED;
jint _Jv_JNI_AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)
{
- STATISTICS(jniinvokation());
+ int result;
- return jni_attach_current_thread(penv, args, true);
+ TRACEJNICALLS(("_Jv_JNI_AttachCurrentThreadAsDaemon(vm=%p, penv=%p, args=%p)", vm, penv, args));
+
+ if (vm_created == false)
+ return JNI_ERR;
+
+ result = jni_attach_current_thread(penv, args, true);
+
+ return result;
}
_Jv_JNI_GetVersion,
_Jv_JNI_DefineClass,
- _Jv_JNI_FindClass,
- _Jv_JNI_FromReflectedMethod,
- _Jv_JNI_FromReflectedField,
+ jni_FindClass,
+ jni_FromReflectedMethod,
+ jni_FromReflectedField,
_Jv_JNI_ToReflectedMethod,
_Jv_JNI_GetSuperclass,
_Jv_JNI_IsAssignableFrom,
_Jv_JNI_Throw,
_Jv_JNI_ThrowNew,
_Jv_JNI_ExceptionOccurred,
- _Jv_JNI_ExceptionDescribe,
- _Jv_JNI_ExceptionClear,
+ jni_ExceptionDescribe,
+ jni_ExceptionClear,
_Jv_JNI_FatalError,
_Jv_JNI_PushLocalFrame,
_Jv_JNI_PopLocalFrame,
_Jv_JNI_GetStringRegion,
_Jv_JNI_GetStringUTFRegion,
- _Jv_JNI_GetPrimitiveArrayCritical,
- _Jv_JNI_ReleasePrimitiveArrayCritical,
+ jni_GetPrimitiveArrayCritical,
+ jni_ReleasePrimitiveArrayCritical,
_Jv_JNI_GetStringCritical,
_Jv_JNI_ReleaseStringCritical,
jint JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
{
- TRACEJNICALLS("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs);
+ TRACEJNICALLS(("JNI_GetCreatedJavaVMs(vmBuf=%p, jsize=%d, jsize=%p)", vmBuf, bufLen, nVMs));
if (bufLen <= 0)
return JNI_ERR;
jint JNI_CreateJavaVM(JavaVM **p_vm, void **p_env, void *vm_args)
{
- TRACEJNICALLS("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args);
+ TRACEJNICALLS(("JNI_CreateJavaVM(p_vm=%p, p_env=%p, vm_args=%p)", p_vm, p_env, vm_args));
/* actually create the JVM */
/* src/native/jni.h - JNI types and data structures
- 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.
*/
-/* GNU Classpath jni.h *********************************************************
+/* 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
+ 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
- CLASSPATH_JNI_H is in config.h defined.
+ 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"
-/* XXX quick hack to not include GCJ's jni_md.h */
-#define __GCJ_JNI_MD_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 CLASSPATH_JNI_MD_H
-#include CLASSPATH_JNI_H
+#include INCLUDE_JNI_MD_H
+#include INCLUDE_JNI_H
#ifndef _JNI_H
#define _JNI_H
bool jni_init(void);
bool jni_version_check(int version);
-java_handle_t *_Jv_jni_invokeNative(methodinfo *m, java_handle_t *o,
- java_handle_objectarray_t *params);
-
#endif /* _JNI_H */
/* src/native/jvmti/cacaodbg.c - contains entry points for debugging support
in cacao.
- 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., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Martin Platter
-
- Changes: Edwin Steiner
- Samuel Vinson
-
-
*/
#include "native/jvmti/jvmti.h"
#include "vm/jit/asmpart.h"
#include "vm/stringlocal.h"
#include "toolbox/logging.h"
-#include "threads/native/threads.h"
+#include "threads/mutex.h"
+#include "threads/thread.h"
#include <sys/types.h>
#include <unistd.h>
*******************************************************************************/
jthread jvmti_get_current_thread() {
- return (jthread)(threads_get_current_threadobject())->o.thread;
+ return (jthread)(thread_get_current)->o.thread;
}
void jvmti_set_system_breakpoint(int sysbrk, bool mode) {
struct brkpts *jvmtibrkpt;
- pthread_mutex_lock(&dbgcomlock);
+ mutex_lock(&dbgcomlock);
jvmtibrkpt = &dbgcom->jvmtibrkpt;
assert (sysbrk < BEGINUSERBRK);
/* add breakpoint*/
if (jvmtibrkpt->brk[sysbrk].count > 0) {
jvmtibrkpt->brk[sysbrk].count++;
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
return;
}
dbgcom->addbrkpt = true;
} else {
/* avoid negative counter values */
if (jvmtibrkpt->brk[sysbrk].count > 0) jvmtibrkpt->brk[sysbrk].count--;
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
return;
}
}
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
/* call cacaodbgserver */
__asm__ ("setsysbrkpt:");
TRAP;
void jvmti_add_breakpoint(void* addr, jmethodID method, jlocation location) {
struct brkpts *jvmtibrkpt;
- pthread_mutex_lock(&dbgcomlock);
+ mutex_lock(&dbgcomlock);
jvmtibrkpt = &dbgcom->jvmtibrkpt;;
if (jvmtibrkpt->size == jvmtibrkpt->num)
/* todo: set breakpoint */
/* jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
jvmtibrkpt->num++;
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
fprintf (stderr,"add brk done\n");
}
*******************************************************************************/
void jvmti_cacaodbgserver_quit(){
- pthread_mutex_lock(&dbgcomlock);
+ mutex_lock(&dbgcomlock);
dbgcom->running--;
if (dbgcom->running == 0) {
__asm__ ("cacaodbgserver_quit:");
wait(NULL);
dbgcom = NULL;
}
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
}
pid_t dbgserver;
/* start new cacaodbgserver if needed*/
- pthread_mutex_lock(&dbgcomlock);
+ mutex_lock(&dbgcomlock);
if (dbgcom == NULL) {
dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
dbgcom->running = 1;
}
}
}
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
/* let cacaodbgserver get ready */
sleep(1);
} else {
dbgcom->running++;
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
}
}
/* src/native/jvmti/cacaodbg.h - contains cacao specifics for debugging support
- 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., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Martin Platter
-
- Changes:
-
*/
#ifndef _CACAODBG_H
#define _CACAODBG_H
-#include "threads/native/threads.h"
+#include "threads/mutex.h"
+#include "threads/thread.h"
#include "native/jvmti/jvmti.h"
#include "native/include/java_lang_String.h"
#include <ltdl.h>
bool jvmti; /* jvmti agent */
-extern pthread_mutex_t dbgcomlock;
+extern mutex_t dbgcomlock;
jvmtiEnv* jvmti_new_environment();
void jvmti_set_phase(jvmtiPhase p);
/* src/native/jvmti/jvmti.c - implementation of the Java Virtual Machine
Tool Interface functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/options.h"
#include "vm/stringlocal.h"
#include "mm/memory.h"
-#include "threads/native/threads.h"
-#include "threads/native/lock.h"
+#include "threads/mutex.h"
+#include "threads/thread.h"
+#include "threads/lock-common.h"
#include "vm/exceptions.h"
#include "native/include/java_util_Vector.h"
#include "native/include/java_io_PrintStream.h"
#include "boehm-gc/include/gc.h"
#if defined(ENABLE_THREADS)
-#include "threads/native/threads.h"
#include <sched.h>
#include <pthread.h>
#endif
typedef struct _environment environment;
static environment *envs=NULL;
-pthread_mutex_t dbgcomlock;
+mutex_t dbgcomlock;
extern const struct JNIInvokeInterface _Jv_JNIInvokeInterface;
om=MNEW(java_objectheader*,size);
- pthread_mutex_lock(&lock_global_pool_lock);
+ mutex_lock(&lock_global_pool_lock);
lrp=lock_global_pool;
/* iterate over all lock record pools */
lrp=lrp->header.next;
}
- pthread_mutex_unlock(&lock_global_pool_lock);
+ mutex_unlock(&lock_global_pool_lock);
*owned_monitors_ptr =
heap_allocate(sizeof(java_objectheader*) * i, true, NULL);
#if defined(ENABLE_THREADS)
- pthread_mutex_lock(&lock_global_pool_lock);
+ mutex_lock(&lock_global_pool_lock);
lrp=lock_global_pool;
lrp=lrp->header.next;
}
- pthread_mutex_unlock(&lock_global_pool_lock);
+ mutex_unlock(&lock_global_pool_lock);
#endif
/* src/native/llni.c - low level native interfarce (LLNI)
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <assert.h>
-#include "threads/threads-common.h"
+#include "threads/thread.h"
/* LLNI critical sections ******************************************************
/* src/native/llni.h - low level native interfarce (LLNI)
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
-#include "native/localref.h"
+/* forward defines ************************************************************/
+
+/* LLNI wrapping / unwrapping macros *******************************************
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
+ ATTENTION: Only use these macros inside a LLNI critical section!
+ Once the ciritical section ends, all pointers onto the GC heap
+ retrieved through these macros are void!
+
+*******************************************************************************/
+
+#if defined(ENABLE_HANDLES)
+# define LLNI_WRAP(obj) ((obj) == NULL ? NULL : localref_add(obj))
+# define LLNI_UNWRAP(hdl) ((hdl) == NULL ? NULL : (hdl)->heap_object)
+# define LLNI_QUICKWRAP(obj) ((obj) == NULL ? NULL : &(obj))
+# define LLNI_DIRECT(hdl) ((hdl)->heap_object)
#else
-# include "threads/none/threads.h"
+# define LLNI_WRAP(obj) (obj)
+# define LLNI_UNWRAP(hdl) (hdl)
+# define LLNI_QUICKWRAP(obj) (obj)
+# define LLNI_DIRECT(hdl) (hdl)
#endif
+#include "native/localref.h"
+
+#include "threads/thread.h"
+
+
/* LLNI macros *****************************************************************
The following macros should be used whenever a Java Object is
(variable) = (classinfo *) LLNI_field_direct(obj, field)
#define LLNI_class_get(obj, variable) \
- (variable) = LLNI_field_direct((java_handle_t *) obj, vftbl->class)
+ (variable) = LLNI_field_direct((java_handle_t *) obj, vftbl->clazz)
/* LLNI_equals ****************************************************************
#define LLNI_array_size(arr) (LLNI_DIRECT((java_handle_objectarray_t *) (arr))->header.size)
-/* LLNI wrapping / unwrapping macros *******************************************
-
- ATTENTION: Only use these macros inside a LLNI critical section!
- Once the ciritical section ends, all pointers onto the GC heap
- retrieved through these macros are void!
-
-*******************************************************************************/
-
-#if defined(ENABLE_HANDLES)
-# define LLNI_WRAP(obj) ((obj) == NULL ? NULL : localref_add(obj))
-# define LLNI_UNWRAP(hdl) ((hdl) == NULL ? NULL : (hdl)->heap_object)
-# define LLNI_QUICKWRAP(obj) ((obj) == NULL ? NULL : &(obj))
-# define LLNI_DIRECT(hdl) ((hdl)->heap_object)
-#else
-# define LLNI_WRAP(obj) (obj)
-# define LLNI_UNWRAP(hdl) (hdl)
-# define LLNI_QUICKWRAP(obj) (obj)
-# define LLNI_DIRECT(hdl) (hdl)
-#endif
-
-
/* LLNI critical sections ******************************************************
These macros handle the LLNI critical sections. While a critical
/* src/native/localref.c - Management of local reference tables
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/localref.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
/* some forward declarations **************************************************/
+#if !defined(NDEBUG)
static bool localref_check_uncleared();
+#endif
/* localref_table_init *********************************************************
{
localref_table *lrt;
+ TRACESUBSYSTEMINITIALIZATION("localref_table_init");
+
assert(LOCALREFTABLE == NULL);
#if !defined(ENABLE_GC_BOEHM)
/* src/native/native.c - table of native functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
bool native_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("native_init");
+
#if defined(ENABLE_LTDL)
/* initialize libltdl */
char *utf_ptr;
u2 c;
s4 i;
- s4 dumpsize;
utf *u;
+ int32_t dumpmarker;
/* mark memory */
- dumpsize = dump_size();
+ DMARKER;
utf_ptr = descriptor->text;
namelen = strlen(name->text) + strlen("__") + strlen("0");
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
return u;
}
char *utf_endptr;
u2 c;
u4 pos;
- s4 dumpsize;
utf *u;
+ int32_t dumpmarker;
/* mark memory */
- dumpsize = dump_size();
+ DMARKER;
/* Calculate length of native function name. We multiply the
class and method name length by 6 as this is the maxium
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
return u;
}
/* fill the temporary structure used for searching the tree */
- tmpnmn.classname = m->class->name;
+ tmpnmn.classname = m->clazz->name;
tmpnmn.name = m->name;
tmpnmn.descriptor = m->descriptor;
utf *newname;
functionptr f;
#if defined(ENABLE_LTDL)
- classloader *cl;
+ classloader_t *cl;
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne;
u4 key; /* hashkey */
if (opt_verbosejni) {
printf("[Dynamic-linking native method ");
- utf_display_printable_ascii_classname(m->class->name);
+ 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->class->name, m->name);
+ name = native_method_symbol(m->clazz->name, m->name);
/* generate overloaded function (having the types in it's name) */
#if defined(ENABLE_LTDL)
/* Get the classloader. */
- cl = class_get_classloader(m->class);
+ cl = class_get_classloader(m->clazz);
/* normally addresses are aligned to 4, 8 or 16 bytes */
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_LTDL)
handle = lt_dlopen(filename->text);
if (handle == NULL) {
+ if (opt_verbosejni)
+ printf("failed ]\n");
+
if (opt_verbose) {
log_start();
- log_print("native_library_load: lt_dlopen failed: ");
+ log_print("native_library_open: lt_dlopen failed: ");
log_print(lt_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_LTDL)
+void native_library_close(lt_dlhandle handle)
+{
+ int result;
+
+ if (opt_verbosejni) {
+ printf("[Unloading native library ");
+/* utf_display_printable_ascii(filename); */
+ printf(" ... ");
+ }
+
+ /* Close the library. */
+
+ result = lt_dlclose(handle);
+
+ if (result != 0) {
+ if (opt_verbose) {
+ log_start();
+ log_print("native_library_close: lt_dlclose failed: ");
+ log_print(lt_dlerror());
+ log_finish();
+ }
+ }
+}
+#endif
+
+
/* native_library_add **********************************************************
Adds an entry to the native library hashtable.
*******************************************************************************/
#if defined(ENABLE_LTDL)
-void native_library_add(utf *filename, classloader *loader, lt_dlhandle handle)
+void native_library_add(utf *filename, classloader_t *loader, lt_dlhandle handle)
{
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne; /* library name */
#if defined(ENABLE_LTDL)
hashtable_library_name_entry *native_library_find(utf *filename,
- classloader *loader)
+ classloader_t *loader)
{
hashtable_library_loader_entry *le;
hashtable_library_name_entry *ne; /* library name */
#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_LTDL)
+ lt_dlhandle handle;
+# if defined(ENABLE_JNI)
+ lt_ptr 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 = lt_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)) {
+ lt_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.
/* src/native/native.h - table of native functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
typedef struct hashtable_library_name_entry hashtable_library_name_entry;
struct hashtable_library_loader_entry {
- classloader *loader; /* class loader */
+ classloader_t *loader; /* class loader */
hashtable_library_name_entry *namelink;/* libs loaded by this loader */
hashtable_library_loader_entry *hashlink;/* link for external chaining */
};
#if defined(ENABLE_LTDL)
lt_dlhandle native_library_open(utf *filename);
-void native_library_add(utf *filename, classloader *loader,
- lt_dlhandle handle);
-hashtable_library_name_entry *native_library_find(utf *filename,
- classloader *loader);
+void native_library_close(lt_dlhandle handle);
+void native_library_add(utf *filename, classloader_t *loader, lt_dlhandle 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);
## src/native/vm/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.
##
reflect.c \
reflect.h
-CLASSLOADER_SOURCES = \
- java_lang_ClassLoader.c \
- java_lang_ClassLoader.h
-
-JAVA_LANG_REFLECT_CONSTRUCTOR_SOURCES = \
- java_lang_reflect_Constructor.c \
- java_lang_reflect_Constructor.h
-
-JAVA_LANG_REFLECT_METHOD_SOURCES = \
- java_lang_reflect_Method.c \
- java_lang_reflect_Method.h
-
SUN_MISC_UNSAFE_SOURCES = \
sun_misc_Unsafe.c
endif
nativevm.c \
nativevm.h \
$(REFLECT_SOURCES) \
- \
- java_lang_Class.c \
- java_lang_Class.h \
- $(CLASSLOADER_SOURCES) \
- java_lang_Runtime.c \
- java_lang_Runtime.h \
- java_lang_Thread.c \
- java_lang_Thread.h \
- $(JAVA_LANG_REFLECT_CONSTRUCTOR_SOURCES) \
- $(JAVA_LANG_REFLECT_METHOD_SOURCES) \
$(SUN_MISC_UNSAFE_SOURCES)
libnativevm_la_LIBADD = \
/* src/native/vm/cldc1.1/com_sun_cldchi_jvm_JVM.c
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/com_sun_cldchi_jvm_JVM.h"
-#include "native/vm/java_lang_Runtime.h"
-
#include "vm/exceptions.h"
#include "vm/stringlocal.h"
*/
JNIEXPORT void JNICALL Java_com_sun_cldchi_jvm_JVM_loadLibrary(JNIEnv *env, jclass clazz, java_lang_String *libName)
{
- s4 result;
+ int result;
utf *name;
-#if defined(ENABLE_JNI)
- result = _Jv_java_lang_Runtime_loadLibrary(env, libName, NULL);
-#else
- result = _Jv_java_lang_Runtime_loadLibrary(libName, NULL);
-#endif
+ /* REMOVEME When we use Java-strings internally. */
+
+ if (libName == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
+ name = javastring_toutf((java_handle_t *) libName, false);
+
+ result = native_library_load(env, name, NULL);
- /* check for error and throw one in case */
+ /* Check for error and throw an exception in case. */
if (result == 0) {
- name = javastring_toutf((java_handle_t *) libName, false);
exceptions_throw_unsatisfiedlinkerror(name);
}
}
/* src/native/vm/cldc1.1/java_lang_Class.c
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/java_lang_Class.h"
-#include "native/vm/java_lang_Class.h"
+#include "vm/exceptions.h"
+#include "vm/initialize.h"
/* native methods implemented by this file ************************************/
*/
JNIEXPORT java_lang_Class* JNICALL Java_java_lang_Class_forName(JNIEnv *env, jclass clazz, java_lang_String *name)
{
- return _Jv_java_lang_Class_forName(name);
+ utf *ufile;
+ utf *uname;
+ classinfo *c;
+ u2 *pos;
+ s4 i;
+
+ /* illegal argument */
+
+ if (name == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* create utf string in which '.' is replaced by '/' */
+
+ ufile = javastring_toutf((java_handle_t *) name, true);
+ uname = javastring_toutf((java_handle_t *) name, false);
+
+ /* name must not contain '/' (mauve test) */
+
+ for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
+ if (*pos == '/') {
+ exceptions_throw_classnotfoundexception(uname);
+ return NULL;
+ }
+ }
+
+ /* try to load, ... */
+
+ c = load_class_bootstrap(ufile);
+
+ if (c == NULL)
+ return NULL;
+
+ /* link, ... */
+
+ if (!link_class(c))
+ return NULL;
+
+ /* ...and initialize it. */
+
+ if (!initialize_class(c))
+ return NULL;
+
+ return LLNI_classinfo_wrap(c);
}
* Method: isInstance
* Signature: (Ljava/lang/Object;)Z
*/
-JNIEXPORT s4 JNICALL Java_java_lang_Class_isInstance(JNIEnv *env, java_lang_Class *this, java_lang_Object *obj)
+JNIEXPORT int32_t JNICALL Java_java_lang_Class_isInstance(JNIEnv *env, java_lang_Class *this, java_lang_Object *obj)
{
- return _Jv_java_lang_Class_isInstance(this, obj);
+ classinfo *c;
+ java_handle_t *h;
+
+ c = LLNI_classinfo_unwrap(this);
+ h = (java_handle_t *) obj;
+
+ return class_is_instance(c, h);
}
* Method: isAssignableFrom
* Signature: (Ljava/lang/Class;)Z
*/
-JNIEXPORT s4 JNICALL Java_java_lang_Class_isAssignableFrom(JNIEnv *env, java_lang_Class *this, java_lang_Class *cls)
+JNIEXPORT int32_t JNICALL Java_java_lang_Class_isAssignableFrom(JNIEnv *env, java_lang_Class *this, java_lang_Class *cls)
{
- return _Jv_java_lang_Class_isAssignableFrom(this, cls);
+ classinfo *to;
+ classinfo *from;
+
+ to = LLNI_classinfo_unwrap(this);
+ from = LLNI_classinfo_unwrap(cls);
+
+ if (from == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ return class_is_assignable_from(to, from);
}
*/
JNIEXPORT java_lang_String* JNICALL Java_java_lang_Class_getName(JNIEnv *env, java_lang_Class *this)
{
- return _Jv_java_lang_Class_getName(this);
+ classinfo *c;
+
+ c = LLNI_classinfo_unwrap(this);
+
+ return (java_lang_String*) class_get_classname(c);
}
/* src/native/vm/cldc1.1/java_lang_Runtime.c
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 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 <stdint.h>
+
+#include "mm/gc-common.h"
#include "native/jni.h"
#include "native/native.h"
#include "native/include/java_lang_Runtime.h"
-#include "native/vm/java_lang_Runtime.h"
+#include "vm/vm.h"
+
+#include "vmcore/utf8.h"
/* native methods implemented by this file ************************************/
static JNINativeMethod methods[] = {
- { "exitInternal", "(I)V", (void *) (ptrint) &Java_java_lang_Runtime_exitInternal },
- { "freeMemory", "()J", (void *) (ptrint) &Java_java_lang_Runtime_freeMemory },
- { "totalMemory", "()J", (void *) (ptrint) &Java_java_lang_Runtime_totalMemory },
- { "gc", "()V", (void *) (ptrint) &Java_java_lang_Runtime_gc },
+ { "exitInternal", "(I)V", (void *) (intptr_t) &Java_java_lang_Runtime_exitInternal },
+ { "freeMemory", "()J", (void *) (intptr_t) &Java_java_lang_Runtime_freeMemory },
+ { "totalMemory", "()J", (void *) (intptr_t) &Java_java_lang_Runtime_totalMemory },
+ { "gc", "()V", (void *) (intptr_t) &Java_java_lang_Runtime_gc },
};
* Method: exitInternal
* Signature: (I)V
*/
-JNIEXPORT void JNICALL Java_java_lang_Runtime_exitInternal(JNIEnv *env, java_lang_Runtime *this, s4 status)
+JNIEXPORT void JNICALL Java_java_lang_Runtime_exitInternal(JNIEnv *env, java_lang_Runtime *this, int32_t status)
{
- _Jv_java_lang_Runtime_exit(status);
+ vm_shutdown(status);
}
* Method: freeMemory
* Signature: ()J
*/
-JNIEXPORT s8 JNICALL Java_java_lang_Runtime_freeMemory(JNIEnv *env, java_lang_Runtime *this)
+JNIEXPORT int64_t JNICALL Java_java_lang_Runtime_freeMemory(JNIEnv *env, java_lang_Runtime *this)
{
- return _Jv_java_lang_Runtime_freeMemory();
+ return gc_get_free_bytes();
}
* Method: totalMemory
* Signature: ()J
*/
-JNIEXPORT s8 JNICALL Java_java_lang_Runtime_totalMemory(JNIEnv *env, java_lang_Runtime *this)
+JNIEXPORT int64_t JNICALL Java_java_lang_Runtime_totalMemory(JNIEnv *env, java_lang_Runtime *this)
{
- return _Jv_java_lang_Runtime_totalMemory();
+ return gc_get_heap_size();
}
*/
JNIEXPORT void JNICALL Java_java_lang_Runtime_gc(JNIEnv *env, java_lang_Runtime *this)
{
- _Jv_java_lang_Runtime_gc();
+ gc_call();
}
/* src/native/vm/cldc1.1/java_lang_Thread.c
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/java_lang_Thread.h"
-#include "native/vm/java_lang_Thread.h"
-
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
*/
JNIEXPORT java_lang_Thread* JNICALL Java_java_lang_Thread_currentThread(JNIEnv *env, jclass clazz)
{
- return _Jv_java_lang_Thread_currentThread();
+ java_lang_Thread *to;
+
+ to = (java_lang_Thread *) thread_get_current_object();
+
+ return to;
}
*/
JNIEXPORT void JNICALL Java_java_lang_Thread_setPriority0(JNIEnv *env, java_lang_Thread *this, s4 oldPriority, s4 newPriority)
{
- _Jv_java_lang_Thread_setPriority(this, newPriority);
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+
+ t = (threadobject *) this->vm_thread;
+
+ /* The threadobject is null when a thread is created in Java. The
+ priority is set later during startup. */
+
+ if (t == NULL)
+ return;
+
+ threads_set_thread_priority(t->tid, newPriority);
+#endif
}
*/
JNIEXPORT void JNICALL Java_java_lang_Thread_sleep(JNIEnv *env, jclass clazz, s8 millis)
{
- _Jv_java_lang_Thread_sleep(millis);
+#if defined(ENABLE_THREADS)
+ threads_sleep(millis, 0);
+#endif
}
*/
JNIEXPORT void JNICALL Java_java_lang_Thread_start0(JNIEnv *env, java_lang_Thread *this)
{
- _Jv_java_lang_Thread_start(this, 0);
+#if defined(ENABLE_THREADS)
+ threads_thread_start((java_handle_t *) this);
+#endif
}
/* src/native/vm/cldc1.1/java_lang_Throwable.c - java/lang/Throwable
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include <assert.h>
-
-#include "vm/types.h"
+#include <stdint.h>
#include "native/jni.h"
+#include "native/llni.h"
#include "native/native.h"
#include "native/include/java_lang_Object.h"
/* native methods implemented by this file ************************************/
static JNINativeMethod methods[] = {
- { "printStackTrace", "()V", (void *) (ptrint) &Java_java_lang_Throwable_printStackTrace },
- { "fillInStackTrace", "()V", (void *) (ptrint) &Java_java_lang_Throwable_fillInStackTrace },
+ { "printStackTrace", "()V", (void *) (uintptr_t) &Java_java_lang_Throwable_printStackTrace },
+ { "fillInStackTrace", "()V", (void *) (uintptr_t) &Java_java_lang_Throwable_fillInStackTrace },
};
o = (java_handle_t *) this;
exceptions_print_exception(o);
- stacktrace_print_trace(o);
+ stacktrace_print_exception(o);
}
{
java_handle_bytearray_t *ba;
- ba = stacktrace_fillInStackTrace();
+ ba = stacktrace_get_current();
if (ba == NULL)
return;
- this->backtrace = (java_lang_Object *) ba;
+ LLNI_field_set_ref(this, backtrace, (java_lang_Object *) ba);
}
## src/native/vm/gnu/Makefile.am
##
-## 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.
##
## 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) -I$(top_builddir)/src
libnativevmcore_la_SOURCES = \
gnu_classpath_VMStackWalker.c \
gnu_classpath_VMSystemProperties.c \
+ gnu_java_lang_VMCPStringBuilder.c \
gnu_java_lang_management_VMClassLoadingMXBeanImpl.c \
gnu_java_lang_management_VMMemoryMXBeanImpl.c \
gnu_java_lang_management_VMRuntimeMXBeanImpl.c \
java_lang_VMThread.c \
java_lang_VMThrowable.c \
java_lang_management_VMManagementFactory.c \
- java_lang_reflect_Constructor.c \
- java_lang_reflect_Field.c \
- java_lang_reflect_Method.c \
+ java_lang_reflect_VMConstructor.c \
+ java_lang_reflect_VMField.c \
+ java_lang_reflect_VMMethod.c \
java_lang_reflect_VMProxy.c \
java_security_VMAccessController.c \
java_util_concurrent_atomic_AtomicLong.c \
/* src/native/vm/gnu/gnu_classpath_VMStackWalker.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include "native/jni.h"
-#include "native/llni.h"
#include "native/native.h"
#include "native/include/java_lang_Class.h"
#include "native/include/gnu_classpath_VMStackWalker.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
#include "vm/global.h"
#include "vm/jit/stacktrace.h"
#include "vmcore/class.h"
+#include "vmcore/utf8.h"
/* native methods implemented by this file ************************************/
*/
JNIEXPORT java_lang_Class* JNICALL Java_gnu_classpath_VMStackWalker_getCallingClass(JNIEnv *env, jclass clazz)
{
- java_handle_objectarray_t *oa;
- java_handle_t *o;
-
- oa = stacktrace_getClassContext();
-
- if (oa == NULL)
- return NULL;
+ classinfo *c;
- if (LLNI_array_size(oa) < 2)
- return NULL;
+ c = stacktrace_get_caller_class(2);
- o = array_objectarray_element_get(oa, 1);
-
- return (java_lang_Class *) o;
+ return (java_lang_Class *) c;
}
*/
JNIEXPORT java_lang_ClassLoader* JNICALL Java_gnu_classpath_VMStackWalker_getCallingClassLoader(JNIEnv *env, jclass clazz)
{
- java_handle_objectarray_t *oa;
- classinfo *c;
- classloader *cl;
-
- oa = stacktrace_getClassContext();
+ classinfo *c;
+ classloader_t *cl;
- if (oa == NULL)
- return NULL;
-
- if (LLNI_array_size(oa) < 2)
- return NULL;
-
- c = (classinfo *) LLNI_array_direct(oa, 1);
+ c = stacktrace_get_caller_class(2);
cl = class_get_classloader(c);
return (java_lang_ClassLoader *) cl;
*/
JNIEXPORT java_lang_ClassLoader* JNICALL Java_gnu_classpath_VMStackWalker_firstNonNullClassLoader(JNIEnv *env, jclass clazz)
{
- java_handle_objectarray_t *oa;
- classinfo *c;
- classloader *cl;
- s4 i;
-
- oa = stacktrace_getClassContext();
+ classloader_t *cl;
- if (oa == NULL)
- return NULL;
+ cl = stacktrace_first_nonnull_classloader();
- for (i = 0; i < LLNI_array_size(oa); i++) {
- c = (classinfo *) LLNI_array_direct(oa, i);
- cl = class_get_classloader(c);
-
- if (cl != NULL)
- return (java_lang_ClassLoader *) cl;
- }
-
- return NULL;
+ return (java_lang_ClassLoader *) cl;
}
/* src/native/vm/gnu/gnu_classpath_VMSystemProperties.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
JNIEXPORT void JNICALL Java_gnu_classpath_VMSystemProperties_postInit(JNIEnv *env, jclass clazz, java_util_Properties *properties)
{
java_handle_t *p;
-#if defined(WITH_JRE_LAYOUT)
+#if defined(ENABLE_JRE_LAYOUT)
char *java_home;
char *path;
s4 len;
/* post-set some properties */
-#if defined(WITH_JRE_LAYOUT)
+#if defined(ENABLE_JRE_LAYOUT)
/* XXX when we do it that way, we can't set these properties on
commandline */
-/* src/native/vm/VMFrame.c - jdwp->jvmti interface
+/* src/native/vm/gnu/gnu_classpath_jdwp_VMFrame.c - jdwp->jvmti interface
-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.
+ This file is part of CACAO.
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
+ You should have received a copy of the GNU General Public 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: Martin Platter
-Changes:
+#include "config.h"
-*/
+#include <stdint.h>
-#include "toolbox/logging.h"
#include "native/jni.h"
+
+#include "native/include/java_lang_Object.h"
#include "native/include/gnu_classpath_jdwp_VMFrame.h"
+#include "toolbox/logging.h"
+
/*
* Class: gnu/classpath/jdwp/VMFrame
* Method: getValue
* Signature: (I)Ljava/lang/Object;
*/
-JNIEXPORT struct java_lang_Object* JNICALL Java_gnu_classpath_jdwp_VMFrame_getValue(JNIEnv *env, struct gnu_classpath_jdwp_VMFrame* this, s4 par1) {
- log_text ("JVMTI-Call: IMPLEMENT ME!!!");
- return 0;
+JNIEXPORT java_lang_Object* JNICALL Java_gnu_classpath_jdwp_VMFrame_getValue(JNIEnv *env, gnu_classpath_jdwp_VMFrame* this, int32_t par1)
+{
+ log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+ return 0;
}
* Method: setValue
* Signature: (ILjava/lang/Object;)V
*/
-JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMFrame_setValue(JNIEnv *env, struct gnu_classpath_jdwp_VMFrame* this, s4 par1, struct java_lang_Object* par2) {
- log_text ("JVMTI-Call: IMPLEMENT ME!!!");
+JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMFrame_setValue(JNIEnv *env, gnu_classpath_jdwp_VMFrame* this, int32_t par1, java_lang_Object* par2)
+{
+ log_text ("JVMTI-Call: IMPLEMENT ME!!!");
return 0;
}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
-/* src/native/vm/VMMethod.c - jdwp->jvmti interface
+/* src/native/vm/gnu/gnu_classpath_jdwp_VMMethod.c - jdwp->jvmti interface
-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.
+ This file is part of CACAO.
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
+ You should have received a copy of the GNU General Public 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: Samuel Vinson
- Martin Platter
-
-
-Changes:
+#include "config.h"
+#include <stdint.h>
#include "native/jni.h"
+
#include "native/include/gnu_classpath_jdwp_VMMethod.h"
+
#include "native/jvmti/jvmti.h"
#include "native/jvmti/VMjdwp.h"
* Method: getName
* Signature: ()Ljava/lang/String;
*/
-JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMMethod_getName(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMMethod_getName(JNIEnv *env, gnu_classpath_jdwp_VMMethod* this)
{
jvmtiError err;
char *name;
* Method: getSignature
* Signature: ()Ljava/lang/String;
*/
-JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMMethod_getSignature(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+JNIEXPORT struct java_lang_String* JNICALL Java_gnu_classpath_jdwp_VMMethod_getSignature(JNIEnv *env, gnu_classpath_jdwp_VMMethod* this)
{
jvmtiError err;
char *signature;
* Method: getModifiers
* Signature: ()I
*/
-JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMMethod_getModifiers(JNIEnv *env, struct gnu_classpath_jdwp_VMMethod* this)
+JNIEXPORT int32_t JNICALL Java_gnu_classpath_jdwp_VMMethod_getModifiers(JNIEnv *env, gnu_classpath_jdwp_VMMethod* this)
{
jvmtiError err;
jint modifiers;
-/* src/native/vm/VMVirtualMachine.c - jdwp->jvmti interface
+/* src/native/vm/gnu/gnu_classpath_jdwp_VMVirtualMachine.c - jdwp->jvmti interface
-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.
+ This file is part of CACAO.
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License as
-published by the Free Software Foundation; either version 2, or (at
-your option) any later version.
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.
+ You should have received a copy of the GNU General Public 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: Martin Platter
-Changes: Samuel Vinson
+#include "config.h"
-*/
+#include <stdint.h>
+#include <string.h>
#include "toolbox/logging.h"
#include "native/jni.h"
#include "native/include/gnu_classpath_jdwp_VMVirtualMachine.h"
#include "native/jvmti/jvmti.h"
#include "native/jvmti/VMjdwp.h"
-#include <string.h>
/*
* Method: getSuspendCount
* Signature: (Ljava/lang/Thread;)I
*/
-JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getSuspendCount(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
+JNIEXPORT int32_t JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getSuspendCount(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
log_text ("VMVirtualMachine_getSuspendCount: not supported");
return 1;
}
* Method: getAllLoadedClassesCount
* Signature: ()I
*/
-JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClassesCount(JNIEnv *env, jclass clazz) {
+JNIEXPORT int32_t JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getAllLoadedClassesCount(JNIEnv *env, jclass clazz) {
jint count;
jclass* classes;
jvmtiError err;
* Method: getClassStatus
* Signature: (Ljava/lang/Class;)I
*/
-JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus(JNIEnv *env, jclass clazz, struct java_lang_Class* par1) {
+JNIEXPORT int32_t JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getClassStatus(JNIEnv *env, jclass clazz, struct java_lang_Class* par1) {
jint status;
jvmtiError err;
* Method: getFrames
* Signature: (Ljava/lang/Thread;II)Ljava/util/ArrayList;
*/
-JNIEXPORT struct java_util_ArrayList* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrames(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1, s4 par2, s4 par3) {
+JNIEXPORT struct java_util_ArrayList* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrames(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1, int32_t par2, int32_t par3) {
log_text ("VMVirtualMachine_getFrames - IMPLEMENT ME!!!");
/* jclass ec = (*env)->FindClass(env,"gnu/classpath/jdwp/JdwpInternalErrorException");
if (JVMTI_ERROR_NONE != (*jvmtienv)->GetClassStatus(jvmtienv, par1, &status))
* Method: getFrameCount
* Signature: (Ljava/lang/Thread;)I
*/
-JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
+JNIEXPORT int32_t JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getFrameCount(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
jint count;
jvmtiError err;
err = (*jvmtienv)->GetFrameCount(jvmtienv, (jthread)par1, &count);
* Method: getThreadStatus
* Signature: (Ljava/lang/Thread;)I
*/
-JNIEXPORT s4 JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
+JNIEXPORT int32_t JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_getThreadStatus(JNIEnv *env, jclass clazz, struct java_lang_Thread* par1) {
jint status;
jvmtiError err;
if (JVMTI_ERROR_NONE != (err = (*jvmtienv)->GetThreadState(jvmtienv, (jthread)par1, &status))) {
* Method: executeMethod
* Signature: (Ljava/lang/Object;Ljava/lang/Thread;Ljava/lang/Class;Ljava/lang/reflect/Method;[Ljava/lang/Object;Z)Lgnu/classpath/jdwp/util/MethodResult;
*/
-JNIEXPORT struct gnu_classpath_jdwp_util_MethodResult* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_executeMethod(JNIEnv *env, jclass clazz, struct java_lang_Object* par1, struct java_lang_Thread* par2, struct java_lang_Class* par3, struct java_lang_reflect_Method* par4, java_objectarray* par5, s4 par6) {
+JNIEXPORT struct gnu_classpath_jdwp_util_MethodResult* JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_executeMethod(JNIEnv *env, jclass clazz, struct java_lang_Object* par1, struct java_lang_Thread* par2, struct java_lang_Class* par3, struct java_lang_reflect_Method* par4, java_objectarray* par5, int32_t par6) {
log_text ("VMVirtualMachine_executeMethod");
return 0;
}
* Method: clearEvents
* Signature: (B)V
*/
-JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_clearEvents(JNIEnv *env, jclass clazz, s4 par1) {
+JNIEXPORT void JNICALL Java_gnu_classpath_jdwp_VMVirtualMachine_clearEvents(JNIEnv *env, jclass clazz, int32_t par1) {
/* jvmti events are not saved - there is nothing to clear */
}
--- /dev/null
+/* src/native/vm/gnu/java_lang_reflect_VMConstructor.c
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "native/include/java_lang_String.h"
+
+#include "native/include/gnu_java_lang_VMCPStringBuilder.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { "toString", "([CII)Ljava/lang/String;", (void *) (intptr_t) &Java_gnu_java_lang_VMCPStringBuilder_toString },
+};
+
+
+/* _Jv_gnu_java_lang_VMCPStringBuilder *****************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+void _Jv_gnu_java_lang_VMCPStringBuilder_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("gnu/java/lang/VMCPStringBuilder");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+
+
+/*
+ * Class: gnu/java/lang/VMCPStringBuilder
+ * Method: toString
+ * Signature: ([CII)Ljava/lang/String;
+ */
+JNIEXPORT java_lang_String* JNICALL Java_gnu_java_lang_VMCPStringBuilder_toString(JNIEnv *env, jclass clazz, java_handle_chararray_t *value, int32_t startIndex, int32_t count)
+{
+ int32_t length;
+ java_handle_t *o;
+ java_lang_String *s;
+
+ /* This is a native version of
+ java.lang.String.<init>([CIIZ)Ljava/lang/String; */
+
+ if (startIndex < 0) {
+/* exceptions_throw_stringindexoutofboundsexception("offset: " + offset); */
+ exceptions_throw_stringindexoutofboundsexception();
+ return NULL;
+ }
+
+ if (count < 0) {
+/* exceptions_throw_stringindexoutofboundsexception("count: " + count); */
+ exceptions_throw_stringindexoutofboundsexception();
+ return NULL;
+ }
+
+ /* equivalent to: offset + count < 0 || offset + count > data.length */
+
+ LLNI_CRITICAL_START;
+ length = LLNI_array_size(value);
+ LLNI_CRITICAL_END;
+
+ if (length - startIndex < count) {
+/* exceptions_throw_stringindexoutofboundsexception("offset + count: " + (offset + count)); */
+ exceptions_throw_stringindexoutofboundsexception();
+ return NULL;
+ }
+
+ o = builtin_new(class_java_lang_String);
+
+ if (o == NULL)
+ return NULL;
+
+ s = (java_lang_String *) o;
+
+ LLNI_field_set_ref(s, value, value);
+ LLNI_field_set_val(s, count, count);
+ LLNI_field_set_val(s, offset, startIndex);
+
+ return s;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
/* src/native/vm/gnu/gnu_java_lang_management_VMMemoryMXBeanImpl.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
-#include "vm/types.h"
+
+#include <stdint.h>
#include "mm/gc-common.h"
/* native methods implemented by this file ************************************/
static JNINativeMethod methods[] = {
- { "getHeapMemoryUsage", "()Ljava/lang/management/MemoryUsage;", (void *) (ptrint) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage },
- { "getNonHeapMemoryUsage", "()Ljava/lang/management/MemoryUsage;", (void *) (ptrint) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage },
- { "getObjectPendingFinalizationCount", "()I", (void *) (ptrint) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount },
- { "isVerbose", "()Z", (void *) (ptrint) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose },
- { "setVerbose", "(Z)V", (void *) (ptrint) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose },
+ { "getHeapMemoryUsage", "()Ljava/lang/management/MemoryUsage;", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage },
+ { "getNonHeapMemoryUsage", "()Ljava/lang/management/MemoryUsage;", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getNonHeapMemoryUsage },
+ { "getObjectPendingFinalizationCount", "()I", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount },
+ { "isVerbose", "()Z", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose },
+ { "setVerbose", "(Z)V", (void *) (uintptr_t) &Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose },
};
java_handle_t *o;
java_lang_management_MemoryUsage *mu;
methodinfo *m;
- s8 init;
- s8 used;
- s8 commited;
- s8 maximum;
+ int64_t init;
+ int64_t used;
+ int64_t commited;
+ int64_t maximum;
/* get the class */
/* XXX optimize me! sometime... */
* Method: getObjectPendingFinalizationCount
* Signature: ()I
*/
-JNIEXPORT s4 JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount(JNIEnv *env, jclass clazz)
+JNIEXPORT int32_t JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount(JNIEnv *env, jclass clazz)
{
log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjectPendingFinalizationCount: IMPLEMENT ME!");
* Method: isVerbose
* Signature: ()Z
*/
-JNIEXPORT s4 JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
+JNIEXPORT int32_t JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
{
return _Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose;
}
* Method: setVerbose
* Signature: (Z)V
*/
-JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, s4 verbose)
+JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, int32_t verbose)
{
_Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose = verbose;
}
/* src/native/vm/gnu/java_lang_VMClass.c
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
-#include "vm/types.h"
-
#include "native/jni.h"
#include "native/llni.h"
#include "native/native.h"
#include "native/include/java_lang_Class.h"
#include "native/include/java_lang_ClassLoader.h"
#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_String.h"
#include "native/include/java_lang_Throwable.h"
#include "native/include/java_lang_reflect_Constructor.h"
#include "native/include/java_lang_reflect_Method.h"
#include "native/include/java_lang_VMClass.h"
-#include "native/vm/java_lang_Class.h"
-
#include "vm/exceptions.h"
+#include "vm/initialize.h"
#include "vm/stringlocal.h"
#include "vmcore/class.h"
+#if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
+#include "native/include/sun_reflect_ConstantPool.h"
+
+#include "vm/vm.h"
+
+#include "vmcore/annotation.h"
+#endif
+
/* native methods implemented by this file ************************************/
static JNINativeMethod methods[] = {
- { "isInstance", "(Ljava/lang/Class;Ljava/lang/Object;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isInstance },
- { "isAssignableFrom", "(Ljava/lang/Class;Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isAssignableFrom },
- { "isInterface", "(Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isInterface },
- { "isPrimitive", "(Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isPrimitive },
- { "getName", "(Ljava/lang/Class;)Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_VMClass_getName },
- { "getSuperclass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClass_getSuperclass },
- { "getInterfaces", "(Ljava/lang/Class;)[Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClass_getInterfaces },
- { "getComponentType", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClass_getComponentType },
- { "getModifiers", "(Ljava/lang/Class;Z)I", (void *) (ptrint) &Java_java_lang_VMClass_getModifiers },
- { "getDeclaringClass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClass_getDeclaringClass },
- { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClass_getDeclaredClasses },
- { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;", (void *) (ptrint) &Java_java_lang_VMClass_getDeclaredFields },
- { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;", (void *) (ptrint) &Java_java_lang_VMClass_getDeclaredMethods },
- { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;", (void *) (ptrint) &Java_java_lang_VMClass_getDeclaredConstructors },
- { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;", (void *) (ptrint) &Java_java_lang_VMClass_getClassLoader },
- { "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClass_forName },
- { "isArray", "(Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isArray },
- { "throwException", "(Ljava/lang/Throwable;)V", (void *) (ptrint) &Java_java_lang_VMClass_throwException },
+ { "isInstance", "(Ljava/lang/Class;Ljava/lang/Object;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isInstance },
+ { "isAssignableFrom", "(Ljava/lang/Class;Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isAssignableFrom },
+ { "isInterface", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isInterface },
+ { "isPrimitive", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isPrimitive },
+ { "getName", "(Ljava/lang/Class;)Ljava/lang/String;", (void *) (uintptr_t) &Java_java_lang_VMClass_getName },
+ { "getSuperclass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getSuperclass },
+ { "getInterfaces", "(Ljava/lang/Class;)[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getInterfaces },
+ { "getComponentType", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getComponentType },
+ { "getModifiers", "(Ljava/lang/Class;Z)I", (void *) (uintptr_t) &Java_java_lang_VMClass_getModifiers },
+ { "getDeclaringClass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaringClass },
+ { "getDeclaredClasses", "(Ljava/lang/Class;Z)[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredClasses },
+ { "getDeclaredFields", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredFields },
+ { "getDeclaredMethods", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredMethods },
+ { "getDeclaredConstructors", "(Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredConstructors },
+ { "getClassLoader", "(Ljava/lang/Class;)Ljava/lang/ClassLoader;", (void *) (uintptr_t) &Java_java_lang_VMClass_getClassLoader },
+ { "forName", "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_forName },
+ { "isArray", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isArray },
+ { "throwException", "(Ljava/lang/Throwable;)V", (void *) (uintptr_t) &Java_java_lang_VMClass_throwException },
#if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
- { "getDeclaredAnnotations", "(Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;", (void *) (ptrint) &Java_java_lang_VMClass_getDeclaredAnnotations },
+ { "getDeclaredAnnotations", "(Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;", (void *) (uintptr_t) &Java_java_lang_VMClass_getDeclaredAnnotations },
#endif
- { "getEnclosingClass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClass_getEnclosingClass },
- { "getEnclosingConstructor", "(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", (void *) (ptrint) &Java_java_lang_VMClass_getEnclosingConstructor },
- { "getEnclosingMethod", "(Ljava/lang/Class;)Ljava/lang/reflect/Method;", (void *) (ptrint) &Java_java_lang_VMClass_getEnclosingMethod },
- { "getClassSignature", "(Ljava/lang/Class;)Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_VMClass_getClassSignature },
- { "isAnonymousClass", "(Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isAnonymousClass },
- { "isLocalClass", "(Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isLocalClass },
- { "isMemberClass", "(Ljava/lang/Class;)Z", (void *) (ptrint) &Java_java_lang_VMClass_isMemberClass },
+ { "getEnclosingClass", "(Ljava/lang/Class;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClass_getEnclosingClass },
+ { "getEnclosingConstructor", "(Ljava/lang/Class;)Ljava/lang/reflect/Constructor;", (void *) (uintptr_t) &Java_java_lang_VMClass_getEnclosingConstructor },
+ { "getEnclosingMethod", "(Ljava/lang/Class;)Ljava/lang/reflect/Method;", (void *) (uintptr_t) &Java_java_lang_VMClass_getEnclosingMethod },
+ { "getClassSignature", "(Ljava/lang/Class;)Ljava/lang/String;", (void *) (uintptr_t) &Java_java_lang_VMClass_getClassSignature },
+ { "isAnonymousClass", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isAnonymousClass },
+ { "isLocalClass", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isLocalClass },
+ { "isMemberClass", "(Ljava/lang/Class;)Z", (void *) (uintptr_t) &Java_java_lang_VMClass_isMemberClass },
};
* Method: isInstance
* Signature: (Ljava/lang/Class;Ljava/lang/Object;)Z
*/
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Object *o)
+JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isInstance(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Object *o)
{
- return _Jv_java_lang_Class_isInstance(klass, o);
+ classinfo *c;
+ java_handle_t *h;
+
+ c = LLNI_classinfo_unwrap(klass);
+ h = (java_handle_t *) o;
+
+ return class_is_instance(c, h);
}
* Method: isAssignableFrom
* Signature: (Ljava/lang/Class;Ljava/lang/Class;)Z
*/
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Class *c)
+JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isAssignableFrom(JNIEnv *env, jclass clazz, java_lang_Class *klass, java_lang_Class *c)
{
- return _Jv_java_lang_Class_isAssignableFrom(klass, c);
+ classinfo *to;
+ classinfo *from;
+
+ to = LLNI_classinfo_unwrap(klass);
+ from = LLNI_classinfo_unwrap(c);
+
+ if (from == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ return class_is_assignable_from(to, from);
}
* Method: isInterface
* Signature: (Ljava/lang/Class;)Z
*/
-JNIEXPORT s4 JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *klass)
+JNIEXPORT int32_t JNICALL Java_java_lang_VMClass_isInterface(JNIEnv *env, jclass clazz, java_lang_Class *klass)
{
classinfo *c;
*/
JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMClass_getName(JNIEnv *env, jclass clazz, java_lang_Class *klass)
{
- return _Jv_java_lang_Class_getName(klass);
+ classinfo* c;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ return (java_lang_String*) class_get_classname(c);
}
* Method: getDeclaredClasses
* Signature: (Ljava/lang/Class;Z)[Ljava/lang/Class;
*/
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredClasses(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
{
classinfo *c;
java_handle_objectarray_t *oa;
* Method: getDeclaredFields
* Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Field;
*/
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredFields(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
{
- return _Jv_java_lang_Class_getDeclaredFields(klass, publicOnly);
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_declaredfields(c, publicOnly);
+
+ return oa;
}
* Method: getDeclaredMethods
* Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Method;
*/
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredMethods(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
{
- return _Jv_java_lang_Class_getDeclaredMethods(klass, publicOnly);
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_declaredmethods(c, publicOnly);
+
+ return oa;
}
* Method: getDeclaredConstructors
* Signature: (Ljava/lang/Class;Z)[Ljava/lang/reflect/Constructor;
*/
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, java_lang_Class *klass, s4 publicOnly)
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredConstructors(JNIEnv *env, jclass clazz, java_lang_Class *klass, int32_t publicOnly)
{
- return _Jv_java_lang_Class_getDeclaredConstructors(klass, publicOnly);
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ oa = class_get_declaredconstructors(c, publicOnly);
+
+ return oa;
}
*/
JNIEXPORT java_lang_ClassLoader* JNICALL Java_java_lang_VMClass_getClassLoader(JNIEnv *env, jclass clazz, java_lang_Class *klass)
{
- classinfo *c;
- classloader *cl;
+ classinfo *c;
+ classloader_t *cl;
c = LLNI_classinfo_unwrap(klass);
cl = class_get_classloader(c);
* Method: forName
* Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
*/
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClass_forName(JNIEnv *env, jclass clazz, java_lang_String *name, int32_t initialize, java_lang_ClassLoader *loader)
{
- return _Jv_java_lang_Class_forName(name, initialize, loader);
+ classloader_t *cl;
+ utf *ufile;
+ utf *uname;
+ classinfo *c;
+ u2 *pos;
+ int32_t i;
+
+ cl = loader_hashtable_classloader_add((java_handle_t *) loader);
+
+ /* illegal argument */
+
+ if (name == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* create utf string in which '.' is replaced by '/' */
+
+ ufile = javastring_toutf((java_handle_t *) name, true);
+ uname = javastring_toutf((java_handle_t *) name, false);
+
+ /* name must not contain '/' (mauve test) */
+
+ for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
+ if (*pos == '/') {
+ exceptions_throw_classnotfoundexception(uname);
+ return NULL;
+ }
+ }
+
+ /* try to load, ... */
+
+ c = load_class_from_classloader(ufile, cl);
+
+ if (c == NULL)
+ return NULL;
+
+ /* link, ... */
+
+ if (!link_class(c))
+ return NULL;
+
+ /* ...and initialize it, if required */
+
+ if (initialize)
+ if (!initialize_class(c))
+ return NULL;
+
+ return LLNI_classinfo_wrap(c);
}
*/
JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMClass_getDeclaredAnnotations(JNIEnv *env, jclass clazz, java_lang_Class* klass)
{
- return _Jv_java_lang_Class_getDeclaredAnnotations(klass);
+ classinfo *c = NULL; /* classinfo for the java.lang.Class object 'klass' */
+ static methodinfo *m_parseAnnotationsIntoArray = NULL; /* parser method (cached, therefore static) */
+ utf *utf_parseAnnotationsIntoArray = NULL; /* parser method name */
+ utf *utf_desc = NULL; /* parser method descriptor (signature) */
+ java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
+ sun_reflect_ConstantPool *constantPool = NULL; /* constant pool of klass */
+ java_lang_Object *constantPoolOop = (java_lang_Object*)klass; /* constantPoolOop field of */
+ /* sun.reflect.ConstantPool */
+
+ if (klass == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ c = LLNI_classinfo_unwrap(klass);
+
+ /* get annotations: */
+ annotations = class_get_annotations(c);
+
+ constantPool =
+ (sun_reflect_ConstantPool*)native_new_and_init(
+ class_sun_reflect_ConstantPool);
+
+ if (constantPool == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+
+ LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
+
+ /* only resolve the parser method the first time */
+ if (m_parseAnnotationsIntoArray == NULL) {
+ utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
+ utf_desc = utf_new_char(
+ "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
+ "[Ljava/lang/annotation/Annotation;");
+
+ if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+
+ m_parseAnnotationsIntoArray = class_resolveclassmethod(
+ class_sun_reflect_annotation_AnnotationParser,
+ utf_parseAnnotationsIntoArray,
+ utf_desc,
+ class_java_lang_Class,
+ true);
+
+ if (m_parseAnnotationsIntoArray == NULL) {
+ /* method not found */
+ return NULL;
+ }
+ }
+
+ return (java_handle_objectarray_t*)vm_call_method(
+ m_parseAnnotationsIntoArray, NULL,
+ annotations, constantPool, klass);
}
#endif
*/
JNIEXPORT java_lang_reflect_Constructor* JNICALL Java_java_lang_VMClass_getEnclosingConstructor(JNIEnv *env, jclass clazz, java_lang_Class *klass)
{
- return _Jv_java_lang_Class_getEnclosingConstructor(klass);
+ classinfo* c;
+ java_handle_t* h;
+
+ c = LLNI_classinfo_unwrap(klass);
+ h = class_get_enclosingconstructor(c);
+
+ return (java_lang_reflect_Constructor*) h;
}
*/
JNIEXPORT java_lang_reflect_Method* JNICALL Java_java_lang_VMClass_getEnclosingMethod(JNIEnv *env, jclass clazz, java_lang_Class *klass)
{
- return _Jv_java_lang_Class_getEnclosingMethod(klass);
+ classinfo* c;
+ java_handle_t* h;
+
+ c = LLNI_classinfo_unwrap(klass);
+ h = class_get_enclosingmethod(c);
+
+ return (java_lang_reflect_Method*) h;
}
-/* src/native/vm/gnu/VMClassLoader.c
+/* src/native/vm/gnu/java_lang_VMClassLoader.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include <assert.h>
+#include <stdint.h>
#include <sys/stat.h>
-#include "vm/types.h"
-
#include "mm/memory.h"
#include "native/jni.h"
#include "native/include/java_lang_VMClassLoader.h"
-#include "native/vm/java_lang_ClassLoader.h"
-
#include "toolbox/logging.h"
#include "toolbox/list.h"
/* native methods implemented by this file ************************************/
static JNINativeMethod methods[] = {
- { "defineClass", "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClassLoader_defineClass },
- { "getPrimitiveClass", "(C)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClassLoader_getPrimitiveClass },
- { "resolveClass", "(Ljava/lang/Class;)V", (void *) (ptrint) &Java_java_lang_VMClassLoader_resolveClass },
- { "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClassLoader_loadClass },
- { "nativeGetResources", "(Ljava/lang/String;)Ljava/util/Vector;", (void *) (ptrint) &Java_java_lang_VMClassLoader_nativeGetResources },
- { "defaultAssertionStatus", "()Z", (void *) (ptrint) &Java_java_lang_VMClassLoader_defaultAssertionStatus },
- { "defaultUserAssertionStatus", "()Z", (void *) (ptrint) &Java_java_lang_VMClassLoader_defaultUserAssertionStatus },
- { "packageAssertionStatus0", "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void *) (ptrint) &Java_java_lang_VMClassLoader_packageAssertionStatus0 },
- { "classAssertionStatus0", "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void *) (ptrint) &Java_java_lang_VMClassLoader_classAssertionStatus0 },
- { "findLoadedClass", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_VMClassLoader_findLoadedClass },
+ { "defineClass", "(Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defineClass },
+ { "getPrimitiveClass", "(C)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_getPrimitiveClass },
+ { "resolveClass", "(Ljava/lang/Class;)V", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_resolveClass },
+ { "loadClass", "(Ljava/lang/String;Z)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_loadClass },
+ { "nativeGetResources", "(Ljava/lang/String;)Ljava/util/Vector;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_nativeGetResources },
+ { "defaultAssertionStatus", "()Z", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defaultAssertionStatus },
+ { "defaultUserAssertionStatus", "()Z", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_defaultUserAssertionStatus },
+ { "packageAssertionStatus0", "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_packageAssertionStatus0 },
+ { "classAssertionStatus0", "(Ljava/lang/Boolean;Ljava/lang/Boolean;)Ljava/util/Map;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_classAssertionStatus0 },
+ { "findLoadedClass", "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_VMClassLoader_findLoadedClass },
};
* Method: defineClass
* Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
*/
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_handle_bytearray_t *data, s4 offset, s4 len, java_security_ProtectionDomain *pd)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_defineClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *cl, java_lang_String *name, java_handle_bytearray_t *data, int32_t offset, int32_t len, java_security_ProtectionDomain *pd)
{
- return _Jv_java_lang_ClassLoader_defineClass(cl, name, data, offset, len, pd);
+ utf *utfname;
+ classinfo *c;
+ classloader_t *loader;
+ java_lang_Class *o;
+
+#if defined(ENABLE_JVMTI)
+ jint new_class_data_len = 0;
+ unsigned char* new_class_data = NULL;
+#endif
+
+ /* check if data was passed */
+
+ if (data == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* check the indexes passed */
+
+ if ((offset < 0) || (len < 0) || ((offset + len) > LLNI_array_size(data))) {
+ exceptions_throw_arrayindexoutofboundsexception();
+ return NULL;
+ }
+
+ /* add classloader to classloader hashtable */
+
+ loader = loader_hashtable_classloader_add((java_handle_t *) cl);
+
+ if (name != NULL) {
+ /* convert '.' to '/' in java string */
+
+ utfname = javastring_toutf((java_handle_t *) name, true);
+ }
+ else {
+ utfname = NULL;
+ }
+
+#if defined(ENABLE_JVMTI)
+ /* XXX again this will not work because of the indirection cell for classloaders */
+ assert(0);
+ /* fire Class File Load Hook JVMTI event */
+
+ if (jvmti)
+ jvmti_ClassFileLoadHook(utfname, len, (unsigned char *) data->data,
+ loader, (java_handle_t *) pd,
+ &new_class_data_len, &new_class_data);
+#endif
+
+ /* define the class */
+
+#if defined(ENABLE_JVMTI)
+ /* check if the JVMTI wants to modify the class */
+
+ if (new_class_data == NULL)
+ c = class_define(utfname, loader, new_class_data_len, new_class_data, pd);
+ else
+#endif
+ c = class_define(utfname, loader, len, (uint8_t *) &LLNI_array_direct(data, offset), (java_handle_t *) pd);
+
+ if (c == NULL)
+ return NULL;
+
+ /* for convenience */
+
+ o = LLNI_classinfo_wrap(c);
+
+#if defined(WITH_CLASSPATH_GNU)
+ /* set ProtectionDomain */
+
+ LLNI_field_set_ref(o, pd, pd);
+#endif
+
+ return o;
}
* Method: getPrimitiveClass
* Signature: (C)Ljava/lang/Class;
*/
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, s4 type)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_getPrimitiveClass(JNIEnv *env, jclass clazz, int32_t type)
{
classinfo *c;
* Method: loadClass
* Signature: (Ljava/lang/String;Z)Ljava/lang/Class;
*/
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, s4 resolve)
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_loadClass(JNIEnv *env, jclass clazz, java_lang_String *name, int32_t resolve)
{
classinfo *c;
utf *u;
char *buffer; /* char buffer */
char *namestart; /* start of name to use */
char *tmppath; /* temporary buffer */
- s4 namelen; /* length of name to use */
- s4 searchlen; /* length of name to search */
- s4 bufsize; /* size of buffer allocated */
- s4 pathlen; /* name of path to assemble */
+ int32_t namelen; /* length of name to use */
+ int32_t searchlen; /* length of name to search */
+ int32_t bufsize; /* size of buffer allocated */
+ int32_t pathlen; /* name of path to assemble */
struct stat buf; /* buffer for stat */
jboolean ret; /* return value of "add" */
* Method: defaultAssertionStatus
* Signature: ()Z
*/
-JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
+JNIEXPORT int32_t JNICALL Java_java_lang_VMClassLoader_defaultAssertionStatus(JNIEnv *env, jclass clazz)
{
#if defined(ENABLE_ASSERTION)
return assertion_system_enabled;
* Method: userAssertionStatus
* Signature: ()Z
*/
-JNIEXPORT s4 JNICALL Java_java_lang_VMClassLoader_defaultUserAssertionStatus(JNIEnv *env, jclass clazz)
+JNIEXPORT int32_t JNICALL Java_java_lang_VMClassLoader_defaultUserAssertionStatus(JNIEnv *env, jclass clazz)
{
#if defined(ENABLE_ASSERTION)
return assertion_user_enabled;
*/
JNIEXPORT java_lang_Class* JNICALL Java_java_lang_VMClassLoader_findLoadedClass(JNIEnv *env, jclass clazz, java_lang_ClassLoader *loader, java_lang_String *name)
{
- classloader *cl;
- classinfo *c;
- utf *u;
+ classloader_t *cl;
+ classinfo *c;
+ utf *u;
/* XXX is it correct to add the classloader to the hashtable here? */
/* src/native/vm/gnu/java_lang_VMRuntime.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <sys/utsname.h>
#if defined(__DARWIN__)
-# define OS_INLINE /* required for <libkern/ppc/OSByteOrder.h> */
+# if defined(__POWERPC__)
+# define OS_INLINE /* required for <libkern/ppc/OSByteOrder.h> */
+# endif
# include <mach/mach.h>
#endif
+#include "mm/dumpmemory.h"
#include "mm/gc-common.h"
-#include "mm/memory.h"
#include "native/jni.h"
#include "native/native.h"
#include "native/include/java_lang_VMRuntime.h"
-#include "native/vm/java_lang_Runtime.h"
-
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/stringlocal.h"
}
+static bool finalizeOnExit = false;
+
+
/*
* Class: java/lang/VMRuntime
* Method: exit
*/
JNIEXPORT void JNICALL Java_java_lang_VMRuntime_exit(JNIEnv *env, jclass clazz, int32_t status)
{
- _Jv_java_lang_Runtime_exit(status);
+ if (finalizeOnExit)
+ gc_finalize_all();
+
+ vm_shutdown(status);
}
*/
JNIEXPORT int64_t JNICALL Java_java_lang_VMRuntime_freeMemory(JNIEnv *env, jclass clazz)
{
- return _Jv_java_lang_Runtime_freeMemory();
+ return gc_get_free_bytes();
}
*/
JNIEXPORT int64_t JNICALL Java_java_lang_VMRuntime_totalMemory(JNIEnv *env, jclass clazz)
{
- return _Jv_java_lang_Runtime_totalMemory();
+ return gc_get_heap_size();
}
*/
JNIEXPORT void JNICALL Java_java_lang_VMRuntime_gc(JNIEnv *env, jclass clazz)
{
- _Jv_java_lang_Runtime_gc();
+ gc_call();
}
*/
JNIEXPORT void JNICALL Java_java_lang_VMRuntime_runFinalizersOnExit(JNIEnv *env, jclass clazz, int32_t value)
{
- _Jv_java_lang_Runtime_runFinalizersOnExit(value);
+ /* XXX threading */
+
+ finalizeOnExit = value;
}
*/
JNIEXPORT int32_t JNICALL Java_java_lang_VMRuntime_nativeLoad(JNIEnv *env, jclass clazz, java_lang_String *libname, java_lang_ClassLoader *loader)
{
- classloader *cl;
+ classloader_t *cl;
+ utf *name;
cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-#if defined(ENABLE_JNI)
- return _Jv_java_lang_Runtime_loadLibrary(env, libname, cl);
-#else
- return _Jv_java_lang_Runtime_loadLibrary(libname, cl);
-#endif
+ /* REMOVEME When we use Java-strings internally. */
+
+ if (libname == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ name = javastring_toutf((java_handle_t *) libname, false);
+
+ return native_library_load(env, name, cl);
}
utf *u;
char *buffer;
int32_t buffer_len;
- int32_t dumpsize;
java_handle_t *o;
+ int32_t dumpmarker;
if (libname == NULL) {
exceptions_throw_nullpointerexception();
buffer_len += strlen("0");
- dumpsize = dump_size();
+ DMARKER;
+
buffer = DMNEW(char, buffer_len);
/* generate library name */
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
return (java_lang_String *) o;
}
/* src/native/vm/gnu/java_lang_VMSystem.c - java/lang/VMSystem
- 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 <stdint.h>
#include <string.h>
-#include "vm/types.h"
-
#include "mm/gc-common.h"
#include "native/jni.h"
/* native methods implemented by this file ************************************/
static JNINativeMethod methods[] = {
- { "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", (void *) (ptrint) &Java_java_lang_VMSystem_arraycopy },
- { "identityHashCode", "(Ljava/lang/Object;)I", (void *) (ptrint) &Java_java_lang_VMSystem_identityHashCode },
+ { "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V", (void *) (uintptr_t) &Java_java_lang_VMSystem_arraycopy },
+ { "identityHashCode", "(Ljava/lang/Object;)I", (void *) (uintptr_t) &Java_java_lang_VMSystem_identityHashCode },
};
* Method: arraycopy
* Signature: (Ljava/lang/Object;ILjava/lang/Object;II)V
*/
-JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy(JNIEnv *env, jclass clazz, java_lang_Object *src, s4 srcStart, java_lang_Object *dest, s4 destStart, s4 len)
+JNIEXPORT void JNICALL Java_java_lang_VMSystem_arraycopy(JNIEnv *env, jclass clazz, java_lang_Object *src, int32_t srcStart, java_lang_Object *dest, int32_t destStart, int32_t len)
{
builtin_arraycopy((java_handle_t *) src, srcStart,
(java_handle_t *) dest, destStart, len);
* Method: identityHashCode
* Signature: (Ljava/lang/Object;)I
*/
-JNIEXPORT s4 JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, java_lang_Object *o)
+JNIEXPORT int32_t JNICALL Java_java_lang_VMSystem_identityHashCode(JNIEnv *env, jclass clazz, java_lang_Object *o)
{
- s4 hashcode;
+ int32_t hashcode;
LLNI_CRITICAL_START;
/* src/native/vm/gnu/java_lang_VMThread.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/java_lang_Object.h" /* java_lang_Thread.h */
#include "native/include/java_lang_Throwable.h" /* java_lang_Thread.h */
#include "native/include/java_lang_VMThread.h"
+#include "native/include/java_lang_String.h"
#include "native/include/java_lang_Thread.h"
-#include "native/include/java_lang_VMThread.h"
-
-#include "native/vm/java_lang_Thread.h"
+#include "threads/lock-common.h"
+#include "threads/thread.h"
-#include "threads/threads-common.h"
+#include "vm/exceptions.h"
+#include "vm/stringlocal.h"
#include "vmcore/utf8.h"
LLNI_field_get_ref(this, thread, thread);
- return _Jv_java_lang_Thread_countStackFrames(thread);
+ log_println("Java_java_lang_VMThread_countStackFrames: IMPLEMENT ME!");
+
+ return 0;
}
LLNI_field_get_ref(this, thread, thread);
- _Jv_java_lang_Thread_start(thread, stacksize);
+#if defined(ENABLE_THREADS)
+ threads_thread_start((java_handle_t *) thread);
+#endif
}
JNIEXPORT void JNICALL Java_java_lang_VMThread_interrupt(JNIEnv *env, java_lang_VMThread *this)
{
#if defined(ENABLE_THREADS)
- java_lang_Thread *object;
- threadobject *t;
-
- /* XXX TWISTI: I think this and object->vmThread are equal. */
-
- LLNI_field_get_ref(this, thread, object);
+ java_handle_t *h;
+ threadobject *t;
- t = (threadobject *) LLNI_field_direct(object, vmThread)->vmdata;
+ h = (java_handle_t *) this;
+ t = thread_get_thread(h);
threads_thread_interrupt(t);
#endif
*/
JNIEXPORT int32_t JNICALL Java_java_lang_VMThread_isInterrupted(JNIEnv *env, java_lang_VMThread *this)
{
- java_lang_Thread *thread;
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+ threadobject *t;
- LLNI_field_get_ref(this, thread, thread);
+ h = (java_handle_t *) this;
+ t = thread_get_thread(h);
- return _Jv_java_lang_Thread_isInterrupted(thread);
+ return thread_is_interrupted(t);
+#else
+ return 0;
+#endif
}
*/
JNIEXPORT void JNICALL Java_java_lang_VMThread_suspend(JNIEnv *env, java_lang_VMThread *this)
{
- java_lang_Thread *thread;
-
- LLNI_field_get_ref(this, thread, thread);
-
- _Jv_java_lang_Thread_suspend(thread);
+#if defined(ENABLE_THREADS)
+ /* TODO Should we implement this or is it obsolete? */
+#endif
}
*/
JNIEXPORT void JNICALL Java_java_lang_VMThread_resume(JNIEnv *env, java_lang_VMThread *this)
{
- java_lang_Thread *thread;
-
- LLNI_field_get_ref(this, thread, thread);
-
- _Jv_java_lang_Thread_resume(thread);
+#if defined(ENABLE_THREADS)
+ /* TODO Should we implement this or is it obsolete? */
+#endif
}
*/
JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeSetPriority(JNIEnv *env, java_lang_VMThread *this, int32_t priority)
{
- java_lang_Thread *thread;
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+ threadobject *t;
- LLNI_field_get_ref(this, thread, thread);
+ h = (java_handle_t *) this;
+ t = thread_get_thread(h);
- _Jv_java_lang_Thread_setPriority(thread, priority);
+ threads_set_thread_priority(t->tid, priority);
+#endif
}
*/
JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeStop(JNIEnv *env, java_lang_VMThread *this, java_lang_Throwable *t)
{
- java_lang_Thread *thread;
-
- LLNI_field_get_ref(this, thread, thread);
-
- _Jv_java_lang_Thread_stop(thread, t);
+#if defined(ENABLE_THREADS)
+ /* TODO Should we implement this or is it obsolete? */
+#endif
}
*/
JNIEXPORT java_lang_Thread* JNICALL Java_java_lang_VMThread_currentThread(JNIEnv *env, jclass clazz)
{
- return _Jv_java_lang_Thread_currentThread();
+ java_lang_Thread *to;
+
+ to = (java_lang_Thread *) thread_get_current_object();
+
+ return to;
}
*/
JNIEXPORT void JNICALL Java_java_lang_VMThread_yield(JNIEnv *env, jclass clazz)
{
- _Jv_java_lang_Thread_yield();
+#if defined(ENABLE_THREADS)
+ threads_yield();
+#endif
}
*/
JNIEXPORT int32_t JNICALL Java_java_lang_VMThread_interrupted(JNIEnv *env, jclass clazz)
{
- return _Jv_java_lang_Thread_interrupted();
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+ int32_t interrupted;
+
+ t = thread_get_current();
+
+ interrupted = thread_is_interrupted(t);
+
+ if (interrupted)
+ thread_set_interrupted(t, false);
+
+ return interrupted;
+#else
+ return 0;
+#endif
}
*/
JNIEXPORT int32_t JNICALL Java_java_lang_VMThread_holdsLock(JNIEnv *env, jclass clazz, java_lang_Object* o)
{
- return _Jv_java_lang_Thread_holdsLock(o);
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+
+ h = (java_handle_t *) o;
+
+ if (h == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ return lock_is_held_by_current_thread(h);
+#else
+ return 0;
+#endif
}
*/
JNIEXPORT java_lang_String* JNICALL Java_java_lang_VMThread_getState(JNIEnv *env, java_lang_VMThread *this)
{
- java_lang_Thread *thread;
-
- LLNI_field_get_ref(this, thread, thread);
-
- return _Jv_java_lang_Thread_getState(thread);
+#if defined(ENABLE_THREADS)
+ java_handle_t *h;
+ threadobject *t;
+ int state;
+ utf *u;
+ java_handle_t *o;
+
+ h = (java_handle_t *) this;
+ t = thread_get_thread(h);
+
+ state = cacaothread_get_state(t);
+
+ switch (state) {
+ case THREAD_STATE_NEW:
+ u = utf_new_char("NEW");
+ break;
+ case THREAD_STATE_RUNNABLE:
+ u = utf_new_char("RUNNABLE");
+ break;
+ case THREAD_STATE_BLOCKED:
+ u = utf_new_char("BLOCKED");
+ break;
+ case THREAD_STATE_WAITING:
+ u = utf_new_char("WAITING");
+ break;
+ case THREAD_STATE_TIMED_WAITING:
+ u = utf_new_char("TIMED_WAITING");
+ break;
+ case THREAD_STATE_TERMINATED:
+ u = utf_new_char("TERMINATED");
+ break;
+ default:
+ vm_abort("Java_java_lang_VMThread_getState: unknown thread state %d", state);
+
+ /* Keep compiler happy. */
+
+ u = NULL;
+ }
+
+ o = javastring_new(u);
+
+ return (java_lang_String *) o;
+#else
+ return NULL;
+#endif
}
/* src/native/vm/gnu/java_lang_VMThrowable.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/llni.h"
#include "native/native.h"
-#include "native/include/gnu_classpath_Pointer.h"
+#include "native/include/java_lang_Object.h"
#include "native/include/java_lang_Class.h"
+#include "native/include/java_lang_String.h"
#include "native/include/java_lang_StackTraceElement.h"
#include "native/include/java_lang_Throwable.h"
#include "native/include/java_lang_VMThrowable.h"
-#include "native/vm/java_lang_Class.h"
-
#include "vm/array.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
*/
JNIEXPORT java_lang_VMThrowable* JNICALL Java_java_lang_VMThrowable_fillInStackTrace(JNIEnv *env, jclass clazz, java_lang_Throwable *t)
{
- java_lang_VMThrowable *o;
+ java_lang_VMThrowable *vmto;
java_handle_bytearray_t *ba;
+ java_lang_Object *o;
- o = (java_lang_VMThrowable *)
+ vmto = (java_lang_VMThrowable *)
native_new_and_init(class_java_lang_VMThrowable);
- if (o == NULL)
+ if (vmto == NULL)
return NULL;
- ba = stacktrace_get();
+ ba = stacktrace_get_current();
if (ba == NULL)
return NULL;
- LLNI_field_set_ref(o, vmData, (gnu_classpath_Pointer *) ba);
+ o = (java_lang_Object *) ba;
+
+ LLNI_field_set_ref(vmto, vmdata, o);
- return o;
+ return vmto;
}
*/
JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_VMThrowable_getStackTrace(JNIEnv *env, java_lang_VMThrowable *this, java_lang_Throwable *t)
{
+ java_lang_Object *o;
java_handle_bytearray_t *ba;
stacktrace_t *st;
stacktrace_entry_t *ste;
java_handle_objectarray_t *oa;
- java_lang_StackTraceElement *o;
+ java_lang_StackTraceElement *steo;
codeinfo *code;
methodinfo *m;
java_lang_String *filename;
s4 linenumber;
- java_lang_String *declaringclass;
+ java_handle_t *declaringclass;
int i;
- /* get the stacktrace buffer from the VMThrowable object */
+ /* Get the stacktrace from the VMThrowable object. */
+
+ LLNI_field_get_ref(this, vmdata, o);
- LLNI_field_get_ref(this, vmData, ba);
+ ba = (java_handle_bytearray_t *) o;
st = (stacktrace_t *) LLNI_array_data(ba);
for (i = 0; i < st->length; i++, ste++) {
/* allocate a new stacktrace element */
- o = (java_lang_StackTraceElement *)
+ steo = (java_lang_StackTraceElement *)
builtin_new(class_java_lang_StackTraceElement);
- if (o == NULL)
+ if (steo == NULL)
return NULL;
/* Get the codeinfo and methodinfo. */
/* Get filename. */
if (!(m->flags & ACC_NATIVE)) {
- if (m->class->sourcefile)
- filename = (java_lang_String *) javastring_new(m->class->sourcefile);
+ if (m->clazz->sourcefile)
+ filename = (java_lang_String *) javastring_new(m->clazz->sourcefile);
else
filename = NULL;
}
/* get declaring class name */
- declaringclass =
- _Jv_java_lang_Class_getName(LLNI_classinfo_wrap(m->class));
+ declaringclass = class_get_classname(m->clazz);
/* Fill the java.lang.StackTraceElement object. */
- LLNI_field_set_ref(o, fileName , filename);
- LLNI_field_set_val(o, lineNumber , linenumber);
- LLNI_field_set_ref(o, declaringClass, declaringclass);
- LLNI_field_set_ref(o, methodName , (java_lang_String *) javastring_new(m->name));
- LLNI_field_set_val(o, isNative , (m->flags & ACC_NATIVE) ? 1 : 0);
+ LLNI_field_set_ref(steo, fileName , filename);
+ LLNI_field_set_val(steo, lineNumber , linenumber);
+ LLNI_field_set_ref(steo, declaringClass, (java_lang_String*) declaringclass);
+ LLNI_field_set_ref(steo, methodName , (java_lang_String *) javastring_new(m->name));
+ LLNI_field_set_val(steo, isNative , (m->flags & ACC_NATIVE) ? 1 : 0);
- array_objectarray_element_set(oa, i, (java_handle_t *) o);
+ array_objectarray_element_set(oa, i, (java_handle_t *) steo);
}
return oa;
+++ /dev/null
-/* src/native/vm/gnu/java_lang_reflect_Constructor.c
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "vm/vm.h"
-#include "vm/exceptions.h"
-#endif
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_reflect_Constructor.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-# include "native/include/java_util_Map.h"
-# include "native/include/sun_reflect_ConstantPool.h"
-
-# include "native/vm/reflect.h"
-#endif
-
-#include "native/vm/java_lang_reflect_Constructor.h"
-
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getModifiersInternal", "()I", (void *) (ptrint) &_Jv_java_lang_reflect_Constructor_getModifiers },
- { "getParameterTypes", "()[Ljava/lang/Class;", (void *) (ptrint) &_Jv_java_lang_reflect_Constructor_getParameterTypes },
- { "getExceptionTypes", "()[Ljava/lang/Class;", (void *) (ptrint) &_Jv_java_lang_reflect_Constructor_getExceptionTypes },
- { "constructNative", "([Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;", (void *) (ptrint) &Java_java_lang_reflect_Constructor_constructNative },
- { "getSignature", "()Ljava/lang/String;", (void *) (ptrint) &_Jv_java_lang_reflect_Constructor_getSignature },
-#if defined(ENABLE_ANNOTATIONS)
- { "declaredAnnotations", "()Ljava/util/Map;", (void *) (ptrint) &Java_java_lang_reflect_Constructor_declaredAnnotations },
- { "getParameterAnnotations", "()[[Ljava/lang/annotation/Annotation;", (void *) (ptrint) &Java_java_lang_reflect_Constructor_getParameterAnnotations },
-#endif
-};
-
-
-/* _Jv_java_lang_reflect_Constructor_init **************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_reflect_Constructor_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/reflect/Constructor");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/reflect/Constructor
- * Method: constructNative
- * Signature: ([Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_Constructor_constructNative(JNIEnv *env, java_lang_reflect_Constructor *this, java_handle_objectarray_t *args, java_lang_Class *declaringClass, s4 slot)
-{
- /* just to be sure */
-
- assert(LLNI_field_direct(this, clazz) == LLNI_DIRECT(declaringClass));
- assert(LLNI_field_direct(this, slot) == slot);
-
- return _Jv_java_lang_reflect_Constructor_newInstance(env, this, args);
-}
-
-
-#if defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/reflect/Constructor
- * Method: declaredAnnotations
- * Signature: ()Ljava/util/Map;
- *
- * Parses the annotations (if they aren't parsed yet) and stores them into
- * the declaredAnnotations map and return this map.
- */
-JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_Constructor_declaredAnnotations(JNIEnv *env, java_lang_reflect_Constructor *this)
-{
- java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
-
- /* are the annotations parsed yet? */
- if (declaredAnnotations == NULL) {
- LLNI_field_get_ref(this, annotations, annotations);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
-
- LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
- }
-
- return declaredAnnotations;
-}
-
-
-/*
- * Class: java/lang/reflect/Constructor
- * Method: getParameterAnnotations
- * Signature: ()[[Ljava/lang/annotation/Annotation;
- *
- * Parses the parameter annotations and returns them in an 2 dimensional array.
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_Constructor_getParameterAnnotations(JNIEnv *env, java_lang_reflect_Constructor *this)
-{
- java_handle_bytearray_t *parameterAnnotations = NULL; /* unparsed parameter annotations */
- int32_t slot = -1; /* slot of the method */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, parameterAnnotations, parameterAnnotations);
- LLNI_field_get_val(this, slot, slot);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- return reflect_get_parameterannotations((java_handle_t*)parameterAnnotations, slot, declaringClass, referer);
-}
-#endif
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/native/vm/gnu/java_lang_reflect_Field.c
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Boolean.h"
-#include "native/include/java_lang_Byte.h"
-#include "native/include/java_lang_Character.h"
-#include "native/include/java_lang_Short.h"
-#include "native/include/java_lang_Integer.h"
-#include "native/include/java_lang_Long.h"
-#include "native/include/java_lang_Float.h"
-#include "native/include/java_lang_Double.h"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_String.h"
-
-#include "native/include/java_lang_reflect_Field.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "native/include/java_util_Map.h"
-#include "native/include/sun_reflect_ConstantPool.h"
-#include "native/vm/reflect.h"
-#endif
-
-#include "vm/access.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-#include "vm/primitive.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/utf8.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getModifiersInternal", "()I", (void *) (intptr_t) &Java_java_lang_reflect_Field_getModifiersInternal },
- { "getType", "()Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_reflect_Field_getType },
- { "get", "(Ljava/lang/Object;)Ljava/lang/Object;", (void *) (intptr_t) &Java_java_lang_reflect_Field_get },
- { "getBoolean", "(Ljava/lang/Object;)Z", (void *) (intptr_t) &Java_java_lang_reflect_Field_getBoolean },
- { "getByte", "(Ljava/lang/Object;)B", (void *) (intptr_t) &Java_java_lang_reflect_Field_getByte },
- { "getChar", "(Ljava/lang/Object;)C", (void *) (intptr_t) &Java_java_lang_reflect_Field_getChar },
- { "getShort", "(Ljava/lang/Object;)S", (void *) (intptr_t) &Java_java_lang_reflect_Field_getShort },
- { "getInt", "(Ljava/lang/Object;)I", (void *) (intptr_t) &Java_java_lang_reflect_Field_getInt },
- { "getLong", "(Ljava/lang/Object;)J", (void *) (intptr_t) &Java_java_lang_reflect_Field_getLong },
- { "getFloat", "(Ljava/lang/Object;)F", (void *) (intptr_t) &Java_java_lang_reflect_Field_getFloat },
- { "getDouble", "(Ljava/lang/Object;)D", (void *) (intptr_t) &Java_java_lang_reflect_Field_getDouble },
- { "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_set },
- { "setBoolean", "(Ljava/lang/Object;Z)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setBoolean },
- { "setByte", "(Ljava/lang/Object;B)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setByte },
- { "setChar", "(Ljava/lang/Object;C)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setChar },
- { "setShort", "(Ljava/lang/Object;S)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setShort },
- { "setInt", "(Ljava/lang/Object;I)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setInt },
- { "setLong", "(Ljava/lang/Object;J)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setLong },
- { "setFloat", "(Ljava/lang/Object;F)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setFloat },
- { "setDouble", "(Ljava/lang/Object;D)V", (void *) (intptr_t) &Java_java_lang_reflect_Field_setDouble },
- { "getSignature", "()Ljava/lang/String;", (void *) (intptr_t) &Java_java_lang_reflect_Field_getSignature },
-#if defined(ENABLE_ANNOTATIONS)
- { "declaredAnnotations", "()Ljava/util/Map;", (void *) (intptr_t) &Java_java_lang_reflect_Field_declaredAnnotations },
-#endif
-};
-
-
-/* _Jv_java_lang_reflect_Field_init ********************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_reflect_Field_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/reflect/Field");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/* _field_access_check *********************************************************
-
- Checks if the field can be accessed.
-
- RETURN VALUE:
- true......field can be accessed, or
- false.....otherwise (maybe an Exception was thrown).
-
-*******************************************************************************/
-
-static bool _field_access_check(java_lang_reflect_Field *this,
- fieldinfo *f, classinfo *c, java_handle_t *o)
-{
- int32_t flag;
-
- /* check if we should bypass security checks (AccessibleObject) */
-
- LLNI_field_get_val(this, flag, flag);
- if (flag == false) {
- /* this function is always called like this:
- java.lang.reflect.Field.xxx (Native Method)
- [0] <caller>
- */
- if (!access_check_field(f, 0))
- return false;
- }
-
- /* some general checks */
-
- if (f->flags & ACC_STATIC) {
- /* initialize class if required */
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return false;
-
- /* everything is ok */
-
- return true;
-
- } else {
- /* obj is required for not-static fields */
-
- if (o == NULL) {
- exceptions_throw_nullpointerexception();
- return false;
- }
-
- if (builtin_instanceof(o, c))
- return true;
- }
-
- /* exception path */
-
- exceptions_throw_illegalargumentexception();
- return false;
-}
-
-
-/* _field_get_type *************************************************************
-
- Returns the content of the given field.
-
-*******************************************************************************/
-
-#define _FIELD_GET_TYPE(name, type, uniontype) \
-static inline type _field_get_##name(fieldinfo *f, java_lang_Object *o) \
-{ \
- type ret; \
- if (f->flags & ACC_STATIC) { \
- ret = f->value->uniontype; \
- } else { \
- LLNI_CRITICAL_START; \
- ret = *(type *) (((intptr_t) LLNI_DIRECT(o)) + f->offset); \
- LLNI_CRITICAL_END; \
- } \
- return ret; \
-}
-
-static inline java_handle_t *_field_get_handle(fieldinfo *f, java_lang_Object *o)
-{
- java_object_t *obj;
- java_handle_t *hdl;
-
- LLNI_CRITICAL_START;
-
- if (f->flags & ACC_STATIC) {
- obj = f->value->a;
- } else {
- obj = *(java_object_t **) (((intptr_t) LLNI_DIRECT(o)) + f->offset);
- }
-
- hdl = LLNI_WRAP(obj);
-
- LLNI_CRITICAL_END;
-
- return hdl;
-}
-
-_FIELD_GET_TYPE(int, int32_t, i)
-_FIELD_GET_TYPE(long, int64_t, l)
-_FIELD_GET_TYPE(float, float, f)
-_FIELD_GET_TYPE(double, double, d)
-
-
-/* _field_set_type *************************************************************
-
- Sets the content of the given field to the given value.
-
-*******************************************************************************/
-
-#define _FIELD_SET_TYPE(name, type, uniontype) \
-static inline void _field_set_##name(fieldinfo *f, java_lang_Object *o, type value) \
-{ \
- if (f->flags & ACC_STATIC) { \
- f->value->uniontype = value; \
- } else { \
- LLNI_CRITICAL_START; \
- *(type *) (((intptr_t) LLNI_DIRECT(o)) + f->offset) = value; \
- LLNI_CRITICAL_END; \
- } \
-}
-
-static inline void _field_set_handle(fieldinfo *f, java_lang_Object *o, java_handle_t *value)
-{
- LLNI_CRITICAL_START;
-
- if (f->flags & ACC_STATIC) {
- f->value->a = LLNI_DIRECT(value);
- } else {
- *(java_object_t **) (((intptr_t) LLNI_DIRECT(o)) + f->offset) = LLNI_DIRECT(value);
- }
-
- LLNI_CRITICAL_END;
-}
-
-_FIELD_SET_TYPE(int, int32_t, i)
-_FIELD_SET_TYPE(long, int64_t, l)
-_FIELD_SET_TYPE(float, float, f)
-_FIELD_SET_TYPE(double, double, d)
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getModifiersInternal
- * Signature: ()I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_Field_getModifiersInternal(JNIEnv *env, java_lang_reflect_Field *this)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &(c->fields[slot]);
-
- return f->flags;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getType
- * Signature: ()Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_reflect_Field_getType(JNIEnv *env, java_lang_reflect_Field *this)
-{
- classinfo *c;
- typedesc *desc;
- classinfo *ret;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- desc = c->fields[slot].parseddesc;
-
- if (desc == NULL)
- return NULL;
-
- if (!resolve_class_from_typedesc(desc, true, false, &ret))
- return NULL;
-
- return LLNI_classinfo_wrap(ret);
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: get
- * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_Field_get(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
- imm_union value;
- java_handle_t *object;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return NULL;
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- value.i = _field_get_int(f, o);
- break;
-
- case PRIMITIVETYPE_LONG:
- value.l = _field_get_long(f, o);
- break;
-
- case PRIMITIVETYPE_FLOAT:
- value.f = _field_get_float(f, o);
- break;
-
- case PRIMITIVETYPE_DOUBLE:
- value.d = _field_get_double(f, o);
- break;
-
- case TYPE_ADR:
- return (java_lang_Object *) _field_get_handle(f, o);
- }
-
- /* Now box the primitive types. */
-
- object = primitive_box(f->parseddesc->decltype, value);
-
- return (java_lang_Object *) object;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getBoolean
- * Signature: (Ljava/lang/Object;)Z
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_Field_getBoolean(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getByte
- * Signature: (Ljava/lang/Object;)B
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_Field_getByte(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getChar
- * Signature: (Ljava/lang/Object;)C
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_Field_getChar(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_CHAR:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getShort
- * Signature: (Ljava/lang/Object;)S
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_Field_getShort(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getInt
- * Signature: (Ljava/lang/Object;)I
- */
-JNIEXPORT int32_t JNICALL Java_java_lang_reflect_Field_getInt(JNIEnv *env , java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (int32_t) _field_get_int(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getLong
- * Signature: (Ljava/lang/Object;)J
- */
-JNIEXPORT int64_t JNICALL Java_java_lang_reflect_Field_getLong(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (int64_t) _field_get_int(f, o);
- case PRIMITIVETYPE_LONG:
- return (int64_t) _field_get_long(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getFloat
- * Signature: (Ljava/lang/Object;)F
- */
-JNIEXPORT float JNICALL Java_java_lang_reflect_Field_getFloat(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (float) _field_get_int(f, o);
- case PRIMITIVETYPE_LONG:
- return (float) _field_get_long(f, o);
- case PRIMITIVETYPE_FLOAT:
- return (float) _field_get_float(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getDouble
- * Signature: (Ljava/lang/Object;)D
- */
-JNIEXPORT double JNICALL Java_java_lang_reflect_Field_getDouble(JNIEnv *env , java_lang_reflect_Field *this, java_lang_Object *o)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return 0;
-
- /* check the field type and return the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- return (double) _field_get_int(f, o);
- case PRIMITIVETYPE_LONG:
- return (double) _field_get_long(f, o);
- case PRIMITIVETYPE_FLOAT:
- return (double) _field_get_float(f, o);
- case PRIMITIVETYPE_DOUBLE:
- return (double) _field_get_double(f, o);
- default:
- exceptions_throw_illegalargumentexception();
- return 0;
- }
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: set
- * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_set(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, java_lang_Object *value)
-{
- classinfo *sc;
- classinfo *dc;
- fieldinfo *sf;
- fieldinfo *df;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, dc);
- LLNI_field_get_val(this, slot , slot);
- df = &dc->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, df, dc, (java_handle_t *) o))
- return;
-
- /* get the source classinfo from the object */
-
- if (value == NULL)
- sc = NULL;
- else
- LLNI_class_get(value, sc);
-
- /* The fieldid is used to set the new value, for primitive
- types the value has to be retrieved from the wrapping
- object */
-
- switch (df->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN: {
- int32_t val;
-
- /* determine the field to read the value */
-
- if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_Z)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- LLNI_field_get_val((java_lang_Boolean *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_BYTE: {
- int32_t val;
-
- if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_B)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_CHAR: {
- int32_t val;
-
- if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_C)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_SHORT: {
- int32_t val;
-
- /* get field only by name, it can be one of B, S */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_INT: {
- int32_t val;
-
- /* get field only by name, it can be one of B, S, C, I */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_int(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_LONG: {
- int64_t val;
-
- /* get field only by name, it can be one of B, S, C, I, J */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- case PRIMITIVETYPE_LONG:
- LLNI_field_get_val((java_lang_Long *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_long(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_FLOAT: {
- float val;
-
- /* get field only by name, it can be one of B, S, C, I, J, F */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- case PRIMITIVETYPE_LONG:
- LLNI_field_get_val((java_lang_Long *) value, value, val);
- break;
- case PRIMITIVETYPE_FLOAT:
- LLNI_field_get_val((java_lang_Float *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_float(df, o, val);
- return;
- }
-
- case PRIMITIVETYPE_DOUBLE: {
- double val;
-
- /* get field only by name, it can be one of B, S, C, I, J, F, D */
-
- if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
- break;
-
- switch (sf->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- LLNI_field_get_val((java_lang_Byte *) value, value, val);
- break;
- case PRIMITIVETYPE_CHAR:
- LLNI_field_get_val((java_lang_Character *) value, value, val);
- break;
- case PRIMITIVETYPE_SHORT:
- LLNI_field_get_val((java_lang_Short *) value, value, val);
- break;
- case PRIMITIVETYPE_INT:
- LLNI_field_get_val((java_lang_Integer *) value, value, val);
- break;
- case PRIMITIVETYPE_LONG:
- LLNI_field_get_val((java_lang_Long *) value, value, val);
- break;
- case PRIMITIVETYPE_FLOAT:
- LLNI_field_get_val((java_lang_Float *) value, value, val);
- break;
- case PRIMITIVETYPE_DOUBLE:
- LLNI_field_get_val((java_lang_Double *) value, value, val);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- return;
- }
-
- _field_set_double(df, o, val);
- return;
- }
-
- case TYPE_ADR:
- /* check if value is an instance of the destination class */
-
- /* XXX TODO */
- /* if (!builtin_instanceof((java_handle_t *) value, df->class)) */
- /* break; */
-
- _field_set_handle(df, o, (java_handle_t *) value);
- return;
- }
-
- /* raise exception */
-
- exceptions_throw_illegalargumentexception();
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setBoolean
- * Signature: (Ljava/lang/Object;Z)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setBoolean(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BOOLEAN:
- _field_set_int(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setByte
- * Signature: (Ljava/lang/Object;B)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setByte(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_BYTE:
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setChar
- * Signature: (Ljava/lang/Object;C)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setChar(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_CHAR:
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setShort
- * Signature: (Ljava/lang/Object;S)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setShort(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_SHORT:
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setInt
- * Signature: (Ljava/lang/Object;I)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setInt(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, int32_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_INT:
- _field_set_int(f, o, value);
- break;
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setLong
- * Signature: (Ljava/lang/Object;J)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setLong(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, int64_t value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_LONG:
- _field_set_long(f, o, value);
- break;
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setFloat
- * Signature: (Ljava/lang/Object;F)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setFloat(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, float value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_FLOAT:
- _field_set_float(f, o, value);
- break;
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: setDouble
- * Signature: (Ljava/lang/Object;D)V
- */
-JNIEXPORT void JNICALL Java_java_lang_reflect_Field_setDouble(JNIEnv *env, java_lang_reflect_Field *this, java_lang_Object *o, double value)
-{
- classinfo *c;
- fieldinfo *f;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- /* check if the field can be accessed */
-
- if (!_field_access_check(this, f, c, (java_handle_t *) o))
- return;
-
- /* check the field type and set the value */
-
- switch (f->parseddesc->decltype) {
- case PRIMITIVETYPE_DOUBLE:
- _field_set_double(f, o, value);
- break;
- default:
- exceptions_throw_illegalargumentexception();
- }
-
- return;
-}
-
-
-/*
- * Class: java/lang/reflect/Field
- * Method: getSignature
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_Field_getSignature(JNIEnv *env, java_lang_reflect_Field* this)
-{
- classinfo *c;
- fieldinfo *f;
- java_handle_t *o;
- int32_t slot;
-
- /* get the class and the field */
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- f = &c->fields[slot];
-
- if (f->signature == NULL)
- return NULL;
-
- o = javastring_new(f->signature);
-
- /* in error case o is NULL */
-
- return (java_lang_String *) o;
-}
-
-
-#if defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/reflect/Field
- * Method: declaredAnnotations
- * Signature: ()Ljava/util/Map;
- */
-JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_Field_declaredAnnotations(JNIEnv *env, java_lang_reflect_Field *this)
-{
- java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
-
- /* are the annotations parsed yet? */
- if (declaredAnnotations == NULL) {
- LLNI_field_get_ref(this, annotations, annotations);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
-
- LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
- }
-
- return declaredAnnotations;
-}
-#endif
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/native/vm/gnu/java_lang_reflect_Method.c
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "vm/vm.h"
-#endif
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_String.h"
-
-#if defined(ENABLE_ANNOTATIONS)
-#include "native/include/java_util_Map.h"
-#include "native/include/sun_reflect_ConstantPool.h"
-#include "native/vm/reflect.h"
-#endif
-
-#include "native/include/java_lang_reflect_Method.h"
-
-#include "native/vm/java_lang_reflect_Method.h"
-
-#include "vm/access.h"
-#include "vm/global.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/initialize.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/method.h"
-
-
-/* native methods implemented by this file ************************************/
-
-static JNINativeMethod methods[] = {
- { "getModifiersInternal", "()I", (void *) (ptrint) &Java_java_lang_reflect_Method_getModifiersInternal },
- { "getReturnType", "()Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_reflect_Method_getReturnType },
- { "getParameterTypes", "()[Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_reflect_Method_getParameterTypes },
- { "getExceptionTypes", "()[Ljava/lang/Class;", (void *) (ptrint) &Java_java_lang_reflect_Method_getExceptionTypes },
- { "invokeNative", "(Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;", (void *) (ptrint) &Java_java_lang_reflect_Method_invokeNative },
- { "getSignature", "()Ljava/lang/String;", (void *) (ptrint) &Java_java_lang_reflect_Method_getSignature },
-#if defined(ENABLE_ANNOTATIONS)
- { "getDefaultValue", "()Ljava/lang/Object;", (void *) (ptrint) &Java_java_lang_reflect_Method_getDefaultValue },
- { "declaredAnnotations", "()Ljava/util/Map;", (void *) (ptrint) &Java_java_lang_reflect_Method_declaredAnnotations },
- { "getParameterAnnotations", "()[[Ljava/lang/annotation/Annotation;", (void *) (ptrint) &Java_java_lang_reflect_Method_getParameterAnnotations },
-#endif
-};
-
-
-/* _Jv_java_lang_reflect_Method_init *******************************************
-
- Register native functions.
-
-*******************************************************************************/
-
-void _Jv_java_lang_reflect_Method_init(void)
-{
- utf *u;
-
- u = utf_new_char("java/lang/reflect/Method");
-
- native_method_register(u, methods, NATIVE_METHODS_COUNT);
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: getModifiersInternal
- * Signature: ()I
- */
-JNIEXPORT s4 JNICALL Java_java_lang_reflect_Method_getModifiersInternal(JNIEnv *env, java_lang_reflect_Method *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return m->flags;
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: getReturnType
- * Signature: ()Ljava/lang/Class;
- */
-JNIEXPORT java_lang_Class* JNICALL Java_java_lang_reflect_Method_getReturnType(JNIEnv *env, java_lang_reflect_Method *this)
-{
- classinfo *c;
- methodinfo *m;
- classinfo *result;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- result = method_returntype_get(m);
-
- return LLNI_classinfo_wrap(result);
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: getParameterTypes
- * Signature: ()[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_Method_getParameterTypes(JNIEnv *env, java_lang_reflect_Method *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return method_get_parametertypearray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: getExceptionTypes
- * Signature: ()[Ljava/lang/Class;
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_Method_getExceptionTypes(JNIEnv *env, java_lang_reflect_Method *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return method_get_exceptionarray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: invokeNative
- * Signature: (Ljava/lang/Object;[Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;
- */
-JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_Method_invokeNative(JNIEnv *env, java_lang_reflect_Method *this, java_lang_Object *o, java_handle_objectarray_t *args, java_lang_Class *clazz, s4 slot)
-{
- /* just to be sure */
-
- assert(LLNI_field_direct(this, clazz) == LLNI_DIRECT(clazz));
- assert(LLNI_field_direct(this, slot) == slot);
-
- return _Jv_java_lang_reflect_Method_invoke(this, o, args);
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: getSignature
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_Method_getSignature(JNIEnv *env, java_lang_reflect_Method* this)
-{
- classinfo *c;
- methodinfo *m;
- java_handle_t *o;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- if (m->signature == NULL)
- return NULL;
-
- o = javastring_new(m->signature);
-
- /* in error case o is NULL */
-
- return (java_lang_String *) o;
-}
-
-#if defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/reflect/Method
- * Method: getDefaultValue
- * Signature: ()Ljava/lang/Object;
- *
- * Parses the annotation default value and returnes it (boxed, if it's a primitive).
- */
-JNIEXPORT struct java_lang_Object* JNICALL Java_java_lang_reflect_Method_getDefaultValue(JNIEnv *env, struct java_lang_reflect_Method* this)
-{
- java_handle_bytearray_t *annotationDefault = NULL; /* unparsed annotation default value */
- static methodinfo *m_parseAnnotationDefault = NULL; /* parser method (will be chached, therefore static) */
- utf *utf_parseAnnotationDefault = NULL; /* parser method name */
- utf *utf_desc = NULL; /* parser method descriptor (signature) */
- sun_reflect_ConstantPool *constantPool = NULL; /* constant pool object to use */
- java_lang_Class *constantPoolOop = NULL; /* methods declaring class */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- if (this == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- constantPool =
- (sun_reflect_ConstantPool*)native_new_and_init(
- class_sun_reflect_ConstantPool);
-
- if (constantPool == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_field_get_ref(this, clazz, constantPoolOop);
- LLNI_field_set_ref(constantPool, constantPoolOop, (java_lang_Object*)constantPoolOop);
-
- /* only resolve the parser method the first time */
- if (m_parseAnnotationDefault == NULL) {
- utf_parseAnnotationDefault = utf_new_char("parseAnnotationDefault");
- utf_desc = utf_new_char(
- "(Ljava/lang/reflect/Method;[BLsun/reflect/ConstantPool;)"
- "Ljava/lang/Object;");
-
- if (utf_parseAnnotationDefault == NULL || utf_desc == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_class_get(this, referer);
-
- m_parseAnnotationDefault = class_resolveclassmethod(
- class_sun_reflect_annotation_AnnotationParser,
- utf_parseAnnotationDefault,
- utf_desc,
- referer,
- true);
-
- if (m_parseAnnotationDefault == NULL) {
- /* method not found */
- return NULL;
- }
- }
-
- LLNI_field_get_ref(this, annotationDefault, annotationDefault);
-
- return (java_lang_Object*)vm_call_method(
- m_parseAnnotationDefault, NULL,
- this, annotationDefault, constantPool);
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: declaredAnnotations
- * Signature: ()Ljava/util/Map;
- *
- * Parses the annotations (if they aren't parsed yet) and stores them into
- * the declaredAnnotations map and return this map.
- */
-JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_Method_declaredAnnotations(JNIEnv *env, java_lang_reflect_Method *this)
-{
- java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
-
- /* are the annotations parsed yet? */
- if (declaredAnnotations == NULL) {
- LLNI_field_get_ref(this, annotations, annotations);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
-
- LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
- }
-
- return declaredAnnotations;
-}
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: getParameterAnnotations
- * Signature: ()[[Ljava/lang/annotation/Annotation;
- *
- * Parses the parameter annotations and returns them in an 2 dimensional array.
- */
-JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_Method_getParameterAnnotations(JNIEnv *env, java_lang_reflect_Method *this)
-{
- java_handle_bytearray_t *parameterAnnotations = NULL; /* unparsed parameter annotations */
- int32_t slot = -1; /* slot of the method */
- java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
- classinfo *referer = NULL; /* class, which calles the annotation parser */
- /* (for the parameter 'referer' of vm_call_method()) */
-
- LLNI_field_get_ref(this, parameterAnnotations, parameterAnnotations);
- LLNI_field_get_val(this, slot, slot);
- LLNI_field_get_ref(this, clazz, declaringClass);
- LLNI_class_get(this, referer);
-
- return reflect_get_parameterannotations((java_handle_t*)parameterAnnotations, slot, declaringClass, referer);
-}
-#endif
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
--- /dev/null
+/* src/native/vm/gnu/java_lang_reflect_VMConstructor.c
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#if defined(ENABLE_ANNOTATIONS)
+#include "vm/vm.h"
+#include "vm/exceptions.h"
+#endif
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "native/include/java_lang_Class.h"
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_String.h"
+
+#if defined(ENABLE_ANNOTATIONS)
+# include "native/include/java_util_Map.h"
+# include "native/include/sun_reflect_ConstantPool.h"
+#endif
+
+#include "native/include/java_lang_reflect_Constructor.h"
+#include "native/include/java_lang_reflect_VMConstructor.h"
+
+#include "native/vm/reflect.h"
+
+#include "vm/stringlocal.h"
+
+#include "vmcore/utf8.h"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { "getModifiersInternal", "()I", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getModifiersInternal },
+ { "getParameterTypes", "()[Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getParameterTypes },
+ { "getExceptionTypes", "()[Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getExceptionTypes },
+ { "construct", "([Ljava/lang/Object;)Ljava/lang/Object;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_construct },
+ { "getSignature", "()Ljava/lang/String;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getSignature },
+#if defined(ENABLE_ANNOTATIONS)
+ { "declaredAnnotations", "()Ljava/util/Map;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_declaredAnnotations },
+ { "getParameterAnnotations", "()[[Ljava/lang/annotation/Annotation;", (void *) (intptr_t) &Java_java_lang_reflect_VMConstructor_getParameterAnnotations },
+#endif
+};
+
+
+/* _Jv_java_lang_reflect_VMConstructor_init ************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+void _Jv_java_lang_reflect_VMConstructor_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/reflect/VMConstructor");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMConstructor_getModifiersInternal(JNIEnv *env, java_lang_reflect_VMConstructor *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot, slot);
+
+ m = &(c->methods[slot]);
+
+ return m->flags;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getParameterTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMConstructor_getParameterTypes(JNIEnv *env, java_lang_reflect_VMConstructor *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot, slot);
+
+ m = &(c->methods[slot]);
+
+ return method_get_parametertypearray(m);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getExceptionTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMConstructor_getExceptionTypes(JNIEnv *env, java_lang_reflect_VMConstructor *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot, slot);
+
+ m = &(c->methods[slot]);
+
+ return method_get_exceptionarray(m);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: construct
+ * Signature: ([Ljava/lang/Object;Ljava/lang/Class;I)Ljava/lang/Object;
+ */
+JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_VMConstructor_construct(JNIEnv *env, java_lang_reflect_VMConstructor *this, java_handle_objectarray_t *args)
+{
+ classinfo *c;
+ int32_t slot;
+ java_lang_reflect_Constructor *rc;
+ int32_t override;
+ methodinfo *m;
+ java_handle_t *o;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot, slot);
+
+ LLNI_field_get_ref(this, cons, rc);
+ LLNI_field_get_val(rc, flag, override);
+
+ m = &(c->methods[slot]);
+
+ o = reflect_constructor_newinstance(m, args, override);
+
+ return (java_lang_Object *) o;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_VMConstructor_getSignature(JNIEnv *env, java_lang_reflect_VMConstructor *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ java_handle_t *o;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot, slot);
+
+ m = &(c->methods[slot]);
+
+ if (m->signature == NULL)
+ return NULL;
+
+ o = javastring_new(m->signature);
+
+ /* In error case o is NULL. */
+
+ return (java_lang_String *) o;
+}
+
+
+#if defined(ENABLE_ANNOTATIONS)
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: declaredAnnotations
+ * Signature: ()Ljava/util/Map;
+ *
+ * Parses the annotations (if they aren't parsed yet) and stores them into
+ * the declaredAnnotations map and return this map.
+ */
+JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_VMConstructor_declaredAnnotations(JNIEnv *env, java_lang_reflect_VMConstructor *this)
+{
+ java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
+ java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
+ java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
+ classinfo *referer = NULL; /* class, which calles the annotation parser */
+ /* (for the parameter 'referer' of vm_call_method()) */
+
+ LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
+
+ /* are the annotations parsed yet? */
+ if (declaredAnnotations == NULL) {
+ LLNI_field_get_ref(this, annotations, annotations);
+ LLNI_field_get_ref(this, clazz, declaringClass);
+ LLNI_class_get(this, referer);
+
+ declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
+
+ LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
+ }
+
+ return declaredAnnotations;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMConstructor
+ * Method: getParameterAnnotations
+ * Signature: ()[[Ljava/lang/annotation/Annotation;
+ *
+ * Parses the parameter annotations and returns them in an 2 dimensional array.
+ */
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMConstructor_getParameterAnnotations(JNIEnv *env, java_lang_reflect_VMConstructor *this)
+{
+ java_handle_bytearray_t *parameterAnnotations = NULL; /* unparsed parameter annotations */
+ int32_t slot = -1; /* slot of the method */
+ java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
+ classinfo *referer = NULL; /* class, which calles the annotation parser */
+ /* (for the parameter 'referer' of vm_call_method()) */
+
+ LLNI_field_get_ref(this, parameterAnnotations, parameterAnnotations);
+ LLNI_field_get_val(this, slot, slot);
+ LLNI_field_get_ref(this, clazz, declaringClass);
+ LLNI_class_get(this, referer);
+
+ return reflect_get_parameterannotations((java_handle_t*)parameterAnnotations, slot, declaringClass, referer);
+}
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/native/vm/gnu/java_lang_reflect_VMField.c
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "native/include/java_lang_Boolean.h"
+#include "native/include/java_lang_Byte.h"
+#include "native/include/java_lang_Character.h"
+#include "native/include/java_lang_Short.h"
+#include "native/include/java_lang_Integer.h"
+#include "native/include/java_lang_Long.h"
+#include "native/include/java_lang_Float.h"
+#include "native/include/java_lang_Double.h"
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_Class.h"
+#include "native/include/java_lang_String.h"
+
+#include "native/include/java_lang_reflect_Field.h"
+#include "native/include/java_lang_reflect_VMField.h"
+
+#if defined(ENABLE_ANNOTATIONS)
+#include "native/include/java_util_Map.h"
+#include "native/include/sun_reflect_ConstantPool.h"
+#include "native/vm/reflect.h"
+#endif
+
+#include "vm/access.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/initialize.h"
+#include "vm/primitive.h"
+#include "vm/resolve.h"
+#include "vm/stringlocal.h"
+
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/loader.h"
+#include "vmcore/utf8.h"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { "getModifiersInternal", "()I", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getModifiersInternal },
+ { "getType", "()Ljava/lang/Class;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getType },
+ { "get", "(Ljava/lang/Object;)Ljava/lang/Object;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_get },
+ { "getBoolean", "(Ljava/lang/Object;)Z", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getBoolean },
+ { "getByte", "(Ljava/lang/Object;)B", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getByte },
+ { "getChar", "(Ljava/lang/Object;)C", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getChar },
+ { "getShort", "(Ljava/lang/Object;)S", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getShort },
+ { "getInt", "(Ljava/lang/Object;)I", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getInt },
+ { "getLong", "(Ljava/lang/Object;)J", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getLong },
+ { "getFloat", "(Ljava/lang/Object;)F", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getFloat },
+ { "getDouble", "(Ljava/lang/Object;)D", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getDouble },
+ { "set", "(Ljava/lang/Object;Ljava/lang/Object;)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_set },
+ { "setBoolean", "(Ljava/lang/Object;Z)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setBoolean },
+ { "setByte", "(Ljava/lang/Object;B)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setByte },
+ { "setChar", "(Ljava/lang/Object;C)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setChar },
+ { "setShort", "(Ljava/lang/Object;S)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setShort },
+ { "setInt", "(Ljava/lang/Object;I)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setInt },
+ { "setLong", "(Ljava/lang/Object;J)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setLong },
+ { "setFloat", "(Ljava/lang/Object;F)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setFloat },
+ { "setDouble", "(Ljava/lang/Object;D)V", (void *) (intptr_t) &Java_java_lang_reflect_VMField_setDouble },
+ { "getSignature", "()Ljava/lang/String;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_getSignature },
+#if defined(ENABLE_ANNOTATIONS)
+ { "declaredAnnotations", "()Ljava/util/Map;", (void *) (intptr_t) &Java_java_lang_reflect_VMField_declaredAnnotations },
+#endif
+};
+
+
+/* _Jv_java_lang_reflect_VMField_init ******************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+void _Jv_java_lang_reflect_VMField_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/reflect/VMField");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+
+
+/* _field_access_check *********************************************************
+
+ Checks if the field can be accessed.
+
+ RETURN VALUE:
+ true......field can be accessed, or
+ false.....otherwise (maybe an Exception was thrown).
+
+*******************************************************************************/
+
+static bool _field_access_check(java_lang_reflect_VMField *this,
+ fieldinfo *f, classinfo *c, java_handle_t *o)
+{
+ java_lang_reflect_Field *rf;
+ int32_t flag;
+
+ /* check if we should bypass security checks (AccessibleObject) */
+
+ LLNI_field_get_ref(this, f, rf);
+ LLNI_field_get_val(rf, flag, flag);
+
+ if (flag == false) {
+ /* This function is always called like this:
+ [0] java.lang.reflect.VMField.xxx (Native Method)
+ [1] java.lang.reflect.Field.xxx
+ [2] <caller>
+ */
+
+ if (!access_check_field(f, 2))
+ return false;
+ }
+
+ /* some general checks */
+
+ if (f->flags & ACC_STATIC) {
+ /* initialize class if required */
+
+ if (!(c->state & CLASS_INITIALIZED))
+ if (!initialize_class(c))
+ return false;
+
+ /* everything is ok */
+
+ return true;
+ }
+ else {
+ /* obj is required for not-static fields */
+
+ if (o == NULL) {
+ exceptions_throw_nullpointerexception();
+ return false;
+ }
+
+ if (builtin_instanceof(o, c))
+ return true;
+ }
+
+ /* exception path */
+
+ exceptions_throw_illegalargumentexception();
+ return false;
+}
+
+
+/* _field_get_type *************************************************************
+
+ Returns the content of the given field.
+
+*******************************************************************************/
+
+#define _FIELD_GET_TYPE(name, type, uniontype) \
+static inline type _field_get_##name(fieldinfo *f, java_lang_Object *o) \
+{ \
+ type ret; \
+ if (f->flags & ACC_STATIC) { \
+ ret = f->value->uniontype; \
+ } else { \
+ LLNI_CRITICAL_START; \
+ ret = *(type *) (((intptr_t) LLNI_DIRECT(o)) + f->offset); \
+ LLNI_CRITICAL_END; \
+ } \
+ return ret; \
+}
+
+static inline java_handle_t *_field_get_handle(fieldinfo *f, java_lang_Object *o)
+{
+ java_object_t *obj;
+ java_handle_t *hdl;
+
+ LLNI_CRITICAL_START;
+
+ if (f->flags & ACC_STATIC) {
+ obj = f->value->a;
+ } else {
+ obj = *(java_object_t **) (((intptr_t) LLNI_DIRECT(o)) + f->offset);
+ }
+
+ hdl = LLNI_WRAP(obj);
+
+ LLNI_CRITICAL_END;
+
+ return hdl;
+}
+
+_FIELD_GET_TYPE(int, int32_t, i)
+_FIELD_GET_TYPE(long, int64_t, l)
+_FIELD_GET_TYPE(float, float, f)
+_FIELD_GET_TYPE(double, double, d)
+
+
+/* _field_set_type *************************************************************
+
+ Sets the content of the given field to the given value.
+
+*******************************************************************************/
+
+#define _FIELD_SET_TYPE(name, type, uniontype) \
+static inline void _field_set_##name(fieldinfo *f, java_lang_Object *o, type value) \
+{ \
+ if (f->flags & ACC_STATIC) { \
+ f->value->uniontype = value; \
+ } else { \
+ LLNI_CRITICAL_START; \
+ *(type *) (((intptr_t) LLNI_DIRECT(o)) + f->offset) = value; \
+ LLNI_CRITICAL_END; \
+ } \
+}
+
+static inline void _field_set_handle(fieldinfo *f, java_lang_Object *o, java_handle_t *value)
+{
+ LLNI_CRITICAL_START;
+
+ if (f->flags & ACC_STATIC) {
+ f->value->a = LLNI_DIRECT(value);
+ } else {
+ *(java_object_t **) (((intptr_t) LLNI_DIRECT(o)) + f->offset) = LLNI_DIRECT(value);
+ }
+
+ LLNI_CRITICAL_END;
+}
+
+_FIELD_SET_TYPE(int, int32_t, i)
+_FIELD_SET_TYPE(long, int64_t, l)
+_FIELD_SET_TYPE(float, float, f)
+_FIELD_SET_TYPE(double, double, d)
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getModifiersInternal(JNIEnv *env, java_lang_reflect_VMField *this)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &(c->fields[slot]);
+
+ return f->flags;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getType
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_reflect_VMField_getType(JNIEnv *env, java_lang_reflect_VMField *this)
+{
+ classinfo *c;
+ typedesc *desc;
+ classinfo *ret;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ desc = c->fields[slot].parseddesc;
+
+ if (desc == NULL)
+ return NULL;
+
+ if (!resolve_class_from_typedesc(desc, true, false, &ret))
+ return NULL;
+
+ return LLNI_classinfo_wrap(ret);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: get
+ * Signature: (Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_VMField_get(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+ imm_union value;
+ java_handle_t *object;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return NULL;
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ value.i = _field_get_int(f, o);
+ break;
+
+ case PRIMITIVETYPE_LONG:
+ value.l = _field_get_long(f, o);
+ break;
+
+ case PRIMITIVETYPE_FLOAT:
+ value.f = _field_get_float(f, o);
+ break;
+
+ case PRIMITIVETYPE_DOUBLE:
+ value.d = _field_get_double(f, o);
+ break;
+
+ case TYPE_ADR:
+ return (java_lang_Object *) _field_get_handle(f, o);
+ }
+
+ /* Now box the primitive types. */
+
+ object = primitive_box(f->parseddesc->decltype, value);
+
+ return (java_lang_Object *) object;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getBoolean
+ * Signature: (Ljava/lang/Object;)Z
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getBoolean(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ return (int32_t) _field_get_int(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getByte
+ * Signature: (Ljava/lang/Object;)B
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getByte(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ return (int32_t) _field_get_int(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getChar
+ * Signature: (Ljava/lang/Object;)C
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getChar(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_CHAR:
+ return (int32_t) _field_get_int(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getShort
+ * Signature: (Ljava/lang/Object;)S
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getShort(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ return (int32_t) _field_get_int(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getInt
+ * Signature: (Ljava/lang/Object;)I
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMField_getInt(JNIEnv *env , java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (int32_t) _field_get_int(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getLong
+ * Signature: (Ljava/lang/Object;)J
+ */
+JNIEXPORT int64_t JNICALL Java_java_lang_reflect_VMField_getLong(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (int64_t) _field_get_int(f, o);
+ case PRIMITIVETYPE_LONG:
+ return (int64_t) _field_get_long(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getFloat
+ * Signature: (Ljava/lang/Object;)F
+ */
+JNIEXPORT float JNICALL Java_java_lang_reflect_VMField_getFloat(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (float) _field_get_int(f, o);
+ case PRIMITIVETYPE_LONG:
+ return (float) _field_get_long(f, o);
+ case PRIMITIVETYPE_FLOAT:
+ return (float) _field_get_float(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getDouble
+ * Signature: (Ljava/lang/Object;)D
+ */
+JNIEXPORT double JNICALL Java_java_lang_reflect_VMField_getDouble(JNIEnv *env , java_lang_reflect_VMField *this, java_lang_Object *o)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return 0;
+
+ /* check the field type and return the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ return (double) _field_get_int(f, o);
+ case PRIMITIVETYPE_LONG:
+ return (double) _field_get_long(f, o);
+ case PRIMITIVETYPE_FLOAT:
+ return (double) _field_get_float(f, o);
+ case PRIMITIVETYPE_DOUBLE:
+ return (double) _field_get_double(f, o);
+ default:
+ exceptions_throw_illegalargumentexception();
+ return 0;
+ }
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: set
+ * Signature: (Ljava/lang/Object;Ljava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_set(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, java_lang_Object *value)
+{
+ classinfo *sc;
+ classinfo *dc;
+ fieldinfo *sf;
+ fieldinfo *df;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, dc);
+ LLNI_field_get_val(this, slot , slot);
+ df = &dc->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, df, dc, (java_handle_t *) o))
+ return;
+
+ /* get the source classinfo from the object */
+
+ if (value == NULL)
+ sc = NULL;
+ else
+ LLNI_class_get(value, sc);
+
+ /* The fieldid is used to set the new value, for primitive
+ types the value has to be retrieved from the wrapping
+ object */
+
+ switch (df->parseddesc->decltype) {
+ case PRIMITIVETYPE_BOOLEAN: {
+ int32_t val;
+
+ /* determine the field to read the value */
+
+ if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_Z)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ LLNI_field_get_val((java_lang_Boolean *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, o, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_BYTE: {
+ int32_t val;
+
+ if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_B)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ LLNI_field_get_val((java_lang_Byte *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, o, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_CHAR: {
+ int32_t val;
+
+ if ((sc == NULL) || !(sf = class_findfield(sc, utf_value, utf_C)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_CHAR:
+ LLNI_field_get_val((java_lang_Character *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, o, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_SHORT: {
+ int32_t val;
+
+ /* get field only by name, it can be one of B, S */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ LLNI_field_get_val((java_lang_Byte *) value, value, val);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ LLNI_field_get_val((java_lang_Short *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, o, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_INT: {
+ int32_t val;
+
+ /* get field only by name, it can be one of B, S, C, I */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ LLNI_field_get_val((java_lang_Byte *) value, value, val);
+ break;
+ case PRIMITIVETYPE_CHAR:
+ LLNI_field_get_val((java_lang_Character *) value, value, val);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ LLNI_field_get_val((java_lang_Short *) value, value, val);
+ break;
+ case PRIMITIVETYPE_INT:
+ LLNI_field_get_val((java_lang_Integer *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_int(df, o, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_LONG: {
+ int64_t val;
+
+ /* get field only by name, it can be one of B, S, C, I, J */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ LLNI_field_get_val((java_lang_Byte *) value, value, val);
+ break;
+ case PRIMITIVETYPE_CHAR:
+ LLNI_field_get_val((java_lang_Character *) value, value, val);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ LLNI_field_get_val((java_lang_Short *) value, value, val);
+ break;
+ case PRIMITIVETYPE_INT:
+ LLNI_field_get_val((java_lang_Integer *) value, value, val);
+ break;
+ case PRIMITIVETYPE_LONG:
+ LLNI_field_get_val((java_lang_Long *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_long(df, o, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_FLOAT: {
+ float val;
+
+ /* get field only by name, it can be one of B, S, C, I, J, F */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ LLNI_field_get_val((java_lang_Byte *) value, value, val);
+ break;
+ case PRIMITIVETYPE_CHAR:
+ LLNI_field_get_val((java_lang_Character *) value, value, val);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ LLNI_field_get_val((java_lang_Short *) value, value, val);
+ break;
+ case PRIMITIVETYPE_INT:
+ LLNI_field_get_val((java_lang_Integer *) value, value, val);
+ break;
+ case PRIMITIVETYPE_LONG:
+ LLNI_field_get_val((java_lang_Long *) value, value, val);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ LLNI_field_get_val((java_lang_Float *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_float(df, o, val);
+ return;
+ }
+
+ case PRIMITIVETYPE_DOUBLE: {
+ double val;
+
+ /* get field only by name, it can be one of B, S, C, I, J, F, D */
+
+ if ((sc == NULL) || !(sf = class_findfield_by_name(sc, utf_value)))
+ break;
+
+ switch (sf->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ LLNI_field_get_val((java_lang_Byte *) value, value, val);
+ break;
+ case PRIMITIVETYPE_CHAR:
+ LLNI_field_get_val((java_lang_Character *) value, value, val);
+ break;
+ case PRIMITIVETYPE_SHORT:
+ LLNI_field_get_val((java_lang_Short *) value, value, val);
+ break;
+ case PRIMITIVETYPE_INT:
+ LLNI_field_get_val((java_lang_Integer *) value, value, val);
+ break;
+ case PRIMITIVETYPE_LONG:
+ LLNI_field_get_val((java_lang_Long *) value, value, val);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ LLNI_field_get_val((java_lang_Float *) value, value, val);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ LLNI_field_get_val((java_lang_Double *) value, value, val);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ _field_set_double(df, o, val);
+ return;
+ }
+
+ case TYPE_ADR:
+ /* check if value is an instance of the destination class */
+
+ /* XXX TODO */
+ /* if (!builtin_instanceof((java_handle_t *) value, df->class)) */
+ /* break; */
+
+ _field_set_handle(df, o, (java_handle_t *) value);
+ return;
+ }
+
+ /* raise exception */
+
+ exceptions_throw_illegalargumentexception();
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setBoolean
+ * Signature: (Ljava/lang/Object;Z)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setBoolean(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BOOLEAN:
+ _field_set_int(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setByte
+ * Signature: (Ljava/lang/Object;B)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setByte(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_BYTE:
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, o, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, o, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, o, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setChar
+ * Signature: (Ljava/lang/Object;C)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setChar(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_CHAR:
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, o, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, o, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, o, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setShort
+ * Signature: (Ljava/lang/Object;S)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setShort(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_SHORT:
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, o, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, o, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, o, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setInt
+ * Signature: (Ljava/lang/Object;I)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setInt(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int32_t value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_INT:
+ _field_set_int(f, o, value);
+ break;
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, o, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, o, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setLong
+ * Signature: (Ljava/lang/Object;J)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setLong(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, int64_t value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_LONG:
+ _field_set_long(f, o, value);
+ break;
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, o, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setFloat
+ * Signature: (Ljava/lang/Object;F)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setFloat(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, float value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_FLOAT:
+ _field_set_float(f, o, value);
+ break;
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: setDouble
+ * Signature: (Ljava/lang/Object;D)V
+ */
+JNIEXPORT void JNICALL Java_java_lang_reflect_VMField_setDouble(JNIEnv *env, java_lang_reflect_VMField *this, java_lang_Object *o, double value)
+{
+ classinfo *c;
+ fieldinfo *f;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ /* check if the field can be accessed */
+
+ if (!_field_access_check(this, f, c, (java_handle_t *) o))
+ return;
+
+ /* check the field type and set the value */
+
+ switch (f->parseddesc->decltype) {
+ case PRIMITIVETYPE_DOUBLE:
+ _field_set_double(f, o, value);
+ break;
+ default:
+ exceptions_throw_illegalargumentexception();
+ }
+
+ return;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_VMField_getSignature(JNIEnv *env, java_lang_reflect_VMField* this)
+{
+ classinfo *c;
+ fieldinfo *f;
+ java_handle_t *o;
+ int32_t slot;
+
+ /* get the class and the field */
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ f = &c->fields[slot];
+
+ if (f->signature == NULL)
+ return NULL;
+
+ o = javastring_new(f->signature);
+
+ /* in error case o is NULL */
+
+ return (java_lang_String *) o;
+}
+
+
+#if defined(ENABLE_ANNOTATIONS)
+/*
+ * Class: java/lang/reflect/VMField
+ * Method: declaredAnnotations
+ * Signature: ()Ljava/util/Map;
+ */
+JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_VMField_declaredAnnotations(JNIEnv *env, java_lang_reflect_VMField *this)
+{
+ java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
+ java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
+ java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
+ classinfo *referer = NULL; /* class, which calles the annotation parser */
+ /* (for the parameter 'referer' of vm_call_method()) */
+
+ LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
+
+ /* are the annotations parsed yet? */
+ if (declaredAnnotations == NULL) {
+ LLNI_field_get_ref(this, annotations, annotations);
+ LLNI_field_get_ref(this, clazz, declaringClass);
+ LLNI_class_get(this, referer);
+
+ declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
+
+ LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
+ }
+
+ return declaredAnnotations;
+}
+#endif
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/native/vm/gnu/java_lang_reflect_VMMethod.c
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#if defined(ENABLE_ANNOTATIONS)
+#include "vm/vm.h"
+#endif
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_Class.h"
+#include "native/include/java_lang_String.h"
+
+#if defined(ENABLE_ANNOTATIONS)
+# include "native/include/java_util_Map.h"
+# include "native/include/sun_reflect_ConstantPool.h"
+#endif
+
+#include "native/include/java_lang_reflect_Method.h"
+#include "native/include/java_lang_reflect_VMMethod.h"
+
+#include "native/vm/reflect.h"
+
+#include "vm/access.h"
+#include "vm/global.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/initialize.h"
+#include "vm/resolve.h"
+#include "vm/stringlocal.h"
+
+#include "vmcore/method.h"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+ { "getModifiersInternal", "()I", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getModifiersInternal },
+ { "getReturnType", "()Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getReturnType },
+ { "getParameterTypes", "()[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getParameterTypes },
+ { "getExceptionTypes", "()[Ljava/lang/Class;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getExceptionTypes },
+ { "invoke", "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_invoke },
+ { "getSignature", "()Ljava/lang/String;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getSignature },
+#if defined(ENABLE_ANNOTATIONS)
+ { "getDefaultValue", "()Ljava/lang/Object;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getDefaultValue },
+ { "declaredAnnotations", "()Ljava/util/Map;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_declaredAnnotations },
+ { "getParameterAnnotations", "()[[Ljava/lang/annotation/Annotation;", (void *) (uintptr_t) &Java_java_lang_reflect_VMMethod_getParameterAnnotations },
+#endif
+};
+
+
+/* _Jv_java_lang_reflect_VMMethod_init *******************************************
+
+ Register native functions.
+
+*******************************************************************************/
+
+void _Jv_java_lang_reflect_VMMethod_init(void)
+{
+ utf *u;
+
+ u = utf_new_char("java/lang/reflect/VMMethod");
+
+ native_method_register(u, methods, NATIVE_METHODS_COUNT);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getModifiersInternal
+ * Signature: ()I
+ */
+JNIEXPORT int32_t JNICALL Java_java_lang_reflect_VMMethod_getModifiersInternal(JNIEnv *env, java_lang_reflect_VMMethod *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ m = &(c->methods[slot]);
+
+ return m->flags;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getReturnType
+ * Signature: ()Ljava/lang/Class;
+ */
+JNIEXPORT java_lang_Class* JNICALL Java_java_lang_reflect_VMMethod_getReturnType(JNIEnv *env, java_lang_reflect_VMMethod *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ classinfo *result;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ m = &(c->methods[slot]);
+
+ result = method_returntype_get(m);
+
+ return LLNI_classinfo_wrap(result);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getParameterTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMMethod_getParameterTypes(JNIEnv *env, java_lang_reflect_VMMethod *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ m = &(c->methods[slot]);
+
+ return method_get_parametertypearray(m);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getExceptionTypes
+ * Signature: ()[Ljava/lang/Class;
+ */
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMMethod_getExceptionTypes(JNIEnv *env, java_lang_reflect_VMMethod *this)
+{
+ classinfo *c;
+ methodinfo *m;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ m = &(c->methods[slot]);
+
+ return method_get_exceptionarray(m);
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: invoke
+ * Signature: (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
+ */
+JNIEXPORT java_lang_Object* JNICALL Java_java_lang_reflect_VMMethod_invoke(JNIEnv *env, java_lang_reflect_VMMethod *this, java_lang_Object *o, java_handle_objectarray_t *args)
+{
+ classinfo *c;
+ int32_t slot;
+ java_lang_reflect_Method *rm;
+ int32_t override;
+ methodinfo *m;
+ java_handle_t *ro;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot, slot);
+
+ LLNI_field_get_ref(this, m, rm);
+ LLNI_field_get_val(rm, flag, override);
+
+ m = &(c->methods[slot]);
+
+ ro = reflect_method_invoke(m, (java_handle_t *) o, args, override);
+
+ return (java_lang_Object *) ro;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getSignature
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT java_lang_String* JNICALL Java_java_lang_reflect_VMMethod_getSignature(JNIEnv *env, java_lang_reflect_VMMethod* this)
+{
+ classinfo *c;
+ methodinfo *m;
+ java_handle_t *o;
+ int32_t slot;
+
+ LLNI_field_get_cls(this, clazz, c);
+ LLNI_field_get_val(this, slot , slot);
+ m = &(c->methods[slot]);
+
+ if (m->signature == NULL)
+ return NULL;
+
+ o = javastring_new(m->signature);
+
+ /* in error case o is NULL */
+
+ return (java_lang_String *) o;
+}
+
+#if defined(ENABLE_ANNOTATIONS)
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getDefaultValue
+ * Signature: ()Ljava/lang/Object;
+ *
+ * Parses the annotation default value and returnes it (boxed, if it's a primitive).
+ */
+JNIEXPORT struct java_lang_Object* JNICALL Java_java_lang_reflect_VMMethod_getDefaultValue(JNIEnv *env, struct java_lang_reflect_VMMethod* this)
+{
+ java_handle_bytearray_t *annotationDefault = NULL; /* unparsed annotation default value */
+ static methodinfo *m_parseAnnotationDefault = NULL; /* parser method (will be chached, therefore static) */
+ utf *utf_parseAnnotationDefault = NULL; /* parser method name */
+ utf *utf_desc = NULL; /* parser method descriptor (signature) */
+ sun_reflect_ConstantPool *constantPool = NULL; /* constant pool object to use */
+ java_lang_Class *constantPoolOop = NULL; /* methods declaring class */
+ classinfo *referer = NULL; /* class, which calles the annotation parser */
+ /* (for the parameter 'referer' of vm_call_method()) */
+ java_lang_reflect_Method* rm;
+ java_handle_t* h;
+
+ if (this == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ constantPool =
+ (sun_reflect_ConstantPool*)native_new_and_init(
+ class_sun_reflect_ConstantPool);
+
+ if (constantPool == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+
+ LLNI_field_get_ref(this, clazz, constantPoolOop);
+ LLNI_field_set_ref(constantPool, constantPoolOop, (java_lang_Object*)constantPoolOop);
+
+ /* only resolve the parser method the first time */
+ if (m_parseAnnotationDefault == NULL) {
+ utf_parseAnnotationDefault = utf_new_char("parseAnnotationDefault");
+ utf_desc = utf_new_char(
+ "(Ljava/lang/reflect/Method;[BLsun/reflect/ConstantPool;)"
+ "Ljava/lang/Object;");
+
+ if (utf_parseAnnotationDefault == NULL || utf_desc == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+
+ LLNI_class_get(this, referer);
+
+ m_parseAnnotationDefault = class_resolveclassmethod(
+ class_sun_reflect_annotation_AnnotationParser,
+ utf_parseAnnotationDefault,
+ utf_desc,
+ referer,
+ true);
+
+ if (m_parseAnnotationDefault == NULL) {
+ /* method not found */
+ return NULL;
+ }
+ }
+
+ LLNI_field_get_ref(this, m, rm);
+ LLNI_field_get_ref(this, annotationDefault, annotationDefault);
+
+ h = vm_call_method(m_parseAnnotationDefault, NULL, rm, annotationDefault, constantPool);
+
+ return (java_lang_Object*) h;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: declaredAnnotations
+ * Signature: ()Ljava/util/Map;
+ *
+ * Parses the annotations (if they aren't parsed yet) and stores them into
+ * the declaredAnnotations map and return this map.
+ */
+JNIEXPORT struct java_util_Map* JNICALL Java_java_lang_reflect_VMMethod_declaredAnnotations(JNIEnv *env, java_lang_reflect_VMMethod *this)
+{
+ java_util_Map *declaredAnnotations = NULL; /* parsed annotations */
+ java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
+ java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
+ classinfo *referer = NULL; /* class, which calles the annotation parser */
+ /* (for the parameter 'referer' of vm_call_method()) */
+
+ LLNI_field_get_ref(this, declaredAnnotations, declaredAnnotations);
+
+ /* are the annotations parsed yet? */
+ if (declaredAnnotations == NULL) {
+ LLNI_field_get_ref(this, annotations, annotations);
+ LLNI_field_get_ref(this, clazz, declaringClass);
+ LLNI_class_get(this, referer);
+
+ declaredAnnotations = reflect_get_declaredannotatios(annotations, declaringClass, referer);
+
+ LLNI_field_set_ref(this, declaredAnnotations, declaredAnnotations);
+ }
+
+ return declaredAnnotations;
+}
+
+
+/*
+ * Class: java/lang/reflect/VMMethod
+ * Method: getParameterAnnotations
+ * Signature: ()[[Ljava/lang/annotation/Annotation;
+ *
+ * Parses the parameter annotations and returns them in an 2 dimensional array.
+ */
+JNIEXPORT java_handle_objectarray_t* JNICALL Java_java_lang_reflect_VMMethod_getParameterAnnotations(JNIEnv *env, java_lang_reflect_VMMethod *this)
+{
+ java_handle_bytearray_t *parameterAnnotations = NULL; /* unparsed parameter annotations */
+ int32_t slot = -1; /* slot of the method */
+ java_lang_Class *declaringClass = NULL; /* the constant pool of this class is used */
+ classinfo *referer = NULL; /* class, which calles the annotation parser */
+ /* (for the parameter 'referer' of vm_call_method()) */
+
+ LLNI_field_get_ref(this, parameterAnnotations, parameterAnnotations);
+ LLNI_field_get_val(this, slot, slot);
+ LLNI_field_get_ref(this, clazz, declaringClass);
+ LLNI_class_get(this, referer);
+
+ return reflect_get_parameterannotations((java_handle_t*)parameterAnnotations, slot, declaringClass, referer);
+}
+#endif
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+++ /dev/null
-/* src/native/vm/java_lang_Class.c - java/lang/Class
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-/* keep this order of the native includes */
-
-#include "native/include/java_lang_String.h"
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_CLASSPATH_SUN)
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-# endif
-# include "native/include/java_lang_ClassLoader.h"
-#endif
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_Class.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_reflect_Constructor.h"
-# include "native/include/java_lang_reflect_Field.h"
-# include "native/include/java_lang_reflect_Method.h"
-#endif
-
-#include "native/vm/java_lang_Class.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/vm/reflect.h"
-#endif
-
-#include "toolbox/logging.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-#include "vm/primitive.h"
-#include "vm/resolve.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-
-#if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
-#include "native/include/sun_reflect_ConstantPool.h"
-
-#include "vm/vm.h"
-
-#include "vmcore/annotation.h"
-#endif
-
-/*
- * Class: java/lang/Class
- * Method: getName
- * Signature: ()Ljava/lang/String;
- */
-java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass)
-{
- classinfo *c;
- java_lang_String *s;
- java_handle_chararray_t *ca;
- u4 i;
-
- c = LLNI_classinfo_unwrap(klass);
-
- /* create a java string */
-
- s = (java_lang_String *) javastring_new(c->name);
-
- if (s == NULL)
- return NULL;
-
- /* return string where '/' is replaced by '.' */
-
- LLNI_field_get_ref(s, value, ca);
-
- for (i = 0; i < LLNI_array_size(ca); i++) {
- if (LLNI_array_direct(ca, i) == '/')
- LLNI_array_direct(ca, i) = '.';
- }
-
- return s;
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: forName
- * Signature: (Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;
- */
-#if defined(ENABLE_JAVASE)
-java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader)
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name)
-#endif
-{
-#if defined(ENABLE_JAVASE)
- classloader *cl;
-#endif
- utf *ufile;
- utf *uname;
- classinfo *c;
- u2 *pos;
- s4 i;
-
-#if defined(ENABLE_JAVASE)
- cl = loader_hashtable_classloader_add((java_handle_t *) loader);
-#endif
-
- /* illegal argument */
-
- if (name == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* create utf string in which '.' is replaced by '/' */
-
- ufile = javastring_toutf((java_handle_t *) name, true);
- uname = javastring_toutf((java_handle_t *) name, false);
-
- /* name must not contain '/' (mauve test) */
-
- for (i = 0, pos = LLNI_field_direct(name, value)->data + LLNI_field_direct(name, offset); i < LLNI_field_direct(name, count); i++, pos++) {
- if (*pos == '/') {
- exceptions_throw_classnotfoundexception(uname);
- return NULL;
- }
- }
-
- /* try to load, ... */
-
-#if defined(ENABLE_JAVASE)
- c = load_class_from_classloader(ufile, cl);
-#elif defined(ENABLE_JAVAME_CLDC1_1)
- c = load_class_bootstrap(ufile);
-#endif
-
- if (c == NULL)
- return NULL;
-
- /* link, ... */
-
- if (!link_class(c))
- return NULL;
-
- /* ...and initialize it, if required */
-
-#if defined(ENABLE_JAVASE)
- if (initialize)
-#endif
- if (!initialize_class(c))
- return NULL;
-
- return LLNI_classinfo_wrap(c);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: isInstance
- * Signature: (Ljava/lang/Object;)Z
- */
-s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o)
-{
- classinfo *c;
- java_handle_t *ob;
-
- c = LLNI_classinfo_unwrap(klass);
- ob = (java_handle_t *) o;
-
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- return 0;
-
- return builtin_instanceof(ob, c);
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: isAssignableFrom
- * Signature: (Ljava/lang/Class;)Z
- */
-s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c)
-{
- classinfo *kc;
- classinfo *cc;
-
- kc = LLNI_classinfo_unwrap(klass);
- cc = LLNI_classinfo_unwrap(c);
-
- if (cc == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- if (!(kc->state & CLASS_LINKED))
- if (!link_class(kc))
- return 0;
-
- if (!(cc->state & CLASS_LINKED))
- if (!link_class(cc))
- return 0;
-
- return class_isanysubclass(cc, kc);
-}
-
-
-#if defined(ENABLE_JAVASE)
-
-/*
- * Class: java/lang/Class
- * Method: getDeclaredFields
- * Signature: (Z)[Ljava/lang/reflect/Field;
- */
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly)
-{
- classinfo *c;
- java_handle_objectarray_t *oa; /* result: array of field-objects */
- fieldinfo *f;
- java_lang_reflect_Field *rf;
- s4 public_fields; /* number of elements in field-array */
- s4 pos;
- s4 i;
-
- c = LLNI_classinfo_unwrap(klass);
-
- /* determine number of fields */
-
- for (i = 0, public_fields = 0; i < c->fieldscount; i++)
- if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
- public_fields++;
-
- /* create array of fields */
-
- oa = builtin_anewarray(public_fields, class_java_lang_reflect_Field);
-
- if (oa == NULL)
- return NULL;
-
- /* get the fields and store in the array */
-
- for (i = 0, pos = 0; i < c->fieldscount; i++) {
- f = &(c->fields[i]);
-
- if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
- /* create Field object */
-
- rf = reflect_field_new(f);
-
- /* store object into array */
-
- array_objectarray_element_set(oa, pos, (java_handle_t *) rf);
- pos++;
- }
- }
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: getDeclaredMethods
- * Signature: (Z)[Ljava/lang/reflect/Method;
- */
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly)
-{
- classinfo *c;
- java_lang_reflect_Method *rm;
- java_handle_objectarray_t *oa; /* result: array of Method-objects */
- methodinfo *m; /* the current method to be represented */
- s4 public_methods; /* number of public methods of the class */
- s4 pos;
- s4 i;
-
- c = LLNI_classinfo_unwrap(klass);
-
- public_methods = 0;
-
- /* JOWENN: array classes do not declare methods according to mauve
- test. It should be considered, if we should return to my old
- clone method overriding instead of declaring it as a member
- function. */
-
- if (class_is_array(c))
- return builtin_anewarray(0, class_java_lang_reflect_Method);
-
- /* determine number of methods */
-
- for (i = 0; i < c->methodscount; i++) {
- m = &c->methods[i];
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
- ((m->name != utf_init) && (m->name != utf_clinit)) &&
- !(m->flags & ACC_MIRANDA))
- public_methods++;
- }
-
- oa = builtin_anewarray(public_methods, class_java_lang_reflect_Method);
-
- if (oa == NULL)
- return NULL;
-
- for (i = 0, pos = 0; i < c->methodscount; i++) {
- m = &c->methods[i];
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
- ((m->name != utf_init) && (m->name != utf_clinit)) &&
- !(m->flags & ACC_MIRANDA)) {
- /* create Method object */
-
- rm = reflect_method_new(m);
-
- /* store object into array */
-
- array_objectarray_element_set(oa, pos, (java_handle_t *) rm);
- pos++;
- }
- }
-
- return oa;
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: getDeclaredConstructors
- * Signature: (Z)[Ljava/lang/reflect/Constructor;
- */
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly)
-{
- classinfo *c;
- methodinfo *m; /* the current method to be represented */
- java_handle_objectarray_t *oa; /* result: array of Method-objects */
- java_lang_reflect_Constructor *rc;
- s4 public_methods; /* number of public methods of the class */
- s4 pos;
- s4 i;
-
- c = LLNI_classinfo_unwrap(klass);
-
- /* determine number of constructors */
-
- for (i = 0, public_methods = 0; i < c->methodscount; i++) {
- m = &c->methods[i];
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
- (m->name == utf_init))
- public_methods++;
- }
-
- oa = builtin_anewarray(public_methods, class_java_lang_reflect_Constructor);
-
- if (oa == NULL)
- return NULL;
-
- for (i = 0, pos = 0; i < c->methodscount; i++) {
- m = &c->methods[i];
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
- (m->name == utf_init)) {
- /* create Constructor object */
-
- rc = reflect_constructor_new(m);
-
- /* store object into array */
-
- array_objectarray_element_set(oa, pos, (java_handle_t *) rc);
- pos++;
- }
- }
-
- return oa;
-}
-
-
-#if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
-/*
- * Class: java/lang/Class
- * Method: getDeclaredAnnotations
- * Signature: (Ljava/lang/Class;)[Ljava/lang/annotation/Annotation;
- */
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass)
-{
- classinfo *c = NULL; /* classinfo for the java.lang.Class object 'klass' */
- static methodinfo *m_parseAnnotationsIntoArray = NULL; /* parser method (cached, therefore static) */
- utf *utf_parseAnnotationsIntoArray = NULL; /* parser method name */
- utf *utf_desc = NULL; /* parser method descriptor (signature) */
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- sun_reflect_ConstantPool *constantPool = NULL; /* constant pool of klass */
- java_lang_Object *constantPoolOop = (java_lang_Object*)klass; /* constantPoolOop field of */
- /* sun.reflect.ConstantPool */
-
- if (klass == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- c = LLNI_classinfo_unwrap(klass);
-
- /* get annotations: */
- annotations = class_get_annotations(c);
-
- constantPool =
- (sun_reflect_ConstantPool*)native_new_and_init(
- class_sun_reflect_ConstantPool);
-
- if (constantPool == NULL) {
- /* out of memory */
- return NULL;
- }
-
- LLNI_field_set_ref(constantPool, constantPoolOop, constantPoolOop);
-
- /* only resolve the parser method the first time */
- if (m_parseAnnotationsIntoArray == NULL) {
- utf_parseAnnotationsIntoArray = utf_new_char("parseAnnotationsIntoArray");
- utf_desc = utf_new_char(
- "([BLsun/reflect/ConstantPool;Ljava/lang/Class;)"
- "[Ljava/lang/annotation/Annotation;");
-
- if (utf_parseAnnotationsIntoArray == NULL || utf_desc == NULL) {
- /* out of memory */
- return NULL;
- }
-
- m_parseAnnotationsIntoArray = class_resolveclassmethod(
- class_sun_reflect_annotation_AnnotationParser,
- utf_parseAnnotationsIntoArray,
- utf_desc,
- class_java_lang_Class,
- true);
-
- if (m_parseAnnotationsIntoArray == NULL) {
- /* method not found */
- return NULL;
- }
- }
-
- return (java_handle_objectarray_t*)vm_call_method(
- m_parseAnnotationsIntoArray, NULL,
- annotations, constantPool, klass);
-}
-#endif
-
-
-/* _Jv_java_lang_Class_getEnclosingMethod_intern *******************************
-
- Helper function for _Jv_java_lang_Class_getEnclosingConstructor and
- _Jv_java_lang_Class_getEnclosingMethod.
-
-*******************************************************************************/
-
-static methodinfo *_Jv_java_lang_Class_getEnclosingMethod_intern(classinfo *c)
-{
- constant_nameandtype *cn;
- classinfo *ec;
- methodinfo *m;
-
- /* get enclosing class and method */
-
- ec = class_get_enclosingclass(c);
- cn = c->enclosingmethod;
-
- /* check for enclosing class and method */
-
- if (ec == NULL)
- return NULL;
-
- if (cn == NULL)
- return NULL;
-
- /* find method in enclosing class */
-
- m = class_findmethod(ec, cn->name, cn->descriptor);
-
- if (m == NULL) {
- exceptions_throw_internalerror("Enclosing method doesn't exist");
- return NULL;
- }
-
- return m;
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: getEnclosingConstructor
- * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Constructor;
- */
-java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass)
-{
- classinfo *c;
- methodinfo *m;
- java_lang_reflect_Constructor *rc;
-
- c = LLNI_classinfo_unwrap(klass);
-
- /* get enclosing method */
-
- m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
-
- if (m == NULL)
- return NULL;
-
- /* check for <init> */
-
- if (m->name != utf_init)
- return NULL;
-
- /* create Constructor object */
-
- rc = reflect_constructor_new(m);
-
- return rc;
-}
-
-
-/*
- * Class: java/lang/Class
- * Method: getEnclosingMethod
- * Signature: (Ljava/lang/Class;)Ljava/lang/reflect/Method;
- */
-java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass)
-{
- classinfo *c;
- methodinfo *m;
- java_lang_reflect_Method *rm;
-
- c = LLNI_classinfo_unwrap(klass);
-
- /* get enclosing method */
-
- m = _Jv_java_lang_Class_getEnclosingMethod_intern(c);
-
- if (m == NULL)
- return NULL;
-
- /* check for <init> */
-
- if (m->name == utf_init)
- return NULL;
-
- /* create java.lang.reflect.Method object */
-
- rm = reflect_method_new(m);
-
- return rm;
-}
-
-#endif /* ENABLE_JAVASE */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/native/vm/java_lang_Class.h - java/lang/Class 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 _JV_JAVA_LANG_CLASS_H
-#define _JV_JAVA_LANG_CLASS_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-
-#include "native/include/java_lang_String.h" /* required by java_lang_Class.h */
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_Object.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ClassLoader.h"
-# include "native/include/java_lang_Throwable.h"
-# include "native/include/java_lang_reflect_Constructor.h"
-# include "native/include/java_lang_reflect_Method.h"
-#endif
-
-
-/* function prototypes ********************************************************/
-
-java_lang_String *_Jv_java_lang_Class_getName(java_lang_Class *klass);
-
-#if defined(ENABLE_JAVASE)
-java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name, s4 initialize, java_lang_ClassLoader *loader);
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-java_lang_Class *_Jv_java_lang_Class_forName(java_lang_String *name);
-#endif
-
-s4 _Jv_java_lang_Class_isInstance(java_lang_Class *klass, java_lang_Object *o);
-s4 _Jv_java_lang_Class_isAssignableFrom(java_lang_Class *klass, java_lang_Class *c);
-
-#if defined(ENABLE_JAVASE)
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredFields(java_lang_Class *klass, s4 publicOnly);
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredMethods(java_lang_Class *klass, s4 publicOnly);
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredConstructors(java_lang_Class *klass, s4 publicOnly);
-
-#if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
-java_handle_objectarray_t *_Jv_java_lang_Class_getDeclaredAnnotations(java_lang_Class* klass);
-#endif
-
-java_lang_reflect_Constructor *_Jv_java_lang_Class_getEnclosingConstructor(java_lang_Class *klass);
-java_lang_reflect_Method *_Jv_java_lang_Class_getEnclosingMethod(java_lang_Class *klass);
-#endif
-
-#endif /* _JV_JAVA_LANG_CLASS_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/native/vm/java_lang_ClassLoader.c - java/lang/ClassLoader
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "vm/global.h" /* required by native headers */
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-/* keep this order of the native includes */
-
-#include "native/include/java_lang_Object.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_String.h" /* required by j.l.C */
-
-# if defined(WITH_CLASSPATH_SUN)
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-# endif
-
-# include "native/include/java_lang_ClassLoader.h" /* required by j.l.C */
-# include "native/include/java_lang_Class.h"
-# include "native/include/java_security_ProtectionDomain.h"
-#endif
-
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-
-/*
- * Class: java/lang/ClassLoader
- * Method: defineClass
- * Signature: (Ljava/lang/ClassLoader;Ljava/lang/String;[BIILjava/security/ProtectionDomain;)Ljava/lang/Class;
- */
-java_lang_Class *_Jv_java_lang_ClassLoader_defineClass(java_lang_ClassLoader *cl, java_lang_String *name, java_handle_bytearray_t *data, s4 offset, s4 len, java_security_ProtectionDomain *pd)
-{
- utf *utfname;
- classinfo *c;
- classloader *loader;
- java_lang_Class *o;
-
-#if defined(ENABLE_JVMTI)
- jint new_class_data_len = 0;
- unsigned char* new_class_data = NULL;
-#endif
-
- /* check if data was passed */
-
- if (data == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- /* check the indexes passed */
-
- if ((offset < 0) || (len < 0) || ((offset + len) > LLNI_array_size(data))) {
- exceptions_throw_arrayindexoutofboundsexception();
- return NULL;
- }
-
- /* add classloader to classloader hashtable */
-
- loader = loader_hashtable_classloader_add((java_handle_t *) cl);
-
- if (name != NULL) {
- /* convert '.' to '/' in java string */
-
- utfname = javastring_toutf((java_handle_t *) name, true);
- }
- else {
- utfname = NULL;
- }
-
-#if defined(ENABLE_JVMTI)
- /* XXX again this will not work because of the indirection cell for classloaders */
- assert(0);
- /* fire Class File Load Hook JVMTI event */
-
- if (jvmti)
- jvmti_ClassFileLoadHook(utfname, len, (unsigned char *) data->data,
- loader, (java_handle_t *) pd,
- &new_class_data_len, &new_class_data);
-#endif
-
- /* define the class */
-
-#if defined(ENABLE_JVMTI)
- /* check if the JVMTI wants to modify the class */
-
- if (new_class_data == NULL)
- c = class_define(utfname, loader, new_class_data_len, new_class_data, pd);
- else
-#endif
- c = class_define(utfname, loader, len, (const uint8_t *) &LLNI_array_direct(data, offset), pd);
-
- if (c == NULL)
- return NULL;
-
- /* for convenience */
-
- o = LLNI_classinfo_wrap(c);
-
-#if defined(WITH_CLASSPATH_GNU)
- /* set ProtectionDomain */
-
- LLNI_field_set_ref(o, pd, pd);
-#endif
-
- 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/vm/java_lang_ClassLoader.h - java/lang/ClassLoader functions
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public 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 _JV_JAVA_LANG_CLASSLOADER_H
-#define _JV_JAVA_LANG_CLASSLOADER_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "native/jni.h"
-
-#include "native/include/java_lang_Object.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_String.h"/* required by java_lang_Class.h */
-# include "native/include/java_lang_Class.h"
-# include "native/include/java_lang_ClassLoader.h"
-# include "native/include/java_security_ProtectionDomain.h"
-#endif
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-#if defined(ENABLE_JAVASE)
-java_lang_Class *_Jv_java_lang_ClassLoader_defineClass(java_lang_ClassLoader *cl, java_lang_String *name, java_handle_bytearray_t *data, s4 offset, s4 len, java_security_ProtectionDomain *pd);
-#endif
-
-#endif /* _JV_JAVA_LANG_CLASSLOADER_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/java_lang_VMRuntime.c
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#if defined(ENABLE_LTDL) && defined(HAVE_LTDL_H)
-# include <ltdl.h>
-#endif
-
-#include "vm/types.h"
-
-#include "mm/gc-common.h"
-
-#include "native/jni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/options.h"
-
-
-/* should we run all finalizers on exit? */
-static bool finalizeOnExit = false;
-
-
-/*
- * Class: java/lang/Runtime
- * Method: exitInternal
- * Signature: (I)V
- */
-void _Jv_java_lang_Runtime_exit(s4 status)
-{
- if (finalizeOnExit)
- gc_finalize_all();
-
- vm_shutdown(status);
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: freeMemory
- * Signature: ()J
- */
-s8 _Jv_java_lang_Runtime_freeMemory(void)
-{
- return gc_get_free_bytes();
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: totalMemory
- * Signature: ()J
- */
-s8 _Jv_java_lang_Runtime_totalMemory(void)
-{
- return gc_get_heap_size();
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: gc
- * Signature: ()V
- */
-void _Jv_java_lang_Runtime_gc(void)
-{
- gc_call();
-}
-
-
-/*
- * Class: java/lang/Runtime
- * Method: loadLibrary
- * Signature: (Ljava/lang/String;Ljava/lang/ClassLoader;)I
- */
-#if defined(ENABLE_JNI)
-s4 _Jv_java_lang_Runtime_loadLibrary(JNIEnv *env, java_lang_String *libname, classloader *cl)
-#else
-s4 _Jv_java_lang_Runtime_loadLibrary(java_lang_String *libname, classloader *cl)
-#endif
-{
-#if defined(ENABLE_LTDL)
- utf *name;
- lt_dlhandle handle;
-# if defined(ENABLE_JNI)
- lt_ptr onload;
- s4 version;
-# endif
-
- if (libname == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- name = javastring_toutf((java_handle_t *) libname, false);
-
- /* 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 = lt_dlsym(handle, "JNI_OnLoad");
-
- if (onload != NULL) {
- JNIEXPORT s4 (JNICALL *JNI_OnLoad) (JavaVM *, void *);
- JavaVM *vm;
-
- JNI_OnLoad = (JNIEXPORT s4 (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)) {
- lt_dlclose(handle);
-
- return 0;
- }
- }
-# endif
-
- /* insert the library name into the library hash */
-
- native_library_add(name, cl, handle);
-
- return 1;
-#else
- vm_abort("_Jv_java_lang_Runtime_loadLibrary: not available");
-
- /* keep compiler happy */
-
- return 0;
-#endif
-}
-
-
-#if defined(ENABLE_JAVASE)
-
-/*
- * Class: java/lang/Runtime
- * Method: runFinalizersOnExit
- * Signature: (Z)V
- */
-void _Jv_java_lang_Runtime_runFinalizersOnExit(s4 value)
-{
- /* XXX threading */
-
- finalizeOnExit = value;
-}
-
-#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/java_lang_Runtime.h
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _JV_JAVA_LANG_RUNTIME_H
-#define _JV_JAVA_LANG_RUNTIME_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/include/java_lang_String.h"
-
-
-/* function prototypes *******************************************************/
-
-void _Jv_java_lang_Runtime_exit(s4 status);
-s8 _Jv_java_lang_Runtime_freeMemory(void);
-s8 _Jv_java_lang_Runtime_totalMemory(void);
-void _Jv_java_lang_Runtime_gc(void);
-
-#if defined(ENABLE_JNI)
-s4 _Jv_java_lang_Runtime_loadLibrary(JNIEnv *env, java_lang_String *libname, classloader *cl);
-#else
-s4 _Jv_java_lang_Runtime_loadLibrary(java_lang_String *libname, classloader *cl);
-#endif
-
-#if defined(ENABLE_JAVASE)
-void _Jv_java_lang_Runtime_runFinalizersOnExit(s4 value);
-#endif
-
-#endif /* _JV_JAVA_LANG_RUNTIME_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/java_lang_Thread.c - java/lang/Thread functions
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Object.h" /* java_lang_Thread.h */
-#include "native/include/java_lang_Throwable.h" /* java_lang_Thread.h */
-#include "native/include/java_lang_Thread.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-
-# if defined(WITH_CLASSPATH_GNU)
-# include "native/include/java_lang_VMThread.h"
-# endif
-#endif
-
-#include "threads/lock-common.h"
-#include "threads/threads-common.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/options.h"
-
-
-/*
- * Class: java/lang/Thread
- * Method: countStackFrames
- * Signature: ()I
- */
-s4 _Jv_java_lang_Thread_countStackFrames(java_lang_Thread *this)
-{
- log_text("java_lang_Thread_countStackFrames called");
-
- return 0;
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: sleep
- * Signature: (J)V
- */
-void _Jv_java_lang_Thread_sleep(s8 millis)
-{
-#if defined(ENABLE_THREADS)
- threads_sleep(millis, 0);
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: start
- * Signature: (J)V
- */
-void _Jv_java_lang_Thread_start(java_lang_Thread *this, s8 stacksize)
-{
-#if defined(ENABLE_THREADS)
- threads_thread_start((java_handle_t *) this);
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: isInterrupted
- * Signature: ()Z
- */
-s4 _Jv_java_lang_Thread_isInterrupted(java_lang_Thread *this)
-{
-#if defined(ENABLE_THREADS)
- threadobject *t;
-
-# if defined(WITH_CLASSPATH_GNU)
- t = (threadobject *) LLNI_field_direct(this, vmThread)->vmdata;
-# elif defined(WITH_CLASSPATH_SUN)
- /* XXX this is just a quick hack */
-
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- if (t->object == this)
- break;
- }
-# elif defined(WITH_CLASSPATH_CLDC1_1)
- t = (threadobject *) this->vm_thread;
-# else
-# error unknown classpath configuration
-# endif
-
- return threads_thread_has_been_interrupted(t);
-#else
- return 0;
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: suspend
- * Signature: ()V
- */
-void _Jv_java_lang_Thread_suspend(java_lang_Thread *this)
-{
-#if defined(ENABLE_THREADS)
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: resume
- * Signature: ()V
- */
-void _Jv_java_lang_Thread_resume(java_lang_Thread *this)
-{
-#if defined(ENABLE_THREADS)
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: setPriority
- * Signature: (I)V
- */
-void _Jv_java_lang_Thread_setPriority(java_lang_Thread *this, s4 priority)
-{
-#if defined(ENABLE_THREADS)
- threadobject *t;
-
-# if defined(WITH_CLASSPATH_GNU)
- t = (threadobject *) LLNI_field_direct(this, vmThread)->vmdata;
-# elif defined(WITH_CLASSPATH_SUN)
- /* XXX this is just a quick hack */
-
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- if (t->object == this)
- break;
- }
-
- /* The threadobject is null when a thread is created in Java. The
- priority is set later during startup. */
-
- if (t == NULL)
- return;
-# elif defined(WITH_CLASSPATH_CLDC1_1)
- t = (threadobject *) this->vm_thread;
-
- /* The threadobject is null when a thread is created in Java. The
- priority is set later during startup. */
-
- if (t == NULL)
- return;
-# else
-# error unknown classpath configuration
-# endif
-
- threads_set_thread_priority(t->tid, priority);
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: stop
- * Signature: (Ljava/lang/Object;)V
- */
-void _Jv_java_lang_Thread_stop(java_lang_Thread *this, java_lang_Throwable *t)
-{
-#if defined(ENABLE_THREADS)
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: currentThread
- * Signature: ()Ljava/lang/Thread;
- */
-java_lang_Thread *_Jv_java_lang_Thread_currentThread(void)
-{
-#if defined(ENABLE_THREADS)
- threadobject *thread;
-#endif
- java_lang_Thread *t;
-#if defined(ENABLE_JAVASE)
- java_lang_ThreadGroup *group;
-#endif
-
-#if defined(ENABLE_THREADS)
- thread = THREADOBJECT;
-
- t = (java_lang_Thread *) threads_thread_get_object(thread);
-
- if (t == NULL)
- log_text("t ptr is NULL\n");
-
-# if defined(ENABLE_JAVASE)
- LLNI_field_get_ref(t, group, group);
-
- if (group == NULL) {
- /* ThreadGroup of currentThread is not initialized */
-
- group = (java_lang_ThreadGroup *)
- native_new_and_init(class_java_lang_ThreadGroup);
-
- if (group == NULL)
- log_text("unable to create ThreadGroup");
-
- LLNI_field_set_ref(t, group, group);
- }
-# endif
-#else
- /* we just return a fake java.lang.Thread object, otherwise we get
- NullPointerException's in GNU classpath */
-
- t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
-#endif
-
- return t;
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: yield
- * Signature: ()V
- */
-void _Jv_java_lang_Thread_yield(void)
-{
-#if defined(ENABLE_THREADS)
- threads_yield();
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: interrupted
- * Signature: ()Z
- */
-s4 _Jv_java_lang_Thread_interrupted(void)
-{
-#if defined(ENABLE_THREADS)
- return threads_check_if_interrupted_and_reset();
-#else
- return 0;
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: holdsLock
- * Signature: (Ljava/lang/Object;)Z
- */
-s4 _Jv_java_lang_Thread_holdsLock(java_lang_Object* obj)
-{
-#if defined(ENABLE_THREADS)
- java_handle_t *o;
-
- o = (java_handle_t *) obj;
-
- if (o == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- return lock_is_held_by_current_thread(o);
-#else
- return 0;
-#endif
-}
-
-
-/*
- * Class: java/lang/Thread
- * Method: getState
- * Signature: ()Ljava/lang/String;
- */
-java_lang_String *_Jv_java_lang_Thread_getState(java_lang_Thread *this)
-{
-#if defined(ENABLE_THREADS)
- threadobject *thread;
- utf *u;
- java_handle_t *o;
-
-# if defined(WITH_CLASSPATH_GNU)
- thread = (threadobject *) LLNI_field_direct(this, vmThread)->vmdata;
-# elif defined(WITH_CLASSPATH_CLDC1_1)
- thread = (threadobject *) this->vm_thread;
-# endif
-
- u = threads_thread_get_state(thread);
- o = javastring_new(u);
-
- return (java_lang_String *) o;
-#else
- return NULL;
-#endif
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/native/vm/java_lang_Thread.h - java/lang/Thread 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 _JV_JAVA_LANG_THREAD_H
-#define _JV_JAVA_LANG_THREAD_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Object.h" /* java_lang_Thread.h */
-#include "native/include/java_lang_Throwable.h" /* java_lang_Thread.h */
-#include "native/include/java_lang_Thread.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-#endif
-
-#if defined(WITH_CLASSPATH_GNU)
-# include "native/include/java_lang_VMThread.h"
-#endif
-
-
-/* function prototypes ********************************************************/
-
-s4 _Jv_java_lang_Thread_countStackFrames(java_lang_Thread *this);
-void _Jv_java_lang_Thread_sleep(s8 millis);
-void _Jv_java_lang_Thread_start(java_lang_Thread *this, s8 stacksize);
-s4 _Jv_java_lang_Thread_isInterrupted(java_lang_Thread *this);
-void _Jv_java_lang_Thread_suspend(java_lang_Thread *this);
-void _Jv_java_lang_Thread_resume(java_lang_Thread *this);
-void _Jv_java_lang_Thread_setPriority(java_lang_Thread *this, s4 priority);
-void _Jv_java_lang_Thread_stop(java_lang_Thread *this, java_lang_Throwable *t);
-java_lang_Thread *_Jv_java_lang_Thread_currentThread(void);
-void _Jv_java_lang_Thread_yield(void);
-s4 _Jv_java_lang_Thread_interrupted(void);
-s4 _Jv_java_lang_Thread_holdsLock(java_lang_Object* o);
-java_lang_String *_Jv_java_lang_Thread_getState(java_lang_Thread *this);
-
-#endif /* _JV_JAVA_LANG_THREAD_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/native/vm/java_lang_reflect_Constructor.c
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#if defined(WITH_CLASSPATH_SUN)
-# include "native/include/java_lang_String.h" /* required by j.l.CL */
-# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
-# include "native/include/java_lang_ClassLoader.h" /* required my j.l.C */
-#endif
-
-#include "native/include/java_lang_Object.h" /* required my j.l.C */
-#include "native/include/java_lang_Class.h"
-#include "native/include/java_lang_String.h"
-
-#include "native/include/java_lang_reflect_Constructor.h"
-
-#include "native/vm/java_lang_reflect_Constructor.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/access.h"
-#include "vm/stringlocal.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-
-
-/*
- * Class: java/lang/reflect/Constructor
- * Method: getModifiers
- * Signature: ()I
- */
-s4 _Jv_java_lang_reflect_Constructor_getModifiers(JNIEnv *env, java_lang_reflect_Constructor *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return m->flags;
-}
-
-
-/*
- * Class: java/lang/reflect/Constructor
- * Method: getParameterTypes
- * Signature: ()[Ljava/lang/Class;
- */
-java_handle_objectarray_t *_Jv_java_lang_reflect_Constructor_getParameterTypes(JNIEnv *env, java_lang_reflect_Constructor *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return method_get_parametertypearray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/Constructor
- * Method: getExceptionTypes
- * Signature: ()[Ljava/lang/Class;
- */
-java_handle_objectarray_t *_Jv_java_lang_reflect_Constructor_getExceptionTypes(JNIEnv *env, java_lang_reflect_Constructor *this)
-{
- classinfo *c;
- methodinfo *m;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- return method_get_exceptionarray(m);
-}
-
-
-/*
- * Class: java/lang/reflect/Constructor
- * Method: newInstance
- * Signature: ([Ljava/lang/Object;)Ljava/lang/Object;
- */
-java_lang_Object *_Jv_java_lang_reflect_Constructor_newInstance(JNIEnv *env, java_lang_reflect_Constructor *this, java_handle_objectarray_t *args)
-{
- classinfo *c;
- methodinfo *m;
- s4 override;
- java_handle_t *o;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- /* check method access */
-
- /* check if we should bypass security checks (AccessibleObject) */
-
-#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_get_val(this, flag, override);
-#elif defined(WITH_CLASSPATH_SUN)
- LLNI_field_get_val(this, override, override);
-#else
-# error unknown classpath configuration
-#endif
-
- if (override == false) {
- if (!access_check_method(m, 1))
- return NULL;
- }
-
- /* create object */
-
- o = builtin_new(c);
-
- if (o == NULL)
- return NULL;
-
- /* call initializer */
-
- (void) _Jv_jni_invokeNative(m, o, args);
-
- return (java_lang_Object *) o;
-}
-
-
-/*
- * Class: java/lang/reflect/Constructor
- * Method: getSignature
- * Signature: ()Ljava/lang/String;
- */
-java_lang_String *_Jv_java_lang_reflect_Constructor_getSignature(JNIEnv *env, java_lang_reflect_Constructor *this)
-{
- classinfo *c;
- methodinfo *m;
- java_handle_t *o;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
- if (m->signature == NULL)
- return NULL;
-
- o = javastring_new(m->signature);
-
- /* in error case o is NULL */
-
- return (java_lang_String *) o;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of 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/java_lang_reflect_Constructor.h
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _JV_JAVA_LANG_REFLECT_CONSTRUCTOR_H
-#define _JV_JAVA_LANG_REFLECT_CONSTRUCTOR_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "native/jni.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_reflect_Constructor.h"
-
-
-/* function prototypes ********************************************************/
-
-s4 _Jv_java_lang_reflect_Constructor_getModifiers(JNIEnv *env, java_lang_reflect_Constructor *this);
-java_handle_objectarray_t *_Jv_java_lang_reflect_Constructor_getParameterTypes(JNIEnv *env, java_lang_reflect_Constructor *this);
-java_handle_objectarray_t *_Jv_java_lang_reflect_Constructor_getExceptionTypes(JNIEnv *env, java_lang_reflect_Constructor *this);
-java_lang_Object *_Jv_java_lang_reflect_Constructor_newInstance(JNIEnv *env, java_lang_reflect_Constructor *this, java_handle_objectarray_t *args);
-java_lang_String *_Jv_java_lang_reflect_Constructor_getSignature(JNIEnv *env, java_lang_reflect_Constructor *this);
-
-#endif /* _JV_JAVA_LANG_REFLECT_CONSTRUCTOR_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/java_lang_reflect_Method.c
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-
-#include "native/include/java_lang_Object.h"
-
-#include "native/include/java_lang_reflect_Method.h"
-
-#include "vm/access.h"
-#include "vm/builtin.h"
-#include "vm/initialize.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-
-
-/*
- * Class: java/lang/reflect/Method
- * Method: invoke
- * Signature: (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
- */
-java_lang_Object *_Jv_java_lang_reflect_Method_invoke(java_lang_reflect_Method *this, java_lang_Object *o, java_handle_objectarray_t *args)
-{
- classinfo *c;
- methodinfo *m;
- s4 override;
- int32_t slot;
-
- LLNI_field_get_cls(this, clazz, c);
- LLNI_field_get_val(this, slot , slot);
- m = &(c->methods[slot]);
-
-
- /* check method access */
-
- /* check if we should bypass security checks (AccessibleObject) */
-
-#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_get_val(this, flag, override);
-#elif defined(WITH_CLASSPATH_SUN)
- LLNI_field_get_val(this, override, override);
-#else
-# error unknown classpath configuration
-#endif
-
- if (override == false) {
- if (!access_check_method(m, 1))
- return NULL;
- }
-
- /* check if method class is initialized */
-
- if (!(c->state & CLASS_INITIALIZED))
- if (!initialize_class(c))
- return NULL;
-
- /* call the Java method via a helper function */
-
- return (java_lang_Object *) _Jv_jni_invokeNative(m, (java_handle_t *) o, args);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/native/vm/java_lang_reflect_Method.h
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _JV_JAVA_LANG_REFLECT_METHOD_H
-#define _JV_JAVA_LANG_REFLECT_METHOD_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "native/jni.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_reflect_Method.h"
-
-#include "native/vm/java_lang_reflect_Method.h"
-
-#include "vm/global.h"
-
-
-/* function prototypes ********************************************************/
-
-java_lang_Object *_Jv_java_lang_reflect_Method_invoke(java_lang_reflect_Method *this, java_lang_Object *o, java_handle_objectarray_t *args);
-
-#endif /* _JV_JAVA_LANG_REFLECT_METHOD_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
/* src/native/vm/nativevm.c - register the native functions
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
-#if defined(WITH_CLASSPATH_SUN)
-# include <string.h>
-#endif
-
#include "native/vm/nativevm.h"
+#include "vm/initialize.h"
+
+#include "vmcore/class.h"
#include "vmcore/method.h"
+#include "vmcore/options.h"
+#include "vmcore/system.h"
#if defined(WITH_CLASSPATH_SUN)
# include "mm/memory.h"
# include "native/native.h"
+# include "native/vm/sun/hpi.h"
+
# include "vm/properties.h"
# include "vm/vm.h"
-# include "vmcore/class.h"
# include "vmcore/utf8.h"
#endif
*******************************************************************************/
-bool nativevm_preinit(void)
+void nativevm_preinit(void)
{
- /* register native methods of all classes implemented */
+ /* Register native methods of all classes implemented. */
#if defined(ENABLE_JAVASE)
-
# if defined(WITH_CLASSPATH_GNU)
+ 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_java_lang_VMThread_init();
_Jv_java_lang_VMThrowable_init();
_Jv_java_lang_management_VMManagementFactory_init();
- _Jv_java_lang_reflect_Constructor_init();
- _Jv_java_lang_reflect_Field_init();
- _Jv_java_lang_reflect_Method_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();
utf *u;
lt_dlhandle handle;
+ TRACESUBSYSTEMINITIALIZATION("nativevm_preinit");
+
+ /* Load libjava.so */
+
boot_library_path = properties_get("sun.boot.library.path");
len =
- strlen(boot_library_path) +
- strlen("/libjava.so") +
- strlen("0");
+ system_strlen(boot_library_path) +
+ system_strlen("/libjava.so") +
+ system_strlen("0");
p = MNEW(char, len);
- strcpy(p, boot_library_path);
- strcat(p, "/libjava.so");
+ system_strcpy(p, boot_library_path);
+ system_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);
- handle = native_library_open(u);
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_java_lang_Throwable_init();
#else
-
# error unknown Java configuration
-
#endif
-
- /* everything's ok */
-
- return true;
}
*******************************************************************************/
-bool nativevm_init(void)
+void nativevm_init(void)
{
#if defined(ENABLE_JAVASE)
# if defined(WITH_CLASSPATH_GNU)
+ TRACESUBSYSTEMINITIALIZATION("nativevm_init");
+
/* nothing to do */
# elif defined(WITH_CLASSPATH_SUN)
methodinfo *m;
+ TRACESUBSYSTEMINITIALIZATION("nativevm_init");
+
m = class_resolveclassmethod(class_java_lang_System,
utf_new_char("initializeSystemClass"),
utf_void__void,
false);
if (m == NULL)
- return false;
+ 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
-
- /* everything's ok */
-
- return true;
}
/* src/native/vm/nativevm.h - register the native functions
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* function prototypes ********************************************************/
-bool nativevm_preinit(void);
-bool nativevm_init(void);
+void nativevm_preinit(void);
+void nativevm_init(void);
#if defined(ENABLE_JAVASE)
-
# if defined(WITH_CLASSPATH_GNU)
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_java_lang_VMThread_init();
void _Jv_java_lang_VMThrowable_init();
void _Jv_java_lang_management_VMManagementFactory_init();
-void _Jv_java_lang_reflect_Constructor_init();
-void _Jv_java_lang_reflect_Field_init();
-void _Jv_java_lang_reflect_Method_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();
# else
-
# error unknown classpath configuration
-
# endif
#elif defined(ENABLE_JAVAME_CLDC1_1)
void _Jv_java_lang_Throwable_init();
#else
-
# error unknown Java configuration
-
#endif
#endif /* _NATIVEVM_H */
/* src/native/vm/reflect.c - helper functions for java/lang/reflect
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/java_lang_reflect_Field.h"
#include "native/include/java_lang_reflect_Method.h"
+#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_reflect_VMConstructor.h"
+# include "native/include/java_lang_reflect_VMField.h"
+# include "native/include/java_lang_reflect_VMMethod.h"
+#endif
+
#if defined(ENABLE_ANNOTATIONS) && defined(WITH_CLASSPATH_GNU)
# include "vm/vm.h"
# include "native/include/sun_reflect_ConstantPool.h"
#include "native/vm/reflect.h"
+#include "vm/access.h"
#include "vm/builtin.h"
+#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/initialize.h"
#include "vm/stringlocal.h"
#include "vmcore/method.h"
java_lang_reflect_Constructor *reflect_constructor_new(methodinfo *m)
{
- classinfo *c;
- java_handle_t *o;
- java_lang_reflect_Constructor *rc;
- int32_t slot;
-
- /* get declaring class */
+ java_handle_t *o;
+ java_lang_reflect_Constructor *rc;
+ int32_t slot;
- c = m->class;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_reflect_VMConstructor *rvmc;
+#endif
- /* allocate a new object */
+ /* Allocate a java.lang.reflect.Constructor object. */
o = builtin_new(class_java_lang_reflect_Constructor);
if (o == NULL)
return NULL;
- /* initialize instance fields */
+ /* Initialize instance fields. */
rc = (java_lang_reflect_Constructor *) o;
- /* calculate the slot */
+ /* Calculate the slot. */
- slot = m - c->methods;
+ slot = m - m->clazz->methods;
#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_set_cls(rc, clazz , c);
- LLNI_field_set_val(rc, slot , slot);
- LLNI_field_set_ref(rc, annotations , method_get_annotations(m));
- LLNI_field_set_ref(rc, parameterAnnotations, method_get_parameterannotations(m));
+ /* Allocate a java.lang.reflect.VMConstructor object. */
+
+ o = builtin_new(class_java_lang_reflect_VMConstructor);
+
+ if (o == NULL)
+ return NULL;
+
+ rvmc = (java_lang_reflect_VMConstructor *) o;
+
+ /* Link the two Java objects. */
+
+ LLNI_field_set_ref(rc, cons, rvmc);
+ LLNI_field_set_ref(rvmc, cons, rc);
+
+ /* Set Java object instance fields. */
+
+ LLNI_field_set_cls(rvmc, clazz, m->clazz);
+ LLNI_field_set_val(rvmc, slot, slot);
+ LLNI_field_set_ref(rvmc, annotations, method_get_annotations(m));
+ LLNI_field_set_ref(rvmc, parameterAnnotations, method_get_parameterannotations(m));
#elif defined(WITH_CLASSPATH_SUN)
- LLNI_field_set_cls(rc, clazz , c);
+ /* Set Java object instance fields. */
+
+ LLNI_field_set_cls(rc, clazz , m->clazz);
LLNI_field_set_ref(rc, parameterTypes , method_get_parametertypearray(m));
LLNI_field_set_ref(rc, exceptionTypes , method_get_exceptionarray(m));
LLNI_field_set_val(rc, modifiers , m->flags & ACC_CLASS_REFLECT_MASK);
java_lang_reflect_Field *reflect_field_new(fieldinfo *f)
{
- classinfo *c;
- java_handle_t *o;
- java_lang_reflect_Field *rf;
- int32_t slot;
+ java_handle_t *o;
+ java_lang_reflect_Field *rf;
+ int32_t slot;
- /* get declaring class */
-
- c = f->class;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_reflect_VMField *rvmf;
+#endif
- /* allocate a new object */
+ /* Allocate a java.lang.reflect.Field object. */
o = builtin_new(class_java_lang_reflect_Field);
rf = (java_lang_reflect_Field *) o;
- /* calculate the slot */
+ /* Calculate the slot. */
- slot = f - c->fields;
+ slot = f - f->clazz->fields;
#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_set_cls(rf, clazz , c);
+ /* Allocate a java.lang.reflect.VMField object. */
+
+ o = builtin_new(class_java_lang_reflect_VMField);
+
+ if (o == NULL)
+ return NULL;
+
+ rvmf = (java_lang_reflect_VMField *) o;
+
+ /* Link the two Java objects. */
+
+ LLNI_field_set_ref(rf, f, rvmf);
+ LLNI_field_set_ref(rvmf, f, rf);
+
+ /* Set the Java object fields. */
+
+ LLNI_field_set_cls(rvmf, clazz, f->clazz);
/* The name needs to be interned */
/* XXX implement me better! */
- LLNI_field_set_ref(rf, name , javastring_intern(javastring_new(f->name)));
- LLNI_field_set_val(rf, slot , slot);
- LLNI_field_set_ref(rf, annotations , field_get_annotations(f));
+ LLNI_field_set_ref(rvmf, name, (java_lang_String *) javastring_intern(javastring_new(f->name)));
+ LLNI_field_set_val(rvmf, slot, slot);
+ LLNI_field_set_ref(rvmf, annotations, field_get_annotations(f));
#elif defined(WITH_CLASSPATH_SUN)
- LLNI_field_set_cls(rf, clazz , c);
+ /* Set the Java object fields. */
+
+ LLNI_field_set_cls(rf, clazz, f->clazz);
/* The name needs to be interned */
/* XXX implement me better! */
- LLNI_field_set_ref(rf, name , javastring_intern(javastring_new(f->name)));
- LLNI_field_set_cls(rf, type , (java_lang_Class *) field_get_type(f));
- LLNI_field_set_val(rf, modifiers , f->flags);
- LLNI_field_set_val(rf, slot , slot);
- LLNI_field_set_ref(rf, signature , f->signature ? (java_lang_String *) javastring_new(f->signature) : NULL);
- LLNI_field_set_ref(rf, annotations , field_get_annotations(f));
+ LLNI_field_set_ref(rf, name, (java_lang_String *) javastring_intern(javastring_new(f->name)));
+ LLNI_field_set_cls(rf, type, (java_lang_Class *) field_get_type(f));
+ LLNI_field_set_val(rf, modifiers, f->flags);
+ LLNI_field_set_val(rf, slot, slot);
+ LLNI_field_set_ref(rf, signature, f->signature ? (java_lang_String *) javastring_new(f->signature) : NULL);
+ LLNI_field_set_ref(rf, annotations, field_get_annotations(f));
#else
# error unknown classpath configuration
java_lang_reflect_Method *reflect_method_new(methodinfo *m)
{
- classinfo *c;
- java_handle_t *o;
- java_lang_reflect_Method *rm;
- int32_t slot;
-
- /* get declaring class */
+ java_handle_t *o;
+ java_lang_reflect_Method *rm;
+ int32_t slot;
- c = m->class;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_reflect_VMMethod *rvmm;
+#endif
- /* allocate a new object */
+ /* Allocate a java.lang.reflect.Method object. */
o = builtin_new(class_java_lang_reflect_Method);
rm = (java_lang_reflect_Method *) o;
- /* calculate the slot */
+ /* Calculate the slot. */
- slot = m - c->methods;
+ slot = m - m->clazz->methods;
#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_set_cls(rm, clazz , m->class);
+ /* Allocate a java.lang.reflect.VMMethod object. */
+
+ o = builtin_new(class_java_lang_reflect_VMMethod);
+
+ if (o == NULL)
+ return NULL;
+
+ rvmm = (java_lang_reflect_VMMethod *) o;
+
+ /* Link the two Java objects. */
+
+ LLNI_field_set_ref(rm, m, rvmm);
+ LLNI_field_set_ref(rvmm, m, rm);
+
+ /* Set Java object instance fields. */
+
+ LLNI_field_set_cls(rvmm, clazz, m->clazz);
/* The name needs to be interned */
/* XXX implement me better! */
- LLNI_field_set_ref(rm, name , javastring_intern(javastring_new(m->name)));
- LLNI_field_set_val(rm, slot , slot);
- LLNI_field_set_ref(rm, annotations , method_get_annotations(m));
- LLNI_field_set_ref(rm, parameterAnnotations, method_get_parameterannotations(m));
- LLNI_field_set_ref(rm, annotationDefault , method_get_annotationdefault(m));
+ LLNI_field_set_ref(rvmm, name, (java_lang_String *) javastring_intern(javastring_new(m->name)));
+ LLNI_field_set_val(rvmm, slot, slot);
+ LLNI_field_set_ref(rvmm, annotations, method_get_annotations(m));
+ LLNI_field_set_ref(rvmm, parameterAnnotations, method_get_parameterannotations(m));
+ LLNI_field_set_ref(rvmm, annotationDefault, method_get_annotationdefault(m));
#elif defined(WITH_CLASSPATH_SUN)
- LLNI_field_set_cls(rm, clazz , m->class);
+ LLNI_field_set_cls(rm, clazz, m->clazz);
/* The name needs to be interned */
/* XXX implement me better! */
- LLNI_field_set_ref(rm, name , javastring_intern(javastring_new(m->name)));
- LLNI_field_set_ref(rm, parameterTypes , method_get_parametertypearray(m));
- LLNI_field_set_cls(rm, returnType , (java_lang_Class *) method_returntype_get(m));
- LLNI_field_set_ref(rm, exceptionTypes , method_get_exceptionarray(m));
- LLNI_field_set_val(rm, modifiers , m->flags & ACC_CLASS_REFLECT_MASK);
- LLNI_field_set_val(rm, slot , slot);
- LLNI_field_set_ref(rm, signature , m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL);
- LLNI_field_set_ref(rm, annotations , method_get_annotations(m));
+ LLNI_field_set_ref(rm, name, (java_lang_String *) javastring_intern(javastring_new(m->name)));
+ LLNI_field_set_ref(rm, parameterTypes, method_get_parametertypearray(m));
+ LLNI_field_set_cls(rm, returnType, (java_lang_Class *) method_returntype_get(m));
+ LLNI_field_set_ref(rm, exceptionTypes, method_get_exceptionarray(m));
+ LLNI_field_set_val(rm, modifiers, m->flags & ACC_CLASS_REFLECT_MASK);
+ LLNI_field_set_val(rm, slot, slot);
+ LLNI_field_set_ref(rm, signature, m->signature ? (java_lang_String *) javastring_new(m->signature) : NULL);
+ LLNI_field_set_ref(rm, annotations, method_get_annotations(m));
LLNI_field_set_ref(rm, parameterAnnotations, method_get_parameterannotations(m));
- LLNI_field_set_ref(rm, annotationDefault , method_get_annotationdefault(m));
+ LLNI_field_set_ref(rm, annotationDefault, method_get_annotationdefault(m));
#else
# error unknown classpath configuration
}
+/* reflect_invoke **************************************************************
+
+ Invoke a method on the given object with the given arguments.
+
+ For instance methods OBJ must be != NULL and the method is looked up
+ in the vftbl of the object.
+
+ For static methods, OBJ is ignored.
+
+*******************************************************************************/
+
+static java_handle_t *reflect_invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *params)
+{
+ methodinfo *resm;
+ java_handle_t *ro;
+ int argcount;
+ int paramcount;
+
+ /* Sanity check. */
+
+ assert(m != NULL);
+
+ argcount = m->parseddesc->paramcount;
+ paramcount = argcount;
+
+ /* If method is non-static, remove the `this' pointer. */
+
+ if (!(m->flags & ACC_STATIC))
+ paramcount--;
+
+ /* For instance methods the object has to be an instance of the
+ class the method belongs to. For static methods the obj
+ parameter is ignored. */
+
+ if (!(m->flags & ACC_STATIC) && o && (!builtin_instanceof(o, m->clazz))) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* check if we got the right number of arguments */
+
+ if (((params == NULL) && (paramcount != 0)) ||
+ (params && (LLNI_array_size(params) != paramcount)))
+ {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* for instance methods we need an object */
+
+ if (!(m->flags & ACC_STATIC) && (o == NULL)) {
+ /* XXX not sure if that is the correct exception */
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ /* for static methods, zero object to make subsequent code simpler */
+ if (m->flags & ACC_STATIC)
+ o = NULL;
+
+ if (o != NULL) {
+ /* for instance methods we must do a vftbl lookup */
+ resm = method_vftbl_lookup(LLNI_vftbl_direct(o), m);
+ }
+ else {
+ /* for static methods, just for convenience */
+ resm = m;
+ }
+
+ ro = vm_call_method_objectarray(resm, o, params);
+
+ return ro;
+}
+
+
+/* reflect_constructor_newinstance ********************************************
+
+ Creates an Java object instance of the given constructor.
+
+ ARGUMENTS:
+ m .......... methodinfo of the constructor
+ args ....... constructor arguments
+ override ... override security checks
+
+ RETURN:
+ constructed Java object
+
+*******************************************************************************/
+
+java_handle_t *reflect_constructor_newinstance(methodinfo *m, java_handle_objectarray_t *args, bool override)
+{
+ java_handle_t *o;
+
+ /* Should we bypass security the checks (AccessibleObject)? */
+
+ if (override == false) {
+ /* This method is always called like this:
+ [0] java.lang.reflect.Constructor.constructNative (Native Method)
+ [1] java.lang.reflect.Constructor.newInstance
+ [2] <caller>
+ */
+
+ if (!access_check_method(m, 2))
+ return NULL;
+ }
+
+ /* Create a Java object. */
+
+ o = builtin_new(m->clazz);
+
+ if (o == NULL)
+ return NULL;
+
+ /* Call initializer. */
+
+ (void) reflect_invoke(m, o, args);
+
+ return o;
+}
+
+
+/* reflect_method_invoke *******************************************************
+
+ Invokes the given method.
+
+ ARGUMENTS:
+ m .......... methodinfo
+ args ....... method arguments
+ override ... override security checks
+
+ RETURN:
+ return value of the method
+
+*******************************************************************************/
+
+java_handle_t *reflect_method_invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *args, bool override)
+{
+ java_handle_t *ro;
+
+ /* Should we bypass security the checks (AccessibleObject)? */
+
+ if (override == false) {
+#if defined(WITH_CLASSPATH_GNU)
+ /* This method is always called like this:
+ [0] java.lang.reflect.Method.invokeNative (Native Method)
+ [1] java.lang.reflect.Method.invoke (Method.java:329)
+ [2] <caller>
+ */
+
+ if (!access_check_method(m, 2))
+ return NULL;
+#elif defined(WITH_CLASSPATH_SUN)
+ /* We only pass 1 here as stacktrace_get_caller_class, which
+ is called from access_check_method, skips
+ java.lang.reflect.Method.invoke(). */
+
+ if (!access_check_method(m, 1))
+ return NULL;
+#endif
+ }
+
+ /* Check if method class is initialized. */
+
+ if (!(m->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(m->clazz))
+ return NULL;
+
+ /* Call the Java method. */
+
+ ro = reflect_invoke(m, o, args);
+
+ return ro;
+}
+
+
#if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
/* reflect_get_declaredannotatios *********************************************
/* src/native/vm/reflect.h - helper functions for java/lang/reflect
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
*/
+#ifndef _REFLECT_H
+#define _REFLECT_H
+
#include "config.h"
#include <stdint.h>
#include "native/jni.h"
#include "native/native.h"
-/* keep this order of the native includes */
+/* Keep this order of the native includes. */
#include "native/include/java_lang_String.h"
java_lang_reflect_Constructor *reflect_constructor_new(methodinfo *m);
java_lang_reflect_Field *reflect_field_new(fieldinfo *f);
java_lang_reflect_Method *reflect_method_new(methodinfo *m);
+java_handle_t *reflect_constructor_newinstance(methodinfo *m, java_handle_objectarray_t *args, bool override);
+java_handle_t *reflect_method_invoke(methodinfo *m, java_handle_t *o, java_handle_objectarray_t *args, bool override);
#if defined(WITH_CLASSPATH_GNU) && defined(ENABLE_ANNOTATIONS)
struct java_util_Map* reflect_get_declaredannotatios(
classinfo *referer);
#endif
+#endif /* _REFLECT_H */
+
+
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
## src/native/vm/sun/Makefile.am
##
-## Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
+## Copyright (C) 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
##
## This file is part of CACAO.
##
libnativevmcore.la
libnativevmcore_la_SOURCES = \
+ hpi.c \
+ hpi.h \
jvm.c
--- /dev/null
+/* src/native/vm/sun/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 "vm/properties.h"
+#include "vm/vm.h"
+
+#include "vmcore/options.h"
+#include "vmcore/system.h"
+#include "vmcore/utf8.h"
+
+
+/* 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)
+{
+ char *boot_library_path;
+ int len;
+ char *p;
+ utf *u;
+ lt_dlhandle handle;
+ lt_ptr 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 =
+ system_strlen(boot_library_path) +
+ system_strlen("/native_threads/libhpi.so") +
+ system_strlen("0");
+
+ p = MNEW(char, len);
+
+ system_strcpy(p, boot_library_path);
+ system_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 = lt_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", lt_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/sun/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
+
+#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);
+
+#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:
+ */
/* src/native/vm/sun/jvm.c - HotSpot JVM interface functions
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
*/
-#define PRINTJVM 0
-
#include "config.h"
#include <assert.h>
#include <errno.h>
-#include <fcntl.h>
#include <ltdl.h>
#include <stdint.h>
#include <stdio.h>
#include "native/include/java_lang_StackTraceElement.h"
#include "native/include/java_lang_Throwable.h"
#include "native/include/java_security_ProtectionDomain.h"
-#include "native/include/java_lang_Integer.h"
-#include "native/include/java_lang_Long.h"
-#include "native/include/java_lang_Short.h"
-#include "native/include/java_lang_Byte.h"
-#include "native/include/java_lang_Character.h"
-#include "native/include/java_lang_Boolean.h"
-#include "native/include/java_lang_Float.h"
-#include "native/include/java_lang_Double.h"
#if defined(ENABLE_ANNOTATIONS)
#include "native/include/sun_reflect_ConstantPool.h"
#endif
-#include "native/vm/java_lang_Class.h"
-#include "native/vm/java_lang_ClassLoader.h"
-#include "native/vm/java_lang_Runtime.h"
-#include "native/vm/java_lang_Thread.h"
-#include "native/vm/java_lang_reflect_Constructor.h"
-#include "native/vm/java_lang_reflect_Method.h"
#include "native/vm/reflect.h"
+#include "native/vm/sun/hpi.h"
+
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
#include "toolbox/list.h"
#if !defined(NDEBUG)
-# define TRACEJVMCALLS(...) \
+# define TRACEJVMCALLS(x) \
+ do { \
+ if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
+ log_println x; \
+ } \
+ } while (0)
+
+# define TRACEJVMCALLSENTER(x) \
+ do { \
+ if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
+ log_start(); \
+ log_print x; \
+ } \
+ } while (0)
+
+# define TRACEJVMCALLSEXIT(x) \
+ do { \
+ if (opt_TraceJVMCalls || opt_TraceJVMCallsVerbose) { \
+ log_print x; \
+ log_finish(); \
+ } \
+ } while (0)
+
+# define TRACEJVMCALLSVERBOSE(x) \
do { \
- if (opt_TraceJVMCalls) { \
- log_println(__VA_ARGS__); \
+ if (opt_TraceJVMCallsVerbose) { \
+ log_println x; \
} \
} while (0)
-# define PRINTJVMWARNINGS(...)
+# define PRINTJVMWARNINGS(x)
/* do { \ */
/* if (opt_PrintJVMWarnings) { \ */
-/* log_println(__VA_ARGS__); \ */
+/* log_println x; \ */
/* } \ */
/* } while (0) */
#else
-# define TRACEJVMCALLS(...)
-# define PRINTJVMWARNINGS(...)
+# define TRACEJVMCALLS(x)
+# define TRACEJVMCALLSENTER(x)
+# define TRACEJVMCALLSEXIT(x)
+# define TRACEJVMCALLSVERBOSE(x)
+# define PRINTJVMWARNINGS(x)
#endif
int jio_fprintf(FILE* f, const char *fmt, ...)
{
log_println("jio_fprintf: IMPLEMENT ME!");
+
+ return 0;
}
int jio_vfprintf(FILE* f, const char *fmt, va_list args)
{
log_println("jio_vfprintf: IMPLEMENT ME!");
+
+ return 0;
}
int jio_printf(const char *fmt, ...)
{
log_println("jio_printf: IMPLEMENT ME!");
+
+ return 0;
}
jlong JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored)
{
-#if PRINTJVM
- log_println("JVM_CurrentTimeMillis");
-#endif
+ TRACEJVMCALLS(("JVM_CurrentTimeMillis(env=%p, ignored=%p)", env, ignored));
+
return (jlong) builtin_currenttimemillis();
}
jlong JVM_NanoTime(JNIEnv *env, jclass ignored)
{
-#if PRINTJVM
- log_println("JVM_NanoTime");
-#endif
+ TRACEJVMCALLS(("JVM_NanoTime(env=%p, ignored=%p)", env, ignored));
+
return (jlong) builtin_nanotime();
}
s = (java_handle_t *) src;
d = (java_handle_t *) dst;
-#if PRINTJVM
- log_println("JVM_ArrayCopy: src=%p, src_pos=%d, dst=%p, dst_pos=%d, length=%d", src, src_pos, dst, dst_pos, length);
-#endif
+ TRACEJVMCALLSVERBOSE(("JVM_ArrayCopy(env=%p, ignored=%p, src=%p, src_pos=%d, dst=%p, dst_pos=%d, length=%d)", env, ignored, src, src_pos, dst, dst_pos, length));
builtin_arraycopy(s, src_pos, d, dst_pos, length);
}
jobject JVM_InitProperties(JNIEnv *env, jobject properties)
{
java_handle_t *h;
+ char buf[256];
- TRACEJVMCALLS("JVM_InitProperties(env=%p, properties=%p)", env, properties);
+ TRACEJVMCALLS(("JVM_InitProperties(env=%p, properties=%p)", env, properties));
h = (java_handle_t *) properties;
+ /* Convert the -XX:MaxDirectMemorySize= command line flag to the
+ sun.nio.MaxDirectMemorySize property. Do this after setting
+ user properties to prevent people from setting the value with a
+ -D option, as requested. */
+
+ jio_snprintf(buf, sizeof(buf), PRINTF_FORMAT_INT64_T, opt_MaxDirectMemorySize);
+ properties_add("sun.nio.MaxDirectMemorySize", buf);
+
+ /* Add all properties. */
+
properties_system_add_all(h);
return properties;
void JVM_Halt(jint code)
{
-#if PRINTJVM
- log_println("JVM_Halt: code=%d", code);
-#endif
+ TRACEJVMCALLS(("JVM_Halt(code=%d)", code));
+
/* vm_exit(code); */
vm_shutdown(code);
}
void JVM_GC(void)
{
- TRACEJVMCALLS("JVM_GC()");
+ TRACEJVMCALLS(("JVM_GC()"));
gc_call();
}
jlong JVM_MaxObjectInspectionAge(void)
{
log_println("JVM_MaxObjectInspectionAge: IMPLEMENT ME!");
+
+ return 0;
}
jlong JVM_TotalMemory(void)
{
- TRACEJVMCALLS("JVM_TotalMemory()");
+ TRACEJVMCALLS(("JVM_TotalMemory()"));
return gc_get_heap_size();
}
jlong JVM_FreeMemory(void)
{
- TRACEJVMCALLS("JVM_FreeMemory()");
+ TRACEJVMCALLS(("JVM_FreeMemory()"));
return gc_get_free_bytes();
}
jlong JVM_MaxMemory(void)
{
- TRACEJVMCALLS("JVM_MaxMemory()");
+ TRACEJVMCALLS(("JVM_MaxMemory()"));
return gc_get_max_heap_size();
}
jint JVM_ActiveProcessorCount(void)
{
- TRACEJVMCALLS("JVM_ActiveProcessorCount()");
+ TRACEJVMCALLS(("JVM_ActiveProcessorCount()"));
return system_processors_online();
}
java_lang_Throwable *o;
java_handle_bytearray_t *ba;
- TRACEJVMCALLS("JVM_FillInStackTrace(env=%p, receiver=%p)", env, receiver);
+ TRACEJVMCALLS(("JVM_FillInStackTrace(env=%p, receiver=%p)", env, receiver));
o = (java_lang_Throwable *) receiver;
- ba = stacktrace_get();
+ ba = stacktrace_get_current();
if (ba == NULL)
return;
- LLNI_field_set_ref(o, backtrace, ba);
+ LLNI_field_set_ref(o, backtrace, (java_lang_Object *) ba);
}
jint JVM_GetStackTraceDepth(JNIEnv *env, jobject throwable)
{
- java_lang_Throwable *t;
+ java_lang_Throwable *to;
+ java_lang_Object *o;
java_handle_bytearray_t *ba;
stacktrace_t *st;
int32_t depth;
- TRACEJVMCALLS("JVM_GetStackTraceDepth(env=%p, throwable=%p)", env, throwable);
+ TRACEJVMCALLS(("JVM_GetStackTraceDepth(env=%p, throwable=%p)", env, throwable));
if (throwable == NULL) {
exceptions_throw_nullpointerexception();
return 0;
}
- t = (java_lang_Throwable *) throwable;
+ to = (java_lang_Throwable *) throwable;
+
+ LLNI_field_get_ref(to, backtrace, o);
- LLNI_field_get_ref(t, backtrace, ba);
+ ba = (java_handle_bytearray_t *) o;
if (ba == NULL)
return 0;
jobject JVM_GetStackTraceElement(JNIEnv *env, jobject throwable, jint index)
{
- java_lang_Throwable *t;
+ java_lang_Throwable *to;
+ java_lang_Object *o;
java_handle_bytearray_t *ba;
stacktrace_t *st;
stacktrace_entry_t *ste;
codeinfo *code;
methodinfo *m;
classinfo *c;
- java_lang_StackTraceElement *o;
- java_lang_String *declaringclass;
+ java_lang_StackTraceElement *steo;
+ java_handle_t* declaringclass;
java_lang_String *filename;
int32_t linenumber;
- TRACEJVMCALLS("JVM_GetStackTraceElement(env=%p, throwable=%p, index=%d)", env, throwable, index);
+ TRACEJVMCALLS(("JVM_GetStackTraceElement(env=%p, throwable=%p, index=%d)", env, throwable, index));
+
+ to = (java_lang_Throwable *) throwable;
- t = (java_lang_Throwable *) throwable;
+ LLNI_field_get_ref(to, backtrace, o);
- LLNI_field_get_ref(t, backtrace, ba);
+ ba = (java_handle_bytearray_t *) o;
/* FIXME critical section */
code = ste->code;
m = code->m;
- c = m->class;
+ c = m->clazz;
/* allocate a new StackTraceElement */
- o = (java_lang_StackTraceElement *)
+ steo = (java_lang_StackTraceElement *)
builtin_new(class_java_lang_StackTraceElement);
- if (o == NULL)
+ if (steo == NULL)
return NULL;
/* get filename */
/* get declaring class name */
- declaringclass = _Jv_java_lang_Class_getName(LLNI_classinfo_wrap(c));
+ declaringclass = class_get_classname(c);
/* fill the java.lang.StackTraceElement element */
/* FIXME critical section */
- o->declaringClass = declaringclass;
- o->methodName = (java_lang_String *) javastring_new(m->name);
- o->fileName = filename;
- o->lineNumber = linenumber;
+ steo->declaringClass = (java_lang_String*) declaringclass;
+ steo->methodName = (java_lang_String*) javastring_new(m->name);
+ steo->fileName = filename;
+ steo->lineNumber = linenumber;
- return (jobject) o;
+ return (jobject) steo;
}
jint JVM_IHashCode(JNIEnv* env, jobject handle)
{
- TRACEJVMCALLS("JVM_IHashCode(env=%p, jobject=%p)", env, handle);
+ TRACEJVMCALLS(("JVM_IHashCode(env=%p, jobject=%p)", env, handle));
return (jint) ((ptrint) handle);
}
java_handle_t *o;
#endif
- TRACEJVMCALLS("JVM_MonitorWait(env=%p, handle=%p, ms=%ld)", env, handle, ms);
+ TRACEJVMCALLS(("JVM_MonitorWait(env=%p, handle=%p, ms=%ld)", env, handle, ms));
if (ms < 0) {
/* exceptions_throw_illegalargumentexception("argument out of range"); */
exceptions_throw_illegalargumentexception();
java_handle_t *o;
#endif
- TRACEJVMCALLS("JVM_MonitorNotify(env=%p, handle=%p)", env, handle);
+ TRACEJVMCALLS(("JVM_MonitorNotify(env=%p, handle=%p)", env, handle));
#if defined(ENABLE_THREADS)
o = (java_handle_t *) handle;
java_handle_t *o;
#endif
- TRACEJVMCALLS("JVM_MonitorNotifyAll(env=%p, handle=%p)", env, handle);
+ TRACEJVMCALLS(("JVM_MonitorNotifyAll(env=%p, handle=%p)", env, handle));
#if defined(ENABLE_THREADS)
o = (java_handle_t *) handle;
jobject JVM_Clone(JNIEnv* env, jobject handle)
{
-#if PRINTJVM
- log_println("JVM_Clone: handle=%p", handle);
-#endif
+ TRACEJVMCALLS(("JVM_Clone(env=%p, handle=%p)", env, handle));
+
return (jobject) builtin_clone(env, (java_handle_t *) handle);
}
jboolean JVM_IsSilentCompiler(JNIEnv *env, jclass compCls)
{
log_println("JVM_IsSilentCompiler: IMPLEMENT ME!");
+
+ return 0;
}
jboolean JVM_CompileClass(JNIEnv *env, jclass compCls, jclass cls)
{
log_println("JVM_CompileClass: IMPLEMENT ME!");
+
+ return 0;
}
jboolean JVM_CompileClasses(JNIEnv *env, jclass cls, jstring jname)
{
log_println("JVM_CompileClasses: IMPLEMENT ME!");
+
+ return 0;
}
jobject JVM_CompilerCommand(JNIEnv *env, jclass compCls, jobject arg)
{
log_println("JVM_CompilerCommand: IMPLEMENT ME!");
+
+ return 0;
}
void JVM_EnableCompiler(JNIEnv *env, jclass compCls)
{
- TRACEJVMCALLS("JVM_EnableCompiler(env=%p, compCls=%p)", env, compCls);
- PRINTJVMWARNINGS("JVM_EnableCompiler not supported");
+ TRACEJVMCALLS(("JVM_EnableCompiler(env=%p, compCls=%p)", env, compCls));
+ PRINTJVMWARNINGS(("JVM_EnableCompiler not supported"));
}
void JVM_DisableCompiler(JNIEnv *env, jclass compCls)
{
- TRACEJVMCALLS("JVM_DisableCompiler(env=%p, compCls=%p)", env, compCls);
- PRINTJVMWARNINGS("JVM_DisableCompiler not supported");
+ TRACEJVMCALLS(("JVM_DisableCompiler(env=%p, compCls=%p)", env, compCls));
+ PRINTJVMWARNINGS(("JVM_DisableCompiler not supported"));
}
jint JVM_GetLastErrorString(char *buf, int len)
{
- const char *s;
- int n;
-
- if (errno == 0) {
- return 0;
- }
- else {
- s = strerror(errno);
- n = strlen(s);
+ TRACEJVMCALLS(("JVM_GetLastErrorString(buf=%p, len=%d", buf, len));
- if (n >= len)
- n = len - 1;
-
- strncpy(buf, s, n);
-
- buf[n] = '\0';
-
- return n;
- }
+ return hpi_system->GetLastErrorString(buf, len);
}
char *JVM_NativePath(char *path)
{
- TRACEJVMCALLS("JVM_NativePath(path=%s)", path);
+ TRACEJVMCALLS(("JVM_NativePath(path=%s)", path));
- /* XXX is this correct? */
-
- return path;
+ return hpi_file->NativePath(path);
}
jclass JVM_GetCallerClass(JNIEnv* env, int depth)
{
- java_handle_objectarray_t *oa;
-
- TRACEJVMCALLS("JVM_GetCallerClass(env=%p, depth=%d)", env, depth);
-
- oa = stacktrace_getClassContext();
-
- if (oa == NULL)
- return NULL;
+ classinfo *c;
- if (oa->header.size < depth)
- return NULL;
+ TRACEJVMCALLS(("JVM_GetCallerClass(env=%p, depth=%d)", env, depth));
- return (jclass) oa->data[depth - 1];
+ c = stacktrace_get_caller_class(depth);
+ return (jclass) c;
}
classinfo *c;
utf *u;
- TRACEJVMCALLS("JVM_FindPrimitiveClass(env=%p, s=%s)", env, s);
+ TRACEJVMCALLS(("JVM_FindPrimitiveClass(env=%p, s=%s)", env, s));
u = utf_new_char(s);
c = primitive_class_get_by_name(u);
void JVM_ResolveClass(JNIEnv* env, jclass cls)
{
- TRACEJVMCALLS("JVM_ResolveClass(env=%p, cls=%p)", env, cls);
- PRINTJVMWARNINGS("JVM_ResolveClass not implemented");
+ TRACEJVMCALLS(("JVM_ResolveClass(env=%p, cls=%p)", env, cls));
+ PRINTJVMWARNINGS(("JVM_ResolveClass not implemented"));
}
jclass JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init, jobject loader, jboolean throwError)
{
- classinfo *c;
- utf *u;
- classloader *cl;
+ classinfo *c;
+ utf *u;
+ classloader_t *cl;
+
+ TRACEJVMCALLS(("JVM_FindClassFromClassLoader(name=%s, init=%d, loader=%p, throwError=%d)", name, init, loader, throwError));
+
+ /* As of now, OpenJDK does not call this function with throwError
+ is true. */
- TRACEJVMCALLS("JVM_FindClassFromClassLoader: name=%s, init=%d, loader=%p, throwError=%d", name, init, loader, throwError);
+ assert(throwError == false);
u = utf_new_char(name);
cl = loader_hashtable_classloader_add((java_handle_t *) loader);
jclass JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init, jclass from)
{
log_println("JVM_FindClassFromClass: IMPLEMENT ME!");
+
+ return NULL;
}
jclass JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd)
{
log_println("JVM_DefineClass: IMPLEMENT ME!");
+
+ return NULL;
}
jclass JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source)
{
- classinfo *c;
- utf *u;
- classloader *cl;
+ classinfo *c;
+ utf *u;
+ classloader_t *cl;
- TRACEJVMCALLS("JVM_DefineClassWithSource(env=%p, name=%s, loader=%p, buf=%p, len=%d, pd=%p, source=%s)", env, name, loader, buf, len, pd, source);
+ TRACEJVMCALLS(("JVM_DefineClassWithSource(env=%p, name=%s, loader=%p, buf=%p, len=%d, pd=%p, source=%s)", env, name, loader, buf, len, pd, source));
if (name != NULL)
u = utf_new_char(name);
/* XXX do something with source */
- c = class_define(u, cl, len, (const uint8_t *) buf, (java_handle_t *) pd);
+ c = class_define(u, cl, len, (uint8_t *) buf, (java_handle_t *) pd);
return (jclass) LLNI_classinfo_wrap(c);
}
jclass JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
{
- classloader *cl;
- utf *u;
- classinfo *c;
+ classloader_t *cl;
+ utf *u;
+ classinfo *c;
- TRACEJVMCALLS("JVM_FindLoadedClass(env=%p, loader=%p, name=%p)", env, loader, name);
+ TRACEJVMCALLS(("JVM_FindLoadedClass(env=%p, loader=%p, name=%p)", env, loader, name));
cl = loader_hashtable_classloader_add((java_handle_t *) loader);
jstring JVM_GetClassName(JNIEnv *env, jclass cls)
{
-#if PRINTJVM
- log_println("JVM_GetClassName: cls=%p", cls);
-#endif
- return (jstring) _Jv_java_lang_Class_getName((java_lang_Class *) cls);
+ classinfo* c;
+
+ TRACEJVMCALLS(("JVM_GetClassName(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ return (jstring) class_get_classname(c);
}
classinfo *c;
java_handle_objectarray_t *oa;
- TRACEJVMCALLS("JVM_GetClassInterfaces(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLS(("JVM_GetClassInterfaces(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
jobject JVM_GetClassLoader(JNIEnv *env, jclass cls)
{
- classinfo *c;
- classloader *cl;
+ classinfo *c;
+ classloader_t *cl;
- TRACEJVMCALLS("JVM_GetClassLoader(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLSENTER(("JVM_GetClassLoader(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
cl = class_get_classloader(c);
+ TRACEJVMCALLSEXIT(("->%p", cl));
+
return (jobject) cl;
}
{
classinfo *c;
-#if PRINTJVM
- log_println("JVM_IsInterface: cls=%p", cls);
-#endif
+ TRACEJVMCALLS(("JVM_IsInterface(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
jobjectArray JVM_GetClassSigners(JNIEnv *env, jclass cls)
{
log_println("JVM_GetClassSigners: IMPLEMENT ME!");
+
+ return NULL;
}
classinfo *c;
java_handle_objectarray_t *hoa;
- TRACEJVMCALLS("JVM_SetClassSigners(env=%p, cls=%p, signers=%p)", env, cls, signers);
+ TRACEJVMCALLS(("JVM_SetClassSigners(env=%p, cls=%p, signers=%p)", env, cls, signers));
c = LLNI_classinfo_unwrap(cls);
{
classinfo *c;
- TRACEJVMCALLS("JVM_GetProtectionDomain(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLS(("JVM_GetProtectionDomain(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
jobject JVM_DoPrivileged(JNIEnv *env, jclass cls, jobject action, jobject context, jboolean wrapException)
{
- java_handle_t *o;
+ java_handle_t *h;
classinfo *c;
methodinfo *m;
java_handle_t *result;
java_handle_t *e;
-#if PRINTJVM
- log_println("JVM_DoPrivileged: action=%p, context=%p, wrapException=%d", action, context, wrapException);
-#endif
+ TRACEJVMCALLS(("JVM_DoPrivileged(env=%p, cls=%p, action=%p, context=%p, wrapException=%d)", env, cls, action, context, wrapException));
- o = (java_handle_t *) action;
- c = o->vftbl->class;
+ h = (java_handle_t *) action;
+ LLNI_class_get(h, c);
if (action == NULL) {
exceptions_throw_nullpointerexception();
/* XXX It seems something with a privileged stack needs to be done
here. */
- result = vm_call_method(m, o);
+ result = vm_call_method(m, h);
- e = exceptions_get_and_clear_exception();
+ e = exceptions_get_exception();
if (e != NULL) {
- exceptions_throw_privilegedactionexception(e);
+ if ( builtin_instanceof(e, class_java_lang_Exception) &&
+ !builtin_instanceof(e, class_java_lang_RuntimeException)) {
+ exceptions_clear_exception();
+ exceptions_throw_privilegedactionexception(e);
+ }
+
return NULL;
}
jobject JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls)
{
log_println("JVM_GetInheritedAccessControlContext: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)
{
- TRACEJVMCALLS("JVM_GetStackAccessControlContext(env=%p, cls=%p): IMPLEMENT ME!", env, cls);
+ TRACEJVMCALLS(("JVM_GetStackAccessControlContext(env=%p, cls=%p): IMPLEMENT ME!", env, cls));
/* XXX All stuff I tested so far works without that function. At
some point we have to implement it, but I disable the output
jboolean JVM_IsArrayClass(JNIEnv *env, jclass cls)
{
-#if PRINTJVM
- log_println("JVM_IsArrayClass: cls=%p", cls);
-#endif
- return class_is_array(LLNI_classinfo_unwrap(cls));
+ classinfo *c;
+
+ TRACEJVMCALLS(("JVM_IsArrayClass(env=%p, cls=%p)", env, cls));
+
+ c = LLNI_classinfo_unwrap(cls);
+
+ return class_is_array(c);
}
{
classinfo *c;
- c = LLNI_classinfo_unwrap(cls);
+ TRACEJVMCALLS(("JVM_IsPrimitiveClass(env=%p, cls=%p)", env, cls));
-#if PRINTJVM
- log_println("JVM_IsPrimitiveClass(cls=%p)", cls);
-#endif
+ c = LLNI_classinfo_unwrap(cls);
return class_is_primitive(c);
}
classinfo *component;
classinfo *c;
- TRACEJVMCALLS("JVM_GetComponentType(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLS(("JVM_GetComponentType(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
classinfo *c;
int32_t flags;
- TRACEJVMCALLS("JVM_GetClassModifiers(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLS(("JVM_GetClassModifiers(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
classinfo *c;
java_handle_objectarray_t *oa;
- TRACEJVMCALLS("JVM_GetDeclaredClasses(env=%p, ofClass=%p)", env, ofClass);
+ TRACEJVMCALLS(("JVM_GetDeclaredClasses(env=%p, ofClass=%p)", env, ofClass));
c = LLNI_classinfo_unwrap(ofClass);
classinfo *c;
classinfo *dc;
- TRACEJVMCALLS("JVM_GetDeclaringClass(env=%p, ofClass=%p)", env, ofClass);
+ TRACEJVMCALLS(("JVM_GetDeclaringClass(env=%p, ofClass=%p)", env, ofClass));
c = LLNI_classinfo_unwrap(ofClass);
utf *u;
java_handle_t *s;
- TRACEJVMCALLS("JVM_GetClassSignature(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLS(("JVM_GetClassSignature(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
classinfo *c = NULL; /* classinfo for 'cls' */
java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
- TRACEJVMCALLS("JVM_GetClassAnnotations: cls=%p", cls);
+ TRACEJVMCALLS(("JVM_GetClassAnnotations: cls=%p", cls));
if (cls == NULL) {
exceptions_throw_nullpointerexception();
java_lang_reflect_Field *rf = NULL; /* java.lang.reflect.Field for 'field' */
java_handle_bytearray_t *ba = NULL; /* unparsed annotations */
- TRACEJVMCALLS("JVM_GetFieldAnnotations: field=%p", field);
+ TRACEJVMCALLS(("JVM_GetFieldAnnotations: field=%p", field));
if (field == NULL) {
exceptions_throw_nullpointerexception();
java_lang_reflect_Method *rm = NULL; /* java.lang.reflect.Method for 'method' */
java_handle_bytearray_t *ba = NULL; /* unparsed annotations */
- TRACEJVMCALLS("JVM_GetMethodAnnotations: method=%p", method);
+ TRACEJVMCALLS(("JVM_GetMethodAnnotations: method=%p", method));
if (method == NULL) {
exceptions_throw_nullpointerexception();
java_lang_reflect_Method *rm = NULL; /* java.lang.reflect.Method for 'method' */
java_handle_bytearray_t *ba = NULL; /* unparsed annotation default value */
- TRACEJVMCALLS("JVM_GetMethodDefaultAnnotationValue: method=%p", method);
+ TRACEJVMCALLS(("JVM_GetMethodDefaultAnnotationValue: method=%p", method));
if (method == NULL) {
exceptions_throw_nullpointerexception();
java_lang_reflect_Method *rm = NULL; /* java.lang.reflect.Method for 'method' */
java_handle_bytearray_t *ba = NULL; /* unparsed parameter annotations */
- TRACEJVMCALLS("JVM_GetMethodParameterAnnotations: method=%p", method);
+ TRACEJVMCALLS(("JVM_GetMethodParameterAnnotations: method=%p", method));
if (method == NULL) {
exceptions_throw_nullpointerexception();
jobjectArray JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly)
{
-#if PRINTJVM
- log_println("JVM_GetClassDeclaredFields: ofClass=%p, publicOnly=%d", ofClass, publicOnly);
-#endif
- return (jobjectArray) _Jv_java_lang_Class_getDeclaredFields((java_lang_Class *) ofClass, publicOnly);
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetClassDeclaredFields(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ oa = class_get_declaredfields(c, publicOnly);
+
+ return (jobjectArray) oa;
}
jobjectArray JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)
{
-#if PRINTJVM
- log_println("JVM_GetClassDeclaredMethods: ofClass=%p, publicOnly=%d", ofClass, publicOnly);
-#endif
- return (jobjectArray) _Jv_java_lang_Class_getDeclaredMethods((java_lang_Class *) ofClass, publicOnly);
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetClassDeclaredMethods(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ oa = class_get_declaredmethods(c, publicOnly);
+
+ return (jobjectArray) oa;
}
jobjectArray JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly)
{
-#if PRINTJVM
- log_println("JVM_GetClassDeclaredConstructors: ofClass=%p, publicOnly=%d", ofClass, publicOnly);
-#endif
- return (jobjectArray) _Jv_java_lang_Class_getDeclaredConstructors((java_lang_Class *) ofClass, publicOnly);
+ classinfo *c;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetClassDeclaredConstructors(env=%p, ofClass=%p, publicOnly=%d)", env, ofClass, publicOnly));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ oa = class_get_declaredconstructors(c, publicOnly);
+
+ return (jobjectArray) oa;
}
{
classinfo *c;
- TRACEJVMCALLS("JVM_GetClassAccessFlags(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLS(("JVM_GetClassAccessFlags(env=%p, cls=%p)", env, cls));
c = LLNI_classinfo_unwrap(cls);
java_lang_Object *constantPoolOop = (java_lang_Object*)cls;
/* constantPoolOop field of the constant pool object */
- TRACEJVMCALLS("JVM_GetClassConstantPool(env=%p, cls=%p)", env, cls);
+ TRACEJVMCALLS(("JVM_GetClassConstantPool(env=%p, cls=%p)", env, cls));
constantPool =
(sun_reflect_ConstantPool*)native_new_and_init(
{
classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetSize(env=%p, unused=%p, jcpool=%p)", env, unused, jcpool);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetSize(env=%p, unused=%p, jcpool=%p)", env, unused, jcpool));
c = LLNI_classinfo_unwrap(jcpool);
classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
classinfo *result; /* classinfo of the class at constant pool index 'index' */
- TRACEJVMCALLS("JVM_ConstantPoolGetClassAt(env=%p, jcpool=%p, index=%d)", env, jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetClassAt(env=%p, jcpool=%p, index=%d)", env, jcpool, index));
c = LLNI_classinfo_unwrap(jcpool);
classinfo *c; /* classinfo of the class for which 'this' is the constant pool */
classinfo *result; /* classinfo of the class at constant pool index 'index' */
- TRACEJVMCALLS("JVM_ConstantPoolGetClassAtIfLoaded(env=%p, unused=%p, jcpool=%p, index=%d)", env, unused, jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetClassAtIfLoaded(env=%p, unused=%p, jcpool=%p, index=%d)", env, unused, jcpool, index));
c = LLNI_classinfo_unwrap(jcpool);
constant_FMIref *ref; /* reference to the method in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetMethodAt: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetMethodAt: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Methodref);
classinfo *c = NULL; /* resolved declaring class of the method */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetMethodAtIfLoaded: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetMethodAtIfLoaded: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Methodref);
constant_FMIref *ref; /* reference to the field in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetFieldAt: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetFieldAt: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Fieldref);
classinfo *c; /* resolved declaring class for the field */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetFieldAtIfLoaded: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetFieldAtIfLoaded: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_FMIref*)class_getconstant(cls, index, CONSTANT_Fieldref);
constant_integer *ref; /* reference to the int value in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetIntAt: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetIntAt: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_integer*)class_getconstant(cls, index, CONSTANT_Integer);
constant_long *ref; /* reference to the long value in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetLongAt: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetLongAt: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_long*)class_getconstant(cls, index, CONSTANT_Long);
constant_float *ref; /* reference to the float value in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetFloatAt: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetFloatAt: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_float*)class_getconstant(cls, index, CONSTANT_Float);
constant_double *ref; /* reference to the double value in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetDoubleAt: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetDoubleAt: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (constant_double*)class_getconstant(cls, index, CONSTANT_Double);
utf *ref; /* utf object for the string in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetStringAt: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetStringAt: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (utf*)class_getconstant(cls, index, CONSTANT_String);
utf *ref; /* utf object for the utf8 data in constant pool at index 'index' */
classinfo *cls; /* classinfo of the class for which 'this' is the constant pool */
- TRACEJVMCALLS("JVM_ConstantPoolGetUTF8At: jcpool=%p, index=%d", jcpool, index);
+ TRACEJVMCALLS(("JVM_ConstantPoolGetUTF8At: jcpool=%p, index=%d", jcpool, index));
cls = LLNI_classinfo_unwrap(jcpool);
ref = (utf*)class_getconstant(cls, index, CONSTANT_Utf8);
jboolean status;
utf *name;
- TRACEJVMCALLS("JVM_DesiredAssertionStatus(env=%p, unused=%p, cls=%p)", env, unused, cls);
+ TRACEJVMCALLS(("JVM_DesiredAssertionStatus(env=%p, unused=%p, cls=%p)", env, unused, cls));
c = LLNI_classinfo_unwrap(cls);
s4 i, j;
#endif
- TRACEJVMCALLS("JVM_AssertionStatusDirectives(env=%p, unused=%p)", env, unused);
+ TRACEJVMCALLS(("JVM_AssertionStatusDirectives(env=%p, unused=%p)", env, unused));
c = load_class_bootstrap(utf_new_char("java/lang/AssertionStatusDirectives"));
/* JVM_GetClassNameUTF */
-const char* JVM_GetClassNameUTF(JNIEnv *env, jclass cls)
+const char *JVM_GetClassNameUTF(JNIEnv *env, jclass cls)
{
log_println("JVM_GetClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
}
jint JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cls)
{
log_println("JVM_GetClassCPEntriesCount: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetClassFieldsCount(JNIEnv *env, jclass cls)
{
log_println("JVM_GetClassFieldsCount: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetClassMethodsCount(JNIEnv *env, jclass cls)
{
log_println("JVM_GetClassMethodsCount: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cls, jint method_index)
{
log_println("JVM_GetMethodIxExceptionsCount: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cls, jint method_index)
{
log_println("JVM_GetMethodIxByteCodeLength: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cls, int method_index)
{
log_println("JVM_GetMethodIxExceptionTableLength: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetMethodIxModifiers(JNIEnv *env, jclass cls, int method_index)
{
log_println("JVM_GetMethodIxModifiers: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetFieldIxModifiers(JNIEnv *env, jclass cls, int field_index)
{
log_println("JVM_GetFieldIxModifiers: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cls, int method_index)
{
log_println("JVM_GetMethodIxLocalsCount: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cls, int method_index)
{
log_println("JVM_GetMethodIxArgsSize: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cls, int method_index)
{
log_println("JVM_GetMethodIxMaxStack: IMPLEMENT ME!");
+
+ return 0;
}
jboolean JVM_IsConstructorIx(JNIEnv *env, jclass cls, int method_index)
{
log_println("JVM_IsConstructorIx: IMPLEMENT ME!");
+
+ return 0;
}
/* JVM_GetMethodIxNameUTF */
-const char* JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)
+const char *JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cls, jint method_index)
{
log_println("JVM_GetMethodIxNameUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetMethodIxSignatureUTF */
-const char* JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cls, jint method_index)
+const char *JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cls, jint method_index)
{
log_println("JVM_GetMethodIxSignatureUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetCPFieldNameUTF */
-const char* JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+const char *JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cls, jint cp_index)
{
log_println("JVM_GetCPFieldNameUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetCPMethodNameUTF */
-const char* JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+const char *JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cls, jint cp_index)
{
log_println("JVM_GetCPMethodNameUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetCPMethodSignatureUTF */
-const char* JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
+const char *JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
{
log_println("JVM_GetCPMethodSignatureUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetCPFieldSignatureUTF */
-const char* JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
+const char *JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cls, jint cp_index)
{
log_println("JVM_GetCPFieldSignatureUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetCPClassNameUTF */
-const char* JVM_GetCPClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+const char *JVM_GetCPClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
{
log_println("JVM_GetCPClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetCPFieldClassNameUTF */
-const char* JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+const char *JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
{
log_println("JVM_GetCPFieldClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetCPMethodClassNameUTF */
-const char* JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
+const char *JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cls, jint cp_index)
{
log_println("JVM_GetCPMethodClassNameUTF: IMPLEMENT ME!");
+
+ return NULL;
}
jint JVM_GetCPFieldModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)
{
log_println("JVM_GetCPFieldModifiers: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetCPMethodModifiers(JNIEnv *env, jclass cls, int cp_index, jclass called_cls)
{
log_println("JVM_GetCPMethodModifiers: IMPLEMENT ME!");
+
+ return 0;
}
jboolean JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2)
{
log_println("JVM_IsSameClassPackage: IMPLEMENT ME!");
+
+ return 0;
}
/* JVM_Open */
+/* Taken from: hotspot/src/share/vm/prims/jvm.h */
+
+/*
+ * JVM I/O error codes
+ */
+#define JVM_EEXIST -100
+
jint JVM_Open(const char *fname, jint flags, jint mode)
{
int result;
-#if PRINTJVM
- log_println("JVM_Open: fname=%s, flags=%d, mode=%d", fname, flags, mode);
-#endif
+ TRACEJVMCALLS(("JVM_Open(fname=%s, flags=%d, mode=%d)", fname, flags, mode));
- result = open(fname, flags, mode);
+ result = hpi_file->Open(fname, flags, mode);
if (result >= 0) {
return result;
}
else {
- switch(errno) {
+ switch (errno) {
case EEXIST:
- /* XXX don't know what to do here */
-/* return JVM_EEXIST; */
- return -1;
+ return JVM_EEXIST;
default:
return -1;
}
jint JVM_Close(jint fd)
{
-#if PRINTJVM
- log_println("JVM_Close: fd=%d", fd);
-#endif
- return close(fd);
+ TRACEJVMCALLS(("JVM_Close(fd=%d)", fd));
+
+ return hpi_file->Close(fd);
}
jint JVM_Read(jint fd, char *buf, jint nbytes)
{
-#if PRINTJVM
- log_println("JVM_Read: fd=%d, buf=%p, nbytes=%d", fd, buf, nbytes);
-#endif
- return read(fd, buf, nbytes);
+ TRACEJVMCALLS(("JVM_Read(fd=%d, buf=%p, nbytes=%d)", fd, buf, nbytes));
+
+ return (jint) hpi_file->Read(fd, buf, nbytes);
}
jint JVM_Write(jint fd, char *buf, jint nbytes)
{
-#if PRINTJVM
- log_println("JVM_Write: fd=%d, buf=%s, nbytes=%d", fd, buf, nbytes);
-#endif
- return write(fd, buf, nbytes);
+ TRACEJVMCALLS(("JVM_Write(fd=%d, buf=%s, nbytes=%d)", fd, buf, nbytes));
+
+ return (jint) hpi_file->Write(fd, buf, nbytes);
}
jint JVM_Available(jint fd, jlong *pbytes)
{
-#if defined(FIONREAD)
- int bytes;
-
- TRACEJVMCALLS("JVM_Available(fd=%d, pbytes=%p)", fd, pbytes);
-
- *pbytes = 0;
-
- if (ioctl(fd, FIONREAD, &bytes) < 0)
- return 0;
+ TRACEJVMCALLS(("JVM_Available(fd=%d, pbytes=%p)", fd, pbytes));
- *pbytes = bytes;
-
- return 1;
-#else
-# error FIONREAD not defined
-#endif
+ return hpi_file->Available(fd, pbytes);
}
jlong JVM_Lseek(jint fd, jlong offset, jint whence)
{
- TRACEJVMCALLS("JVM_Lseek(fd=%d, offset=%ld, whence=%d)", fd, offset, whence);
+ TRACEJVMCALLS(("JVM_Lseek(fd=%d, offset=%ld, whence=%d)", fd, offset, whence));
- return (jlong) lseek(fd, (off_t) offset, whence);
+ return hpi_file->Seek(fd, (off_t) offset, whence);
}
jint JVM_SetLength(jint fd, jlong length)
{
- TRACEJVMCALLS("JVM_SetLength(fd=%d, length=%ld)", length);
+ TRACEJVMCALLS(("JVM_SetLength(fd=%d, length=%ld)", length));
- return ftruncate(fd, length);
+ return hpi_file->SetLength(fd, length);
}
jint JVM_Sync(jint fd)
{
- TRACEJVMCALLS("JVM_Sync(fd=%d)", fd);
+ TRACEJVMCALLS(("JVM_Sync(fd=%d)", fd));
- return fsync(fd);
+ return hpi_file->Sync(fd);
}
void JVM_StartThread(JNIEnv* env, jobject jthread)
{
-#if PRINTJVM
- log_println("JVM_StartThread: jthread=%p", jthread);
-#endif
- _Jv_java_lang_Thread_start((java_lang_Thread *) jthread, 0);
+ TRACEJVMCALLS(("JVM_StartThread(env=%p, jthread=%p)", env, jthread));
+
+ threads_thread_start((java_handle_t *) jthread);
}
jboolean JVM_IsThreadAlive(JNIEnv* env, jobject jthread)
{
- threadobject *t;
- bool equal;
- bool result;
-
- TRACEJVMCALLS("JVM_IsThreadAlive(env=%p, jthread=%p)", env, jthread);
-
- /* XXX this is just a quick hack */
+ java_handle_t *h;
+ threadobject *t;
+ bool result;
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- LLNI_equals(t->object, jthread, equal);
+ TRACEJVMCALLS(("JVM_IsThreadAlive(env=%p, jthread=%p)", env, jthread));
- if (equal == true)
- break;
- }
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
/* The threadobject is null when a thread is created in Java. The
priority is set later during startup. */
void JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio)
{
-#if PRINTJVM
- log_println("JVM_SetThreadPriority: jthread=%p, prio=%d", jthread, prio);
-#endif
- _Jv_java_lang_Thread_setPriority((java_lang_Thread *) jthread, prio);
+ java_handle_t *h;
+ threadobject *t;
+
+ TRACEJVMCALLS(("JVM_SetThreadPriority(env=%p, jthread=%p, prio=%d)", env, jthread, prio));
+
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
+
+ /* The threadobject is null when a thread is created in Java. The
+ priority is set later during startup. */
+
+ if (t == NULL)
+ return;
+
+ threads_set_thread_priority(t->tid, prio);
}
void JVM_Yield(JNIEnv *env, jclass threadClass)
{
- TRACEJVMCALLS("JVM_Yield(env=%p, threadClass=%p)", env, threadClass);
+ TRACEJVMCALLS(("JVM_Yield(env=%p, threadClass=%p)", env, threadClass));
threads_yield();
}
void JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis)
{
-#if PRINTJVM
- log_println("JVM_Sleep: threadClass=%p, millis=%ld", threadClass, millis);
-#endif
- _Jv_java_lang_Thread_sleep(millis);
+ TRACEJVMCALLS(("JVM_Sleep(env=%p, threadClass=%p, millis=%ld)", env, threadClass, millis));
+
+ threads_sleep(millis, 0);
}
jobject JVM_CurrentThread(JNIEnv* env, jclass threadClass)
{
-#if PRINTJVM
- log_println("JVM_CurrentThread: threadClass=%p", threadClass);
-#endif
- return (jobject) _Jv_java_lang_Thread_currentThread();
+ java_object_t *o;
+
+ TRACEJVMCALLSVERBOSE(("JVM_CurrentThread(env=%p, threadClass=%p)", env, threadClass));
+
+ o = thread_get_current_object();
+
+ return (jobject) o;
}
jint JVM_CountStackFrames(JNIEnv* env, jobject jthread)
{
log_println("JVM_CountStackFrames: IMPLEMENT ME!");
+
+ return 0;
}
void JVM_Interrupt(JNIEnv* env, jobject jthread)
{
- log_println("JVM_Interrupt: IMPLEMENT ME!");
+ java_handle_t *h;
+ threadobject *t;
+
+ TRACEJVMCALLS(("JVM_Interrupt(env=%p, jthread=%p)", env, jthread));
+
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
+
+ if (t == NULL)
+ return;
+
+ threads_thread_interrupt(t);
}
jboolean JVM_IsInterrupted(JNIEnv* env, jobject jthread, jboolean clear_interrupted)
{
-#if PRINTJVM
- log_println("JVM_IsInterrupted: jthread=%p, clear_interrupted=%d", jthread, clear_interrupted);
-#endif
- /* XXX do something with clear_interrupted */
- return _Jv_java_lang_Thread_isInterrupted((java_lang_Thread *) jthread);
+ java_handle_t *h;
+ threadobject *t;
+ jboolean interrupted;
+
+ TRACEJVMCALLS(("JVM_IsInterrupted(env=%p, jthread=%p, clear_interrupted=%d)", env, jthread, clear_interrupted));
+
+ h = (java_handle_t *) jthread;
+ t = thread_get_thread(h);
+
+ interrupted = thread_is_interrupted(t);
+
+ if (interrupted && clear_interrupted)
+ thread_set_interrupted(t, false);
+
+ return interrupted;
}
java_handle_t *h;
bool result;
- TRACEJVMCALLS("JVM_HoldsLock(env=%p, threadClass=%p, obj=%p)", env, threadClass, obj);
+ TRACEJVMCALLS(("JVM_HoldsLock(env=%p, threadClass=%p, obj=%p)", env, threadClass, obj));
h = (java_handle_t *) obj;
jclass JVM_CurrentLoadedClass(JNIEnv *env)
{
log_println("JVM_CurrentLoadedClass: IMPLEMENT ME!");
+
+ return NULL;
}
doPrivileged, return NULL */
log_println("JVM_CurrentClassLoader: IMPLEMENT ME!");
+
+ return NULL;
}
jobjectArray JVM_GetClassContext(JNIEnv *env)
{
-#if PRINTJVM
- log_println("JVM_GetClassContext");
-#endif
+ TRACEJVMCALLS(("JVM_GetClassContext(env=%p)", env));
+
return (jobjectArray) stacktrace_getClassContext();
}
jint JVM_ClassDepth(JNIEnv *env, jstring name)
{
log_println("JVM_ClassDepth: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_ClassLoaderDepth(JNIEnv *env)
{
log_println("JVM_ClassLoaderDepth: IMPLEMENT ME!");
+
+ return 0;
}
utf *u;
utf *result;
- TRACEJVMCALLS("JVM_GetSystemPackage(env=%p, name=%p)", env, name);
+ TRACEJVMCALLS(("JVM_GetSystemPackage(env=%p, name=%p)", env, name));
/* s = package_find(name); */
- u = javastring_toutf(name, false);
+ u = javastring_toutf((java_handle_t *) name, false);
+
result = package_find(u);
+
if (result != NULL)
s = javastring_new(result);
else
jobjectArray JVM_GetSystemPackages(JNIEnv *env)
{
log_println("JVM_GetSystemPackages: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_AllocateNewObject(JNIEnv *env, jobject receiver, jclass currClass, jclass initClass)
{
log_println("JVM_AllocateNewObject: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_AllocateNewArray(JNIEnv *env, jobject obj, jclass currClass, jint length)
{
log_println("JVM_AllocateNewArray: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_LatestUserDefinedLoader(JNIEnv *env)
{
- classloader *cl;
+ classloader_t *cl;
- TRACEJVMCALLS("JVM_LatestUserDefinedLoader(env=%p)", env);
+ TRACEJVMCALLS(("JVM_LatestUserDefinedLoader(env=%p)", env));
cl = stacktrace_first_nonnull_classloader();
jclass JVM_LoadClass0(JNIEnv *env, jobject receiver, jclass currClass, jstring currClassName)
{
log_println("JVM_LoadClass0: IMPLEMENT ME!");
+
+ return NULL;
}
{
java_handle_t *a;
- TRACEJVMCALLS("JVM_GetArrayLength(arr=%p)", arr);
+ TRACEJVMCALLS(("JVM_GetArrayLength(arr=%p)", arr));
a = (java_handle_t *) arr;
java_handle_t *a;
java_handle_t *o;
- TRACEJVMCALLS("JVM_GetArrayElement(env=%p, arr=%p, index=%d)", env, arr, index);
+ TRACEJVMCALLS(("JVM_GetArrayElement(env=%p, arr=%p, index=%d)", env, arr, index));
a = (java_handle_t *) arr;
jvalue JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode)
{
+ jvalue jv;
+
log_println("JVM_GetPrimitiveArrayElement: IMPLEMENT ME!");
+
+ jv.l = NULL;
+
+ return jv;
}
java_handle_t *a;
java_handle_t *value;
- TRACEJVMCALLS("JVM_SetArrayElement(env=%p, arr=%p, index=%d, val=%p)", env, arr, index, val);
+ TRACEJVMCALLS(("JVM_SetArrayElement(env=%p, arr=%p, index=%d, val=%p)", env, arr, index, val));
a = (java_handle_t *) arr;
value = (java_handle_t *) val;
java_handle_t *a;
java_handle_objectarray_t *oa;
- TRACEJVMCALLS("JVM_NewArray(env=%p, eltClass=%p, length=%d)", env, eltClass, length);
+ TRACEJVMCALLS(("JVM_NewArray(env=%p, eltClass=%p, length=%d)", env, eltClass, length));
if (eltClass == NULL) {
exceptions_throw_nullpointerexception();
c = LLNI_classinfo_unwrap(eltClass);
- /* create primitive or object array */
+ /* Create primitive or object array. */
if (class_is_primitive(c)) {
pc = primitive_arrayclass_get_by_name(c->name);
+
+ /* void arrays are not allowed. */
+
+ if (pc == NULL) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
a = builtin_newarray(length, pc);
return (jobject) a;
classinfo *ac;
java_handle_objectarray_t *a;
- TRACEJVMCALLS("JVM_NewMultiArray(env=%p, eltClass=%p, dim=%p)", env, eltClass, dim);
+ TRACEJVMCALLS(("JVM_NewMultiArray(env=%p, eltClass=%p, dim=%p)", env, eltClass, dim));
if (eltClass == NULL) {
exceptions_throw_nullpointerexception();
c = LLNI_classinfo_unwrap(eltClass);
- /* XXX This is just a quick hack to get it working. */
-
ia = (java_handle_intarray_t *) dim;
- length = array_length_get(ia);
+ length = array_length_get((java_handle_t *) ia);
+
+ /* We check here for exceptions thrown in array_length_get,
+ otherwise these exceptions get overwritten by the following
+ IllegalArgumentException. */
+
+ if (length < 0)
+ return NULL;
+
+ if ((length <= 0) || (length > /* MAX_DIM */ 255)) {
+ exceptions_throw_illegalargumentexception();
+ return NULL;
+ }
+
+ /* XXX This is just a quick hack to get it working. */
dims = MNEW(long, length);
if (ac == NULL)
return NULL;
- a = builtin_multianewarray(length, ac, dims);
+ a = builtin_multianewarray(length, (java_handle_t *) ac, dims);
return (jobject) a;
}
jint JVM_InitializeSocketLibrary()
{
- log_println("JVM_InitializeSocketLibrary: IMPLEMENT ME!");
+ TRACEJVMCALLS(("JVM_InitializeSocketLibrary()"));
+
+ return hpi_initialize_socket_library();
}
jint JVM_Socket(jint domain, jint type, jint protocol)
{
- TRACEJVMCALLS("JVM_Socket(domain=%d, type=%d, protocol=%d)", domain, type, protocol);
+ TRACEJVMCALLS(("JVM_Socket(domain=%d, type=%d, protocol=%d)", domain, type, protocol));
- return socket(domain, type, protocol);
+ return system_socket(domain, type, protocol);
}
jint JVM_SocketClose(jint fd)
{
- TRACEJVMCALLS("JVM_SocketClose(fd=%d)", fd);
+ TRACEJVMCALLS(("JVM_SocketClose(fd=%d)", fd));
- return close(fd);
+ return system_close(fd);
}
jint JVM_SocketShutdown(jint fd, jint howto)
{
- TRACEJVMCALLS("JVM_SocketShutdown(fd=%d, howto=%d)", fd, howto);
+ TRACEJVMCALLS(("JVM_SocketShutdown(fd=%d, howto=%d)", fd, howto));
- return shutdown(fd, howto);
+ return system_shutdown(fd, howto);
}
jint JVM_Recv(jint fd, char *buf, jint nBytes, jint flags)
{
log_println("JVM_Recv: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_Send(jint fd, char *buf, jint nBytes, jint flags)
{
log_println("JVM_Send: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_Timeout(int fd, long timeout)
{
log_println("JVM_Timeout: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_Listen(jint fd, jint count)
{
- TRACEJVMCALLS("JVM_Listen(fd=%d, count=%d)", fd, count);
+ TRACEJVMCALLS(("JVM_Listen(fd=%d, count=%d)", fd, count));
- return listen(fd, count);
+ return system_listen(fd, count);
}
jint JVM_Connect(jint fd, struct sockaddr *him, jint len)
{
- TRACEJVMCALLS("JVM_Connect(fd=%d, him=%p, len=%d)", fd, him, len);
+ TRACEJVMCALLS(("JVM_Connect(fd=%d, him=%p, len=%d)", fd, him, len));
- return connect(fd, him, len);
+ return system_connect(fd, him, len);
}
jint JVM_Bind(jint fd, struct sockaddr *him, jint len)
{
log_println("JVM_Bind: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_Accept(jint fd, struct sockaddr *him, jint *len)
{
- TRACEJVMCALLS("JVM_Accept(fd=%d, him=%p, len=%p)", fd, him, len);
+ TRACEJVMCALLS(("JVM_Accept(fd=%d, him=%p, len=%p)", fd, him, len));
- return accept(fd, him, (socklen_t *) len);
+ return system_accept(fd, him, (socklen_t *) len);
}
jint JVM_RecvFrom(jint fd, char *buf, int nBytes, int flags, struct sockaddr *from, int *fromlen)
{
log_println("JVM_RecvFrom: IMPLEMENT ME!");
+
+ return 0;
}
jint JVM_GetSockName(jint fd, struct sockaddr *him, int *len)
{
- TRACEJVMCALLS("JVM_GetSockName(fd=%d, him=%p, len=%p)", fd, him, len);
+ TRACEJVMCALLS(("JVM_GetSockName(fd=%d, him=%p, len=%p)", fd, him, len));
- return getsockname(fd, him, (socklen_t *) len);
+ return system_getsockname(fd, him, (socklen_t *) len);
}
jint JVM_SendTo(jint fd, char *buf, int len, int flags, struct sockaddr *to, int tolen)
{
log_println("JVM_SendTo: IMPLEMENT ME!");
+
+ return 0;
}
{
#if defined(FIONREAD)
int bytes;
+ int result;
- TRACEJVMCALLS("JVM_SocketAvailable(fd=%d, pbytes=%p)", fd, pbytes);
+ TRACEJVMCALLS(("JVM_SocketAvailable(fd=%d, pbytes=%p)", fd, pbytes));
*pbytes = 0;
- if (ioctl(fd, FIONREAD, &bytes) < 0)
+ result = ioctl(fd, FIONREAD, &bytes);
+
+ if (result < 0)
return 0;
*pbytes = bytes;
jint JVM_GetSockOpt(jint fd, int level, int optname, char *optval, int *optlen)
{
-#if defined(HAVE_GETSOCKOPT)
- TRACEJVMCALLS("JVM_GetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%p)", fd, level, optname, optval, optlen);
+ TRACEJVMCALLS(("JVM_GetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%p)", fd, level, optname, optval, optlen));
- return getsockopt(fd, level, optname, optval, (socklen_t *) optlen);
-#else
-# error getsockopt not available
-#endif
+ return system_getsockopt(fd, level, optname, optval, (socklen_t *) optlen);
}
jint JVM_SetSockOpt(jint fd, int level, int optname, const char *optval, int optlen)
{
-#if defined(HAVE_SETSOCKOPT)
- TRACEJVMCALLS("JVM_SetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%d)", fd, level, optname, optval, optlen);
+ TRACEJVMCALLS(("JVM_SetSockOpt(fd=%d, level=%d, optname=%d, optval=%s, optlen=%d)", fd, level, optname, optval, optlen));
- return setsockopt(fd, level, optname, optval, optlen);
-#else
-# error setsockopt not available
-#endif
+ return system_setsockopt(fd, level, optname, optval, optlen);
}
/* JVM_GetHostName */
-int JVM_GetHostName(char* name, int namelen)
+int JVM_GetHostName(char *name, int namelen)
{
- TRACEJVMCALLS("JVM_GetHostName(name=%s, namelen=%d)", name, namelen);
+ int result;
+
+ TRACEJVMCALLSENTER(("JVM_GetHostName(name=%s, namelen=%d)", name, namelen));
+
+ result = system_gethostname(name, namelen);
+
+ TRACEJVMCALLSEXIT(("->%d (name=%s)", result, name));
- return gethostname(name, namelen);
+ return result;
}
/* JVM_GetHostByAddr */
-struct hostent* JVM_GetHostByAddr(const char* name, int len, int type)
+struct hostent *JVM_GetHostByAddr(const char* name, int len, int type)
{
log_println("JVM_GetHostByAddr: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetHostByName */
-struct hostent* JVM_GetHostByName(char* name)
+struct hostent *JVM_GetHostByName(char* name)
{
log_println("JVM_GetHostByName: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetProtoByName */
-struct protoent* JVM_GetProtoByName(char* name)
+struct protoent *JVM_GetProtoByName(char* name)
{
log_println("JVM_GetProtoByName: IMPLEMENT ME!");
+
+ return NULL;
}
void *JVM_LoadLibrary(const char *name)
{
- utf *u;
+ utf* u;
+ void* handle;
- TRACEJVMCALLS("JVM_LoadLibrary(name=%s)", name);
+ TRACEJVMCALLSENTER(("JVM_LoadLibrary(name=%s)", name));
u = utf_new_char(name);
- return native_library_open(u);
+ handle = native_library_open(u);
+
+ TRACEJVMCALLSEXIT(("->%p", handle));
+
+ return handle;
}
void JVM_UnloadLibrary(void* handle)
{
- log_println("JVM_UnloadLibrary: IMPLEMENT ME!");
+ TRACEJVMCALLS(("JVM_UnloadLibrary(handle=%p)", handle));
+
+ native_library_close(handle);
}
{
lt_ptr symbol;
- TRACEJVMCALLS("JVM_FindLibraryEntry(handle=%p, name=%s)", handle, name);
+ TRACEJVMCALLSENTER(("JVM_FindLibraryEntry(handle=%p, name=%s)", handle, name));
symbol = lt_dlsym(handle, name);
+ TRACEJVMCALLSEXIT(("->%p", symbol));
+
return symbol;
}
jboolean JVM_IsNaN(jdouble a)
{
log_println("JVM_IsNaN: IMPLEMENT ME!");
+
+ return 0;
}
jboolean JVM_IsSupportedJNIVersion(jint version)
{
- TRACEJVMCALLS("JVM_IsSupportedJNIVersion(version=%d)", version);
+ TRACEJVMCALLS(("JVM_IsSupportedJNIVersion(version=%d)", version));
return jni_version_check(version);
}
jstring JVM_InternString(JNIEnv *env, jstring str)
{
- TRACEJVMCALLS("JVM_InternString(env=%p, str=%p)", env, str);
+ TRACEJVMCALLS(("JVM_InternString(env=%p, str=%p)", env, str));
return (jstring) javastring_intern((java_handle_t *) str);
}
{
java_object_t *o;
-#if PRINTJVM
- log_println("JVM_RawMonitorCreate");
-#endif
+ TRACEJVMCALLS(("JVM_RawMonitorCreate()"));
o = NEW(java_object_t);
JNIEXPORT void JNICALL JVM_RawMonitorDestroy(void *mon)
{
-#if PRINTJVM
- log_println("JVM_RawMonitorDestroy: mon=%p", mon);
-#endif
+ TRACEJVMCALLS(("JVM_RawMonitorDestroy(mon=%p)", mon));
+
FREE(mon, java_object_t);
}
JNIEXPORT jint JNICALL JVM_RawMonitorEnter(void *mon)
{
-#if PRINTJVM
- log_println("JVM_RawMonitorEnter: mon=%p", mon);
-#endif
+ TRACEJVMCALLS(("JVM_RawMonitorEnter(mon=%p)", mon));
+
(void) lock_monitor_enter((java_object_t *) mon);
return 0;
JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon)
{
-#if PRINTJVM
- log_println("JVM_RawMonitorExit: mon=%p", mon);
-#endif
+ TRACEJVMCALLS(("JVM_RawMonitorExit(mon=%p)", mon));
+
(void) lock_monitor_exit((java_object_t *) mon);
}
jboolean JVM_AccessVMBooleanFlag(const char* name, jboolean* value, jboolean is_get)
{
log_println("JVM_AccessVMBooleanFlag: IMPLEMENT ME!");
+
+ return 0;
}
jboolean JVM_AccessVMIntFlag(const char* name, jint* value, jboolean is_get)
{
log_println("JVM_AccessVMIntFlag: IMPLEMENT ME!");
+
+ return 0;
}
jobjectArray JVM_GetClassFields(JNIEnv *env, jclass cls, jint which)
{
log_println("JVM_GetClassFields: IMPLEMENT ME!");
+
+ return NULL;
}
jobjectArray JVM_GetClassMethods(JNIEnv *env, jclass cls, jint which)
{
log_println("JVM_GetClassMethods: IMPLEMENT ME!");
+
+ return NULL;
}
jobjectArray JVM_GetClassConstructors(JNIEnv *env, jclass cls, jint which)
{
log_println("JVM_GetClassConstructors: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_GetClassField(JNIEnv *env, jclass cls, jstring name, jint which)
{
log_println("JVM_GetClassField: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_GetClassMethod(JNIEnv *env, jclass cls, jstring name, jobjectArray types, jint which)
{
log_println("JVM_GetClassMethod: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_GetClassConstructor(JNIEnv *env, jclass cls, jobjectArray types, jint which)
{
log_println("JVM_GetClassConstructor: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_NewInstance(JNIEnv *env, jclass cls)
{
log_println("JVM_NewInstance: IMPLEMENT ME!");
+
+ return NULL;
}
jobject JVM_GetField(JNIEnv *env, jobject field, jobject obj)
{
log_println("JVM_GetField: IMPLEMENT ME!");
+
+ return NULL;
}
jvalue JVM_GetPrimitiveField(JNIEnv *env, jobject field, jobject obj, unsigned char wCode)
{
+ jvalue jv;
+
log_println("JVM_GetPrimitiveField: IMPLEMENT ME!");
+
+ jv.l = NULL;
+
+ return jv;
}
jobject JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0)
{
-#if PRINTJVM
- log_println("JVM_InvokeMethod: method=%p, obj=%p, args0=%p", method, obj, args0);
-#endif
- return (jobject) _Jv_java_lang_reflect_Method_invoke((java_lang_reflect_Method *) method, (java_lang_Object *) obj, (java_handle_objectarray_t *) args0);
+ java_lang_reflect_Method *rm;
+ classinfo *c;
+ int32_t slot;
+ int32_t override;
+ methodinfo *m;
+ java_handle_t *ro;
+
+ TRACEJVMCALLS(("JVM_InvokeMethod(env=%p, method=%p, obj=%p, args0=%p)", env, method, obj, args0));
+
+ rm = (java_lang_reflect_Method *) method;
+
+ LLNI_field_get_cls(rm, clazz, c);
+ LLNI_field_get_val(rm, slot, slot);
+ LLNI_field_get_val(rm, override, override);
+
+ m = &(c->methods[slot]);
+
+ ro = reflect_method_invoke(m, (java_handle_t *) obj, (java_handle_objectarray_t *) args0, override);
+
+ return (jobject) ro;
}
/* JVM_NewInstanceFromConstructor */
-jobject JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0)
+jobject JVM_NewInstanceFromConstructor(JNIEnv *env, jobject con, jobjectArray args0)
{
-#if PRINTJVM
- log_println("JVM_NewInstanceFromConstructor: c=%p, args0=%p", c, args0);
-#endif
- return (jobject) _Jv_java_lang_reflect_Constructor_newInstance(env, (java_lang_reflect_Constructor *) c, (java_handle_objectarray_t *) args0);
+ java_lang_reflect_Constructor *rc;
+ classinfo *c;
+ int32_t slot;
+ int32_t override;
+ methodinfo *m;
+ java_handle_t *o;
+
+ TRACEJVMCALLS(("JVM_NewInstanceFromConstructor(env=%p, c=%p, args0=%p)", env, con, args0));
+
+ rc = (java_lang_reflect_Constructor *) con;
+
+ LLNI_field_get_cls(rc, clazz, c);
+ LLNI_field_get_val(rc, slot, slot);
+ LLNI_field_get_val(rc, override, override);
+
+ m = &(c->methods[slot]);
+
+ o = reflect_constructor_newinstance(m, (java_handle_objectarray_t *) args0, override);
+
+ return (jobject) o;
}
jboolean JVM_SupportsCX8()
{
- TRACEJVMCALLS("JVM_SupportsCX8()");
+ TRACEJVMCALLS(("JVM_SupportsCX8()"));
/* IMPLEMENT ME */
jboolean JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong oldVal, jlong newVal)
{
log_println("JVM_CX8Field: IMPLEMENT ME!");
+
+ return 0;
}
jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy)
{
log_println("JVM_GetAllThreads: IMPLEMENT ME!");
+
+ return NULL;
}
jobjectArray JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads)
{
log_println("JVM_DumpThreads: IMPLEMENT ME!");
+
+ return NULL;
}
/* JVM_GetManagement */
-void* JVM_GetManagement(jint version)
+void *JVM_GetManagement(jint version)
{
- log_println("JVM_GetManagement: IMPLEMENT ME!");
+ TRACEJVMCALLS(("JVM_GetManagement(version=%d)", version));
+
+ /* TODO We current don't support the management interface. */
+
+ return NULL;
}
jobject JVM_InitAgentProperties(JNIEnv *env, jobject properties)
{
log_println("JVM_InitAgentProperties: IMPLEMENT ME!");
+
+ return NULL;
}
jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass ofClass)
{
- log_println("JVM_GetEnclosingMethodInfo: IMPLEMENT ME!");
+ classinfo *c;
+ methodinfo *m;
+ java_handle_objectarray_t *oa;
+
+ TRACEJVMCALLS(("JVM_GetEnclosingMethodInfo(env=%p, ofClass=%p)", env, ofClass));
+
+ c = LLNI_classinfo_unwrap(ofClass);
+
+ if ((c == NULL) || class_is_primitive(c))
+ return NULL;
+
+ m = class_get_enclosingmethod(c);
+
+ if (m == NULL)
+ return NULL;
+
+ oa = builtin_anewarray(3, class_java_lang_Object);
+
+ if (oa == NULL)
+ return NULL;
+
+ array_objectarray_element_set(oa, 0, (java_handle_t *) LLNI_classinfo_wrap(m->clazz));
+ array_objectarray_element_set(oa, 1, javastring_new(m->name));
+ array_objectarray_element_set(oa, 2, javastring_new(m->descriptor));
+
+ return (jobjectArray) oa;
}
{
java_handle_intarray_t *ia;
- TRACEJVMCALLS("JVM_GetThreadStateValues(env=%p, javaThreadState=%d)",
- env, javaThreadState);
+ TRACEJVMCALLS(("JVM_GetThreadStateValues(env=%p, javaThreadState=%d)",
+ env, javaThreadState));
/* If new thread states are added in future JDK and VM versions,
this should check if the JDK version is compatible with thread
java_handle_objectarray_t *oa;
java_object_t *s;
- TRACEJVMCALLS("JVM_GetThreadStateNames(env=%p, javaThreadState=%d, values=%p)",
- env, javaThreadState, values);
+ TRACEJVMCALLS(("JVM_GetThreadStateNames(env=%p, javaThreadState=%d, values=%p)",
+ env, javaThreadState, values));
ia = (java_handle_intarray_t *) values;
{
functionptr newHandler;
- TRACEJVMCALLS("JVM_RegisterSignal(sig=%d, handler=%p)", sig, handler);
+ TRACEJVMCALLS(("JVM_RegisterSignal(sig=%d, handler=%p)", sig, handler));
if (handler == (void *) 2)
newHandler = (functionptr) signal_thread_handler;
jboolean JVM_RaiseSignal(jint sig)
{
log_println("JVM_RaiseSignal: IMPLEMENT ME! sig=%s", sig);
+
return false;
}
jint JVM_FindSignal(const char *name)
{
- TRACEJVMCALLS("JVM_FindSignal(name=%s)", name);
+ TRACEJVMCALLS(("JVM_FindSignal(name=%s)", name));
#if defined(__LINUX__)
if (strcmp(name, "HUP") == 0)
/* src/native/vm/sun_misc_Unsafe.c - sun/misc/Unsafe
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
#include <unistd.h>
+#include "machine-instr.h"
+
#include "mm/memory.h"
#include "native/jni.h"
#include "native/include/java_lang_Thread.h" /* required by s.m.U */
#include "native/include/java_lang_Throwable.h"
+#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_reflect_VMField.h"
+#endif
+
#include "native/include/java_security_ProtectionDomain.h" /* required by smU */
#include "native/include/sun_misc_Unsafe.h"
#include "vm/initialize.h"
#include "vm/stringlocal.h"
+#include "vmcore/system.h"
#include "vmcore/utf8.h"
{ "putByte", "(JB)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putByte__JB },
{ "getShort", "(J)S", (void *) (intptr_t) &Java_sun_misc_Unsafe_getShort__J },
{ "putShort", "(JS)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putShort__JS },
+ { "getChar", "(J)C", (void *) (intptr_t) &Java_sun_misc_Unsafe_getChar__J },
+ { "putChar", "(JC)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putChar__JC },
{ "getInt", "(J)I", (void *) (intptr_t) &Java_sun_misc_Unsafe_getInt__J },
{ "putInt", "(JI)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putInt__JI },
{ "getLong", "(J)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_getLong__J },
{ "getFloat", "(J)F", (void *) (intptr_t) &Java_sun_misc_Unsafe_getFloat__J },
{ "objectFieldOffset", "(Ljava/lang/reflect/Field;)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_objectFieldOffset },
{ "allocateMemory", "(J)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_allocateMemory },
+#if 0
+ /* OpenJDK 7 */
{ "setMemory", "(Ljava/lang/Object;JJB)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_setMemory },
+ { "copyMemory", "(Ljava/lang/Object;JLjava/lang/Object;JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_copyMemory },
+#else
+ { "setMemory", "(JJB)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_setMemory },
+ { "copyMemory", "(JJJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_copyMemory },
+#endif
{ "freeMemory", "(J)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_freeMemory },
{ "staticFieldOffset", "(Ljava/lang/reflect/Field;)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldOffset },
{ "staticFieldBase", "(Ljava/lang/reflect/Field;)Ljava/lang/Object;", (void *) (intptr_t) &Java_sun_misc_Unsafe_staticFieldBase },
{ "compareAndSwapInt", "(Ljava/lang/Object;JII)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapInt },
{ "compareAndSwapLong", "(Ljava/lang/Object;JJJ)Z", (void *) (intptr_t) &Java_sun_misc_Unsafe_compareAndSwapLong },
{ "getObjectVolatile", "(Ljava/lang/Object;J)Ljava/lang/Object;", (void *) (intptr_t) &Java_sun_misc_Unsafe_getObjectVolatile },
+ { "putObjectVolatile", "(Ljava/lang/Object;JLjava/lang/Object;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putObjectVolatile },
{ "getIntVolatile", "(Ljava/lang/Object;J)I", (void *) (intptr_t) &Java_sun_misc_Unsafe_getIntVolatile },
+ { "putIntVolatile", "(Ljava/lang/Object;JI)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putIntVolatile },
{ "getLongVolatile", "(Ljava/lang/Object;J)J", (void *) (intptr_t) &Java_sun_misc_Unsafe_getLongVolatile },
+ { "putLongVolatile", "(Ljava/lang/Object;JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putLongVolatile },
+ { "putOrderedObject", "(Ljava/lang/Object;JLjava/lang/Object;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedObject },
+ { "putOrderedInt", "(Ljava/lang/Object;JI)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedInt },
+ { "putOrderedLong", "(Ljava/lang/Object;JJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_putOrderedLong },
{ "unpark", "(Ljava/lang/Object;)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_unpark },
{ "park", "(ZJ)V", (void *) (intptr_t) &Java_sun_misc_Unsafe_park },
};
}
+/*
+ * Class: sun/misc/Unsafe
+ * Method: getChar
+ * Signature: (J)C
+ */
+JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getChar__J(JNIEnv *env, sun_misc_Unsafe *this, int64_t address)
+{
+ uint16_t *p;
+ uint16_t value;
+
+ p = (uint16_t *) (intptr_t) address;
+
+ value = *p;
+
+ return (int32_t) value;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putChar
+ * Signature: (JC)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putChar__JC(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int32_t value)
+{
+ uint16_t *p;
+
+ p = (uint16_t *) (intptr_t) address;
+
+ *p = (uint16_t) value;
+}
+
+
/*
* Class: sun/misc/Unsafe
* Method: getInt
fieldinfo *f;
int32_t slot;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_reflect_VMField *rvmf;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ LLNI_field_get_ref(field, f, rvmf);
+ LLNI_field_get_cls(rvmf, clazz, c);
+ LLNI_field_get_val(rvmf, slot , slot);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
LLNI_field_get_cls(field, clazz, c);
LLNI_field_get_val(field, slot , slot);
- f = &c->fields[slot];
+#else
+# error unknown configuration
+#endif
+
+ f = &(c->fields[slot]);
return (int64_t) f->offset;
}
}
+#if 0
+/* OpenJDK 7 */
+
/*
* Class: sun/misc/Unsafe
* Method: setMemory
/* XXX Not sure this is correct. */
- MSET(p, value, uint8_t, length);
+ system_memset(p, value, length);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: copyMemory
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *srcBase, int64_t srcOffset, java_lang_Object *destBase, int64_t destOffset, int64_t bytes)
+{
+ size_t length;
+ void *src;
+ void *dest;
+
+ if (bytes == 0)
+ return;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ /* XXX Missing LLNI: We need to unwrap these objects. */
+
+ src = (void *) (((uint8_t *) srcBase) + srcOffset);
+ dest = (void *) (((uint8_t *) destBase) + destOffset);
+
+ system_memcpy(dest, src, length);
+}
+#else
+/*
+ * Class: sun/misc/Unsafe
+ * Method: setMemory
+ * Signature: (JJB)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_setMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t address, int64_t bytes, int32_t value)
+{
+ size_t length;
+ void *p;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ p = (void *) (intptr_t) address;
+
+ /* XXX Not sure this is correct. */
+
+ system_memset(p, value, length);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: copyMemory
+ * Signature: (JJJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_copyMemory(JNIEnv *env, sun_misc_Unsafe *this, int64_t srcAddress, int64_t destAddress, int64_t bytes)
+{
+ size_t length;
+ void *src;
+ void *dest;
+
+ if (bytes == 0)
+ return;
+
+ length = (size_t) bytes;
+
+ if ((length != (uint64_t) bytes) || (bytes < 0)) {
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ src = (void *) (intptr_t) srcAddress;
+ dest = (void *) (intptr_t) destAddress;
+
+ system_memcpy(dest, src, length);
}
+#endif
/*
fieldinfo *f;
int32_t slot;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_reflect_VMField *rvmf;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ LLNI_field_get_ref(rf, f, rvmf);
+ LLNI_field_get_cls(rvmf, clazz, c);
+ LLNI_field_get_val(rvmf, slot , slot);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
LLNI_field_get_cls(rf, clazz, c);
LLNI_field_get_val(rf, slot , slot);
+#else
+# error unknown configuration
+#endif
+
f = &(c->fields[slot]);
return (java_lang_Object *) (f->value);
*/
JNIEXPORT java_lang_Class* JNICALL Java_sun_misc_Unsafe_defineClass__Ljava_lang_String_2_3BIILjava_lang_ClassLoader_2Ljava_security_ProtectionDomain_2(JNIEnv *env, sun_misc_Unsafe *this, java_lang_String *name, java_handle_bytearray_t *b, int32_t off, int32_t len, java_lang_ClassLoader *loader, java_security_ProtectionDomain *protectionDomain)
{
- classloader *cl;
+ classloader_t *cl;
utf *utfname;
classinfo *c;
java_lang_Class *o;
/* define the class */
- c = class_define(utfname, cl, len, (const uint8_t *) &(LLNI_array_direct(b, off)),
- protectionDomain);
+ c = class_define(utfname, cl, len, (uint8_t *) &(LLNI_array_direct(b, off)),
+ (java_handle_t *) protectionDomain);
if (c == NULL)
return NULL;
*/
JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *expected, java_lang_Object *x)
{
+#if 1
void **p;
void *value;
}
return false;
+#else
+ volatile void **p;
+ void *result;
+
+ /* XXX Use LLNI */
+
+ p = (volatile void **) (((uint8_t *) o) + offset);
+
+ result = atomic_compare_and_swap_address(p, expected, x);
+
+ if (result == expected)
+ return true;
+
+ return false;
+#endif
}
* Method: compareAndSwapInt
* Signature: (Ljava/lang/Object;JII)Z
*/
-JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapInt(JNIEnv *env, sun_misc_Unsafe* this, java_lang_Object* obj, int64_t offset, int32_t expect, int32_t update)
+JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_compareAndSwapInt(JNIEnv *env, sun_misc_Unsafe* this, java_lang_Object* o, int64_t offset, int32_t expected, int32_t x)
{
+#if 1
int32_t *p;
int32_t value;
- p = (int32_t *) (((uint8_t *) obj) + offset);
+ p = (int32_t *) (((uint8_t *) o) + offset);
/* XXX this should be atomic */
value = *p;
- if (value == expect) {
- *p = update;
+ if (value == expected) {
+ *p = x;
return true;
}
return false;
+#else
+ int32_t *p;
+ int32_t result;
+
+ /* XXX Use LLNI */
+
+ p = (int32_t *) (((uint8_t *) o) + offset);
+
+ result = atomic_compare_and_swap_int(p, expected, x);
+
+ if (result == expected)
+ return true;
+
+ return false;
+#endif
}
}
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putObjectVolatile
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putObjectVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *x)
+{
+ volatile void **p;
+
+ p = (volatile void **) (((uint8_t *) o) + offset);
+
+ *p = x;
+}
+
+
+#define UNSAFE_GET_VOLATILE(type) \
+ java_handle_t *_h; \
+ java_object_t *_o; \
+ volatile type *_p; \
+ volatile type _x; \
+ \
+ _h = (java_handle_t *) o; \
+ \
+ LLNI_CRITICAL_START; \
+ \
+ _o = LLNI_UNWRAP(_h); \
+ _p = (volatile type *) (((uint8_t *) _o) + offset); \
+ \
+ _x = *_p; \
+ \
+ LLNI_CRITICAL_END; \
+ \
+ return _x;
+
+
+#define UNSAFE_PUT_VOLATILE(type) \
+ java_handle_t *_h; \
+ java_object_t *_o; \
+ volatile type *_p; \
+ \
+ _h = (java_handle_t *) o; \
+ \
+ LLNI_CRITICAL_START; \
+ \
+ _o = LLNI_UNWRAP(_h); \
+ _p = (volatile type *) (((uint8_t *) _o) + offset); \
+ \
+ *_p = x; \
+ \
+ MEMORY_BARRIER(); \
+ \
+ LLNI_CRITICAL_END;
+
+
/*
* Class: sun/misc/Unsafe
* Method: getIntVolatile
*/
JNIEXPORT int32_t JNICALL Java_sun_misc_Unsafe_getIntVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
{
- volatile int32_t *p;
- volatile int32_t value;
-
- p = (volatile int32_t *) (((uint8_t *) o) + offset);
+ UNSAFE_GET_VOLATILE(int32_t);
+}
- value = *p;
- return value;
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putIntVolatile
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putIntVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
+{
+ UNSAFE_PUT_VOLATILE(int32_t);
}
*/
JNIEXPORT int64_t JNICALL Java_sun_misc_Unsafe_getLongVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset)
{
- volatile int64_t *p;
- volatile int64_t value;
+ UNSAFE_GET_VOLATILE(int64_t);
+}
- p = (volatile int64_t *) (((uint8_t *) o) + offset);
- value = *p;
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putLongVolatile
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putLongVolatile(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
+{
+ UNSAFE_PUT_VOLATILE(int64_t);
+}
- return value;
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putOrderedObject
+ * Signature: (Ljava/lang/Object;JLjava/lang/Object;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedObject(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, java_lang_Object *x)
+{
+ java_handle_t *_h;
+ java_handle_t *_hx;
+ java_object_t *_o;
+ java_object_t *_x;
+ volatile void **_p;
+
+ _h = (java_handle_t *) o;
+ _hx = (java_handle_t *) x;
+
+ LLNI_CRITICAL_START;
+
+ _o = LLNI_UNWRAP(_h);
+ _x = LLNI_UNWRAP(_hx);
+ _p = (volatile void **) (((uint8_t *) _o) + offset);
+
+ *_p = _x;
+
+ MEMORY_BARRIER();
+
+ LLNI_CRITICAL_END;
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putOrderedInt
+ * Signature: (Ljava/lang/Object;JI)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedInt(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int32_t x)
+{
+ UNSAFE_PUT_VOLATILE(int32_t);
+}
+
+
+/*
+ * Class: sun/misc/Unsafe
+ * Method: putOrderedLong
+ * Signature: (Ljava/lang/Object;JJ)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Unsafe_putOrderedLong(JNIEnv *env, sun_misc_Unsafe *this, java_lang_Object *o, int64_t offset, int64_t x)
+{
+ UNSAFE_PUT_VOLATILE(int64_t);
}
## src/threads/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.
##
LIB =
DIST_SUBDIRS = \
- native \
- none
+ none \
+ posix
+
+if ENABLE_THREADS
+SUBDIRS = \
+ posix
+THREAD_LIB = \
+ posix/libthreadsposix.la
+else
SUBDIRS = \
- native
+ none
THREAD_LIB = \
- native/libthreadsposix.la
+ none/libthreadsnone.la
+endif
+
noinst_LTLIBRARIES = \
libthreads.la
+if ENABLE_THREADS
libthreads_la_SOURCES = \
critical.c \
critical.h \
lock-common.h \
- threads-common.c \
- threads-common.h
+ mutex.h \
+ threadlist.c \
+ threadlist.h \
+ thread.c \
+ thread.h
+else
+libthreads_la_SOURCES =
+endif
libthreads_la_LIBADD = \
$(THREAD_LIB)
A node representing a restartable critical section.
- CAUTION: This order must not be changed, it is used in
- asm_criticalsections!
-
*******************************************************************************/
struct critical_section_node_t {
/* src/threads/lock-common.h - common stuff of lock implementation
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/global.h"
#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
+# include "threads/posix/lock.h"
#else
# include "threads/none/lock.h"
#endif
--- /dev/null
+/* src/threads/mutex.h - machine independent mutual exclusion functions
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MUTEX_H
+#define _MUTEX_H
+
+#include "config.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/posix/mutex-posix.h"
+#endif
+
+
+#endif /* _MUTEX_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+++ /dev/null
-## src/threads/native/Makefile.am
-##
-## Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
-##
-## This file is part of CACAO.
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License as
-## published by the Free Software Foundation; either version 2, or (at
-## your option) any later version.
-##
-## This program is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-## 02110-1301, USA.
-
-
-AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR) -I$(top_builddir)/src -I$(top_srcdir)/contrib/vmlog
-
-LIBS =
-
-noinst_LTLIBRARIES = \
- libthreadsposix.la
-
-libthreadsposix_la_SOURCES = \
- lock.c \
- lock.h \
- threads.c \
- threads.h
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
+++ /dev/null
-/* src/threads/native/generic-primitives.h - machine independent atomic
- operations
-
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
- Anton Ertl
-
- Changes:
-
-
-*/
-
-
-#ifndef _MACHINE_INSTR_H
-#define _MACHINE_INSTR_H
-
-#include <pthread.h>
-
-extern pthread_mutex_t _atomic_add_lock;
-extern pthread_mutex_t _cas_lock;
-extern pthread_mutex_t _mb_lock;
-
-
-static inline void atomic_add(volatile int *mem, int val)
-{
- pthread_mutex_lock(&_atomic_add_lock);
-
- /* do the atomic add */
- *mem += val;
-
- pthread_mutex_unlock(&_atomic_add_lock);
-}
-
-
-static inline long compare_and_swap(volatile long *p, long oldval, long newval)
-{
- long ret;
-
- pthread_mutex_lock(&_cas_lock);
-
- /* do the compare-and-swap */
-
- ret = *p;
-
- if (oldval == ret)
- *p = newval;
-
- pthread_mutex_unlock(&_cas_lock);
-
- return ret;
-}
-
-
-#define MEMORY_BARRIER() (pthread_mutex_lock(&_mb_lock), \
- pthread_mutex_unlock(&_mb_lock))
-#define STORE_ORDER_BARRIER() MEMORY_BARRIER()
-#define MEMORY_BARRIER_BEFORE_ATOMIC() /* nothing */
-#define MEMORY_BARRIER_AFTER_ATOMIC() /* nothing */
-
-#endif /* _MACHINE_INSTR_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/threads/native/lock.c - lock implementation
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public 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/native/lock.h"
-#include "threads/native/threads.h"
-
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-#include "vm/exceptions.h"
-#include "vm/finalizer.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/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/native/generic-primitives.h"
-#else
-#include "machine-instr.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 */
-
-#define COMPARE_AND_SWAP_OLD_VALUE(address, oldvalue, newvalue) \
- ((ptrint) compare_and_swap((long *)(address), (long)(oldvalue), (long)(newvalue)))
-
-
-/******************************************************************************/
-/* MACROS FOR THE FLAT LOCK CONTENTION BIT */
-/******************************************************************************/
-
-#define LOCK_SET_FLC_BIT(obj) ((obj)->hdrflags |= HDRFLAG_FLC)
-#define LOCK_CLEAR_FLC_BIT(obj) ((obj)->hdrflags &= ~ HDRFLAG_FLC)
-#define LOCK_TEST_FLC_BIT(obj) ((obj)->hdrflags & HDRFLAG_FLC)
-
-
-/******************************************************************************/
-/* 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)
-
-
-/* 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 */
-
- pthread_mutex_init(&(lr->mutex), NULL);
-
- 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. */
-
- pthread_mutex_destroy(&(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)
-{
- pthread_mutex_init(&(lock_hashtable.mutex), NULL);
-
- 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 */
-
- pthread_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 */
-
- pthread_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 */
-
- pthread_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 */
-
- pthread_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 */
-
- pthread_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 */
-
- pthread_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;
- LOCK_CLEAR_FLC_BIT(o);
-}
-
-
-/*============================================================================*/
-/* 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)
-{
- pthread_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;
- pthread_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);
- }
- 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));
-
- /* clear flat-lock-contention bit */
-
- LLNI_CRITICAL_START_THREAD(t);
- LOCK_CLEAR_FLC_BIT(LLNI_DIRECT(o));
- LLNI_CRITICAL_END_THREAD(t);
-
- /* notify waiting objects */
-
- lock_record_notify(t, lr, false);
-
- /* install it */
-
- lock_lockword_set(t, o, MAKE_FAT_LOCK(lr));
-}
-
-
-/* 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;
-
- /* most common case: try to thin-lock an unlocked object */
-
- LLNI_CRITICAL_START_THREAD(t);
- lockword = COMPARE_AND_SWAP_OLD_VALUE(&(LLNI_DIRECT(o)->lockword), THIN_UNLOCKED, thinlock);
- LLNI_CRITICAL_END_THREAD(t);
-
- if (lockword == THIN_UNLOCKED) {
- /* success. we locked it */
- /* The Java Memory Model requires a memory barrier here: */
- MEMORY_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++;
-
- 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 ******/
-
- /* first obtain the lock record for this object */
-
- lr = lock_hashtable_get(t, o);
-
-#if defined(ENABLE_JVMTI)
- /* Monitor Contended Enter */
- jvmti_MonitorContendedEntering(false, o);
-#endif
-
- /* enter the monitor */
-
- lock_record_enter(t, lr);
-
-#if defined(ENABLE_JVMTI)
- /* Monitor Contended Entered */
- jvmti_MonitorContendedEntering(true, o);
-#endif
-
- /* inflation loop */
-
- while (IS_THIN_LOCK(lockword = lock_lockword_get(t, o))) {
- /* Set the flat lock contention bit to let the owning thread
- know that we want to be notified of unlocking. */
-
- LLNI_CRITICAL_START_THREAD(t);
- LOCK_SET_FLC_BIT(LLNI_DIRECT(o));
- LLNI_CRITICAL_END_THREAD(t);
-
- DEBUGLOCKS(("thread %d set flc bit on %p lr %p",
- t->index, (void*) o, (void*) lr));
-
- /* try to lock the object */
-
- LLNI_CRITICAL_START_THREAD(t);
- lockword = COMPARE_AND_SWAP_OLD_VALUE(&(LLNI_DIRECT(o)->lockword), THIN_UNLOCKED, thinlock);
- LLNI_CRITICAL_END_THREAD(t);
-
- if (lockword == THIN_UNLOCKED) {
- /* we can inflate the lock ourselves */
-
- DEBUGLOCKS(("thread %d inflating lock of %p to lr %p",
- t->index, (void*) o, (void*) lr));
-
- lock_inflate(t, o, lr);
- }
- else {
- /* Wait until another thread sees the flc bit and notifies
- us of unlocking. */
-
- (void) lock_record_wait(t, lr, 0, 0);
- }
- }
-
- /* we own the inflated lock now */
-
- return true;
-}
-
-
-/* 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 */
- MEMORY_BARRIER();
- lock_lockword_set(t, o, THIN_UNLOCKED);
- /* memory barrier for thin locking */
- MEMORY_BARRIER();
-
- /* check if there has been a flat lock contention on this object */
-
- if (LOCK_TEST_FLC_BIT(LLNI_DIRECT(o))) {
- lock_record_t *lr;
-
- DEBUGLOCKS(("thread %d saw flc bit on %p",
- t->index, (void*) o));
-
- /* there has been a contention on this thin lock */
-
- lr = lock_hashtable_get(t, o);
-
- DEBUGLOCKS(("thread %d for %p got lr %p",
- t->index, (void*) o, (void*) lr));
-
- lock_record_enter(t, lr);
-
- if (LOCK_TEST_FLC_BIT(LLNI_DIRECT(o))) {
- /* notify a thread that it can try to inflate the lock now */
-
- lock_record_notify(t, lr, true);
- }
-
- lock_record_exit(t, lr);
- }
-
- 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;
- pthread_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_unsynced(l); w != NULL; w = list_next_unsynced(l, w)) {
- if (w->thread == thread) {
- /* Remove the waiter entry from the list. */
-
- list_remove_unsynced(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;
-
- 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 */
-
- wasinterrupted = 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;
-
- /* 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);
- }
-
- /* { 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_unsynced(l); w != NULL; w = list_next_unsynced(l, w)) {
- /* signal the waiting thread */
-
- waitingthread = w->thread;
-
- /* If the thread was already signaled but hasn't removed
- itself from the list yet, just ignore it. */
-
- if (waitingthread->signaled == true)
- continue;
-
- /* Enter the wait-mutex. */
-
- pthread_mutex_lock(&(waitingthread->waitmutex));
-
- DEBUGLOCKS(("[lock_record_notify: lr=%p, t=%p, waitingthread=%p, sleeping=%d, one=%d]",
- lr, t, waitingthread, waitingthread->sleeping, one));
-
- /* Signal the thread if it's sleeping. */
-
- if (waitingthread->sleeping)
- pthread_cond_signal(&(waitingthread->waitcond));
-
- /* Mark the thread as signaled. */
-
- waitingthread->signaled = true;
-
- /* Leave the wait-mutex. */
-
- pthread_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;
- }
-
- /* inflate this lock */
-
- lr = lock_hashtable_get(t, o);
- lock_record_enter(t, lr);
- lock_inflate(t, o, lr);
- }
-
- /* { 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/native/lock.h - lock implementation
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public 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"
-
-#include <pthread.h>
-
-#include "vm/types.h"
-
-#include "native/llni.h"
-
-#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 */
- pthread_mutex_t 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 {
- pthread_mutex_t 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))
-
-#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:
- */
+++ /dev/null
-/* src/threads/native/threads.c - native threads support
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-/* XXX cleanup these includes */
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <time.h>
-#include <errno.h>
-
-#include <pthread.h>
-
-#include "vm/types.h"
-
-#include "arch.h"
-
-#if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
-# include "machine-instr.h"
-#else
-# include "threads/native/generic-primitives.h"
-#endif
-
-#include "mm/gc-common.h"
-#include "mm/memory.h"
-
-#if defined(ENABLE_GC_CACAO)
-# include "mm/cacao-gc/gc.h"
-#endif
-
-#include "native/jni.h"
-#include "native/llni.h"
-#include "native/native.h"
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Throwable.h"
-#include "native/include/java_lang_Thread.h"
-
-#if defined(ENABLE_JAVASE)
-# include "native/include/java_lang_ThreadGroup.h"
-#endif
-
-#if defined(WITH_CLASSPATH_GNU)
-# include "native/include/java_lang_VMThread.h"
-#endif
-
-#include "threads/lock-common.h"
-#include "threads/threads-common.h"
-
-#include "threads/native/threads.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.h"
-#include "vm/global.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/asmpart.h"
-
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#if !defined(__DARWIN__)
-# if defined(__LINUX__)
-# define GC_LINUX_THREADS
-# elif defined(__IRIX__)
-# define GC_IRIX_THREADS
-# endif
-# include <semaphore.h>
-# if defined(ENABLE_GC_BOEHM)
-# include "mm/boehm-gc/include/gc.h"
-# endif
-#endif
-
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
-#if defined(__DARWIN__)
-/* Darwin has no working semaphore implementation. This one is taken
- from Boehm-GC. */
-
-/*
- This is a very simple semaphore implementation for darwin. It
- is implemented in terms of pthreads calls so it isn't async signal
- safe. This isn't a problem because signals aren't used to
- suspend threads on darwin.
-*/
-
-static int sem_init(sem_t *sem, int pshared, int value)
-{
- if (pshared)
- assert(0);
-
- sem->value = value;
-
- if (pthread_mutex_init(&sem->mutex, NULL) < 0)
- return -1;
-
- if (pthread_cond_init(&sem->cond, NULL) < 0)
- return -1;
-
- return 0;
-}
-
-static int sem_post(sem_t *sem)
-{
- if (pthread_mutex_lock(&sem->mutex) < 0)
- return -1;
-
- sem->value++;
-
- if (pthread_cond_signal(&sem->cond) < 0) {
- pthread_mutex_unlock(&sem->mutex);
- return -1;
- }
-
- if (pthread_mutex_unlock(&sem->mutex) < 0)
- return -1;
-
- return 0;
-}
-
-static int sem_wait(sem_t *sem)
-{
- if (pthread_mutex_lock(&sem->mutex) < 0)
- return -1;
-
- while (sem->value == 0) {
- pthread_cond_wait(&sem->cond, &sem->mutex);
- }
-
- sem->value--;
-
- if (pthread_mutex_unlock(&sem->mutex) < 0)
- return -1;
-
- return 0;
-}
-
-static int sem_destroy(sem_t *sem)
-{
- if (pthread_cond_destroy(&sem->cond) < 0)
- return -1;
-
- if (pthread_mutex_destroy(&sem->mutex) < 0)
- return -1;
-
- return 0;
-}
-#endif /* defined(__DARWIN__) */
-
-
-/* internally used constants **************************************************/
-
-/* CAUTION: Do not change these values. Boehm GC code depends on them. */
-#define STOPWORLD_FROM_GC 1
-#define STOPWORLD_FROM_CLASS_NUMBERING 2
-
-
-/* startupinfo *****************************************************************
-
- Struct used to pass info from threads_start_thread to
- threads_startup_thread.
-
-******************************************************************************/
-
-typedef struct {
- threadobject *thread; /* threadobject for this thread */
- functionptr function; /* function to run in the new thread */
- sem_t *psem; /* signals when thread has been entered */
- /* in the thread list */
- sem_t *psem_first; /* signals when pthread_create has returned */
-} startupinfo;
-
-
-/* prototypes *****************************************************************/
-
-static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
-
-
-/******************************************************************************/
-/* GLOBAL VARIABLES */
-/******************************************************************************/
-
-static methodinfo *method_thread_init;
-
-/* the thread object of the current thread */
-/* This is either a thread-local variable defined with __thread, or */
-/* a thread-specific value stored with key threads_current_threadobject_key. */
-#if defined(HAVE___THREAD)
-__thread threadobject *threads_current_threadobject;
-#else
-pthread_key_t threads_current_threadobject_key;
-#endif
-
-/* global mutex for the threads table */
-static pthread_mutex_t mutex_threads_list;
-
-/* global mutex for stop-the-world */
-static pthread_mutex_t stopworldlock;
-
-#if defined(ENABLE_GC_CACAO)
-/* global mutex for the GC */
-static pthread_mutex_t mutex_gc;
-#endif
-
-/* global mutex and condition for joining threads on exit */
-static pthread_mutex_t mutex_join;
-static pthread_cond_t cond_join;
-
-/* XXX We disable that whole bunch of code until we have the exact-GC
- running. */
-
-#if 1
-
-/* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
-/* being stopped */
-static volatile int stopworldwhere;
-
-/* semaphore used for acknowleding thread suspension */
-static sem_t suspend_ack;
-#if defined(__IRIX__)
-static pthread_mutex_t suspend_ack_lock = PTHREAD_MUTEX_INITIALIZER;
-static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
-#endif
-
-#endif /* 0 */
-
-/* mutexes used by the fake atomic instructions */
-#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
-pthread_mutex_t _atomic_add_lock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t _cas_lock = PTHREAD_MUTEX_INITIALIZER;
-pthread_mutex_t _mb_lock = PTHREAD_MUTEX_INITIALIZER;
-#endif
-
-
-/* threads_sem_init ************************************************************
-
- Initialize a semaphore. Checks against errors and interruptions.
-
- IN:
- sem..............the semaphore to initialize
- shared...........true if this semaphore will be shared between processes
- value............the initial value for the semaphore
-
-*******************************************************************************/
-
-void threads_sem_init(sem_t *sem, bool shared, int value)
-{
- int r;
-
- assert(sem);
-
- do {
- r = sem_init(sem, shared, value);
- if (r == 0)
- return;
- } while (errno == EINTR);
-
- vm_abort("sem_init failed: %s", strerror(errno));
-}
-
-
-/* threads_sem_wait ************************************************************
-
- Wait for a semaphore, non-interruptible.
-
- IMPORTANT: Always use this function instead of `sem_wait` directly, as
- `sem_wait` may be interrupted by signals!
-
- IN:
- sem..............the semaphore to wait on
-
-*******************************************************************************/
-
-void threads_sem_wait(sem_t *sem)
-{
- int r;
-
- assert(sem);
-
- do {
- r = sem_wait(sem);
- if (r == 0)
- return;
- } while (errno == EINTR);
-
- vm_abort("sem_wait failed: %s", strerror(errno));
-}
-
-
-/* threads_sem_post ************************************************************
-
- Increase the count of a semaphore. Checks for errors.
-
- IN:
- sem..............the semaphore to increase the count of
-
-*******************************************************************************/
-
-void threads_sem_post(sem_t *sem)
-{
- int r;
-
- assert(sem);
-
- /* unlike sem_wait, sem_post is not interruptible */
-
- r = sem_post(sem);
- if (r == 0)
- return;
-
- vm_abort("sem_post failed: %s", strerror(errno));
-}
-
-
-/* lock_stopworld **************************************************************
-
- Enter the stopworld lock, specifying why the world shall be stopped.
-
- IN:
- where........ STOPWORLD_FROM_GC (1) from within GC
- STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
-
-******************************************************************************/
-
-void lock_stopworld(int where)
-{
- pthread_mutex_lock(&stopworldlock);
-/* stopworldwhere = where; */
-}
-
-
-/* unlock_stopworld ************************************************************
-
- Release the stopworld lock.
-
-******************************************************************************/
-
-void unlock_stopworld(void)
-{
-/* stopworldwhere = 0; */
- pthread_mutex_unlock(&stopworldlock);
-}
-
-/* XXX We disable that whole bunch of code until we have the exact-GC
- running. */
-
-#if 0
-
-#if !defined(__DARWIN__)
-/* Caller must hold threadlistlock */
-static s4 threads_cast_sendsignals(s4 sig)
-{
- threadobject *t;
- threadobject *self;
- s4 count;
-
- self = THREADOBJECT;
-
- /* iterate over all started threads */
-
- count = 0;
-
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- /* don't send the signal to ourself */
-
- if (t == self)
- continue;
-
- /* don't send the signal to NEW threads (because they are not
- completely initialized) */
-
- if (t->state == THREAD_STATE_NEW)
- continue;
-
- /* send the signal */
-
- pthread_kill(t->tid, sig);
-
- /* increase threads count */
-
- count++;
- }
-
- return count;
-}
-
-#else
-
-static void threads_cast_darwinstop(void)
-{
- threadobject *tobj = mainthreadobj;
- threadobject *self = THREADOBJECT;
-
- do {
- if (tobj != self)
- {
- thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
- mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
-#if defined(__I386__)
- i386_thread_state_t thread_state;
-#else
- ppc_thread_state_t thread_state;
-#endif
- mach_port_t thread = tobj->mach_thread;
- kern_return_t r;
-
- r = thread_suspend(thread);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_suspend failed");
-
- r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
- &thread_state_count);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_get_state failed");
-
- md_critical_section_restart((ucontext_t *) &thread_state);
-
- r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
- thread_state_count);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_set_state failed");
- }
-
- tobj = tobj->next;
- } while (tobj != mainthreadobj);
-}
-
-static void threads_cast_darwinresume(void)
-{
- threadobject *tobj = mainthreadobj;
- threadobject *self = THREADOBJECT;
-
- do {
- if (tobj != self)
- {
- mach_port_t thread = tobj->mach_thread;
- kern_return_t r;
-
- r = thread_resume(thread);
-
- if (r != KERN_SUCCESS)
- vm_abort("thread_resume failed");
- }
-
- tobj = tobj->next;
- } while (tobj != mainthreadobj);
-}
-
-#endif
-
-#if defined(__IRIX__)
-static void threads_cast_irixresume(void)
-{
- pthread_mutex_lock(&suspend_ack_lock);
- pthread_cond_broadcast(&suspend_cond);
- pthread_mutex_unlock(&suspend_ack_lock);
-}
-#endif
-#endif
-
-#if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
-static void threads_sigsuspend_handler(ucontext_t *_uc)
-{
- int sig;
- sigset_t sigs;
-
- /* XXX TWISTI: this is just a quick hack */
-#if defined(ENABLE_JIT)
- md_critical_section_restart(_uc);
-#endif
-
- /* Do as Boehm does. On IRIX a condition variable is used for wake-up
- (not POSIX async-safe). */
-#if defined(__IRIX__)
- pthread_mutex_lock(&suspend_ack_lock);
- threads_sem_post(&suspend_ack);
- pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
- pthread_mutex_unlock(&suspend_ack_lock);
-#elif defined(__CYGWIN__)
- /* TODO */
- assert(0);
-#else
-
- sig = GC_signum2();
- sigfillset(&sigs);
- sigdelset(&sigs, sig);
- sigsuspend(&sigs);
-#endif
-}
-#endif
-
-/* threads_stopworld ***********************************************************
-
- Stops the world from turning. All threads except the calling one
- are suspended. The function returns as soon as all threads have
- acknowledged their suspension.
-
-*******************************************************************************/
-
-#if !defined(DISABLE_GC)
-void threads_stopworld(void)
-{
-#if !defined(__DARWIN__) && !defined(__CYGWIN__)
- threadobject *t;
- threadobject *self;
- bool result;
- s4 count, i;
-#endif
-
- lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
-
- /* lock the threads lists */
-
- threads_list_lock();
-
-#if defined(__DARWIN__)
- /*threads_cast_darwinstop();*/
- assert(0);
-#elif defined(__CYGWIN__)
- /* TODO */
- assert(0);
-#else
- self = THREADOBJECT;
-
- DEBUGTHREADS("stops World", self);
-
- count = 0;
-
- /* suspend all running threads */
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- /* don't send the signal to ourself */
-
- if (t == self)
- continue;
-
- /* don't send the signal to NEW threads (because they are not
- completely initialized) */
-
- if (t->state == THREAD_STATE_NEW)
- continue;
-
- /* send the signal */
-
- result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
- assert(result);
-
- /* increase threads count */
-
- count++;
- }
-
- /* wait for all threads signaled to suspend */
- for (i = 0; i < count; i++)
- threads_sem_wait(&suspend_ack);
-#endif
-
- /* ATTENTION: Don't unlock the threads-lists here so that
- non-signaled NEW threads can't change their state and execute
- code. */
-}
-#endif /* !defined(DISABLE_GC) */
-
-
-/* threads_startworld **********************************************************
-
- Starts the world again after it has previously been stopped.
-
-*******************************************************************************/
-
-#if !defined(DISABLE_GC)
-void threads_startworld(void)
-{
-#if !defined(__DARWIN__) && !defined(__CYGWIN__)
- threadobject *t;
- threadobject *self;
- bool result;
- s4 count, i;
-#endif
-
-#if defined(__DARWIN__)
- /*threads_cast_darwinresume();*/
- assert(0);
-#elif defined(__IRIX__)
- threads_cast_irixresume();
-#elif defined(__CYGWIN__)
- /* TODO */
- assert(0);
-#else
- self = THREADOBJECT;
-
- DEBUGTHREADS("starts World", self);
-
- count = 0;
-
- /* resume all thread we haltet */
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- /* don't send the signal to ourself */
-
- if (t == self)
- continue;
-
- /* don't send the signal to NEW threads (because they are not
- completely initialized) */
-
- if (t->state == THREAD_STATE_NEW)
- continue;
-
- /* send the signal */
-
- result = threads_resume_thread(t);
- assert(result);
-
- /* increase threads count */
-
- count++;
- }
-
- /* wait for all threads signaled to suspend */
- for (i = 0; i < count; i++)
- threads_sem_wait(&suspend_ack);
-
-#endif
-
- /* unlock the threads lists */
-
- threads_list_unlock();
-
- unlock_stopworld();
-}
-#endif
-
-
-/* threads_set_current_threadobject ********************************************
-
- Set the current thread object.
-
- IN:
- thread.......the thread object to set
-
-*******************************************************************************/
-
-void threads_set_current_threadobject(threadobject *thread)
-{
-#if !defined(HAVE___THREAD)
- if (pthread_setspecific(threads_current_threadobject_key, thread) != 0)
- vm_abort("threads_set_current_threadobject: pthread_setspecific failed: %s", strerror(errno));
-#else
- threads_current_threadobject = thread;
-#endif
-}
-
-
-/* threads_impl_thread_new *****************************************************
-
- Initialize implementation fields of a threadobject.
-
- IN:
- t....the threadobject
-
-*******************************************************************************/
-
-void threads_impl_thread_new(threadobject *t)
-{
- /* get the pthread id */
-
- t->tid = pthread_self();
-
- /* initialize the mutex and the condition */
-
- pthread_mutex_init(&(t->waitmutex), NULL);
- pthread_cond_init(&(t->waitcond), NULL);
- pthread_mutex_init(&(t->suspendmutex), NULL);
- pthread_cond_init(&(t->suspendcond), NULL);
-
-#if defined(ENABLE_DEBUG_FILTER)
- /* Initialize filter counters */
- t->filterverbosecallctr[0] = 0;
- t->filterverbosecallctr[1] = 0;
-#endif
-
-#if !defined(NDEBUG)
- t->tracejavacallindent = 0;
- t->tracejavacallcount = 0;
-#endif
-}
-
-
-/* threads_impl_thread_free ****************************************************
-
- Cleanup thread stuff.
-
- IN:
- t....the threadobject
-
-*******************************************************************************/
-
-void threads_impl_thread_free(threadobject *t)
-{
- /* destroy the mutex and the condition */
-
- if (pthread_mutex_destroy(&(t->waitmutex)) != 0)
- vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
- strerror(errno));
-
- if (pthread_cond_destroy(&(t->waitcond)) != 0)
- vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
- strerror(errno));
-
- if (pthread_mutex_destroy(&(t->suspendmutex)) != 0)
- vm_abort("threads_impl_thread_free: pthread_mutex_destroy failed: %s",
- strerror(errno));
-
- if (pthread_cond_destroy(&(t->suspendcond)) != 0)
- vm_abort("threads_impl_thread_free: pthread_cond_destroy failed: %s",
- strerror(errno));
-}
-
-
-/* threads_get_current_threadobject ********************************************
-
- Return the threadobject of the current thread.
-
- RETURN VALUE:
- the current threadobject *
-
-*******************************************************************************/
-
-threadobject *threads_get_current_threadobject(void)
-{
- return THREADOBJECT;
-}
-
-
-/* threads_impl_preinit ********************************************************
-
- Do some early initialization of stuff required.
-
- ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
- is called AFTER this function!
-
-*******************************************************************************/
-
-void threads_impl_preinit(void)
-{
- pthread_mutex_init(&stopworldlock, NULL);
-
- /* initialize exit mutex and condition (on exit we join all
- threads) */
-
- pthread_mutex_init(&mutex_join, NULL);
- pthread_cond_init(&cond_join, NULL);
-
-#if defined(ENABLE_GC_CACAO)
- /* initialize the GC mutext */
-
- pthread_mutex_init(&mutex_gc, NULL);
-#endif
-
- /* initialize the threads-list mutex */
-
- pthread_mutex_init(&mutex_threads_list, NULL);
-
-#if !defined(HAVE___THREAD)
- pthread_key_create(&threads_current_threadobject_key, NULL);
-#endif
-
- threads_sem_init(&suspend_ack, 0, 0);
-}
-
-
-/* threads_list_lock ***********************************************************
-
- Enter the threads table 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 threads_list_lock(void)
-{
- if (pthread_mutex_lock(&mutex_threads_list) != 0)
- vm_abort("threads_list_lock: pthread_mutex_lock failed: %s",
- strerror(errno));
-}
-
-
-/* threads_list_unlock *********************************************************
-
- Leave the threads list mutex.
-
-*******************************************************************************/
-
-void threads_list_unlock(void)
-{
- if (pthread_mutex_unlock(&mutex_threads_list) != 0)
- vm_abort("threads_list_unlock: pthread_mutex_unlock failed: %s",
- strerror(errno));
-}
-
-
-/* threads_mutex_gc_lock *******************************************************
-
- Enter the global GC mutex.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void threads_mutex_gc_lock(void)
-{
- if (pthread_mutex_lock(&mutex_gc) != 0)
- vm_abort("threads_mutex_gc_lock: pthread_mutex_lock failed: %s",
- strerror(errno));
-}
-#endif
-
-
-/* threads_mutex_gc_unlock *****************************************************
-
- Leave the global GC mutex.
-
-*******************************************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-void threads_mutex_gc_unlock(void)
-{
- if (pthread_mutex_unlock(&mutex_gc) != 0)
- vm_abort("threads_mutex_gc_unlock: pthread_mutex_unlock failed: %s",
- strerror(errno));
-}
-#endif
-
-/* threads_mutex_join_lock *****************************************************
-
- Enter the join mutex.
-
-*******************************************************************************/
-
-void threads_mutex_join_lock(void)
-{
- if (pthread_mutex_lock(&mutex_join) != 0)
- vm_abort("threads_mutex_join_lock: pthread_mutex_lock failed: %s",
- strerror(errno));
-}
-
-
-/* threads_mutex_join_unlock ***************************************************
-
- Leave the join mutex.
-
-*******************************************************************************/
-
-void threads_mutex_join_unlock(void)
-{
- if (pthread_mutex_unlock(&mutex_join) != 0)
- vm_abort("threads_mutex_join_unlock: pthread_mutex_unlock failed: %s",
- strerror(errno));
-}
-
-
-/* threads_init ****************************************************************
-
- Initializes the threads required by the JVM: main, finalizer.
-
-*******************************************************************************/
-
-bool threads_init(void)
-{
- threadobject *mainthread;
- java_handle_t *threadname;
- java_lang_Thread *t;
- java_handle_t *o;
-
-#if defined(ENABLE_JAVASE)
- java_lang_ThreadGroup *threadgroup;
- methodinfo *m;
-#endif
-
-#if defined(WITH_CLASSPATH_GNU)
- java_lang_VMThread *vmt;
-#endif
-
- pthread_attr_t attr;
-
- /* get methods we need in this file */
-
-#if defined(WITH_CLASSPATH_GNU)
- method_thread_init =
- class_resolveclassmethod(class_java_lang_Thread,
- utf_init,
- utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
- class_java_lang_Thread,
- true);
-#elif defined(WITH_CLASSPATH_SUN)
- method_thread_init =
- class_resolveclassmethod(class_java_lang_Thread,
- utf_init,
- utf_new_char("(Ljava/lang/String;)V"),
- class_java_lang_Thread,
- true);
-#elif defined(WITH_CLASSPATH_CLDC1_1)
- method_thread_init =
- class_resolveclassmethod(class_java_lang_Thread,
- utf_init,
- utf_new_char("(Ljava/lang/String;)V"),
- class_java_lang_Thread,
- true);
-#else
-# error unknown classpath configuration
-#endif
-
- if (method_thread_init == NULL)
- return false;
-
- /* Get the main-thread (NOTE: The main threads is always the first
- thread in the list). */
-
- mainthread = threads_list_first();
-
- /* create a java.lang.Thread for the main thread */
-
- t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
-
- if (t == NULL)
- return false;
-
- /* set the object in the internal data structure */
-
- threads_thread_set_object(mainthread, (java_handle_t *) t);
-
-#if defined(ENABLE_INTRP)
- /* create interpreter stack */
-
- if (opt_intrp) {
- MSET(intrp_main_stack, 0, u1, opt_stacksize);
- mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
- }
-#endif
-
- threadname = javastring_new(utf_new_char("main"));
-
-#if defined(ENABLE_JAVASE)
- /* allocate and init ThreadGroup */
-
- threadgroup = (java_lang_ThreadGroup *)
- native_new_and_init(class_java_lang_ThreadGroup);
-
- if (threadgroup == NULL)
- return false;
-#endif
-
-#if defined(WITH_CLASSPATH_GNU)
- /* create a java.lang.VMThread for the main thread */
-
- vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
-
- if (vmt == NULL)
- return false;
-
- /* set the thread */
-
- LLNI_field_set_ref(vmt, thread, t);
- LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) mainthread);
-
- /* call java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
- o = (java_handle_t *) t;
-
- (void) vm_call_method(method_thread_init, o, vmt, threadname, NORM_PRIORITY,
- false);
-
-#elif defined(WITH_CLASSPATH_SUN)
-
- /* We trick java.lang.Thread.<init>, which sets the priority of
- the current thread to the parent's one. */
-
- t->priority = NORM_PRIORITY;
-
- /* Call java.lang.Thread.<init>(Ljava/lang/String;)V */
-
- o = (java_object_t *) t;
-
- (void) vm_call_method(method_thread_init, o, threadname);
-
-#elif defined(WITH_CLASSPATH_CLDC1_1)
-
- /* set the thread */
-
- t->vm_thread = (java_lang_Object *) mainthread;
-
- /* call public Thread(String name) */
-
- o = (java_handle_t *) t;
-
- (void) vm_call_method(method_thread_init, o, threadname);
-#else
-# error unknown classpath configuration
-#endif
-
- if (exceptions_get_exception())
- return false;
-
-#if defined(ENABLE_JAVASE)
- LLNI_field_set_ref(t, group, threadgroup);
-
-# if defined(WITH_CLASSPATH_GNU)
- /* add main thread to java.lang.ThreadGroup */
-
- m = class_resolveclassmethod(class_java_lang_ThreadGroup,
- utf_addThread,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
-
- o = (java_handle_t *) threadgroup;
-
- (void) vm_call_method(m, o, t);
-
- if (exceptions_get_exception())
- return false;
-# else
-# warning Do not know what to do here
-# endif
-#endif
-
- threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
-
- /* initialize the thread attribute object */
-
- if (pthread_attr_init(&attr) != 0)
- vm_abort("threads_init: pthread_attr_init failed: %s", strerror(errno));
-
- if (pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) != 0)
- vm_abort("threads_init: pthread_attr_setdetachstate failed: %s",
- strerror(errno));
-
- DEBUGTHREADS("starting (main)", mainthread);
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* threads_startup_thread ******************************************************
-
- Thread startup function called by pthread_create.
-
- Thread which have a startup.function != NULL are marked as internal
- threads. All other threads are threated as normal Java threads.
-
- NOTE: This function is not called directly by pthread_create. The Boehm GC
- inserts its own GC_start_routine in between, which then calls
- threads_startup.
-
- IN:
- arg..........the argument passed to pthread_create, ie. a pointer to
- a startupinfo struct. CAUTION: When the `psem` semaphore
- is posted, the startupinfo struct becomes invalid! (It
- is allocated on the stack of threads_start_thread.)
-
-******************************************************************************/
-
-static void *threads_startup_thread(void *arg)
-{
- startupinfo *startup;
- threadobject *thread;
- java_lang_Thread *object;
-#if defined(WITH_CLASSPATH_GNU)
- java_lang_VMThread *vmt;
-#endif
- sem_t *psem;
- classinfo *c;
- methodinfo *m;
- java_handle_t *o;
- functionptr function;
-
-#if defined(ENABLE_INTRP)
- u1 *intrp_thread_stack;
-
- /* create interpreter stack */
-
- if (opt_intrp) {
- intrp_thread_stack = GCMNEW(u1, opt_stacksize);
- MSET(intrp_thread_stack, 0, u1, opt_stacksize);
- }
- else
- intrp_thread_stack = NULL;
-#endif
-
- /* get passed startupinfo structure and the values in there */
-
- startup = arg;
-
- thread = startup->thread;
- function = startup->function;
- psem = startup->psem;
-
- /* Seems like we've encountered a situation where thread->tid was
- not set by pthread_create. We alleviate this problem by waiting
- for pthread_create to return. */
-
- threads_sem_wait(startup->psem_first);
-
-#if defined(__DARWIN__)
- thread->mach_thread = mach_thread_self();
-#endif
-
- /* store the internal thread data-structure in the TSD */
-
- threads_set_current_threadobject(thread);
-
- /* get the java.lang.Thread object for this thread */
-
- object = (java_lang_Thread *) threads_thread_get_object(thread);
-
- /* set our priority */
-
- threads_set_thread_priority(thread->tid, LLNI_field_direct(object, priority));
-
- /* thread is completely initialized */
-
- threads_thread_state_runnable(thread);
-
- /* tell threads_startup_thread that we registered ourselves */
- /* CAUTION: *startup becomes invalid with this! */
-
- startup = NULL;
- threads_sem_post(psem);
-
-#if defined(ENABLE_INTRP)
- /* set interpreter stack */
-
- if (opt_intrp)
- thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
-#endif
-
-#if defined(ENABLE_JVMTI)
- /* fire thread start event */
-
- if (jvmti)
- jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
-#endif
-
- DEBUGTHREADS("starting", thread);
-
- /* find and run the Thread.run()V method if no other function was passed */
-
- if (function == NULL) {
-#if defined(WITH_CLASSPATH_GNU)
- /* We need to start the run method of
- java.lang.VMThread. Since this is a final class, we can use
- the class object directly. */
-
- c = class_java_lang_VMThread;
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
- LLNI_class_get(object, c);
-#else
-# error unknown classpath configuration
-#endif
-
- m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
-
- if (m == NULL)
- vm_abort("threads_startup_thread: run() method not found in class");
-
- /* set ThreadMXBean variables */
-
- _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
- _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
-
- if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
- _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
- _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
- _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
-
-#if defined(WITH_CLASSPATH_GNU)
- /* we need to start the run method of java.lang.VMThread */
-
- LLNI_field_get_ref(object, vmThread, vmt);
- o = (java_handle_t *) vmt;
-
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
- o = (java_handle_t *) object;
-#else
-# error unknown classpath configuration
-#endif
-
- /* run the thread */
-
- (void) vm_call_method(m, o);
- }
- else {
- /* set ThreadMXBean variables */
-
- _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
- _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
-
- if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
- _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
- _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
- _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
-
- /* call passed function, e.g. finalizer_thread */
-
- (function)();
- }
-
- DEBUGTHREADS("stopping", thread);
-
-#if defined(ENABLE_JVMTI)
- /* fire thread end event */
-
- if (jvmti)
- jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
-#endif
-
- /* We ignore the return value. */
-
- (void) threads_detach_thread(thread);
-
- /* set ThreadMXBean variables */
-
- _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
-
- return NULL;
-}
-
-
-/* threads_impl_thread_start ***************************************************
-
- Start a thread in the JVM. Both (vm internal and java) thread
- objects exist.
-
- IN:
- thread....the thread object
- f.........function to run in the new thread. NULL means that the
- "run" method of the object `t` should be called
-
-******************************************************************************/
-
-void threads_impl_thread_start(threadobject *thread, functionptr f)
-{
- sem_t sem;
- sem_t sem_first;
- pthread_attr_t attr;
- startupinfo startup;
- int result;
-
- /* fill startupinfo structure passed by pthread_create to
- * threads_startup_thread */
-
- startup.thread = thread;
- startup.function = f; /* maybe we don't call Thread.run()V */
- startup.psem = &sem;
- startup.psem_first = &sem_first;
-
- threads_sem_init(&sem, 0, 0);
- threads_sem_init(&sem_first, 0, 0);
-
- /* Initialize thread attributes. */
-
- result = pthread_attr_init(&attr);
-
- if (result != 0)
- vm_abort("threads_impl_thread_start: pthread_attr_init failed: %s",
- strerror(result));
-
- result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- if (result != 0)
- vm_abort("threads_impl_thread_start: pthread_attr_setdetachstate failed: %s",
- strerror(result));
-
- /* initialize thread stacksize */
-
- result = pthread_attr_setstacksize(&attr, opt_stacksize);
-
- if (result != 0)
- vm_abort("threads_impl_thread_start: pthread_attr_setstacksize failed: %s",
- strerror(result));
-
- /* create the thread */
-
- result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
-
- if (result != 0)
- vm_abort("threads_impl_thread_start: pthread_create failed: %s",
- strerror(result));
-
- /* destroy the thread attributes */
-
- result = pthread_attr_destroy(&attr);
-
- if (result != 0)
- vm_abort("threads_impl_thread_start: pthread_attr_destroy failed: %s",
- strerror(result));
-
- /* signal that pthread_create has returned, so thread->tid is valid */
-
- threads_sem_post(&sem_first);
-
- /* wait here until the thread has entered itself into the thread list */
-
- threads_sem_wait(&sem);
-
- /* cleanup */
-
- sem_destroy(&sem);
- sem_destroy(&sem_first);
-}
-
-
-/* threads_set_thread_priority *************************************************
-
- Set the priority of the given thread.
-
- IN:
- tid..........thread id
- priority.....priority to set
-
-******************************************************************************/
-
-void threads_set_thread_priority(pthread_t tid, int priority)
-{
- struct sched_param schedp;
- int policy;
-
- pthread_getschedparam(tid, &policy, &schedp);
- schedp.sched_priority = priority;
- pthread_setschedparam(tid, policy, &schedp);
-}
-
-
-/* threads_attach_current_thread ***********************************************
-
- Attaches the current thread to the VM. Used in JNI.
-
-*******************************************************************************/
-
-bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
-{
- threadobject *thread;
- utf *u;
- java_handle_t *s;
- java_handle_t *o;
- java_lang_Thread *t;
-
-#if defined(ENABLE_JAVASE)
- java_lang_ThreadGroup *group;
- threadobject *mainthread;
- java_lang_Thread *mainthreado;
- classinfo *c;
- methodinfo *m;
-#endif
-
-#if defined(WITH_CLASSPATH_GNU)
- java_lang_VMThread *vmt;
-#endif
-
- /* Enter the join-mutex, so if the main-thread is currently
- waiting to join all threads, the number of non-daemon threads
- is correct. */
-
- threads_mutex_join_lock();
-
- /* create internal thread data-structure */
-
- thread = threads_thread_new();
-
- /* thread is a Java thread and running */
-
- thread->flags = THREAD_FLAG_JAVA;
-
- if (isdaemon)
- thread->flags |= THREAD_FLAG_DAEMON;
-
- /* The thread is flagged and (non-)daemon thread, we can leave the
- mutex. */
-
- threads_mutex_join_unlock();
-
- /* create a java.lang.Thread object */
-
- t = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
-
- /* XXX memory leak!!! */
- if (t == NULL)
- return false;
-
- threads_thread_set_object(thread, (java_handle_t *) t);
-
- /* thread is completely initialized */
-
- threads_thread_state_runnable(thread);
-
- DEBUGTHREADS("attaching", thread);
-
-#if defined(ENABLE_INTRP)
- /* create interpreter stack */
-
- if (opt_intrp) {
- MSET(intrp_main_stack, 0, u1, opt_stacksize);
- thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
- }
-#endif
-
-#if defined(WITH_CLASSPATH_GNU)
-
- /* create a java.lang.VMThread object */
-
- vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
-
- /* XXX memory leak!!! */
- if (vmt == NULL)
- return false;
-
- /* set the thread */
-
- LLNI_field_set_ref(vmt, thread, t);
- LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
-
-#elif defined(WITH_CLASSPATH_SUN)
-
- vm_abort("threads_attach_current_thread: IMPLEMENT ME!");
-
-#elif defined(WITH_CLASSPATH_CLDC1_1)
-
- LLNI_field_set_val(t, vm_thread, (java_lang_Object *) thread);
-
-#else
-# error unknown classpath configuration
-#endif
-
- if (vm_aargs != NULL) {
- u = utf_new_char(vm_aargs->name);
-#if defined(ENABLE_JAVASE)
- group = (java_lang_ThreadGroup *) vm_aargs->group;
-#endif
- }
- else {
- u = utf_null;
-#if defined(ENABLE_JAVASE)
- /* get the main thread */
-
- mainthread = threads_list_first();
- mainthreado = (java_lang_Thread *) threads_thread_get_object(mainthread);
- LLNI_field_get_ref(mainthreado, group, group);
-#endif
- }
-
- /* the the thread name */
-
- s = javastring_new(u);
-
- /* for convenience */
-
- o = (java_handle_t *) t;
-
-#if defined(WITH_CLASSPATH_GNU)
- (void) vm_call_method(method_thread_init, o, vmt, s, NORM_PRIORITY,
- isdaemon);
-#elif defined(WITH_CLASSPATH_CLDC1_1)
- (void) vm_call_method(method_thread_init, o, s);
-#endif
-
- if (exceptions_get_exception())
- return false;
-
-#if defined(ENABLE_JAVASE)
- /* store the thread group in the object */
-
- LLNI_field_set_ref(t, group, group);
-
- /* add thread to given thread-group */
-
- LLNI_class_get(group, c);
-
- m = class_resolveclassmethod(c,
- utf_addThread,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
-
- o = (java_handle_t *) group;
-
- (void) vm_call_method(m, o, t);
-
- if (exceptions_get_exception())
- return false;
-#endif
-
- return true;
-}
-
-
-/* threads_detach_thread *******************************************************
-
- Detaches the passed thread from the VM. Used in JNI.
-
-*******************************************************************************/
-
-bool threads_detach_thread(threadobject *t)
-{
- java_lang_Thread *object;
- java_handle_t *o;
-#if defined(ENABLE_JAVASE)
- java_lang_ThreadGroup *group;
- java_handle_t *e;
- java_lang_Object *handler;
- classinfo *c;
- methodinfo *m;
-#endif
-
- DEBUGTHREADS("detaching", t);
-
- object = (java_lang_Thread *) threads_thread_get_object(t);
-
-#if defined(ENABLE_JAVASE)
- LLNI_field_get_ref(object, group, group);
-
- /* If there's an uncaught exception, call uncaughtException on the
- thread's exception handler, or the thread's group if this is
- unset. */
-
- e = exceptions_get_and_clear_exception();
-
- if (e != NULL) {
- /* We use a java_lang_Object here, as it's not trivial to
- build the java_lang_Thread_UncaughtExceptionHandler header
- file. */
-
-# if defined(WITH_CLASSPATH_GNU)
- LLNI_field_get_ref(object, exceptionHandler, handler);
-# elif defined(WITH_CLASSPATH_SUN)
- LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
-# endif
-
- if (handler != NULL) {
- LLNI_class_get(handler, c);
- o = (java_handle_t *) handler;
- }
- else {
- LLNI_class_get(group, c);
- o = (java_handle_t *) group;
- }
-
- m = class_resolveclassmethod(c,
- utf_uncaughtException,
- utf_java_lang_Thread_java_lang_Throwable__V,
- NULL,
- true);
-
- if (m == NULL)
- return false;
-
- (void) vm_call_method(m, o, object, e);
-
- if (exceptions_get_exception())
- return false;
- }
-
- /* XXX TWISTI: should all threads be in a ThreadGroup? */
-
- /* Remove thread from the thread group. */
-
- if (group != NULL) {
- LLNI_class_get(group, c);
-
-# if defined(WITH_CLASSPATH_GNU)
- m = class_resolveclassmethod(c,
- utf_removeThread,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
-# elif defined(WITH_CLASSPATH_SUN)
- m = class_resolveclassmethod(c,
- utf_remove,
- utf_java_lang_Thread__V,
- class_java_lang_ThreadGroup,
- true);
-# else
-# error unknown classpath configuration
-# endif
-
- if (m == NULL)
- return false;
-
- o = (java_handle_t *) group;
-
- (void) vm_call_method(m, o, object);
-
- if (exceptions_get_exception())
- return false;
- }
-#endif
-
- /* Thread has terminated. */
-
- threads_thread_state_terminated(t);
-
- /* Notify all threads waiting on this thread. These are joining
- this thread. */
-
- o = (java_handle_t *) object;
-
- /* XXX Care about exceptions? */
- (void) lock_monitor_enter(o);
-
- lock_notify_all_object(o);
-
- /* XXX Care about exceptions? */
- (void) lock_monitor_exit(o);
-
- /* Enter the join-mutex before calling threads_thread_free, so
- threads_join_all_threads gets the correct number of non-daemon
- threads. */
-
- threads_mutex_join_lock();
-
- /* free the vm internal thread object */
-
- threads_thread_free(t);
-
- /* Signal that this thread has finished and leave the mutex. */
-
- pthread_cond_signal(&cond_join);
- threads_mutex_join_unlock();
-
- return true;
-}
-
-
-/* threads_suspend_thread ******************************************************
-
- Suspend the passed thread. Execution stops until the thread
- is explicitly resumend again.
-
- IN:
- reason.....Reason for suspending this thread.
-
-*******************************************************************************/
-
-bool threads_suspend_thread(threadobject *thread, s4 reason)
-{
- /* acquire the suspendmutex */
- if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
- vm_abort("threads_suspend_thread: pthread_mutex_lock failed: %s",
- strerror(errno));
-
- if (thread->suspended) {
- pthread_mutex_unlock(&(thread->suspendmutex));
- return false;
- }
-
- /* set the reason for the suspension */
- thread->suspend_reason = reason;
-
- /* send the suspend signal to the thread */
- assert(thread != THREADOBJECT);
- if (pthread_kill(thread->tid, SIGUSR1) != 0)
- vm_abort("threads_suspend_thread: pthread_kill failed: %s",
- strerror(errno));
-
- /* REMEMBER: do not release the suspendmutex, this is done
- by the thread itself in threads_suspend_ack(). */
-
- return true;
-}
-
-
-/* threads_suspend_ack *********************************************************
-
- Acknowledges the suspension of the current thread.
-
- IN:
- pc.....The PC where the thread suspended its execution.
- sp.....The SP before the thread suspended its execution.
-
-*******************************************************************************/
-
-void threads_suspend_ack(u1* pc, u1* sp)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- assert(thread->suspend_reason != 0);
-
- /* TODO: remember dump memory size */
-
-#if defined(ENABLE_GC_CACAO)
- /* inform the GC about the suspension */
- if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
-
- /* check if the GC wants to leave the thread running */
- if (!gc_suspend(thread, pc, sp)) {
-
- /* REMEMBER: we do not unlock the suspendmutex because the thread
- will suspend itself again at a later time */
- return;
-
- }
- }
-#endif
-
- /* mark this thread as suspended and remember the PC */
- thread->pc = pc;
- thread->suspended = true;
-
- /* if we are stopping the world, we should send a global ack */
- if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
- threads_sem_post(&suspend_ack);
- }
-
- DEBUGTHREADS("suspending", thread);
-
- /* release the suspension mutex and wait till we are resumed */
- pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
-
- DEBUGTHREADS("resuming", thread);
-
- /* if we are stopping the world, we should send a global ack */
- if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
- threads_sem_post(&suspend_ack);
- }
-
- /* TODO: free dump memory */
-
- /* release the suspendmutex */
- if (pthread_mutex_unlock(&(thread->suspendmutex)) != 0)
- vm_abort("threads_suspend_ack: pthread_mutex_unlock failed: %s",
- strerror(errno));
-}
-
-
-/* threads_resume_thread *******************************************************
-
- Resumes the execution of the passed thread.
-
-*******************************************************************************/
-
-bool threads_resume_thread(threadobject *thread)
-{
- /* acquire the suspendmutex */
- if (pthread_mutex_lock(&(thread->suspendmutex)) != 0)
- vm_abort("threads_resume_ack: pthread_mutex_unlock failed: %s",
- strerror(errno));
-
- if (!thread->suspended) {
- pthread_mutex_unlock(&(thread->suspendmutex));
- return false;
- }
-
- thread->suspended = false;
-
- /* tell everyone that the thread should resume */
- assert(thread != THREADOBJECT);
- pthread_cond_broadcast(&(thread->suspendcond));
-
- /* release the suspendmutex */
- pthread_mutex_unlock(&(thread->suspendmutex));
-
- return true;
-}
-
-
-/* threads_join_all_threads ****************************************************
-
- Join all non-daemon threads.
-
-*******************************************************************************/
-
-void threads_join_all_threads(void)
-{
- threadobject *t;
-
- /* get current thread */
-
- t = THREADOBJECT;
-
- /* this thread is waiting for all non-daemon threads to exit */
-
- threads_thread_state_waiting(t);
-
- /* enter join mutex */
-
- threads_mutex_join_lock();
-
- /* Wait for condition as long as we have non-daemon threads. We
- compare against 1 because the current (main thread) is also a
- non-daemon thread. */
-
- while (threads_list_get_non_daemons() > 1)
- pthread_cond_wait(&cond_join, &mutex_join);
-
- /* leave join mutex */
-
- threads_mutex_join_unlock();
-}
-
-
-/* threads_timespec_earlier ****************************************************
-
- Return true if timespec tv1 is earlier than timespec tv2.
-
- IN:
- tv1..........first timespec
- tv2..........second timespec
-
- RETURN VALUE:
- true, if the first timespec is earlier
-
-*******************************************************************************/
-
-static inline bool threads_timespec_earlier(const struct timespec *tv1,
- const struct timespec *tv2)
-{
- return (tv1->tv_sec < tv2->tv_sec)
- ||
- (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
-}
-
-
-/* threads_current_time_is_earlier_than ****************************************
-
- Check if the current time is earlier than the given timespec.
-
- IN:
- tv...........the timespec to compare against
-
- RETURN VALUE:
- true, if the current time is earlier
-
-*******************************************************************************/
-
-static bool threads_current_time_is_earlier_than(const struct timespec *tv)
-{
- struct timeval tvnow;
- struct timespec tsnow;
-
- /* get current time */
-
- if (gettimeofday(&tvnow, NULL) != 0)
- vm_abort("gettimeofday failed: %s\n", strerror(errno));
-
- /* convert it to a timespec */
-
- tsnow.tv_sec = tvnow.tv_sec;
- tsnow.tv_nsec = tvnow.tv_usec * 1000;
-
- /* compare current time with the given timespec */
-
- return threads_timespec_earlier(&tsnow, tv);
-}
-
-
-/* threads_wait_with_timeout ***************************************************
-
- Wait until the given point in time on a monitor until either
- we are notified, we are interrupted, or the time is up.
-
- IN:
- t............the current thread
- wakeupTime...absolute (latest) wakeup time
- If both tv_sec and tv_nsec are zero, this function
- waits for an unlimited amount of time.
-
- RETURN VALUE:
- true.........if the wait has been interrupted,
- false........if the wait was ended by notification or timeout
-
-*******************************************************************************/
-
-static bool threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
-{
- bool wasinterrupted;
-
- /* acquire the waitmutex */
-
- pthread_mutex_lock(&t->waitmutex);
-
- /* mark us as sleeping */
-
- t->sleeping = true;
-
- /* wait on waitcond */
-
- if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
- /* with timeout */
- while (!t->interrupted && !t->signaled
- && threads_current_time_is_earlier_than(wakeupTime))
- {
- threads_thread_state_timed_waiting(t);
-
- pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
- wakeupTime);
-
- threads_thread_state_runnable(t);
- }
- }
- else {
- /* no timeout */
- while (!t->interrupted && !t->signaled) {
- threads_thread_state_waiting(t);
-
- pthread_cond_wait(&t->waitcond, &t->waitmutex);
-
- threads_thread_state_runnable(t);
- }
- }
-
- /* check if we were interrupted */
-
- wasinterrupted = t->interrupted;
-
- /* reset all flags */
-
- t->interrupted = false;
- t->signaled = false;
- t->sleeping = false;
-
- /* release the waitmutex */
-
- pthread_mutex_unlock(&t->waitmutex);
-
- return wasinterrupted;
-}
-
-
-/* threads_wait_with_timeout_relative ******************************************
-
- Wait for the given maximum amount of time on a monitor until either
- we are notified, we are interrupted, or the time is up.
-
- IN:
- t............the current thread
- millis.......milliseconds to wait
- nanos........nanoseconds to wait
-
- RETURN VALUE:
- true.........if the wait has been interrupted,
- false........if the wait was ended by notification or timeout
-
-*******************************************************************************/
-
-bool threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
- s4 nanos)
-{
- struct timespec wakeupTime;
-
- /* calculate the the (latest) wakeup time */
-
- threads_calc_absolute_time(&wakeupTime, millis, nanos);
-
- /* wait */
-
- return threads_wait_with_timeout(thread, &wakeupTime);
-}
-
-
-/* threads_calc_absolute_time **************************************************
-
- Calculate the absolute point in time a given number of ms and ns from now.
-
- IN:
- millis............milliseconds from now
- nanos.............nanoseconds from now
-
- OUT:
- *tm...............receives the timespec of the absolute point in time
-
-*******************************************************************************/
-
-static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
-{
- if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
- struct timeval tv;
- long nsec;
- gettimeofday(&tv, NULL);
- tv.tv_sec += millis / 1000;
- millis %= 1000;
- nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
- tm->tv_sec = tv.tv_sec + nsec / 1000000000;
- tm->tv_nsec = nsec % 1000000000;
- }
- else {
- tm->tv_sec = 0;
- tm->tv_nsec = 0;
- }
-}
-
-
-/* threads_thread_interrupt ****************************************************
-
- Interrupt the given thread.
-
- The thread gets the "waitcond" signal and
- its interrupted flag is set to true.
-
- IN:
- thread............the thread to interrupt
-
-*******************************************************************************/
-
-void threads_thread_interrupt(threadobject *thread)
-{
- /* Signal the thread a "waitcond" and tell it that it has been
- interrupted. */
-
- pthread_mutex_lock(&thread->waitmutex);
-
- DEBUGTHREADS("interrupted", thread);
-
- /* Interrupt blocking system call using a signal. */
-
- pthread_kill(thread->tid, SIGHUP);
-
- if (thread->sleeping)
- pthread_cond_signal(&thread->waitcond);
-
- thread->interrupted = true;
-
- pthread_mutex_unlock(&thread->waitmutex);
-}
-
-
-/* threads_check_if_interrupted_and_reset **************************************
-
- Check if the current thread has been interrupted and reset the
- interruption flag.
-
- RETURN VALUE:
- true, if the current thread had been interrupted
-
-*******************************************************************************/
-
-bool threads_check_if_interrupted_and_reset(void)
-{
- threadobject *thread;
- bool intr;
-
- thread = THREADOBJECT;
-
- /* get interrupted flag */
-
- intr = thread->interrupted;
-
- /* reset interrupted flag */
-
- thread->interrupted = false;
-
- return intr;
-}
-
-
-/* threads_thread_has_been_interrupted *****************************************
-
- Check if the given thread has been interrupted
-
- IN:
- t............the thread to check
-
- RETURN VALUE:
- true, if the given thread had been interrupted
-
-*******************************************************************************/
-
-bool threads_thread_has_been_interrupted(threadobject *thread)
-{
- return thread->interrupted;
-}
-
-
-/* threads_sleep ***************************************************************
-
- Sleep the current thread for the specified amount of time.
-
-*******************************************************************************/
-
-void threads_sleep(s8 millis, s4 nanos)
-{
- threadobject *thread;
- struct timespec wakeupTime;
- bool wasinterrupted;
-
- thread = THREADOBJECT;
-
- threads_calc_absolute_time(&wakeupTime, millis, nanos);
-
- wasinterrupted = threads_wait_with_timeout(thread, &wakeupTime);
-
- if (wasinterrupted)
- exceptions_throw_interruptedexception();
-}
-
-
-/* threads_yield ***************************************************************
-
- Yield to the scheduler.
-
-*******************************************************************************/
-
-void threads_yield(void)
-{
- sched_yield();
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/threads/native/threads.h - native threads header
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _THREADS_H
-#define _THREADS_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct threadobject threadobject;
-
-
-#include "config.h"
-
-#include <pthread.h>
-#include <ucontext.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-#include "native/jni.h"
-#include "native/localref.h"
-
-#include "threads/native/lock.h"
-
-#include "vm/global.h"
-
-#if defined(ENABLE_GC_CACAO)
-# include "vm/jit/replace.h"
-#endif
-
-#include "vm/jit/stacktrace.h"
-
-#if defined(ENABLE_INTRP)
-#include "vm/jit/intrp/intrp.h"
-#endif
-
-#if defined(__DARWIN__)
-# include <mach/mach.h>
-
-typedef struct {
- pthread_mutex_t mutex;
- pthread_cond_t cond;
- int value;
-} sem_t;
-
-#else
-# include <semaphore.h>
-#endif
-
-
-/* current threadobject *******************************************************/
-
-#if defined(HAVE___THREAD)
-
-#define THREADSPECIFIC __thread
-#define THREADOBJECT threads_current_threadobject
-
-extern __thread threadobject *threads_current_threadobject;
-
-#else /* defined(HAVE___THREAD) */
-
-#define THREADSPECIFIC
-#define THREADOBJECT \
- ((threadobject *) pthread_getspecific(threads_current_threadobject_key))
-
-extern pthread_key_t threads_current_threadobject_key;
-
-#endif /* defined(HAVE___THREAD) */
-
-
-/* threadobject ****************************************************************
-
- Struct holding thread local variables.
-
-*******************************************************************************/
-
-#define THREAD_FLAG_JAVA 0x01 /* a normal Java thread */
-#define THREAD_FLAG_INTERNAL 0x02 /* CACAO internal thread */
-#define THREAD_FLAG_DAEMON 0x04 /* daemon thread */
-#define THREAD_FLAG_IN_NATIVE 0x08 /* currently executing native code */
-
-#define SUSPEND_REASON_JNI 1 /* suspended from JNI */
-#define SUSPEND_REASON_STOPWORLD 2 /* suspended from stop-thw-world */
-
-
-struct threadobject {
- java_object_t *object; /* link to java.lang.Thread object */
-
- ptrint thinlock; /* pre-computed thin lock value */
-
- s4 index; /* thread index, starting with 1 */
- u4 flags; /* flag field */
- u4 state; /* state field */
-
- pthread_t tid; /* pthread id */
-
-#if defined(__DARWIN__)
- mach_port_t mach_thread; /* Darwin thread id */
-#endif
-
- /* these are used for the wait/notify implementation */
- pthread_mutex_t waitmutex;
- pthread_cond_t waitcond;
-
- pthread_mutex_t suspendmutex; /* lock before suspending this thread */
- pthread_cond_t suspendcond; /* notify to resume this thread */
-
- bool interrupted;
- bool signaled;
- bool sleeping;
-
- bool suspended; /* is this thread suspended? */
- s4 suspend_reason; /* reason for suspending */
-
- u1 *pc; /* current PC (used for profiling) */
-
- java_object_t *_exceptionptr; /* current exception */
- stackframeinfo_t *_stackframeinfo; /* current native stackframeinfo */
- localref_table *_localref_table; /* JNI local references */
-
-#if defined(ENABLE_INTRP)
- Cell *_global_sp; /* stack pointer for interpreter */
-#endif
-
-#if defined(ENABLE_GC_CACAO)
- bool gc_critical; /* indicates a critical section */
-
- sourcestate_t *ss;
- executionstate_t *es;
-#endif
-
- dumpinfo_t dumpinfo; /* dump memory info structure */
-
-#if defined(ENABLE_DEBUG_FILTER)
- u2 filterverbosecallctr[2]; /* counters for verbose call filter */
-#endif
-
-#if !defined(NDEBUG)
- s4 tracejavacallindent;
- u4 tracejavacallcount;
-#endif
-
- listnode_t linkage; /* threads-list */
-};
-
-
-/* stackframeinfo *************************************************************/
-
-#define STACKFRAMEINFO (THREADOBJECT->_stackframeinfo)
-
-
-/* native-world flags *********************************************************/
-
-#if defined(ENABLE_GC_CACAO)
-# define THREAD_NATIVEWORLD_ENTER THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE
-# define THREAD_NATIVEWORLD_EXIT THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE
-#else
-# define THREAD_NATIVEWORLD_ENTER /*nop*/
-# define THREAD_NATIVEWORLD_EXIT /*nop*/
-#endif
-
-
-/* counter for verbose call filter ********************************************/
-
-#if defined(ENABLE_DEBUG_FILTER)
-# define FILTERVERBOSECALLCTR (THREADOBJECT->filterverbosecallctr)
-#endif
-
-/* state for trace java call **************************************************/
-
-#if !defined(NDEBUG)
-# define TRACEJAVACALLINDENT (THREADOBJECT->tracejavacallindent)
-# define TRACEJAVACALLCOUNT (THREADOBJECT->tracejavacallcount)
-#endif
-
-/* functions ******************************************************************/
-
-void threads_sem_init(sem_t *sem, bool shared, int value);
-void threads_sem_wait(sem_t *sem);
-void threads_sem_post(sem_t *sem);
-
-threadobject *threads_get_current_threadobject(void);
-
-bool threads_init(void);
-
-void threads_start_thread(threadobject *thread, functionptr function);
-
-void threads_set_thread_priority(pthread_t tid, int priority);
-
-bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
-bool threads_detach_thread(threadobject *thread);
-
-bool threads_suspend_thread(threadobject *thread, s4 reason);
-void threads_suspend_ack(u1* pc, u1* sp);
-bool threads_resume_thread(threadobject *thread);
-
-void threads_join_all_threads(void);
-
-void threads_sleep(s8 millis, s4 nanos);
-
-bool threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
-
-void threads_thread_interrupt(threadobject *thread);
-bool threads_check_if_interrupted_and_reset(void);
-bool threads_thread_has_been_interrupted(threadobject *thread);
-
-#if !defined(DISABLE_GC)
-void threads_stopworld(void);
-void threads_startworld(void);
-#endif
-
-#endif /* _THREADS_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:
- */
## src/threads/none/Makefile.am
##
-## 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.
##
## 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
-##
-## Changes:
-## Process this file with automake to produce Makefile.in
-EXTRA_DIST = \
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR) -I$(top_builddir)/src -I$(top_srcdir)/contrib/vmlog
+
+LIBS =
+
+noinst_LTLIBRARIES = \
+ libthreadsnone.la
+
+libthreadsnone_la_SOURCES = \
lock.h \
- threads.h
+ thread-none.c \
+ thread-none.h
## Local variables:
--- /dev/null
+/* src/threads/none/thread-none.c - fake threads
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "threads/thread.h"
+
+#include "vm/jit/stacktrace.h"
+
+
+/* global variables ***********************************************************/
+
+stackframeinfo_t *_no_threads_stackframeinfo = 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/threads/none/thread-none.h - fake threads 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 _THREAD_NONE_H
+#define _THREAD_NONE_H
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "vm/builtin.h"
+
+#include "vm/jit/stacktrace.h"
+
+
+/* define some stuff we need to no-ops ****************************************/
+
+#define THREADSPECIFIC
+#define THREADOBJECT NULL
+#define THREADINFO NULL
+
+#define threadobject void
+
+
+/* native-world flags *********************************************************/
+
+#define THREAD_NATIVEWORLD_ENTER /*nop*/
+#define THREAD_NATIVEWORLD_EXIT /*nop*/
+
+
+#if defined(ENABLE_DEBUG_FILTER)
+extern u2 _no_threads_filterverbosecallctr[2];
+#define FILTERVERBOSECALLCTR (_no_threads_filterverbosecallctr)
+#endif
+
+/* state for trace java call **************************************************/
+
+#if !defined(NDEBUG)
+extern s4 _no_threads_tracejavacallindent;
+#define TRACEJAVACALLINDENT (_no_threads_tracejavacallindent)
+
+extern u4 _no_threads_tracejavacallcount;
+#define TRACEJAVACALLCOUNT (_no_threads_tracejavacallcount)
+#endif
+
+
+/* global variables ***********************************************************/
+
+extern stackframeinfo_t *_no_threads_stackframeinfo;
+
+
+/* inline functions ***********************************************************/
+
+inline static java_handle_t *thread_get_current_object(void)
+{
+ java_handle_t *o;
+
+ /* We return a fake java.lang.Thread object, otherwise we get
+ NullPointerException's in GNU Classpath. */
+
+ o = builtin_new(class_java_lang_Thread);
+
+ return o;
+}
+
+inline static stackframeinfo_t *threads_get_current_stackframeinfo(void)
+{
+ return _no_threads_stackframeinfo;
+}
+
+inline static void threads_set_current_stackframeinfo(stackframeinfo_t *sfi)
+{
+ _no_threads_stackframeinfo = sfi;
+}
+
+#endif /* _THREAD_NONE_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/threads/none/threads.h - fake threads header
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _THREADS_H
-#define _THREADS_H
-
-#include "config.h"
-#include "vm/types.h"
-#include "vm/global.h"
-
-
-/* define some stuff we need to no-ops ****************************************/
-
-#define THREADSPECIFIC
-#define THREADOBJECT NULL
-#define THREADINFO NULL
-
-#define threadobject void
-
-
-/* stackframeinfo *************************************************************/
-
-#define STACKFRAMEINFO (_no_threads_stackframeinfo)
-
-
-/* native-world flags *********************************************************/
-
-#define THREAD_NATIVEWORLD_ENTER /*nop*/
-#define THREAD_NATIVEWORLD_EXIT /*nop*/
-
-
-#if defined(ENABLE_DEBUG_FILTER)
-extern u2 _no_threads_filterverbosecallctr[2];
-#define FILTERVERBOSECALLCTR (_no_threads_filterverbosecallctr)
-#endif
-
-/* state for trace java call **************************************************/
-
-#if !defined(NDEBUG)
-extern s4 _no_threads_tracejavacallindent;
-#define TRACEJAVACALLINDENT (_no_threads_tracejavacallindent)
-
-extern u4 _no_threads_tracejavacallcount;
-#define TRACEJAVACALLCOUNT (_no_threads_tracejavacallcount)
-#endif
-
-#endif /* _THREADS_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/threads/posix/Makefile.am
+##
+## Copyright (C) 1996-2005, 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+
+AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR) -I$(top_builddir)/src -I$(top_srcdir)/contrib/vmlog
+
+LIBS =
+
+noinst_LTLIBRARIES = \
+ libthreadsposix.la
+
+libthreadsposix_la_SOURCES = \
+ lock.c \
+ lock.h \
+ mutex-posix.h \
+ thread-posix.c \
+ thread-posix.h
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+/* src/threads/native/generic-primitives.h - machine independent atomic
+ operations
+
+ Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
+ E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
+ J. Wenninger, Institut f. Computersprachen - TU Wien
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Contact: cacao@cacaojvm.org
+
+ Authors: Christian Thalinger
+ Anton Ertl
+
+ Changes:
+
+
+*/
+
+
+#ifndef _MACHINE_INSTR_H
+#define _MACHINE_INSTR_H
+
+#include <pthread.h>
+
+#include "threads/mutex.h"
+
+
+extern mutex_t _cas_lock;
+extern mutex_t _mb_lock;
+
+
+static inline long compare_and_swap(volatile long *p, long oldval, long newval)
+{
+ long ret;
+
+ mutex_lock(&_cas_lock);
+
+ /* do the compare-and-swap */
+
+ ret = *p;
+
+ if (oldval == ret)
+ *p = newval;
+
+ mutex_unlock(&_cas_lock);
+
+ return ret;
+}
+
+
+#define MEMORY_BARRIER() (mutex_lock(&_mb_lock), \
+ mutex_unlock(&_mb_lock))
+#define STORE_ORDER_BARRIER() MEMORY_BARRIER()
+#define MEMORY_BARRIER_AFTER_ATOMIC() /* nothing */
+
+#endif /* _MACHINE_INSTR_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /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.h"
+#include "threads/threadlist.h"
+#include "threads/thread.h"
+
+#include "threads/posix/lock.h"
+
+#include "toolbox/list.h"
+
+#include "vm/global.h"
+#include "vm/exceptions.h"
+#include "vm/finalizer.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
+
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/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 "machine-instr.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 */
+
+#define COMPARE_AND_SWAP_OLD_VALUE(address, oldvalue, newvalue) \
+ ((ptrint) compare_and_swap((long *)(address), (long)(oldvalue), (long)(newvalue)))
+
+
+/******************************************************************************/
+/* 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 */
+
+ mutex_init(&(lr->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. */
+
+ mutex_destroy(&(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)
+{
+ mutex_init(&(lock_hashtable.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:
+ 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 */
+ 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. */
+ pthread_cond_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 */
+ pthread_cond_broadcast(¤t->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 = COMPARE_AND_SWAP_OLD_VALUE(&(LLNI_DIRECT(o)->lockword), THIN_UNLOCKED, thinlock);
+ LLNI_CRITICAL_END_THREAD(t);
+
+ if (lockword == THIN_UNLOCKED) {
+ /* success. we locked it */
+ /* The Java Memory Model requires a memory barrier here: */
+ /* Because of the CAS above, this barrier is a nop on x86 / x86_64 */
+ MEMORY_BARRIER_AFTER_ATOMIC();
+ 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 */
+ STORE_ORDER_BARRIER();
+ lock_lockword_set(t, o, THIN_UNLOCKED);
+ /* memory barrier for thin locking */
+ 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, sleeping=%d, one=%d]",
+ lr, t, waitingthread, waitingthread->sleeping, one));
+
+ /* Signal the thread if it's sleeping. sleeping can be false
+ when the waiting thread is blocked between giving up the
+ monitor and entering the waitmutex. It will eventually
+ observe that it's signaled and refrain from going to
+ sleep. */
+
+ if (waitingthread->sleeping)
+ pthread_cond_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"
+
+#include <pthread.h>
+
+#include "vm/types.h"
+
+#include "native/llni.h"
+
+#include "threads/mutex.h"
+
+#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_t 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_t 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))
+
+#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:
+ */
--- /dev/null
+/* src/threads/posix/mutex-posix.h - POSIX mutual exclusion functions
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MUTEX_POSIX_H
+#define _MUTEX_POSIX_H
+
+#include "config.h"
+
+#include <pthread.h>
+
+#include "vm/vm.h"
+
+
+/* POSIX mutex object *********************************************************/
+
+typedef pthread_mutex_t mutex_t;
+
+
+/* static mutex initializer ***************************************************/
+
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+
+
+/* inline functions ***********************************************************/
+
+/* mutex_init ******************************************************************
+
+ Initializes the given mutex object and checks for errors.
+
+ ARGUMENTS:
+ mutex ... POSIX mutex object
+
+*******************************************************************************/
+
+inline static void mutex_init(mutex_t *mutex)
+{
+ int result;
+
+ result = pthread_mutex_init(mutex, NULL);
+
+ if (result != 0)
+ vm_abort_errnum(result, "mutex_init: pthread_mutex_init failed");
+}
+
+
+/* mutex_lock ******************************************************************
+
+ Locks the given mutex object and checks for errors. If the mutex is
+ already locked by another thread, the calling thread is suspended until
+ the mutex is unlocked.
+
+ If the mutex is already locked by the calling thread, the same applies,
+ thus effectively causing the calling thread to deadlock. (This is because
+ we use "fast" pthread mutexes without error checking.)
+
+ ARGUMENTS:
+ mutex ... POSIX mutex object
+
+*******************************************************************************/
+
+inline static void mutex_lock(mutex_t *mutex)
+{
+ int result;
+
+ result = pthread_mutex_lock(mutex);
+
+ if (result != 0)
+ vm_abort_errnum(result, "mutex_lock: pthread_mutex_lock failed");
+}
+
+
+/* mutex_unlock ****************************************************************
+
+ Unlocks the given mutex object and checks for errors. The mutex is
+ assumed to be locked and owned by the calling thread.
+
+ ARGUMENTS:
+ mutex ... POSIX mutex object
+
+*******************************************************************************/
+
+inline static void mutex_unlock(mutex_t *mutex)
+{
+ int result;
+
+ result = pthread_mutex_unlock(mutex);
+
+ if (result != 0)
+ vm_abort_errnum(result, "mutex_unlock: pthread_mutex_unlock failed");
+}
+
+
+/* mutex_destroy ***************************************************************
+
+ Destroys the given mutex object and checks for errors.
+
+ ARGUMENTS:
+ mutex ... POSIX mutex object
+
+*******************************************************************************/
+
+inline static void mutex_destroy(mutex_t *mutex)
+{
+ int result;
+
+ result = pthread_mutex_destroy(mutex);
+
+ if (result != 0)
+ vm_abort_errnum(result, "mutex_destroy: pthread_mutex_destroy failed");
+}
+
+
+#endif /* _MUTEX_POSIX_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/threads/posix/thread-posix.c - POSIX thread functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+/* XXX cleanup these includes */
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include <pthread.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+
+#if !defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
+# include "machine-instr.h"
+#else
+# include "threads/posix/generic-primitives.h"
+#endif
+
+#include "mm/gc-common.h"
+#include "mm/memory.h"
+
+#if defined(ENABLE_GC_CACAO)
+# include "mm/cacao-gc/gc.h"
+#endif
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_String.h"
+#include "native/include/java_lang_Throwable.h"
+#include "native/include/java_lang_Thread.h"
+
+#if defined(ENABLE_JAVASE)
+# include "native/include/java_lang_ThreadGroup.h"
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_VMThread.h"
+#endif
+
+#include "threads/lock-common.h"
+#include "threads/mutex.h"
+#include "threads/threadlist.h"
+#include "threads/thread.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
+
+#include "vm/jit/asmpart.h"
+
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
+#if !defined(__DARWIN__)
+# if defined(__LINUX__)
+# define GC_LINUX_THREADS
+# elif defined(__IRIX__)
+# define GC_IRIX_THREADS
+# endif
+# include <semaphore.h>
+# if defined(ENABLE_GC_BOEHM)
+# include "mm/boehm-gc/include/gc.h"
+# endif
+#endif
+
+#if defined(ENABLE_JVMTI)
+#include "native/jvmti/cacaodbg.h"
+#endif
+
+#if defined(__DARWIN__)
+/* Darwin has no working semaphore implementation. This one is taken
+ from Boehm-GC. */
+
+/*
+ This is a very simple semaphore implementation for darwin. It
+ is implemented in terms of pthreads calls so it isn't async signal
+ safe. This isn't a problem because signals aren't used to
+ suspend threads on darwin.
+*/
+
+static int sem_init(sem_t *sem, int pshared, int value)
+{
+ if (pshared)
+ assert(0);
+
+ sem->value = value;
+
+ mutex_init(&sem->mutex);
+
+ if (pthread_cond_init(&sem->cond, NULL) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int sem_post(sem_t *sem)
+{
+ mutex_lock(&sem->mutex);
+
+ sem->value++;
+
+ if (pthread_cond_signal(&sem->cond) < 0) {
+ mutex_unlock(&sem->mutex);
+ return -1;
+ }
+
+ mutex_unlock(&sem->mutex);
+
+ return 0;
+}
+
+static int sem_wait(sem_t *sem)
+{
+ mutex_lock(&sem->mutex);
+
+ while (sem->value == 0) {
+ pthread_cond_wait(&sem->cond, &sem->mutex);
+ }
+
+ sem->value--;
+
+ mutex_unlock(&sem->mutex);
+
+ return 0;
+}
+
+static int sem_destroy(sem_t *sem)
+{
+ if (pthread_cond_destroy(&sem->cond) < 0)
+ return -1;
+
+ mutex_destroy(&sem->mutex);
+
+ return 0;
+}
+#endif /* defined(__DARWIN__) */
+
+
+/* internally used constants **************************************************/
+
+/* CAUTION: Do not change these values. Boehm GC code depends on them. */
+#define STOPWORLD_FROM_GC 1
+#define STOPWORLD_FROM_CLASS_NUMBERING 2
+
+
+/* startupinfo *****************************************************************
+
+ Struct used to pass info from threads_start_thread to
+ threads_startup_thread.
+
+******************************************************************************/
+
+typedef struct {
+ threadobject *thread; /* threadobject for this thread */
+ functionptr function; /* function to run in the new thread */
+ sem_t *psem; /* signals when thread has been entered */
+ /* in the thread list */
+ sem_t *psem_first; /* signals when pthread_create has returned */
+} startupinfo;
+
+
+/* prototypes *****************************************************************/
+
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos);
+
+
+/******************************************************************************/
+/* GLOBAL VARIABLES */
+/******************************************************************************/
+
+/* the thread object of the current thread */
+/* This is either a thread-local variable defined with __thread, or */
+/* a thread-specific value stored with key threads_current_threadobject_key. */
+#if defined(HAVE___THREAD)
+__thread threadobject *thread_current;
+#else
+pthread_key_t thread_current_key;
+#endif
+
+/* global mutex for stop-the-world */
+static mutex_t stopworldlock;
+
+#if defined(ENABLE_GC_CACAO)
+/* global mutex for the GC */
+static mutex_t mutex_gc;
+#endif
+
+/* global mutex and condition for joining threads on exit */
+static mutex_t mutex_join;
+static pthread_cond_t cond_join;
+
+/* XXX We disable that whole bunch of code until we have the exact-GC
+ running. */
+
+#if 1
+
+/* this is one of the STOPWORLD_FROM_ constants, telling why the world is */
+/* being stopped */
+static volatile int stopworldwhere;
+
+/* semaphore used for acknowleding thread suspension */
+static sem_t suspend_ack;
+#if defined(__IRIX__)
+static mutex_t suspend_ack_lock = MUTEX_INITIALIZER;
+static pthread_cond_t suspend_cond = PTHREAD_COND_INITIALIZER;
+#endif
+
+#endif /* 0 */
+
+/* mutexes used by the fake atomic instructions */
+#if defined(USE_FAKE_ATOMIC_INSTRUCTIONS)
+mutex_t _cas_lock = MUTEX_INITIALIZER;
+mutex_t _mb_lock = MUTEX_INITIALIZER;
+#endif
+
+
+/* threads_sem_init ************************************************************
+
+ Initialize a semaphore. Checks against errors and interruptions.
+
+ IN:
+ sem..............the semaphore to initialize
+ shared...........true if this semaphore will be shared between processes
+ value............the initial value for the semaphore
+
+*******************************************************************************/
+
+void threads_sem_init(sem_t *sem, bool shared, int value)
+{
+ int r;
+
+ assert(sem);
+
+ do {
+ r = sem_init(sem, shared, value);
+ if (r == 0)
+ return;
+ } while (errno == EINTR);
+
+ vm_abort("sem_init failed: %s", strerror(errno));
+}
+
+
+/* threads_sem_wait ************************************************************
+
+ Wait for a semaphore, non-interruptible.
+
+ IMPORTANT: Always use this function instead of `sem_wait` directly, as
+ `sem_wait` may be interrupted by signals!
+
+ IN:
+ sem..............the semaphore to wait on
+
+*******************************************************************************/
+
+void threads_sem_wait(sem_t *sem)
+{
+ int r;
+
+ assert(sem);
+
+ do {
+ r = sem_wait(sem);
+ if (r == 0)
+ return;
+ } while (errno == EINTR);
+
+ vm_abort("sem_wait failed: %s", strerror(errno));
+}
+
+
+/* threads_sem_post ************************************************************
+
+ Increase the count of a semaphore. Checks for errors.
+
+ IN:
+ sem..............the semaphore to increase the count of
+
+*******************************************************************************/
+
+void threads_sem_post(sem_t *sem)
+{
+ int r;
+
+ assert(sem);
+
+ /* unlike sem_wait, sem_post is not interruptible */
+
+ r = sem_post(sem);
+ if (r == 0)
+ return;
+
+ vm_abort("sem_post failed: %s", strerror(errno));
+}
+
+
+/* lock_stopworld **************************************************************
+
+ Enter the stopworld lock, specifying why the world shall be stopped.
+
+ IN:
+ where........ STOPWORLD_FROM_GC (1) from within GC
+ STOPWORLD_FROM_CLASS_NUMBERING (2) class numbering
+
+******************************************************************************/
+
+void lock_stopworld(int where)
+{
+ mutex_lock(&stopworldlock);
+/* stopworldwhere = where; */
+}
+
+
+/* unlock_stopworld ************************************************************
+
+ Release the stopworld lock.
+
+******************************************************************************/
+
+void unlock_stopworld(void)
+{
+/* stopworldwhere = 0; */
+ mutex_unlock(&stopworldlock);
+}
+
+/* XXX We disable that whole bunch of code until we have the exact-GC
+ running. */
+
+#if 0
+
+#if !defined(__DARWIN__)
+/* Caller must hold threadlistlock */
+static s4 threads_cast_sendsignals(s4 sig)
+{
+ threadobject *t;
+ threadobject *self;
+ s4 count;
+
+ self = THREADOBJECT;
+
+ /* iterate over all started threads */
+
+ count = 0;
+
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ /* don't send the signal to ourself */
+
+ if (t == self)
+ continue;
+
+ /* don't send the signal to NEW threads (because they are not
+ completely initialized) */
+
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+ /* send the signal */
+
+ pthread_kill(t->tid, sig);
+
+ /* increase threads count */
+
+ count++;
+ }
+
+ return count;
+}
+
+#else
+
+static void threads_cast_darwinstop(void)
+{
+ threadobject *tobj = mainthreadobj;
+ threadobject *self = THREADOBJECT;
+
+ do {
+ if (tobj != self)
+ {
+ thread_state_flavor_t flavor = MACHINE_THREAD_STATE;
+ mach_msg_type_number_t thread_state_count = MACHINE_THREAD_STATE_COUNT;
+#if defined(__I386__)
+ i386_thread_state_t thread_state;
+#else
+ ppc_thread_state_t thread_state;
+#endif
+ mach_port_t thread = tobj->mach_thread;
+ kern_return_t r;
+
+ r = thread_suspend(thread);
+
+ if (r != KERN_SUCCESS)
+ vm_abort("thread_suspend failed");
+
+ r = thread_get_state(thread, flavor, (natural_t *) &thread_state,
+ &thread_state_count);
+
+ if (r != KERN_SUCCESS)
+ vm_abort("thread_get_state failed");
+
+ md_critical_section_restart((ucontext_t *) &thread_state);
+
+ r = thread_set_state(thread, flavor, (natural_t *) &thread_state,
+ thread_state_count);
+
+ if (r != KERN_SUCCESS)
+ vm_abort("thread_set_state failed");
+ }
+
+ tobj = tobj->next;
+ } while (tobj != mainthreadobj);
+}
+
+static void threads_cast_darwinresume(void)
+{
+ threadobject *tobj = mainthreadobj;
+ threadobject *self = THREADOBJECT;
+
+ do {
+ if (tobj != self)
+ {
+ mach_port_t thread = tobj->mach_thread;
+ kern_return_t r;
+
+ r = thread_resume(thread);
+
+ if (r != KERN_SUCCESS)
+ vm_abort("thread_resume failed");
+ }
+
+ tobj = tobj->next;
+ } while (tobj != mainthreadobj);
+}
+
+#endif
+
+#if defined(__IRIX__)
+static void threads_cast_irixresume(void)
+{
+ mutex_lock(&suspend_ack_lock);
+ pthread_cond_broadcast(&suspend_cond);
+ mutex_unlock(&suspend_ack_lock);
+}
+#endif
+
+#if defined(ENABLE_GC_BOEHM) && !defined(__DARWIN__)
+static void threads_sigsuspend_handler(ucontext_t *_uc)
+{
+ int sig;
+ sigset_t sigs;
+
+ /* XXX TWISTI: this is just a quick hack */
+#if defined(ENABLE_JIT)
+ md_critical_section_restart(_uc);
+#endif
+
+ /* Do as Boehm does. On IRIX a condition variable is used for wake-up
+ (not POSIX async-safe). */
+#if defined(__IRIX__)
+ mutex_lock(&suspend_ack_lock);
+ threads_sem_post(&suspend_ack);
+ pthread_cond_wait(&suspend_cond, &suspend_ack_lock);
+ mutex_unlock(&suspend_ack_lock);
+#elif defined(__CYGWIN__)
+ /* TODO */
+ assert(0);
+#else
+
+ sig = GC_signum2();
+ sigfillset(&sigs);
+ sigdelset(&sigs, sig);
+ sigsuspend(&sigs);
+#endif
+}
+#endif
+
+#endif
+
+
+/* threads_stopworld ***********************************************************
+
+ Stops the world from turning. All threads except the calling one
+ are suspended. The function returns as soon as all threads have
+ acknowledged their suspension.
+
+*******************************************************************************/
+
+#if !defined(DISABLE_GC)
+void threads_stopworld(void)
+{
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
+ threadobject *t;
+ threadobject *self;
+ bool result;
+ s4 count, i;
+#endif
+
+ lock_stopworld(STOPWORLD_FROM_CLASS_NUMBERING);
+
+ /* lock the threads lists */
+
+ threadlist_lock();
+
+#if defined(__DARWIN__)
+ /*threads_cast_darwinstop();*/
+ assert(0);
+#elif defined(__CYGWIN__)
+ /* TODO */
+ assert(0);
+#else
+ self = THREADOBJECT;
+
+ DEBUGTHREADS("stops World", self);
+
+ count = 0;
+
+ /* suspend all running threads */
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ /* don't send the signal to ourself */
+
+ if (t == self)
+ continue;
+
+ /* don't send the signal to NEW threads (because they are not
+ completely initialized) */
+
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+ /* send the signal */
+
+ result = threads_suspend_thread(t, SUSPEND_REASON_STOPWORLD);
+ assert(result);
+
+ /* increase threads count */
+
+ count++;
+ }
+
+ /* wait for all threads signaled to suspend */
+ for (i = 0; i < count; i++)
+ threads_sem_wait(&suspend_ack);
+#endif
+
+ /* ATTENTION: Don't unlock the threads-lists here so that
+ non-signaled NEW threads can't change their state and execute
+ code. */
+}
+#endif /* !defined(DISABLE_GC) */
+
+
+/* threads_startworld **********************************************************
+
+ Starts the world again after it has previously been stopped.
+
+*******************************************************************************/
+
+#if !defined(DISABLE_GC)
+void threads_startworld(void)
+{
+#if !defined(__DARWIN__) && !defined(__CYGWIN__)
+ threadobject *t;
+ threadobject *self;
+ bool result;
+ s4 count, i;
+#endif
+
+#if defined(__DARWIN__)
+ /*threads_cast_darwinresume();*/
+ assert(0);
+#elif defined(__IRIX__)
+ threads_cast_irixresume();
+#elif defined(__CYGWIN__)
+ /* TODO */
+ assert(0);
+#else
+ self = THREADOBJECT;
+
+ DEBUGTHREADS("starts World", self);
+
+ count = 0;
+
+ /* resume all thread we haltet */
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ /* don't send the signal to ourself */
+
+ if (t == self)
+ continue;
+
+ /* don't send the signal to NEW threads (because they are not
+ completely initialized) */
+
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+ /* send the signal */
+
+ result = threads_resume_thread(t);
+ assert(result);
+
+ /* increase threads count */
+
+ count++;
+ }
+
+ /* wait for all threads signaled to suspend */
+ for (i = 0; i < count; i++)
+ threads_sem_wait(&suspend_ack);
+
+#endif
+
+ /* unlock the threads lists */
+
+ threadlist_unlock();
+
+ unlock_stopworld();
+}
+#endif
+
+
+/* threads_impl_thread_init ****************************************************
+
+ Initialize OS-level locking constructs in threadobject.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+void threads_impl_thread_init(threadobject *t)
+{
+ int result;
+
+ /* initialize the mutex and the condition */
+
+ mutex_init(&t->flc_lock);
+
+ result = pthread_cond_init(&t->flc_cond, NULL);
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
+
+ mutex_init(&(t->waitmutex));
+
+ result = pthread_cond_init(&(t->waitcond), NULL);
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
+
+ mutex_init(&(t->suspendmutex));
+
+ result = pthread_cond_init(&(t->suspendcond), NULL);
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_new: pthread_cond_init failed");
+}
+
+/* threads_impl_thread_clear ***************************************************
+
+ Clears all fields in threadobject the way an MZERO would have
+ done. MZERO cannot be used anymore because it would mess up the
+ pthread_* bits.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+void threads_impl_thread_clear(threadobject *t)
+{
+ t->object = NULL;
+
+ t->thinlock = 0;
+
+ t->index = 0;
+ t->flags = 0;
+ t->state = 0;
+
+ t->tid = 0;
+
+#if defined(__DARWIN__)
+ t->mach_thread = 0;
+#endif
+
+ t->interrupted = false;
+ t->signaled = false;
+ t->sleeping = false;
+
+ t->suspended = false;
+ t->suspend_reason = 0;
+
+ t->pc = NULL;
+
+ t->_exceptionptr = NULL;
+ t->_stackframeinfo = NULL;
+ t->_localref_table = NULL;
+
+#if defined(ENABLE_INTRP)
+ t->_global_sp = NULL;
+#endif
+
+#if defined(ENABLE_GC_CACAO)
+ t->gc_critical = false;
+
+ t->ss = NULL;
+ t->es = NULL;
+#endif
+
+ MZERO(&t->dumpinfo, dumpinfo_t, 1);
+}
+
+/* threads_impl_thread_reuse ***************************************************
+
+ Resets some implementation fields in threadobject. This was
+ previously done in threads_impl_thread_new.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+void threads_impl_thread_reuse(threadobject *t)
+{
+ /* get the pthread id */
+
+ t->tid = pthread_self();
+
+#if defined(ENABLE_DEBUG_FILTER)
+ /* Initialize filter counters */
+ t->filterverbosecallctr[0] = 0;
+ t->filterverbosecallctr[1] = 0;
+#endif
+
+#if !defined(NDEBUG)
+ t->tracejavacallindent = 0;
+ t->tracejavacallcount = 0;
+#endif
+
+ t->flc_bit = false;
+ t->flc_next = NULL;
+ t->flc_list = NULL;
+
+/* not really needed */
+ t->flc_object = NULL;
+}
+
+
+/* threads_impl_thread_free ****************************************************
+
+ Cleanup thread stuff.
+
+ IN:
+ t....the threadobject
+
+*******************************************************************************/
+
+#if 0
+/* never used */
+void threads_impl_thread_free(threadobject *t)
+{
+ int result;
+
+ /* Destroy the mutex and the condition. */
+
+ mutex_destroy(&(t->flc_lock));
+
+ result = pthread_cond_destroy(&(t->flc_cond));
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+
+ mutex_destroy(&(t->waitmutex));
+
+ result = pthread_cond_destroy(&(t->waitcond));
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+
+ mutex_destroy(&(t->suspendmutex));
+
+ result = pthread_cond_destroy(&(t->suspendcond));
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+}
+#endif
+
+
+/* threads_impl_preinit ********************************************************
+
+ Do some early initialization of stuff required.
+
+ ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
+ is called AFTER this function!
+
+*******************************************************************************/
+
+void threads_impl_preinit(void)
+{
+ int result;
+
+ mutex_init(&stopworldlock);
+
+ /* initialize exit mutex and condition (on exit we join all
+ threads) */
+
+ mutex_init(&mutex_join);
+
+ result = pthread_cond_init(&cond_join, NULL);
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_preinit: pthread_cond_init failed");
+
+#if defined(ENABLE_GC_CACAO)
+ /* initialize the GC mutext */
+
+ mutex_init(&mutex_gc);
+#endif
+
+#if !defined(HAVE___THREAD)
+ result = pthread_key_create(&thread_current_key, NULL);
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
+#endif
+
+ threads_sem_init(&suspend_ack, 0, 0);
+}
+
+
+/* threads_mutex_gc_lock *******************************************************
+
+ Enter the global GC mutex.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_lock(void)
+{
+ mutex_lock(&mutex_gc);
+}
+#endif
+
+
+/* threads_mutex_gc_unlock *****************************************************
+
+ Leave the global GC mutex.
+
+*******************************************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_unlock(void)
+{
+ mutex_unlock(&mutex_gc);
+}
+#endif
+
+/* threads_mutex_join_lock *****************************************************
+
+ Enter the join mutex.
+
+*******************************************************************************/
+
+void threads_mutex_join_lock(void)
+{
+ mutex_lock(&mutex_join);
+}
+
+
+/* threads_mutex_join_unlock ***************************************************
+
+ Leave the join mutex.
+
+*******************************************************************************/
+
+void threads_mutex_join_unlock(void)
+{
+ mutex_unlock(&mutex_join);
+}
+
+
+/* threads_impl_init ***********************************************************
+
+ Initializes the implementation specific bits.
+
+*******************************************************************************/
+
+void threads_impl_init(void)
+{
+ pthread_attr_t attr;
+ int result;
+
+ threads_set_thread_priority(pthread_self(), NORM_PRIORITY);
+
+ /* Initialize the thread attribute object. */
+
+ result = pthread_attr_init(&attr);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
+
+ result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
+}
+
+
+/* threads_startup_thread ******************************************************
+
+ Thread startup function called by pthread_create.
+
+ Thread which have a startup.function != NULL are marked as internal
+ threads. All other threads are threated as normal Java threads.
+
+ NOTE: This function is not called directly by pthread_create. The Boehm GC
+ inserts its own GC_start_routine in between, which then calls
+ threads_startup.
+
+ IN:
+ arg..........the argument passed to pthread_create, ie. a pointer to
+ a startupinfo struct. CAUTION: When the `psem` semaphore
+ is posted, the startupinfo struct becomes invalid! (It
+ is allocated on the stack of threads_start_thread.)
+
+******************************************************************************/
+
+static void *threads_startup_thread(void *arg)
+{
+ startupinfo *startup;
+ threadobject *t;
+ java_lang_Thread *object;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_VMThread *vmt;
+#endif
+ sem_t *psem;
+ classinfo *c;
+ methodinfo *m;
+ java_handle_t *o;
+ functionptr function;
+
+#if defined(ENABLE_INTRP)
+ u1 *intrp_thread_stack;
+
+ /* create interpreter stack */
+
+ if (opt_intrp) {
+ intrp_thread_stack = GCMNEW(u1, opt_stacksize);
+ MSET(intrp_thread_stack, 0, u1, opt_stacksize);
+ }
+ else
+ intrp_thread_stack = NULL;
+#endif
+
+ /* get passed startupinfo structure and the values in there */
+
+ startup = arg;
+
+ t = startup->thread;
+ function = startup->function;
+ psem = startup->psem;
+
+ /* Seems like we've encountered a situation where thread->tid was
+ not set by pthread_create. We alleviate this problem by waiting
+ for pthread_create to return. */
+
+ threads_sem_wait(startup->psem_first);
+
+#if defined(__DARWIN__)
+ t->mach_thread = mach_thread_self();
+#endif
+
+ /* Now that we are in the new thread, we can store the internal
+ thread data-structure in the TSD. */
+
+ thread_set_current(t);
+
+ /* get the java.lang.Thread object for this thread */
+
+ object = (java_lang_Thread *) thread_get_object(t);
+
+ /* set our priority */
+
+ threads_set_thread_priority(t->tid, LLNI_field_direct(object, priority));
+
+ /* Thread is completely initialized. */
+
+ thread_set_state_runnable(t);
+
+ /* tell threads_startup_thread that we registered ourselves */
+ /* CAUTION: *startup becomes invalid with this! */
+
+ startup = NULL;
+ threads_sem_post(psem);
+
+#if defined(ENABLE_INTRP)
+ /* set interpreter stack */
+
+ if (opt_intrp)
+ thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
+#endif
+
+#if defined(ENABLE_JVMTI)
+ /* fire thread start event */
+
+ if (jvmti)
+ jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
+#endif
+
+ DEBUGTHREADS("starting", t);
+
+ /* find and run the Thread.run()V method if no other function was passed */
+
+ if (function == NULL) {
+#if defined(WITH_CLASSPATH_GNU)
+ /* We need to start the run method of
+ java.lang.VMThread. Since this is a final class, we can use
+ the class object directly. */
+
+ c = class_java_lang_VMThread;
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+ LLNI_class_get(object, c);
+#else
+# error unknown classpath configuration
+#endif
+
+ m = class_resolveclassmethod(c, utf_run, utf_void__void, c, true);
+
+ if (m == NULL)
+ vm_abort("threads_startup_thread: run() method not found in class");
+
+ /* set ThreadMXBean variables */
+
+ _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+ _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
+
+ if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+ _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+ _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+ _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
+
+#if defined(WITH_CLASSPATH_GNU)
+ /* we need to start the run method of java.lang.VMThread */
+
+ LLNI_field_get_ref(object, vmThread, vmt);
+ o = (java_handle_t *) vmt;
+
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+ o = (java_handle_t *) object;
+#else
+# error unknown classpath configuration
+#endif
+
+ /* Run the thread. */
+
+ (void) vm_call_method(m, o);
+ }
+ else {
+ /* set ThreadMXBean variables */
+
+ _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
+ _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
+
+ if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
+ _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
+ _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
+ _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
+
+ /* call passed function, e.g. finalizer_thread */
+
+ (function)();
+ }
+
+ DEBUGTHREADS("stopping", t);
+
+#if defined(ENABLE_JVMTI)
+ /* fire thread end event */
+
+ if (jvmti)
+ jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
+#endif
+
+ /* We ignore the return value. */
+
+ (void) threads_detach_thread(t);
+
+ /* set ThreadMXBean variables */
+
+ _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--;
+
+ return NULL;
+}
+
+
+/* threads_impl_thread_start ***************************************************
+
+ Start a thread in the JVM. Both (vm internal and java) thread
+ objects exist.
+
+ IN:
+ thread....the thread object
+ f.........function to run in the new thread. NULL means that the
+ "run" method of the object `t` should be called
+
+******************************************************************************/
+
+void threads_impl_thread_start(threadobject *thread, functionptr f)
+{
+ sem_t sem;
+ sem_t sem_first;
+ pthread_attr_t attr;
+ startupinfo startup;
+ int result;
+
+ /* fill startupinfo structure passed by pthread_create to
+ * threads_startup_thread */
+
+ startup.thread = thread;
+ startup.function = f; /* maybe we don't call Thread.run()V */
+ startup.psem = &sem;
+ startup.psem_first = &sem_first;
+
+ threads_sem_init(&sem, 0, 0);
+ threads_sem_init(&sem_first, 0, 0);
+
+ /* Initialize thread attributes. */
+
+ result = pthread_attr_init(&attr);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
+
+ result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setdetachstate failed");
+
+ /* initialize thread stacksize */
+
+ result = pthread_attr_setstacksize(&attr, opt_stacksize);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_setstacksize failed");
+
+ /* create the thread */
+
+ result = pthread_create(&(thread->tid), &attr, threads_startup_thread, &startup);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_create failed");
+
+ /* destroy the thread attributes */
+
+ result = pthread_attr_destroy(&attr);
+
+ if (result != 0)
+ vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
+
+ /* signal that pthread_create has returned, so thread->tid is valid */
+
+ threads_sem_post(&sem_first);
+
+ /* wait here until the thread has entered itself into the thread list */
+
+ threads_sem_wait(&sem);
+
+ /* cleanup */
+
+ sem_destroy(&sem);
+ sem_destroy(&sem_first);
+}
+
+
+/* threads_set_thread_priority *************************************************
+
+ Set the priority of the given thread.
+
+ IN:
+ tid..........thread id
+ priority.....priority to set
+
+******************************************************************************/
+
+void threads_set_thread_priority(pthread_t tid, int priority)
+{
+ struct sched_param schedp;
+ int policy;
+
+ pthread_getschedparam(tid, &policy, &schedp);
+ schedp.sched_priority = priority;
+ pthread_setschedparam(tid, policy, &schedp);
+}
+
+
+/* threads_detach_thread *******************************************************
+
+ Detaches the passed thread from the VM. Used in JNI.
+
+*******************************************************************************/
+
+bool threads_detach_thread(threadobject *t)
+{
+ bool result;
+ java_lang_Thread *object;
+ java_handle_t *o;
+#if defined(ENABLE_JAVASE)
+ java_lang_ThreadGroup *group;
+ java_handle_t *e;
+ void *handler;
+ classinfo *c;
+ methodinfo *m;
+#endif
+
+ /* If the given thread has already been detached, this operation
+ is a no-op. */
+
+ result = thread_is_attached(t);
+
+ if (result == false)
+ return true;
+
+ DEBUGTHREADS("detaching", t);
+
+ object = (java_lang_Thread *) thread_get_object(t);
+
+#if defined(ENABLE_JAVASE)
+ LLNI_field_get_ref(object, group, group);
+
+ /* If there's an uncaught exception, call uncaughtException on the
+ thread's exception handler, or the thread's group if this is
+ unset. */
+
+ e = exceptions_get_and_clear_exception();
+
+ if (e != NULL) {
+ /* We use the type void* for handler here, as it's not trivial
+ to build the java_lang_Thread_UncaughtExceptionHandler
+ header file with cacaoh. */
+
+# if defined(WITH_CLASSPATH_GNU)
+ LLNI_field_get_ref(object, exceptionHandler, handler);
+# elif defined(WITH_CLASSPATH_SUN)
+ LLNI_field_get_ref(object, uncaughtExceptionHandler, handler);
+# endif
+
+ if (handler != NULL) {
+ LLNI_class_get(handler, c);
+ o = (java_handle_t *) handler;
+ }
+ else {
+ LLNI_class_get(group, c);
+ o = (java_handle_t *) group;
+ }
+
+ m = class_resolveclassmethod(c,
+ utf_uncaughtException,
+ utf_java_lang_Thread_java_lang_Throwable__V,
+ NULL,
+ true);
+
+ if (m == NULL)
+ return false;
+
+ (void) vm_call_method(m, o, object, e);
+
+ if (exceptions_get_exception())
+ return false;
+ }
+
+ /* XXX TWISTI: should all threads be in a ThreadGroup? */
+
+ /* Remove thread from the thread group. */
+
+ if (group != NULL) {
+ LLNI_class_get(group, c);
+
+# if defined(WITH_CLASSPATH_GNU)
+ m = class_resolveclassmethod(c,
+ utf_removeThread,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
+# elif defined(WITH_CLASSPATH_SUN)
+ m = class_resolveclassmethod(c,
+ utf_remove,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
+# else
+# error unknown classpath configuration
+# endif
+
+ if (m == NULL)
+ return false;
+
+ o = (java_handle_t *) group;
+
+ (void) vm_call_method(m, o, object);
+
+ if (exceptions_get_exception())
+ return false;
+
+ /* Reset the threadgroup in the Java thread object (Mauve
+ test: gnu/testlet/java/lang/Thread/getThreadGroup). */
+
+ LLNI_field_set_ref(object, group, NULL);
+ }
+#endif
+
+ /* Thread has terminated. */
+
+ thread_set_state_terminated(t);
+
+ /* Notify all threads waiting on this thread. These are joining
+ this thread. */
+
+ o = (java_handle_t *) object;
+
+ /* XXX Care about exceptions? */
+ (void) lock_monitor_enter(o);
+
+ lock_notify_all_object(o);
+
+ /* XXX Care about exceptions? */
+ (void) lock_monitor_exit(o);
+
+ /* Enter the join-mutex before calling thread_free, so
+ threads_join_all_threads gets the correct number of non-daemon
+ threads. */
+
+ threads_mutex_join_lock();
+
+ /* Free the internal thread data-structure. */
+
+ thread_free(t);
+
+ /* Signal that this thread has finished and leave the mutex. */
+
+ pthread_cond_signal(&cond_join);
+ threads_mutex_join_unlock();
+
+ return true;
+}
+
+
+/* threads_suspend_thread ******************************************************
+
+ Suspend the passed thread. Execution stops until the thread
+ is explicitly resumend again.
+
+ IN:
+ reason.....Reason for suspending this thread.
+
+*******************************************************************************/
+
+bool threads_suspend_thread(threadobject *thread, s4 reason)
+{
+ /* acquire the suspendmutex */
+ mutex_lock(&(thread->suspendmutex));
+
+ if (thread->suspended) {
+ mutex_unlock(&(thread->suspendmutex));
+ return false;
+ }
+
+ /* set the reason for the suspension */
+ thread->suspend_reason = reason;
+
+ /* send the suspend signal to the thread */
+ assert(thread != THREADOBJECT);
+ if (pthread_kill(thread->tid, SIGUSR1) != 0)
+ vm_abort("threads_suspend_thread: pthread_kill failed: %s",
+ strerror(errno));
+
+ /* REMEMBER: do not release the suspendmutex, this is done
+ by the thread itself in threads_suspend_ack(). */
+
+ return true;
+}
+
+
+/* threads_suspend_ack *********************************************************
+
+ Acknowledges the suspension of the current thread.
+
+ IN:
+ pc.....The PC where the thread suspended its execution.
+ sp.....The SP before the thread suspended its execution.
+
+*******************************************************************************/
+
+void threads_suspend_ack(u1* pc, u1* sp)
+{
+ threadobject *thread;
+
+ thread = THREADOBJECT;
+
+ assert(thread->suspend_reason != 0);
+
+ /* TODO: remember dump memory size */
+
+#if defined(ENABLE_GC_CACAO)
+ /* inform the GC about the suspension */
+ if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
+
+ /* check if the GC wants to leave the thread running */
+ if (!gc_suspend(thread, pc, sp)) {
+
+ /* REMEMBER: we do not unlock the suspendmutex because the thread
+ will suspend itself again at a later time */
+ return;
+
+ }
+ }
+#endif
+
+ /* mark this thread as suspended and remember the PC */
+ thread->pc = pc;
+ thread->suspended = true;
+
+ /* if we are stopping the world, we should send a global ack */
+ if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+ threads_sem_post(&suspend_ack);
+ }
+
+ DEBUGTHREADS("suspending", thread);
+
+ /* release the suspension mutex and wait till we are resumed */
+ pthread_cond_wait(&(thread->suspendcond), &(thread->suspendmutex));
+
+ DEBUGTHREADS("resuming", thread);
+
+ /* if we are stopping the world, we should send a global ack */
+ if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
+ threads_sem_post(&suspend_ack);
+ }
+
+ /* TODO: free dump memory */
+
+ /* release the suspendmutex */
+ mutex_unlock(&(thread->suspendmutex));
+}
+
+
+/* threads_resume_thread *******************************************************
+
+ Resumes the execution of the passed thread.
+
+*******************************************************************************/
+
+bool threads_resume_thread(threadobject *thread)
+{
+ /* acquire the suspendmutex */
+ mutex_lock(&(thread->suspendmutex));
+
+ if (!thread->suspended) {
+ mutex_unlock(&(thread->suspendmutex));
+ return false;
+ }
+
+ thread->suspended = false;
+
+ /* tell everyone that the thread should resume */
+ assert(thread != THREADOBJECT);
+ pthread_cond_broadcast(&(thread->suspendcond));
+
+ /* release the suspendmutex */
+ mutex_unlock(&(thread->suspendmutex));
+
+ return true;
+}
+
+
+/* threads_join_all_threads ****************************************************
+
+ Join all non-daemon threads.
+
+*******************************************************************************/
+
+void threads_join_all_threads(void)
+{
+ threadobject *t;
+
+ /* get current thread */
+
+ t = THREADOBJECT;
+
+ /* This thread is waiting for all non-daemon threads to exit. */
+
+ thread_set_state_waiting(t);
+
+ /* enter join mutex */
+
+ threads_mutex_join_lock();
+
+ /* Wait for condition as long as we have non-daemon threads. We
+ compare against 1 because the current (main thread) is also a
+ non-daemon thread. */
+
+ while (threadlist_get_non_daemons() > 1)
+ pthread_cond_wait(&cond_join, &mutex_join);
+
+ /* leave join mutex */
+
+ threads_mutex_join_unlock();
+}
+
+
+/* threads_timespec_earlier ****************************************************
+
+ Return true if timespec tv1 is earlier than timespec tv2.
+
+ IN:
+ tv1..........first timespec
+ tv2..........second timespec
+
+ RETURN VALUE:
+ true, if the first timespec is earlier
+
+*******************************************************************************/
+
+static inline bool threads_timespec_earlier(const struct timespec *tv1,
+ const struct timespec *tv2)
+{
+ return (tv1->tv_sec < tv2->tv_sec)
+ ||
+ (tv1->tv_sec == tv2->tv_sec && tv1->tv_nsec < tv2->tv_nsec);
+}
+
+
+/* threads_current_time_is_earlier_than ****************************************
+
+ Check if the current time is earlier than the given timespec.
+
+ IN:
+ tv...........the timespec to compare against
+
+ RETURN VALUE:
+ true, if the current time is earlier
+
+*******************************************************************************/
+
+static bool threads_current_time_is_earlier_than(const struct timespec *tv)
+{
+ struct timeval tvnow;
+ struct timespec tsnow;
+
+ /* get current time */
+
+ if (gettimeofday(&tvnow, NULL) != 0)
+ vm_abort("gettimeofday failed: %s\n", strerror(errno));
+
+ /* convert it to a timespec */
+
+ tsnow.tv_sec = tvnow.tv_sec;
+ tsnow.tv_nsec = tvnow.tv_usec * 1000;
+
+ /* compare current time with the given timespec */
+
+ return threads_timespec_earlier(&tsnow, tv);
+}
+
+
+/* threads_wait_with_timeout ***************************************************
+
+ Wait until the given point in time on a monitor until either
+ we are notified, we are interrupted, or the time is up.
+
+ IN:
+ t............the current thread
+ wakeupTime...absolute (latest) wakeup time
+ If both tv_sec and tv_nsec are zero, this function
+ waits for an unlimited amount of time.
+
+*******************************************************************************/
+
+static void threads_wait_with_timeout(threadobject *t, struct timespec *wakeupTime)
+{
+ /* acquire the waitmutex */
+
+ mutex_lock(&t->waitmutex);
+
+ /* mark us as sleeping */
+
+ t->sleeping = true;
+
+ /* wait on waitcond */
+
+ if (wakeupTime->tv_sec || wakeupTime->tv_nsec) {
+ /* with timeout */
+ while (!t->interrupted && !t->signaled
+ && threads_current_time_is_earlier_than(wakeupTime))
+ {
+ thread_set_state_timed_waiting(t);
+
+ pthread_cond_timedwait(&t->waitcond, &t->waitmutex,
+ wakeupTime);
+
+ thread_set_state_runnable(t);
+ }
+ }
+ else {
+ /* no timeout */
+ while (!t->interrupted && !t->signaled) {
+ thread_set_state_waiting(t);
+
+ pthread_cond_wait(&t->waitcond, &t->waitmutex);
+
+ thread_set_state_runnable(t);
+ }
+ }
+
+ t->sleeping = false;
+
+ /* release the waitmutex */
+
+ mutex_unlock(&t->waitmutex);
+}
+
+
+/* threads_wait_with_timeout_relative ******************************************
+
+ Wait for the given maximum amount of time on a monitor until either
+ we are notified, we are interrupted, or the time is up.
+
+ IN:
+ t............the current thread
+ millis.......milliseconds to wait
+ nanos........nanoseconds to wait
+
+*******************************************************************************/
+
+void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
+ s4 nanos)
+{
+ struct timespec wakeupTime;
+
+ /* calculate the the (latest) wakeup time */
+
+ threads_calc_absolute_time(&wakeupTime, millis, nanos);
+
+ /* wait */
+
+ threads_wait_with_timeout(thread, &wakeupTime);
+}
+
+
+/* threads_calc_absolute_time **************************************************
+
+ Calculate the absolute point in time a given number of ms and ns from now.
+
+ IN:
+ millis............milliseconds from now
+ nanos.............nanoseconds from now
+
+ OUT:
+ *tm...............receives the timespec of the absolute point in time
+
+*******************************************************************************/
+
+static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
+{
+ if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
+ struct timeval tv;
+ long nsec;
+ gettimeofday(&tv, NULL);
+ tv.tv_sec += millis / 1000;
+ millis %= 1000;
+ nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
+ tm->tv_sec = tv.tv_sec + nsec / 1000000000;
+ tm->tv_nsec = nsec % 1000000000;
+ }
+ else {
+ tm->tv_sec = 0;
+ tm->tv_nsec = 0;
+ }
+}
+
+
+/* threads_thread_interrupt ****************************************************
+
+ Interrupt the given thread.
+
+ The thread gets the "waitcond" signal and
+ its interrupted flag is set to true.
+
+ IN:
+ thread............the thread to interrupt
+
+*******************************************************************************/
+
+void threads_thread_interrupt(threadobject *thread)
+{
+ /* Signal the thread a "waitcond" and tell it that it has been
+ interrupted. */
+
+ mutex_lock(&thread->waitmutex);
+
+ DEBUGTHREADS("interrupted", thread);
+
+ /* Interrupt blocking system call using a signal. */
+
+ pthread_kill(thread->tid, SIGHUP);
+
+ if (thread->sleeping)
+ pthread_cond_signal(&thread->waitcond);
+
+ thread->interrupted = true;
+
+ mutex_unlock(&thread->waitmutex);
+}
+
+
+/* threads_sleep ***************************************************************
+
+ Sleep the current thread for the specified amount of time.
+
+*******************************************************************************/
+
+void threads_sleep(int64_t millis, int32_t nanos)
+{
+ threadobject *t;
+ struct timespec wakeupTime;
+ bool interrupted;
+
+ if (millis < 0) {
+/* exceptions_throw_illegalargumentexception("timeout value is negative"); */
+ exceptions_throw_illegalargumentexception();
+ return;
+ }
+
+ t = thread_get_current();
+
+ if (thread_is_interrupted(t) && !exceptions_get_exception()) {
+ /* Clear interrupted flag (Mauve test:
+ gnu/testlet/java/lang/Thread/interrupt). */
+
+ thread_set_interrupted(t, false);
+
+/* exceptions_throw_interruptedexception("sleep interrupted"); */
+ exceptions_throw_interruptedexception();
+ return;
+ }
+
+ threads_calc_absolute_time(&wakeupTime, millis, nanos);
+
+ threads_wait_with_timeout(t, &wakeupTime);
+
+ interrupted = thread_is_interrupted(t);
+
+ if (interrupted) {
+ thread_set_interrupted(t, false);
+
+ /* An other exception could have been thrown
+ (e.g. ThreadDeathException). */
+
+ if (!exceptions_get_exception())
+ exceptions_throw_interruptedexception();
+ }
+}
+
+
+/* threads_yield ***************************************************************
+
+ Yield to the scheduler.
+
+*******************************************************************************/
+
+void threads_yield(void)
+{
+ sched_yield();
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/threads/posix/thread-posix.h - POSIX thread functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _THREAD_POSIX_H
+#define _THREAD_POSIX_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct threadobject threadobject;
+
+
+#include "config.h"
+
+#include <pthread.h>
+#include <ucontext.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/localref.h"
+
+#include "threads/mutex.h"
+
+#include "threads/posix/lock.h"
+
+#include "vm/global.h"
+#include "vm/vm.h"
+
+#if defined(ENABLE_GC_CACAO)
+# include "vm/jit/replace.h"
+#endif
+
+#include "vm/jit/stacktrace.h"
+
+#if defined(ENABLE_INTRP)
+#include "vm/jit/intrp/intrp.h"
+#endif
+
+#if defined(__DARWIN__)
+# include <mach/mach.h>
+
+typedef struct {
+ mutex_t mutex;
+ pthread_cond_t cond;
+ int value;
+} sem_t;
+
+#else
+# include <semaphore.h>
+#endif
+
+
+/* current threadobject *******************************************************/
+
+#if defined(HAVE___THREAD)
+
+#define THREADSPECIFIC __thread
+#define THREADOBJECT thread_current
+
+extern __thread threadobject *thread_current;
+
+#else /* defined(HAVE___THREAD) */
+
+#define THREADSPECIFIC
+#define THREADOBJECT \
+ ((threadobject *) pthread_getspecific(thread_current_key))
+
+extern pthread_key_t thread_current_key;
+
+#endif /* defined(HAVE___THREAD) */
+
+
+/* threadobject ****************************************************************
+
+ Struct holding thread local variables.
+
+*******************************************************************************/
+
+#define THREAD_FLAG_JAVA 0x01 /* a normal Java thread */
+#define THREAD_FLAG_INTERNAL 0x02 /* CACAO internal thread */
+#define THREAD_FLAG_DAEMON 0x04 /* daemon thread */
+#define THREAD_FLAG_IN_NATIVE 0x08 /* currently executing native code */
+
+#define SUSPEND_REASON_JNI 1 /* suspended from JNI */
+#define SUSPEND_REASON_STOPWORLD 2 /* suspended from stop-thw-world */
+
+
+struct threadobject {
+ java_object_t *object; /* link to java.lang.Thread object */
+
+ ptrint thinlock; /* pre-computed thin lock value */
+
+ s4 index; /* thread index, starting with 1 */
+ u4 flags; /* flag field */
+ u4 state; /* state field */
+
+ pthread_t tid; /* pthread id */
+
+#if defined(__DARWIN__)
+ mach_port_t mach_thread; /* Darwin thread id */
+#endif
+
+ /* for the sable tasuki lock extension */
+ bool flc_bit;
+ struct threadobject *flc_list; /* FLC list head for this thread */
+ struct threadobject *flc_next; /* next pointer for FLC list */
+ java_handle_t *flc_object;
+ mutex_t flc_lock; /* controlling access to these fields */
+ pthread_cond_t flc_cond;
+
+ /* these are used for the wait/notify implementation */
+ mutex_t waitmutex;
+ pthread_cond_t waitcond;
+
+ mutex_t suspendmutex; /* lock before suspending this thread */
+ pthread_cond_t suspendcond; /* notify to resume this thread */
+
+ bool interrupted;
+ bool signaled;
+ bool sleeping;
+
+ bool suspended; /* is this thread suspended? */
+ s4 suspend_reason; /* reason for suspending */
+
+ u1 *pc; /* current PC (used for profiling) */
+
+ java_object_t *_exceptionptr; /* current exception */
+ stackframeinfo_t *_stackframeinfo; /* current native stackframeinfo */
+ localref_table *_localref_table; /* JNI local references */
+
+#if defined(ENABLE_INTRP)
+ Cell *_global_sp; /* stack pointer for interpreter */
+#endif
+
+#if defined(ENABLE_GC_CACAO)
+ bool gc_critical; /* indicates a critical section */
+
+ sourcestate_t *ss;
+ executionstate_t *es;
+#endif
+
+ dumpinfo_t dumpinfo; /* dump memory info structure */
+
+#if defined(ENABLE_DEBUG_FILTER)
+ u2 filterverbosecallctr[2]; /* counters for verbose call filter */
+#endif
+
+#if !defined(NDEBUG)
+ s4 tracejavacallindent;
+ u4 tracejavacallcount;
+#endif
+
+ listnode_t linkage; /* threads-list */
+ listnode_t linkage_free; /* free-list */
+};
+
+
+/* native-world flags *********************************************************/
+
+#if defined(ENABLE_GC_CACAO)
+# define THREAD_NATIVEWORLD_ENTER THREADOBJECT->flags |= THREAD_FLAG_IN_NATIVE
+# define THREAD_NATIVEWORLD_EXIT THREADOBJECT->flags &= ~THREAD_FLAG_IN_NATIVE
+#else
+# define THREAD_NATIVEWORLD_ENTER /*nop*/
+# define THREAD_NATIVEWORLD_EXIT /*nop*/
+#endif
+
+
+/* counter for verbose call filter ********************************************/
+
+#if defined(ENABLE_DEBUG_FILTER)
+# define FILTERVERBOSECALLCTR (THREADOBJECT->filterverbosecallctr)
+#endif
+
+/* state for trace java call **************************************************/
+
+#if !defined(NDEBUG)
+# define TRACEJAVACALLINDENT (THREADOBJECT->tracejavacallindent)
+# define TRACEJAVACALLCOUNT (THREADOBJECT->tracejavacallcount)
+#endif
+
+
+/* inline functions ***********************************************************/
+
+/* thread_get_current **********************************************************
+
+ Return the threadobject of the current thread.
+
+ RETURN:
+ the current threadobject *
+
+*******************************************************************************/
+
+inline static threadobject *thread_get_current(void)
+{
+ threadobject *t;
+
+#if defined(HAVE___THREAD)
+ t = thread_current;
+#else
+ t = (threadobject *) pthread_getspecific(thread_current_key);
+#endif
+
+ return t;
+}
+
+
+/* thread_set_current **********************************************************
+
+ Set the current thread object.
+
+ IN:
+ t ... the thread object to set
+
+*******************************************************************************/
+
+inline static void thread_set_current(threadobject *t)
+{
+#if defined(HAVE___THREAD)
+ thread_current = t;
+#else
+ int result;
+
+ result = pthread_setspecific(thread_current_key, t);
+
+ if (result != 0)
+ vm_abort_errnum(result, "thread_set_current: pthread_setspecific failed");
+#endif
+}
+
+
+inline static stackframeinfo_t *threads_get_current_stackframeinfo(void)
+{
+ return THREADOBJECT->_stackframeinfo;
+}
+
+inline static void threads_set_current_stackframeinfo(stackframeinfo_t *sfi)
+{
+ THREADOBJECT->_stackframeinfo = sfi;
+}
+
+
+/* functions ******************************************************************/
+
+void threads_sem_init(sem_t *sem, bool shared, int value);
+void threads_sem_wait(sem_t *sem);
+void threads_sem_post(sem_t *sem);
+
+void threads_start_thread(threadobject *thread, functionptr function);
+
+void threads_set_thread_priority(pthread_t tid, int priority);
+
+bool threads_detach_thread(threadobject *thread);
+
+bool threads_suspend_thread(threadobject *thread, s4 reason);
+void threads_suspend_ack(u1* pc, u1* sp);
+bool threads_resume_thread(threadobject *thread);
+
+void threads_join_all_threads(void);
+
+void threads_sleep(int64_t millis, int32_t nanos);
+
+void threads_wait_with_timeout_relative(threadobject *t, s8 millis, s4 nanos);
+
+void threads_thread_interrupt(threadobject *thread);
+
+#if !defined(DISABLE_GC)
+void threads_stopworld(void);
+void threads_startworld(void);
+#endif
+
+#endif /* _THREAD_POSIX_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/threads/thread.c - machine independent thread functions
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+#include "native/native.h"
+
+#include "native/include/java_lang_Object.h"
+#include "native/include/java_lang_String.h"
+#include "native/include/java_lang_Thread.h"
+
+#if defined(ENABLE_JAVASE)
+# include "native/include/java_lang_ThreadGroup.h"
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/java_lang_VMThread.h"
+#endif
+
+#include "threads/critical.h"
+#include "threads/lock-common.h"
+#include "threads/threadlist.h"
+#include "threads/thread.h"
+
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
+
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/class.h"
+#include "vmcore/method.h"
+#include "vmcore/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vmcore/statistics.h"
+#endif
+
+#include "vmcore/utf8.h"
+
+
+/* global variables ***********************************************************/
+
+static methodinfo *thread_method_init;
+static java_handle_t *threadgroup_system;
+static java_handle_t *threadgroup_main;
+
+#if defined(__LINUX__)
+/* XXX Remove for exact-GC. */
+bool threads_pthreads_implementation_nptl;
+#endif
+
+
+/* static functions ***********************************************************/
+
+static void thread_create_initial_threadgroups(void);
+static void thread_create_initial_thread(void);
+static threadobject *thread_new(void);
+
+
+/* threads_preinit *************************************************************
+
+ Do some early initialization of stuff required.
+
+*******************************************************************************/
+
+void threads_preinit(void)
+{
+ threadobject *mainthread;
+#if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
+ char *pathbuf;
+ size_t len;
+#endif
+
+ TRACESUBSYSTEMINITIALIZATION("threads_preinit");
+
+#if defined(__LINUX__)
+ /* XXX Remove for exact-GC. */
+
+ /* On Linux we need to check the pthread implementation. */
+
+ /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
+ /* If the glibc is a pre-2.3.2 version, we fall back to
+ linuxthreads. */
+
+# if defined(_CS_GNU_LIBPTHREAD_VERSION)
+ len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
+
+ /* Some systems return as length 0 (maybe cross-compilation
+ related). In this case we also fall back to linuxthreads. */
+
+ if (len > 0) {
+ pathbuf = MNEW(char, len);
+
+ (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
+
+ if (strstr(pathbuf, "NPTL") != NULL)
+ threads_pthreads_implementation_nptl = true;
+ else
+ threads_pthreads_implementation_nptl = false;
+ }
+ else
+ threads_pthreads_implementation_nptl = false;
+# else
+ threads_pthreads_implementation_nptl = false;
+# endif
+#endif
+
+ /* Initialize the threads implementation (sets the thinlock on the
+ main thread). */
+
+ threads_impl_preinit();
+
+ /* Create internal thread data-structure for the main thread. */
+
+ mainthread = thread_new();
+
+ /* thread is a Java thread and running */
+
+ mainthread->flags |= THREAD_FLAG_JAVA;
+ mainthread->state = THREAD_STATE_RUNNABLE;
+
+ /* Store the internal thread data-structure in the TSD. */
+
+ thread_set_current(mainthread);
+}
+
+
+/* threads_init ****************************************************************
+
+ Initialize the main thread.
+
+*******************************************************************************/
+
+void threads_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("threads_init");
+
+ /* Create the system and main thread groups. */
+
+ thread_create_initial_threadgroups();
+
+ /* Cache the java.lang.Thread initialization method. */
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ thread_method_init =
+ class_resolveclassmethod(class_java_lang_Thread,
+ utf_init,
+ utf_new_char("(Ljava/lang/VMThread;Ljava/lang/String;IZ)V"),
+ class_java_lang_Thread,
+ true);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
+ thread_method_init =
+ class_resolveclassmethod(class_java_lang_Thread,
+ utf_init,
+ utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V"),
+ class_java_lang_Thread,
+ true);
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+
+ thread_method_init =
+ class_resolveclassmethod(class_java_lang_Thread,
+ utf_init,
+ utf_java_lang_String__void,
+ class_java_lang_Thread,
+ true);
+
+#else
+# error unknown classpath configuration
+#endif
+
+ if (thread_method_init == NULL)
+ vm_abort("threads_init: failed to resolve thread init method");
+
+ thread_create_initial_thread();
+}
+
+
+/* thread_create_object ********************************************************
+
+ Create a Java thread object for the given thread data-structure,
+ initializes it and adds the thread to the threadgroup.
+
+ ARGUMENTS:
+
+ t ....... thread
+ name .... thread name
+ group ... threadgroup
+
+ RETURN:
+
+*******************************************************************************/
+
+static bool thread_create_object(threadobject *t, java_handle_t *name, java_handle_t *group)
+{
+ java_handle_t *o;
+ java_lang_Thread *to;
+
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_VMThread *vmto;
+ classinfo *c;
+ methodinfo *m;
+ bool isdaemon;
+#endif
+
+ /* Create a java.lang.Thread Java object. */
+
+ o = builtin_new(class_java_lang_Thread);
+
+ if (o == NULL)
+ return false;
+
+ to = (java_lang_Thread *) o;
+
+ /* Set the Java object in the thread data-structure. This
+ indicates that the thread is attached to the VM. */
+
+ thread_set_object(t, (java_handle_t *) to);
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ /* Create a java.lang.VMThread Java object. */
+
+ vmto = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
+
+ if (vmto == NULL)
+ return false;
+
+ /* Set the Java thread object in the Java VM-thread object. */
+
+ LLNI_field_set_ref(vmto, thread, to);
+
+ /* Set the thread data-structure in the Java VM-thread object. */
+
+ LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
+
+ /* Call:
+ java.lang.Thread.<init>(Ljava/lang/VMThread;Ljava/lang/String;IZ)V */
+
+ isdaemon = thread_is_daemon(t);
+
+ (void) vm_call_method(thread_method_init, o, vmto, name, NORM_PRIORITY,
+ isdaemon);
+
+ if (exceptions_get_exception())
+ return false;
+
+ /* Set the threadgroup in the Java thread object. */
+
+ LLNI_field_set_ref(to, group, (java_lang_ThreadGroup *) group);
+
+ /* Add thread to the threadgroup. */
+
+ LLNI_class_get(group, c);
+
+ m = class_resolveclassmethod(c,
+ utf_addThread,
+ utf_java_lang_Thread__V,
+ class_java_lang_ThreadGroup,
+ true);
+
+ if (m == NULL)
+ return false;
+
+ (void) vm_call_method(m, group, to);
+
+ if (exceptions_get_exception())
+ return false;
+
+#elif defined(WITH_CLASSPATH_SUN)
+
+ /* OpenJDK's java.lang.Thread does not have a VMThread field in
+ the class. Nothing to do here. */
+
+ /* Set the priority. java.lang.Thread.<init> requires it because
+ it sets the priority of the current thread to the parent's one
+ (which is the current thread in this case). */
+
+ LLNI_field_set_val(to, priority, NORM_PRIORITY);
+
+ /* Call:
+ java.lang.Thread.<init>(Ljava/lang/ThreadGroup;Ljava/lang/String;)V */
+
+ (void) vm_call_method(thread_method_init, o, group, name);
+
+ if (exceptions_get_exception())
+ return false;
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+
+ /* Set the thread data-structure in the Java thread object. */
+
+ LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
+
+ /* Call: public Thread(Ljava/lang/String;)V */
+
+ (void) vm_call_method(thread_method_init, o, name);
+
+ if (exceptions_get_exception())
+ return false;
+
+#else
+# error unknown classpath configuration
+#endif
+
+ return true;
+}
+
+
+/* thread_create_initial_threadgroups ******************************************
+
+ Create the initial threadgroups.
+
+ GNU Classpath:
+ Create the main threadgroup only and set the system
+ threadgroup to the main threadgroup.
+
+ SUN:
+ Create the system and main threadgroup.
+
+ CLDC:
+ This function is a no-op.
+
+*******************************************************************************/
+
+static void thread_create_initial_threadgroups(void)
+{
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_GNU)
+
+ /* Allocate and initialize the main thread group. */
+
+ threadgroup_main = native_new_and_init(class_java_lang_ThreadGroup);
+
+ if (threadgroup_main == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
+
+ /* Use the same threadgroup for system as for main. */
+
+ threadgroup_system = threadgroup_main;
+
+# elif defined(WITH_CLASSPATH_SUN)
+
+ java_handle_t *name;
+ methodinfo *m;
+
+ /* Allocate and initialize the system thread group. */
+
+ threadgroup_system = native_new_and_init(class_java_lang_ThreadGroup);
+
+ if (threadgroup_system == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to allocate system threadgroup");
+
+ /* Allocate and initialize the main thread group. */
+
+ threadgroup_main = builtin_new(class_java_lang_ThreadGroup);
+
+ if (threadgroup_main == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to allocate main threadgroup");
+
+ name = javastring_new(utf_main);
+
+ m = class_resolveclassmethod(class_java_lang_ThreadGroup,
+ utf_init,
+ utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V,
+ class_java_lang_ThreadGroup,
+ true);
+
+ if (m == NULL)
+ vm_abort("thread_create_initial_threadgroups: failed to resolve threadgroup init method");
+
+ (void) vm_call_method(m, threadgroup_main, threadgroup_system, name);
+
+ if (exceptions_get_exception())
+ vm_abort("thread_create_initial_threadgroups: exception while initializing main threadgroup");
+
+# else
+# error unknown classpath configuration
+# endif
+#endif
+}
+
+
+/* thread_create_initial_thread ***********************************************
+
+ Create the initial thread: main
+
+*******************************************************************************/
+
+static void thread_create_initial_thread(void)
+{
+ threadobject *t;
+ java_handle_t *name;
+
+ /* Get the main-thread (NOTE: The main thread is always the first
+ thread in the list). */
+
+ t = threadlist_first();
+
+ /* The thread name. */
+
+ name = javastring_new(utf_main);
+
+#if defined(ENABLE_INTRP)
+ /* create interpreter stack */
+
+ if (opt_intrp) {
+ MSET(intrp_main_stack, 0, u1, opt_stacksize);
+ mainthread->_global_sp = (Cell*) (intrp_main_stack + opt_stacksize);
+ }
+#endif
+
+ /* Create the Java thread object. */
+
+ if (!thread_create_object(t, name, threadgroup_main))
+ vm_abort("thread_create_initial_thread: failed to create Java object");
+
+ /* Initialize the implementation specific bits. */
+
+ threads_impl_init();
+
+ DEBUGTHREADS("starting (main)", t);
+}
+
+
+/* thread_new ******************************************************************
+
+ Allocates and initializes an internal thread data-structure and
+ adds it to the threads list.
+
+*******************************************************************************/
+
+static threadobject *thread_new(void)
+{
+ int32_t index;
+ threadobject *t;
+
+ /* Lock the thread lists */
+
+ threadlist_lock();
+
+ index = threadlist_get_free_index();
+
+ /* Allocate a thread data structure. */
+
+ /* First, try to get one from the free-list. */
+
+ t = threadlist_free_first();
+
+ if (t != NULL) {
+ /* Remove from free list. */
+
+ threadlist_free_remove(t);
+
+ /* Equivalent of MZERO on the else path */
+
+ threads_impl_thread_clear(t);
+ }
+ else {
+#if defined(ENABLE_GC_BOEHM)
+ t = GCNEW_UNCOLLECTABLE(threadobject, 1);
+#else
+ t = NEW(threadobject);
+#endif
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_threadobject += sizeof(threadobject);
+#endif
+
+ /* Clear memory. */
+
+ MZERO(t, threadobject, 1);
+
+#if defined(ENABLE_GC_CACAO)
+ /* Register reference to java.lang.Thread with the GC. */
+ /* FIXME is it ok to do this only once? */
+
+ gc_reference_register(&(t->object), GC_REFTYPE_THREADOBJECT);
+ gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
+#endif
+
+ /* Initialize the implementation-specific bits. */
+
+ threads_impl_thread_init(t);
+ }
+
+ /* Pre-compute the thinlock-word. */
+
+ assert(index != 0);
+
+ t->index = index;
+ t->thinlock = lock_pre_compute_thinlock(t->index);
+ t->flags = 0;
+ t->state = THREAD_STATE_NEW;
+
+#if defined(ENABLE_GC_CACAO)
+ t->flags |= THREAD_FLAG_IN_NATIVE;
+#endif
+
+ /* Initialize the implementation-specific bits. */
+
+ threads_impl_thread_reuse(t);
+
+ /* Add the thread to the thread list. */
+
+ threadlist_add(t);
+
+ /* Unlock the thread lists. */
+
+ threadlist_unlock();
+
+ return t;
+}
+
+
+/* thread_free *****************************************************************
+
+ Remove the thread from the threads-list and free the internal
+ thread data structure. The thread index is added to the
+ thread-index free-list.
+
+ IN:
+ t ... thread data structure
+
+*******************************************************************************/
+
+void thread_free(threadobject *t)
+{
+ /* Lock the thread lists. */
+
+ threadlist_lock();
+
+ /* Remove the thread from the thread-list. */
+
+ threadlist_remove(t);
+
+ /* Add the thread index to the free list. */
+
+ threadlist_index_add(t->index);
+
+ /* Set the reference to the Java object to NULL. */
+
+ thread_set_object(t, NULL);
+
+ /* Add the thread data structure to the free list. */
+
+ threadlist_free_add(t);
+
+ /* Unlock the thread lists. */
+
+ threadlist_unlock();
+}
+
+
+/* threads_thread_start_internal ***********************************************
+
+ Start an internal thread in the JVM. No Java thread objects exists
+ so far.
+
+ IN:
+ name.......UTF-8 name of the thread
+ f..........function pointer to C function to start
+
+*******************************************************************************/
+
+bool threads_thread_start_internal(utf *name, functionptr f)
+{
+ threadobject *t;
+
+ /* Enter the join-mutex, so if the main-thread is currently
+ waiting to join all threads, the number of non-daemon threads
+ is correct. */
+
+ threads_mutex_join_lock();
+
+ /* Create internal thread data-structure. */
+
+ t = thread_new();
+
+ t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
+
+ /* The thread is flagged as (non-)daemon thread, we can leave the
+ mutex. */
+
+ threads_mutex_join_unlock();
+
+ /* Create the Java thread object. */
+
+ if (!thread_create_object(t, javastring_new(name), threadgroup_system))
+ return false;
+
+ /* Start the thread. */
+
+ threads_impl_thread_start(t, f);
+
+ /* everything's ok */
+
+ return true;
+}
+
+
+/* threads_thread_start ********************************************************
+
+ Start a Java thread in the JVM. Only the java thread object exists
+ so far.
+
+ IN:
+ object.....the java thread object java.lang.Thread
+
+*******************************************************************************/
+
+void threads_thread_start(java_handle_t *object)
+{
+ java_lang_Thread *to;
+ threadobject *t;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_VMThread *vmto;
+#endif
+
+ to = (java_lang_Thread *) object;
+
+ /* Enter the join-mutex, so if the main-thread is currently
+ waiting to join all threads, the number of non-daemon threads
+ is correct. */
+
+ threads_mutex_join_lock();
+
+ /* Create internal thread data-structure. */
+
+ t = thread_new();
+
+ /* this is a normal Java thread */
+
+ t->flags |= THREAD_FLAG_JAVA;
+
+#if defined(ENABLE_JAVASE)
+ /* Is this a daemon thread? */
+
+ if (LLNI_field_direct(to, daemon) == true)
+ t->flags |= THREAD_FLAG_DAEMON;
+#endif
+
+ /* The thread is flagged and (non-)daemon thread, we can leave the
+ mutex. */
+
+ threads_mutex_join_unlock();
+
+ /* Link the two objects together. */
+
+ thread_set_object(t, object);
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ /* Get the java.lang.VMThread object and do some sanity checks. */
+
+ LLNI_field_get_ref(to, vmThread, vmto);
+
+ assert(vmto);
+ assert(LLNI_field_direct(vmto, vmdata) == NULL);
+
+ LLNI_field_set_val(vmto, vmdata, (java_lang_Object *) t);
+
+#elif defined(WITH_CLASSPATH_SUN)
+
+ /* Nothing to do. */
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+
+ LLNI_field_set_val(to, vm_thread, (java_lang_Object *) t);
+
+#else
+# error unknown classpath configuration
+#endif
+
+ /* Start the thread. Don't pass a function pointer (NULL) since
+ we want Thread.run()V here. */
+
+ threads_impl_thread_start(t, NULL);
+}
+
+
+/* threads_attach_current_thread ***********************************************
+
+ Attaches the current thread to the VM. Used in JNI.
+
+*******************************************************************************/
+
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
+{
+ bool result;
+ threadobject *t;
+ utf *u;
+ java_handle_t *name;
+ java_handle_t *group;
+
+ /* If the current thread has already been attached, this operation
+ is a no-op. */
+
+ result = thread_current_is_attached();
+
+ if (result == true)
+ return true;
+
+ /* Enter the join-mutex, so if the main-thread is currently
+ waiting to join all threads, the number of non-daemon threads
+ is correct. */
+
+ threads_mutex_join_lock();
+
+ /* Create internal thread data structure. */
+
+ t = thread_new();
+
+ /* Thread is a Java thread and running. */
+
+ t->flags = THREAD_FLAG_JAVA;
+
+ if (isdaemon)
+ t->flags |= THREAD_FLAG_DAEMON;
+
+ /* Store the internal thread data-structure in the TSD. */
+
+ thread_set_current(t);
+
+ /* The thread is flagged and (non-)daemon thread, we can leave the
+ mutex. */
+
+ threads_mutex_join_unlock();
+
+ DEBUGTHREADS("attaching", t);
+
+ /* Get the thread name. */
+
+ if (vm_aargs != NULL) {
+ u = utf_new_char(vm_aargs->name);
+ }
+ else {
+ u = utf_null;
+ }
+
+ name = javastring_new(u);
+
+#if defined(ENABLE_JAVASE)
+ /* Get the threadgroup. */
+
+ if (vm_aargs != NULL)
+ group = (java_handle_t *) vm_aargs->group;
+ else
+ group = NULL;
+
+ /* If no threadgroup was given, use the main threadgroup. */
+
+ if (group == NULL)
+ group = threadgroup_main;
+#endif
+
+#if defined(ENABLE_INTRP)
+ /* create interpreter stack */
+
+ if (opt_intrp) {
+ MSET(intrp_main_stack, 0, u1, opt_stacksize);
+ thread->_global_sp = (Cell *) (intrp_main_stack + opt_stacksize);
+ }
+#endif
+
+ /* Create the Java thread object. */
+
+ if (!thread_create_object(t, name, group))
+ return false;
+
+ /* The thread is completely initialized. */
+
+ thread_set_state_runnable(t);
+
+ return true;
+}
+
+
+/* thread_fprint_name **********************************************************
+
+ Print the name of the given thread to the given stream.
+
+ ARGUMENTS:
+ t ........ thread data-structure
+ stream ... stream to print to
+
+*******************************************************************************/
+
+void thread_fprint_name(threadobject *t, FILE *stream)
+{
+ java_lang_Thread *to;
+
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_String *name;
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+ java_chararray_t *name;
+#endif
+
+ to = (java_lang_Thread *) thread_get_object(t);
+
+ if (to == NULL)
+ vm_abort("");
+
+ LLNI_field_get_ref(to, name, name);
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ javastring_fprint((java_handle_t *) name, stream);
+
+#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
+
+ /* FIXME: In OpenJDK and CLDC the name is a char[]. */
+ /* FIXME This prints to stdout. */
+ utf_display_printable_ascii(utf_null);
+
+#else
+# error unknown classpath configuration
+#endif
+}
+
+
+/* thread_print_info ***********************************************************
+
+ Print information of the passed thread.
+
+ ARGUMENTS:
+ t ... thread data-structure.
+
+*******************************************************************************/
+
+void thread_print_info(threadobject *t)
+{
+ java_lang_Thread *to;
+ int state;
+
+ /* If the thread is currently in initalization, don't print it. */
+
+ to = (java_lang_Thread *) thread_get_object(t);
+
+ /* Print as much as we can when we are in state NEW. */
+
+ if (to != NULL) {
+ /* Print thread name. */
+
+ printf("\"");
+ thread_fprint_name(t, stdout);
+ printf("\"");
+ }
+ else {
+ }
+
+ if (thread_is_daemon(t))
+ printf(" daemon");
+
+ if (to != NULL) {
+ printf(" prio=%d", LLNI_field_direct(to, priority));
+ }
+
+#if SIZEOF_VOID_P == 8
+ printf(" t=0x%016lx tid=0x%016lx (%ld)",
+ (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
+#else
+ printf(" t=0x%08x tid=0x%08x (%d)",
+ (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
+#endif
+
+ printf(" index=%d", t->index);
+
+ /* Print thread state. */
+
+ state = cacaothread_get_state(t);
+
+ switch (state) {
+ case THREAD_STATE_NEW:
+ printf(" new");
+ break;
+ case THREAD_STATE_RUNNABLE:
+ printf(" runnable");
+ break;
+ case THREAD_STATE_BLOCKED:
+ printf(" blocked");
+ break;
+ case THREAD_STATE_WAITING:
+ printf(" waiting");
+ break;
+ case THREAD_STATE_TIMED_WAITING:
+ printf(" waiting on condition");
+ break;
+ case THREAD_STATE_TERMINATED:
+ printf(" terminated");
+ break;
+ default:
+ vm_abort("thread_print_info: unknown thread state %d", state);
+ }
+}
+
+
+/* threads_get_current_tid *****************************************************
+
+ Return the tid of the current thread.
+
+ RETURN VALUE:
+ the current tid
+
+*******************************************************************************/
+
+intptr_t threads_get_current_tid(void)
+{
+ threadobject *thread;
+
+ thread = THREADOBJECT;
+
+ /* this may happen during bootstrap */
+
+ if (thread == NULL)
+ return 0;
+
+ return (intptr_t) thread->tid;
+}
+
+
+/* thread_set_state_runnable ***************************************************
+
+ Set the current state of the given thread to THREAD_STATE_RUNNABLE.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_runnable(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ t->state = THREAD_STATE_RUNNABLE;
+
+ DEBUGTHREADS("is RUNNABLE", t);
+ }
+
+ threadlist_unlock();
+}
+
+
+/* thread_set_state_waiting ****************************************************
+
+ Set the current state of the given thread to THREAD_STATE_WAITING.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_waiting(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ t->state = THREAD_STATE_WAITING;
+
+ DEBUGTHREADS("is WAITING", t);
+ }
+
+ threadlist_unlock();
+}
+
+
+/* thread_set_state_timed_waiting **********************************************
+
+ Set the current state of the given thread to
+ THREAD_STATE_TIMED_WAITING.
+
+ NOTE: If the thread has already terminated, don't set the state.
+ This is important for threads_detach_thread.
+
+*******************************************************************************/
+
+void thread_set_state_timed_waiting(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ if (t->state != THREAD_STATE_TERMINATED) {
+ t->state = THREAD_STATE_TIMED_WAITING;
+
+ DEBUGTHREADS("is TIMED_WAITING", t);
+ }
+
+ threadlist_unlock();
+}
+
+
+/* thread_set_state_terminated *************************************************
+
+ Set the current state of the given thread to
+ THREAD_STATE_TERMINATED.
+
+*******************************************************************************/
+
+void thread_set_state_terminated(threadobject *t)
+{
+ /* Set the state inside a lock. */
+
+ threadlist_lock();
+
+ t->state = THREAD_STATE_TERMINATED;
+
+ DEBUGTHREADS("is TERMINATED", t);
+
+ threadlist_unlock();
+}
+
+
+/* thread_get_thread **********************************************************
+
+ Return the thread data structure of the given Java thread object.
+
+ ARGUMENTS:
+ h ... java.lang.{VM}Thread object
+
+ RETURN VALUE:
+ the thread object
+
+*******************************************************************************/
+
+threadobject *thread_get_thread(java_handle_t *h)
+{
+ threadobject *t;
+#if defined(WITH_CLASSPATH_GNU)
+ java_lang_VMThread *vmto;
+ java_lang_Object *to;
+#endif
+#if defined(WITH_CLASSPATH_SUN)
+ bool equal;
+#endif
+
+#if defined(WITH_CLASSPATH_GNU)
+
+ vmto = (java_lang_VMThread *) h;
+
+ LLNI_field_get_val(vmto, vmdata, to);
+
+ t = (threadobject *) to;
+
+#elif defined(WITH_CLASSPATH_SUN)
+
+ /* XXX This is just a quick hack. */
+
+ threadlist_lock();
+
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ LLNI_equals(t->object, h, equal);
+
+ if (equal == true)
+ break;
+ }
+
+ threadlist_unlock();
+
+#elif defined(WITH_CLASSPATH_CLDC1_1)
+
+ log_println("threads_get_thread: IMPLEMENT ME!");
+
+#else
+# error unknown classpath configuration
+#endif
+
+ return t;
+}
+
+
+/* threads_thread_is_alive *****************************************************
+
+ Returns if the give thread is alive.
+
+*******************************************************************************/
+
+bool threads_thread_is_alive(threadobject *t)
+{
+ int state;
+
+ state = cacaothread_get_state(t);
+
+ switch (state) {
+ case THREAD_STATE_NEW:
+ case THREAD_STATE_TERMINATED:
+ return false;
+
+ case THREAD_STATE_RUNNABLE:
+ case THREAD_STATE_BLOCKED:
+ case THREAD_STATE_WAITING:
+ case THREAD_STATE_TIMED_WAITING:
+ return true;
+
+ default:
+ vm_abort("threads_thread_is_alive: unknown thread state %d", state);
+ }
+
+ /* keep compiler happy */
+
+ return false;
+}
+
+
+/* threads_dump ****************************************************************
+
+ Dumps info for all threads running in the JVM. This function is
+ called when SIGQUIT (<ctrl>-\) is sent to CACAO.
+
+*******************************************************************************/
+
+void threads_dump(void)
+{
+ threadobject *t;
+
+ /* XXX we should stop the world here */
+
+ /* Lock the thread lists. */
+
+ threadlist_lock();
+
+ printf("Full thread dump CACAO "VERSION":\n");
+
+ /* iterate over all started threads */
+
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
+ /* ignore threads which are in state NEW */
+ if (t->state == THREAD_STATE_NEW)
+ continue;
+
+#if defined(ENABLE_GC_CACAO)
+ /* Suspend the thread. */
+ /* XXX Is the suspend reason correct? */
+
+ if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
+ vm_abort("threads_dump: threads_suspend_thread failed");
+#endif
+
+ /* Print thread info. */
+
+ printf("\n");
+ thread_print_info(t);
+ printf("\n");
+
+ /* Print trace of thread. */
+
+ stacktrace_print_of_thread(t);
+
+#if defined(ENABLE_GC_CACAO)
+ /* Resume the thread. */
+
+ if (threads_resume_thread(t) == false)
+ vm_abort("threads_dump: threads_resume_thread failed");
+#endif
+ }
+
+ /* Unlock the thread lists. */
+
+ threadlist_unlock();
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/threads/thread.h - machine independent thread functions
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _THREAD_H
+#define _THREAD_H
+
+#include "config.h"
+
+#include "vmcore/system.h"
+
+#if defined(ENABLE_THREADS)
+# include "threads/posix/thread-posix.h"
+#else
+# include "threads/none/thread-none.h"
+#endif
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+#include "native/jni.h"
+#include "native/llni.h"
+
+#include "vmcore/utf8.h"
+
+
+/* only define the following stuff with thread enabled ************************/
+
+#if defined(ENABLE_THREADS)
+
+/* thread states **************************************************************/
+
+#define THREAD_STATE_NEW 0
+#define THREAD_STATE_RUNNABLE 1
+#define THREAD_STATE_BLOCKED 2
+#define THREAD_STATE_WAITING 3
+#define THREAD_STATE_TIMED_WAITING 4
+#define THREAD_STATE_TERMINATED 5
+
+
+/* thread priorities **********************************************************/
+
+#define MIN_PRIORITY 1
+#define NORM_PRIORITY 5
+#define MAX_PRIORITY 10
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define DEBUGTHREADS(message, thread) \
+ do { \
+ if (opt_DebugThreads) { \
+ printf("[Thread %-16s: ", message); \
+ thread_print_info(thread); \
+ printf("]\n"); \
+ } \
+ } while (0)
+#else
+# define DEBUGTHREADS(message, thread)
+#endif
+
+
+/* global variables ***********************************************************/
+
+#if defined(__LINUX__)
+/* XXX Remove for exact-GC. */
+extern bool threads_pthreads_implementation_nptl;
+#endif
+
+
+/* inline functions ***********************************************************/
+
+/* thread_get_object ***********************************************************
+
+ Return the Java for the given thread.
+
+ ARGUMENTS:
+ t ... thread
+
+ RETURN:
+ the Java object
+
+*******************************************************************************/
+
+inline static java_handle_t *thread_get_object(threadobject *t)
+{
+ return LLNI_WRAP(t->object);
+}
+
+
+/* threads_thread_set_object ***************************************************
+
+ Set the Java object for the given thread.
+
+ ARGUMENTS:
+ t ... thread
+ o ... Java object
+
+*******************************************************************************/
+
+inline static void thread_set_object(threadobject *t, java_handle_t *o)
+{
+ t->object = LLNI_DIRECT(o);
+}
+
+
+/* thread_get_current_object **************************************************
+
+ Return the Java object of the current thread.
+
+ RETURN VALUE:
+ the Java object
+
+*******************************************************************************/
+
+inline static java_handle_t *thread_get_current_object(void)
+{
+ threadobject *t;
+ java_handle_t *o;
+
+ t = THREADOBJECT;
+ o = thread_get_object(t);
+
+ return o;
+}
+
+
+/* cacaothread_get_state *******************************************************
+
+ Returns the current state of the given thread.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN:
+ thread state
+
+*******************************************************************************/
+
+inline static int cacaothread_get_state(threadobject *t)
+{
+ return t->state;
+}
+
+
+/* thread_is_attached **********************************************************
+
+ Returns if the given thread is attached to the VM.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN:
+ true .... the thread is attached to the VM
+ false ... the thread is not
+
+*******************************************************************************/
+
+inline static bool thread_is_attached(threadobject *t)
+{
+ java_handle_t *o;
+
+ o = thread_get_object(t);
+
+ if (o != NULL)
+ return true;
+ else
+ return false;
+}
+
+
+/* thread_is_interrupted *******************************************************
+
+ Check if the given thread has been interrupted.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN VALUE:
+ true, if the given thread had been interrupted
+
+*******************************************************************************/
+
+inline static bool thread_is_interrupted(threadobject *t)
+{
+ return t->interrupted;
+}
+
+
+/* thread_set_interrupted ******************************************************
+
+ Set the interrupted flag to the given value.
+
+ ARGUMENTS:
+ interrupted ... value to set
+
+*******************************************************************************/
+
+inline static void thread_set_interrupted(threadobject *t, bool interrupted)
+{
+ mutex_lock(&t->waitmutex);
+
+ /* Set interrupted flag. */
+
+ t->interrupted = interrupted;
+
+ mutex_unlock(&t->waitmutex);
+}
+
+
+/* thread_is_daemon ************************************************************
+
+ Returns if the given thread is a daemon thread.
+
+ ARGUMENTS:
+ t ... the thread to check
+
+ RETURN:
+ true .... the thread is a daemon thread
+ false ... the thread is not
+
+*******************************************************************************/
+
+inline static bool thread_is_daemon(threadobject *t)
+{
+ if (t->flags & THREAD_FLAG_DAEMON)
+ return true;
+ else
+ return false;
+}
+
+
+/* thread_current_is_attached **************************************************
+
+ Returns if the current thread is attached to the VM.
+
+ RETURN:
+ true .... the thread is attached to the VM
+ false ... the thread is not
+
+*******************************************************************************/
+
+inline static bool thread_current_is_attached(void)
+{
+ threadobject *t;
+ bool result;
+
+ t = thread_get_current();
+
+ if (t == NULL)
+ return false;
+
+ result = thread_is_attached(t);
+
+ return result;
+}
+
+
+/* function prototypes ********************************************************/
+
+void threads_preinit(void);
+void threads_init(void);
+
+void thread_free(threadobject *t);
+
+bool threads_thread_start_internal(utf *name, functionptr f);
+void threads_thread_start(java_handle_t *object);
+
+bool threads_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon);
+
+void thread_fprint_name(threadobject *t, FILE *stream);
+void thread_print_info(threadobject *t);
+
+intptr_t threads_get_current_tid(void);
+
+void thread_set_state_runnable(threadobject *t);
+void thread_set_state_waiting(threadobject *t);
+void thread_set_state_timed_waiting(threadobject *t);
+void thread_set_state_terminated(threadobject *t);
+
+threadobject *thread_get_thread(java_handle_t *h);
+
+bool threads_thread_is_alive(threadobject *t);
+
+void threads_dump(void);
+
+
+/* implementation specific functions */
+
+void threads_impl_preinit(void);
+void threads_impl_init(void);
+
+#if defined(ENABLE_GC_CACAO)
+void threads_mutex_gc_lock(void);
+void threads_mutex_gc_unlock(void);
+#endif
+
+void threads_mutex_join_lock(void);
+void threads_mutex_join_unlock(void);
+
+void threads_impl_thread_init(threadobject *t);
+void threads_impl_thread_clear(threadobject *t);
+void threads_impl_thread_reuse(threadobject *t);
+void threads_impl_thread_free(threadobject *t);
+void threads_impl_thread_start(threadobject *thread, functionptr f);
+
+void threads_yield(void);
+
+#endif /* ENABLE_THREADS */
+
+#endif /* _THREAD_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/threads/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.h"
+#include "threads/threadlist.h"
+#include "threads/thread.h"
+
+#include "toolbox/list.h"
+
+#include "vmcore/options.h"
+
+
+/* global variables ***********************************************************/
+
+static mutex_t 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. */
+
+ mutex_init(&threadlist_mutex);
+
+ /* 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.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>
+
+#include "threads/thread.h"
+
+
+/* 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);
+
+#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/threads-common.c - machine independent thread functions
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-#include "native/llni.h"
-
-#include "native/include/java_lang_Object.h"
-#include "native/include/java_lang_String.h"
-#include "native/include/java_lang_Thread.h"
-
-#if defined(WITH_CLASSPATH_GNU)
-# include "native/include/java_lang_Throwable.h"
-# include "native/include/java_lang_VMThread.h"
-#endif
-
-#include "threads/critical.h"
-#include "threads/lock-common.h"
-#include "threads/threads-common.h"
-
-#include "toolbox/list.h"
-
-#include "vm/builtin.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
-
-#include "vm/jit/stacktrace.h"
-
-#include "vmcore/class.h"
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/utf8.h"
-
-
-/* global variables ***********************************************************/
-
-/* global threads list */
-static list_t *list_threads;
-
-/* global threads free-list */
-
-typedef struct thread_index_t {
- int32_t index;
- listnode_t linkage;
-} thread_index_t;
-
-static list_t *list_free_thread_index;
-
-#if defined(__LINUX__)
-/* XXX Remove for exact-GC. */
-bool threads_pthreads_implementation_nptl;
-#endif
-
-
-/* threads_preinit *************************************************************
-
- Do some early initialization of stuff required.
-
- ATTENTION: Do NOT use any Java heap allocation here, as gc_init()
- is called AFTER this function!
-
-*******************************************************************************/
-
-void threads_preinit(void)
-{
- threadobject *mainthread;
-#if defined(__LINUX__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
- char *pathbuf;
- size_t len;
-#endif
-
-#if defined(__LINUX__)
- /* XXX Remove for exact-GC. */
-
- /* On Linux we need to check the pthread implementation. */
-
- /* _CS_GNU_LIBPTHREAD_VERSION (GNU C library only; since glibc 2.3.2) */
- /* If the glibc is a pre-2.3.2 version, we fall back to
- linuxthreads. */
-
-# if defined(_CS_GNU_LIBPTHREAD_VERSION)
- len = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, (size_t) 0);
-
- /* Some systems return as length 0 (maybe cross-compilation
- related). In this case we also fall back to linuxthreads. */
-
- if (len > 0) {
- pathbuf = MNEW(char, len);
-
- (void) confstr(_CS_GNU_LIBPTHREAD_VERSION, pathbuf, len);
-
- if (strstr(pathbuf, "NPTL") != NULL)
- threads_pthreads_implementation_nptl = true;
- else
- threads_pthreads_implementation_nptl = false;
- }
- else
- threads_pthreads_implementation_nptl = false;
-# else
- threads_pthreads_implementation_nptl = false;
-# endif
-#endif
-
- /* initialize the threads lists */
-
- list_threads = list_create(OFFSET(threadobject, linkage));
- list_free_thread_index = list_create(OFFSET(thread_index_t, linkage));
-
- /* Initialize the threads implementation (sets the thinlock on the
- main thread). */
-
- threads_impl_preinit();
-
- /* create internal thread data-structure for the main thread */
-
- mainthread = threads_thread_new();
-
- /* thread is a Java thread and running */
-
- mainthread->flags |= THREAD_FLAG_JAVA;
- mainthread->state = THREAD_STATE_RUNNABLE;
-
- /* store the internal thread data-structure in the TSD */
-
- threads_set_current_threadobject(mainthread);
-
- /* initialize locking subsystems */
-
- lock_init();
-
- /* initialize the critical section */
-
- critical_init();
-}
-
-
-/* threads_list_first **********************************************************
-
- Return the first entry in the threads list.
-
- NOTE: This function does not lock the lists.
-
-*******************************************************************************/
-
-threadobject *threads_list_first(void)
-{
- threadobject *t;
-
- t = list_first_unsynced(list_threads);
-
- return t;
-}
-
-
-/* threads_list_next ***********************************************************
-
- Return the next entry in the threads list.
-
- NOTE: This function does not lock the lists.
-
-*******************************************************************************/
-
-threadobject *threads_list_next(threadobject *t)
-{
- threadobject *next;
-
- next = list_next_unsynced(list_threads, t);
-
- return next;
-}
-
-
-/* threads_list_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.
-
-*******************************************************************************/
-
-s4 threads_list_get_non_daemons(void)
-{
- threadobject *t;
- s4 nondaemons;
-
- /* lock the threads lists */
-
- threads_list_lock();
-
- nondaemons = 0;
-
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- if (!(t->flags & THREAD_FLAG_DAEMON))
- nondaemons++;
- }
-
- /* unlock the threads lists */
-
- threads_list_unlock();
-
- return nondaemons;
-}
-
-
-/* threads_thread_new **********************************************************
-
- Allocates and initializes an internal thread data-structure and
- adds it to the threads list.
-
-*******************************************************************************/
-
-threadobject *threads_thread_new(void)
-{
- thread_index_t *ti;
- int32_t index;
- threadobject *t;
-
- /* lock the threads-lists */
-
- threads_list_lock();
-
- /* Try to get a thread index from the free-list. */
-
- ti = list_first_unsynced(list_free_thread_index);
-
- /* Is a free thread index available? */
-
- if (ti != NULL) {
- /* Yes, remove it from the free list, get the index and free
- the entry. */
-
- list_remove_unsynced(list_free_thread_index, ti);
-
- index = ti->index;
-
- FREE(ti, thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_thread_index_t -= sizeof(thread_index_t);
-#endif
- }
- else {
- /* Get a new the thread index. */
-
- index = list_threads->size + 1;
- }
-
- /* Allocate a thread data structure. */
-
-#if defined(ENABLE_GC_BOEHM)
- t = GCNEW_UNCOLLECTABLE(threadobject, 1);
-#else
- t = NEW(threadobject);
-#endif
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_threadobject += sizeof(threadobject);
-#endif
-
- /* Clear memory. */
-
- MZERO(t, threadobject, 1);
-
-#if defined(ENABLE_GC_CACAO)
- /* Register reference to java.lang.Thread with the GC. */
-
- gc_reference_register(&(t->object), GC_REFTYPE_THREADOBJECT);
- gc_reference_register(&(t->_exceptionptr), GC_REFTYPE_THREADOBJECT);
-#endif
-
- /* Pre-compute the thinlock-word. */
-
- assert(index != 0);
-
- t->index = index;
- t->thinlock = lock_pre_compute_thinlock(t->index);
- t->flags = 0;
- t->state = THREAD_STATE_NEW;
-
-#if defined(ENABLE_GC_CACAO)
- t->flags |= THREAD_FLAG_IN_NATIVE;
-#endif
-
- /* Initialize the implementation-specific bits. */
-
- threads_impl_thread_new(t);
-
- /* Add the thread to the threads-list. */
-
- list_add_last_unsynced(list_threads, t);
-
- /* Unlock the threads-lists. */
-
- threads_list_unlock();
-
- return t;
-}
-
-
-/* threads_thread_free *********************************************************
-
- Remove the thread from the threads-list and free the internal
- thread data structure. The thread index is added to the
- thread-index free-list.
-
- IN:
- t....thread data structure
-
-*******************************************************************************/
-
-void threads_thread_free(threadobject *t)
-{
- thread_index_t *ti;
-
- /* Lock the threads lists. */
-
- threads_list_lock();
-
- /* Cleanup the implementation specific bits. */
-
- threads_impl_thread_free(t);
-
- /* Remove the thread from the threads-list. */
-
- list_remove_unsynced(list_threads, t);
-
- /* Add the thread index to the free list. */
-
- ti = NEW(thread_index_t);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_thread_index_t += sizeof(thread_index_t);
-#endif
-
- ti->index = t->index;
-
- list_add_last_unsynced(list_free_thread_index, ti);
-
- /* Free the thread data structure. */
-
-#if defined(ENABLE_GC_BOEHM)
- GCFREE(t);
-#else
- FREE(t, threadobject);
-#endif
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_threadobject -= sizeof(threadobject);
-#endif
-
- /* Unlock the threads lists. */
-
- threads_list_unlock();
-}
-
-
-/* threads_thread_start_internal ***********************************************
-
- Start an internal thread in the JVM. No Java thread objects exists
- so far.
-
- IN:
- name.......UTF-8 name of the thread
- f..........function pointer to C function to start
-
-*******************************************************************************/
-
-bool threads_thread_start_internal(utf *name, functionptr f)
-{
- threadobject *t;
- java_lang_Thread *object;
-#if defined(WITH_CLASSPATH_GNU)
- java_lang_VMThread *vmt;
-#endif
-
- /* Enter the join-mutex, so if the main-thread is currently
- waiting to join all threads, the number of non-daemon threads
- is correct. */
-
- threads_mutex_join_lock();
-
- /* create internal thread data-structure */
-
- t = threads_thread_new();
-
- t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
-
- /* The thread is flagged as (non-)daemon thread, we can leave the
- mutex. */
-
- threads_mutex_join_unlock();
-
- /* create the java thread object */
-
- object = (java_lang_Thread *) builtin_new(class_java_lang_Thread);
-
- /* XXX memory leak!!! */
- if (object == NULL)
- return false;
-
-#if defined(WITH_CLASSPATH_GNU)
- vmt = (java_lang_VMThread *) builtin_new(class_java_lang_VMThread);
-
- /* XXX memory leak!!! */
- if (vmt == NULL)
- return false;
-
- LLNI_field_set_ref(vmt, thread, object);
- LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) t);
-
- LLNI_field_set_ref(object, vmThread, vmt);
-#elif defined(WITH_CLASSPATH_CLDC1_1)
- LLNI_field_set_val(object, vm_thread, (java_lang_Object *) t);
-#endif
-
- threads_thread_set_object(t, (java_handle_t *) object);
-
- /* set java.lang.Thread fields */
-
-#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_set_ref(object, name , (java_lang_String *) javastring_new(name));
-#elif defined(WITH_CLASSPATH_CLDC1_1)
- /* FIXME: In cldc the name is a char[] */
-/* LLNI_field_set_ref(object, name , (java_chararray *) javastring_new(name)); */
- LLNI_field_set_ref(object, name , NULL);
-#endif
-
-#if defined(ENABLE_JAVASE)
- LLNI_field_set_val(object, daemon , true);
-#endif
-
- LLNI_field_set_val(object, priority, NORM_PRIORITY);
-
- /* start the thread */
-
- threads_impl_thread_start(t, f);
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* threads_thread_start ********************************************************
-
- Start a Java thread in the JVM. Only the java thread object exists
- so far.
-
- IN:
- object.....the java thread object java.lang.Thread
-
-*******************************************************************************/
-
-void threads_thread_start(java_handle_t *object)
-{
- java_lang_Thread *o;
- threadobject *thread;
-#if defined(WITH_CLASSPATH_GNU)
- java_lang_VMThread *vmt;
-#endif
-
- o = (java_lang_Thread *) object;
-
- /* Enter the join-mutex, so if the main-thread is currently
- waiting to join all threads, the number of non-daemon threads
- is correct. */
-
- threads_mutex_join_lock();
-
- /* create internal thread data-structure */
-
- thread = threads_thread_new();
-
- /* this is a normal Java thread */
-
- thread->flags |= THREAD_FLAG_JAVA;
-
-#if defined(ENABLE_JAVASE)
- /* is this a daemon thread? */
-
- if (LLNI_field_direct(o, daemon) == true)
- thread->flags |= THREAD_FLAG_DAEMON;
-#endif
-
- /* The thread is flagged and (non-)daemon thread, we can leave the
- mutex. */
-
- threads_mutex_join_unlock();
-
- /* link the two objects together */
-
- threads_thread_set_object(thread, object);
-
-#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_get_ref(o, vmThread, vmt);
-
- assert(vmt);
- assert(LLNI_field_direct(vmt, vmdata) == NULL);
-
- LLNI_field_set_val(vmt, vmdata, (java_lang_Object *) thread);
-#elif defined(WITH_CLASSPATH_CLDC1_1)
- LLNI_field_set_val(o, vm_thread, (java_lang_Object *) thread);
-#endif
-
- /* Start the thread. Don't pass a function pointer (NULL) since
- we want Thread.run()V here. */
-
- threads_impl_thread_start(thread, NULL);
-}
-
-
-/* threads_thread_print_info ***************************************************
-
- Print information of the passed thread.
-
-*******************************************************************************/
-
-void threads_thread_print_info(threadobject *t)
-{
- java_lang_Thread *object;
-#if defined(WITH_CLASSPATH_GNU)
- java_lang_String *namestring;
-#endif
- utf *name;
-
- assert(t->state != THREAD_STATE_NEW);
-
- /* the thread may be currently in initalization, don't print it */
-
- object = (java_lang_Thread *) threads_thread_get_object(t);
-
- if (object != NULL) {
- /* get thread name */
-
-#if defined(WITH_CLASSPATH_GNU)
- LLNI_field_get_ref(object, name, namestring);
- name = javastring_toutf((java_handle_t *) namestring, false);
-#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
- /* FIXME: In cldc the name is a char[] */
-/* name = object->name; */
- name = utf_null;
-#else
-# error unknown classpath configuration
-#endif
-
- printf("\"");
- utf_display_printable_ascii(name);
- printf("\"");
-
- if (t->flags & THREAD_FLAG_DAEMON)
- printf(" daemon");
-
- printf(" prio=%d", LLNI_field_direct(object, priority));
-
-#if SIZEOF_VOID_P == 8
- printf(" t=0x%016lx tid=0x%016lx (%ld)",
- (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
-#else
- printf(" t=0x%08x tid=0x%08x (%d)",
- (ptrint) t, (ptrint) t->tid, (ptrint) t->tid);
-#endif
-
- printf(" index=%d", t->index);
-
- /* print thread state */
-
- switch (t->state) {
- case THREAD_STATE_NEW:
- printf(" new");
- break;
- case THREAD_STATE_RUNNABLE:
- printf(" runnable");
- break;
- case THREAD_STATE_BLOCKED:
- printf(" blocked");
- break;
- case THREAD_STATE_WAITING:
- printf(" waiting");
- break;
- case THREAD_STATE_TIMED_WAITING:
- printf(" waiting on condition");
- break;
- case THREAD_STATE_TERMINATED:
- printf(" terminated");
- break;
- default:
- vm_abort("threads_thread_print_info: unknown thread state %d",
- t->state);
- }
- }
-}
-
-
-/* threads_get_current_tid *****************************************************
-
- Return the tid of the current thread.
-
- RETURN VALUE:
- the current tid
-
-*******************************************************************************/
-
-ptrint threads_get_current_tid(void)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- /* this may happen during bootstrap */
-
- if (thread == NULL)
- return 0;
-
- return (ptrint) thread->tid;
-}
-
-
-/* threads_thread_state_runnable ***********************************************
-
- Set the current state of the given thread to THREAD_STATE_RUNNABLE.
-
- NOTE: If the thread has already terminated, don't set the state.
- This is important for threads_detach_thread.
-
-*******************************************************************************/
-
-void threads_thread_state_runnable(threadobject *t)
-{
- /* Set the state inside a lock. */
-
- threads_list_lock();
-
- if (t->state != THREAD_STATE_TERMINATED)
- t->state = THREAD_STATE_RUNNABLE;
-
- DEBUGTHREADS("is RUNNABLE", t);
-
- threads_list_unlock();
-}
-
-
-/* threads_thread_state_waiting ************************************************
-
- Set the current state of the given thread to THREAD_STATE_WAITING.
-
- NOTE: If the thread has already terminated, don't set the state.
- This is important for threads_detach_thread.
-
-*******************************************************************************/
-
-void threads_thread_state_waiting(threadobject *t)
-{
- /* Set the state inside a lock. */
-
- threads_list_lock();
-
- if (t->state != THREAD_STATE_TERMINATED)
- t->state = THREAD_STATE_WAITING;
-
- DEBUGTHREADS("is WAITING", t);
-
- threads_list_unlock();
-}
-
-
-/* threads_thread_state_timed_waiting ******************************************
-
- Set the current state of the given thread to
- THREAD_STATE_TIMED_WAITING.
-
- NOTE: If the thread has already terminated, don't set the state.
- This is important for threads_detach_thread.
-
-*******************************************************************************/
-
-void threads_thread_state_timed_waiting(threadobject *t)
-{
- /* Set the state inside a lock. */
-
- threads_list_lock();
-
- if (t->state != THREAD_STATE_TERMINATED)
- t->state = THREAD_STATE_TIMED_WAITING;
-
- DEBUGTHREADS("is TIMED_WAITING", t);
-
- threads_list_unlock();
-}
-
-
-/* threads_thread_state_terminated *********************************************
-
- Set the current state of the given thread to
- THREAD_STATE_TERMINATED.
-
-*******************************************************************************/
-
-void threads_thread_state_terminated(threadobject *t)
-{
- /* set the state in the lock */
-
- threads_list_lock();
-
- t->state = THREAD_STATE_TERMINATED;
-
- DEBUGTHREADS("is TERMINATED", t);
-
- threads_list_unlock();
-}
-
-
-/* threads_thread_get_state ****************************************************
-
- Returns the current state of the given thread.
-
-*******************************************************************************/
-
-utf *threads_thread_get_state(threadobject *t)
-{
- utf *u;
-
- switch (t->state) {
- case THREAD_STATE_NEW:
- u = utf_new_char("NEW");
- break;
- case THREAD_STATE_RUNNABLE:
- u = utf_new_char("RUNNABLE");
- break;
- case THREAD_STATE_BLOCKED:
- u = utf_new_char("BLOCKED");
- break;
- case THREAD_STATE_WAITING:
- u = utf_new_char("WAITING");
- break;
- case THREAD_STATE_TIMED_WAITING:
- u = utf_new_char("TIMED_WAITING");
- break;
- case THREAD_STATE_TERMINATED:
- u = utf_new_char("TERMINATED");
- break;
- default:
- vm_abort("threads_get_state: unknown thread state %d", t->state);
-
- /* keep compiler happy */
-
- u = NULL;
- }
-
- return u;
-}
-
-
-/* threads_thread_is_alive *****************************************************
-
- Returns if the give thread is alive.
-
-*******************************************************************************/
-
-bool threads_thread_is_alive(threadobject *t)
-{
- switch (t->state) {
- case THREAD_STATE_NEW:
- case THREAD_STATE_TERMINATED:
- return false;
-
- case THREAD_STATE_RUNNABLE:
- case THREAD_STATE_BLOCKED:
- case THREAD_STATE_WAITING:
- case THREAD_STATE_TIMED_WAITING:
- return true;
-
- default:
- vm_abort("threads_thread_is_alive: unknown thread state %d", t->state);
- }
-
- /* keep compiler happy */
-
- return false;
-}
-
-
-/* threads_dump ****************************************************************
-
- Dumps info for all threads running in the JVM. This function is
- called when SIGQUIT (<ctrl>-\) is sent to CACAO.
-
-*******************************************************************************/
-
-void threads_dump(void)
-{
- threadobject *t;
-
- /* XXX we should stop the world here */
-
- /* lock the threads lists */
-
- threads_list_lock();
-
- printf("Full thread dump CACAO "VERSION":\n");
-
- /* iterate over all started threads */
-
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
- /* ignore threads which are in state NEW */
- if (t->state == THREAD_STATE_NEW)
- continue;
-
- /* print thread info */
-
- printf("\n");
- threads_thread_print_info(t);
- printf("\n");
-
- /* print trace of thread */
-
- threads_thread_print_stacktrace(t);
- }
-
- /* unlock the threads lists */
-
- threads_list_unlock();
-}
-
-
-/* threads_thread_print_stacktrace *********************************************
-
- Print the current stacktrace of the given thread.
-
-*******************************************************************************/
-
-void threads_thread_print_stacktrace(threadobject *thread)
-{
- stackframeinfo_t *sfi;
- java_handle_bytearray_t *ba;
- stacktrace_t *st;
-
- /* Build a stacktrace for the passed thread. */
-
- sfi = thread->_stackframeinfo;
-
- ba = stacktrace_get();
-
- /* We need a critical section here as we use the byte-array data
- pointer directly. */
-
- LLNI_CRITICAL_START;
-
- st = (stacktrace_t *) LLNI_array_data(ba);
-
- /* Print stacktrace. */
-
- if (st != NULL)
- stacktrace_print(st);
- else {
- puts("\t<<No stacktrace available>>");
- fflush(stdout);
- }
-
- LLNI_CRITICAL_END;
-}
-
-
-/* threads_print_stacktrace ****************************************************
-
- Print the current stacktrace of the current thread.
-
-*******************************************************************************/
-
-void threads_print_stacktrace(void)
-{
- threadobject *thread;
-
- thread = THREADOBJECT;
-
- threads_thread_print_stacktrace(thread);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically 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/threads-common.h - machine independent thread functions
-
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public 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 _THREADS_COMMON_H
-#define _THREADS_COMMON_H
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "native/llni.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#else
-# include "threads/none/threads.h"
-#endif
-
-#include "vmcore/utf8.h"
-
-
-/* only define the following stuff with thread enabled ************************/
-
-#if defined(ENABLE_THREADS)
-
-/* thread states **************************************************************/
-
-#define THREAD_STATE_NEW 0
-#define THREAD_STATE_RUNNABLE 1
-#define THREAD_STATE_BLOCKED 2
-#define THREAD_STATE_WAITING 3
-#define THREAD_STATE_TIMED_WAITING 4
-#define THREAD_STATE_TERMINATED 5
-
-
-/* thread priorities **********************************************************/
-
-#define MIN_PRIORITY 1
-#define NORM_PRIORITY 5
-#define MAX_PRIORITY 10
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-# define DEBUGTHREADS(message, thread) \
- do { \
- if (opt_DebugThreads) { \
- printf("[Thread %-16s: ", message); \
- threads_thread_print_info(thread); \
- printf("]\n"); \
- } \
- } while (0)
-#else
-# define DEBUGTHREADS(message, thread)
-#endif
-
-
-#if defined(__LINUX__)
-/* XXX Remove for exact-GC. */
-extern bool threads_pthreads_implementation_nptl;
-#endif
-
-
-/* inline functions ***********************************************************/
-
-/* threads_thread_get_object ***************************************************
-
- Return the java.lang.Thread object for the given thread.
-
-*******************************************************************************/
-
-static inline java_handle_t *threads_thread_get_object(threadobject *t)
-{
- return LLNI_WRAP(t->object);
-}
-
-
-/* threads_thread_set_object ***************************************************
-
- Set the java.lang.Thread object for the given thread.
-
-*******************************************************************************/
-
-static inline void threads_thread_set_object(threadobject *t, java_handle_t *object)
-{
- t->object = LLNI_DIRECT(object);
-}
-
-
-/* function prototypes ********************************************************/
-
-void threads_preinit(void);
-
-threadobject *threads_list_first(void);
-threadobject *threads_list_next(threadobject *t);
-s4 threads_list_get_non_daemons(void);
-
-threadobject *threads_thread_new(void);
-void threads_thread_free(threadobject *t);
-
-bool threads_thread_start_internal(utf *name, functionptr f);
-void threads_thread_start(java_handle_t *object);
-
-void threads_thread_print_info(threadobject *t);
-
-ptrint threads_get_current_tid(void);
-
-void threads_thread_state_runnable(threadobject *t);
-void threads_thread_state_waiting(threadobject *t);
-void threads_thread_state_timed_waiting(threadobject *t);
-void threads_thread_state_terminated(threadobject *t);
-utf *threads_thread_get_state(threadobject *t);
-
-bool threads_thread_is_alive(threadobject *t);
-
-void threads_dump(void);
-void threads_thread_print_stacktrace(threadobject *thread);
-void threads_print_stacktrace(void);
-
-
-/* implementation specific functions */
-
-void threads_impl_preinit(void);
-
-void threads_list_lock(void);
-void threads_list_unlock(void);
-
-#if defined(ENABLE_GC_CACAO)
-void threads_mutex_gc_lock(void);
-void threads_mutex_gc_unlock(void);
-#endif
-
-void threads_mutex_join_lock(void);
-void threads_mutex_join_unlock(void);
-
-void threads_set_current_threadobject(threadobject *thread);
-void threads_impl_thread_new(threadobject *t);
-void threads_impl_thread_free(threadobject *t);
-void threads_impl_thread_start(threadobject *thread, functionptr f);
-
-void threads_yield(void);
-
-#endif /* ENABLE_THREADS */
-
-#endif /* _THREADS_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:
- */
list.h \
logging.c \
logging.h \
+ set.h \
+ set.c \
tree.c \
tree.h \
util.c \
#ifndef _BITVECTOR_H
#define _BITVECTOR_H
+#include "vm/global.h"
+
#if !defined(NDEBUG)
#include <assert.h>
/* src/toolbox/list.c - double linked list
- 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 <assert.h>
+#include <stdint.h>
#include <stdlib.h>
-#include "vm/types.h"
-
#include "mm/memory.h"
#include "threads/lock-common.h"
*******************************************************************************/
-list_t *list_create(s4 nodeoffset)
+list_t *list_create(int nodeoffset)
{
list_t *l;
*******************************************************************************/
-list_t *list_create_dump(s4 nodeoffset)
+list_t *list_create_dump(int nodeoffset)
{
list_t *l;
*******************************************************************************/
void list_add_first(list_t *l, void *element)
-{
- LOCK_MONITOR_ENTER(l);
-
- list_add_first_unsynced(l, element);
-
- LOCK_MONITOR_EXIT(l);
-}
-
-
-/* list_add_first_unsynced *****************************************************
-
- Adds the element as first element, but WITHOUT LOCKING!
-
- ATTENTION: Use this function with care!!!
-
-*******************************************************************************/
-
-void list_add_first_unsynced(list_t *l, void *element)
{
listnode_t *ln;
- ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
+ ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
if (l->first) {
ln->prev = NULL;
l->first = ln;
}
- /* increase number of elements */
+ /* Increase number of elements. */
l->size++;
}
*******************************************************************************/
void list_add_last(list_t *l, void *element)
-{
- LOCK_MONITOR_ENTER(l);
-
- list_add_last_unsynced(l, element);
-
- LOCK_MONITOR_EXIT(l);
-}
-
-
-/* list_add_last_unsynced ******************************************************
-
- Adds the element as last element but does NO locking!
-
- ATTENTION: Use this function with care!!!
-
-*******************************************************************************/
-
-void list_add_last_unsynced(list_t *l, void *element)
{
listnode_t *ln;
- ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
+ ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
if (l->last) {
ln->prev = l->last;
l->first = ln;
}
- /* increase number of elements */
+ /* Increase number of elements. */
l->size++;
}
listnode_t *ln;
listnode_t *newln;
- ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
- newln = (listnode_t *) (((u1 *) newelement) + l->nodeoffset);
-
- LOCK_MONITOR_ENTER(l);
+ ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
+ newln = (listnode_t *) (((uint8_t *) newelement) + l->nodeoffset);
- /* set the new links */
+ /* Set the new links. */
newln->prev = ln->prev;
newln->next = ln;
if (l->last == ln)
l->last = newln;
- /* increase number of elements */
+ /* Increase number of elements. */
l->size++;
-
- LOCK_MONITOR_EXIT(l);
}
*******************************************************************************/
void list_remove(list_t *l, void *element)
-{
- LOCK_MONITOR_ENTER(l);
-
- list_remove_unsynced(l, element);
-
- LOCK_MONITOR_EXIT(l);
-}
-
-
-/* list_remove_unsynced ********************************************************
-
- Removes the element but does NO locking!
-
- ATTENTION: Use this function with care!!!
-
-*******************************************************************************/
-
-void list_remove_unsynced(list_t *l, void *element)
{
listnode_t *ln;
- ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
+ ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
if (ln->next)
ln->next->prev = ln->prev;
ln->next = NULL;
ln->prev = NULL;
- /* decrease number of elements */
+ /* Decrease number of elements. */
l->size--;
}
{
void *el;
- LOCK_MONITOR_ENTER(l);
-
- el = list_first_unsynced(l);
-
- LOCK_MONITOR_EXIT(l);
-
- return el;
-}
-
-
-/* list_first_unsynced *********************************************************
-
- Returns the first element of the list, but does NO locking!
-
- ATTENTION: Use this function with care!!!
-
-*******************************************************************************/
-
-void *list_first_unsynced(list_t *l)
-{
- void *el;
-
if (l->first == NULL)
el = NULL;
else
- el = ((u1 *) l->first) - l->nodeoffset;
+ el = ((uint8_t *) l->first) - l->nodeoffset;
return el;
}
{
void *el;
- LOCK_MONITOR_ENTER(l);
-
- el = list_last_unsynced(l);
-
- LOCK_MONITOR_EXIT(l);
-
- return el;
-}
-
-
-/* list_last_unsynced **********************************************************
-
- Returns the last element of the list, but does NO locking!
-
- ATTENTION: Use this function with care!!!
-
-*******************************************************************************/
-
-void *list_last_unsynced(list_t *l)
-{
- void *el;
-
if (l->last == NULL)
el = NULL;
else
- el = ((u1 *) l->last) - l->nodeoffset;
+ el = ((uint8_t *) l->last) - l->nodeoffset;
return el;
}
*******************************************************************************/
void *list_next(list_t *l, void *element)
-{
- void *el;
-
- LOCK_MONITOR_ENTER(l);
-
- el = list_next_unsynced(l, element);
-
- LOCK_MONITOR_EXIT(l);
-
- return el;
-}
-
-
-/* list_next_unsynced **********************************************************
-
- Returns the next element of element from the list, but does NO
- locking!
-
- ATTENTION: Use this function with care!!!
-
-*******************************************************************************/
-
-void *list_next_unsynced(list_t *l, void *element)
{
listnode_t *ln;
- void *el;
+ void *el;
- ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
+ ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
if (ln->next == NULL)
el = NULL;
else
- el = ((u1 *) ln->next) - l->nodeoffset;
+ el = ((uint8_t *) ln->next) - l->nodeoffset;
return el;
}
*******************************************************************************/
void *list_prev(list_t *l, void *element)
-{
- void *el;
-
- LOCK_MONITOR_ENTER(l);
-
- el = list_prev_unsynced(l, element);
-
- LOCK_MONITOR_EXIT(l);
-
- return el;
-}
-
-
-/* list_prev_unsynced **********************************************************
-
- Returns the previous element of element from the list, but does NO
- locking!
-
- ATTENTION: Use this function with care!!!
-
-*******************************************************************************/
-
-void *list_prev_unsynced(list_t *l, void *element)
{
listnode_t *ln;
- void *el;
+ void *el;
- ln = (listnode_t *) (((u1 *) element) + l->nodeoffset);
+ ln = (listnode_t *) (((uint8_t *) element) + l->nodeoffset);
if (ln->prev == NULL)
el = NULL;
else
- el = ((u1 *) ln->prev) - l->nodeoffset;
+ el = ((uint8_t *) ln->prev) - l->nodeoffset;
return el;
}
/* src/toolbox/list.h - synchronized linked list
- 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 _LIST_H
#include "config.h"
-#include "vm/types.h"
+
+#include <stdint.h>
#include "vm/global.h"
#endif
listnode_t *first;
listnode_t *last;
- s4 nodeoffset;
- s4 size; /* number of elements in the list */
+ int nodeoffset;
+ int size; /* number of elements in the list */
};
/* function prototypes ********************************************************/
-list_t *list_create(s4 nodeoffset);
-list_t *list_create_dump(s4 nodeoffset);
+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_first_unsynced(list_t *l, void *element);
-
void list_add_last(list_t *l, void *element);
-void list_add_last_unsynced(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_remove_unsynced(list_t *l, void *element);
void *list_first(list_t *l);
-void *list_first_unsynced(list_t *l);
-
void *list_last(list_t *l);
-void *list_last_unsynced(list_t *l);
void *list_next(list_t *l, void *element);
-void *list_next_unsynced(list_t *l, void *element);
-
void *list_prev(list_t *l, void *element);
-void *list_prev_unsynced(list_t *l, void *element);
#endif /* _LIST_H */
/* src/toolbox/logging.c - contains logging functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
#include "mm/memory.h"
-#include "threads/threads-common.h"
+
+#include "threads/thread.h"
+
#include "toolbox/logging.h"
#include "toolbox/util.h"
+
#include "vm/global.h"
#if defined(ENABLE_STATISTICS)
char *buf;
s4 len;
- len = strlen(msg) + utf_bytes(m->class->name) + strlen(".") +
+ len = strlen(msg) + utf_bytes(m->clazz->name) + strlen(".") +
utf_bytes(m->name) + utf_bytes(m->descriptor) + strlen("0");
buf = MNEW(char, len);
strcpy(buf, msg);
- utf_cat_classname(buf, m->class->name);
+ utf_cat_classname(buf, m->clazz->name);
strcat(buf, ".");
utf_cat(buf, m->name);
utf_cat(buf, m->descriptor);
--- /dev/null
+/* src/toolbox/set.c - Set implementation.
+
+ Copyright (C) 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ This file implements a set of pointers.
+
+ The current implementation is naive and should be improved in the future,
+ so that the O(size) operations take O(log(size)) instead.
+
+ The representation of the set is an contingous unordered array of the
+ elements (pointers).
+*/
+
+#include "toolbox/set.h"
+
+#include <assert.h>
+
+#include "mm/memory.h"
+
+/* struct set ******************************************************************
+
+ Represents the set.
+
+*******************************************************************************/
+
+struct set {
+ void **elements; /* An array of elements */
+ unsigned capacity; /* Size of elements */
+ unsigned size; /* Current number of elements */
+};
+
+/* set_new ********************************************************************
+
+ Creates an instance of a set on the dump area.
+
+ IN:
+ capacity: Maximal number of elements of elements the set can hold.
+
+*******************************************************************************/
+
+set *set_new(unsigned capacity) {
+ set *s = DNEW(set);
+
+ s->elements = DMNEW(void *, capacity);
+ MZERO(s->elements, void *, capacity);
+ s->capacity = capacity;
+ s->size = 0;
+
+ return s;
+}
+
+/* set_insert ******************************************************************
+
+ Inserts element e into set s
+
+ The current implementation takes O(size).
+
+*******************************************************************************/
+
+void set_insert(set *s, void *element) {
+ unsigned i;
+
+ for (i = 0; i < s->size; ++i) {
+ if (s->elements[i] == element) {
+ return;
+ }
+ }
+
+ assert(i < s->capacity);
+
+ s->size += 1;
+ s->elements[i] = element;
+}
+
+/* set_remove ******************************************************************
+
+ Removes element e into set s
+
+ The current implementation takes O(size).
+
+*******************************************************************************/
+
+void set_remove(set *s, void *element) {
+ unsigned i;
+ for (i = 0; i < s->size; ++i) {
+ if (s->elements[i] == element) {
+ /* Do not creaet a "hole".
+ * Overwrite this element with the last element.
+ */
+ if (i == (s->size - 1)) { /* The last one */
+ s->elements[i] = NULL;
+ } else {
+ s->elements[i] = s->elements[s->size - 1];
+ s->elements[s->size - 1] = NULL;
+ }
+ s->size -= 1;
+ }
+ }
+}
+
+/* set_size ********************************************************************
+
+ Returns the number of elements in the set s.
+ The complexity of the operation is O(1).
+
+*******************************************************************************/
+
+unsigned set_size(const set *s) {
+ return s->size;
+}
+
+/* set_empty *******************************************************************
+
+ Returns true, iif the set s is empty.
+ The complexity of the operation is O(1).
+
+*******************************************************************************/
+
+bool set_empty(const set *s) {
+ return s->size == 0;
+}
+
+/* set_contains ****************************************************************
+
+ Returns true, iif the set s contains element element.
+
+ The current implementation takes O(size).
+
+*******************************************************************************/
+
+bool set_contains(const set *s, void *element) {
+ unsigned i;
+ for (i = 0; i < s->size; ++i) {
+ if (s->elements[i] == element) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/* set_pop *********************************************************************
+
+ Pics and removes some element from the set s and returns it.
+ Returns NULL if the set s is empty.
+ The complexity of the operation is O(1).
+
+*******************************************************************************/
+
+void *set_pop(set *s) {
+ void *ret = NULL;
+
+ if (s->size > 0) {
+ ret = s->elements[s->size - 1];
+ s->elements[s->size - 1] = NULL;
+ s->size -= 1;
+ }
+
+ return ret;
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/toolbox/set.h - Set implementation.
+
+ Copyright (C) 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+#ifndef _TOOLBOX_SET_H
+#define _TOOLBOX_SET_H
+
+#include "vm/global.h"
+
+typedef struct set set;
+
+set *set_new(unsigned capacity);
+void set_insert(set *s, void *element);
+void set_remove(set *s, void *element);
+bool set_contains(const set *s, void *element);
+unsigned set_size(const set *s);
+bool set_empty(const set *s);
+void *set_pop(set *s);
+
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
/* src/vm/access.c - checking access rights
- 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.
IN:
f................the field to check
- calldepth........number of callers to ignore
+ callerdepth......number of callers to ignore
For example if the stacktrace looks like this:
- java.lang.reflect.Method.invokeNative (Native Method)
- [0] java.lang.reflect.Method.invoke (Method.java:329)
- [1] <caller>
+ [0] java.lang.reflect.Method.invokeNative (Native Method)
+ [1] java.lang.reflect.Method.invoke
+ [2] <caller>
- you must specify 1 so the access rights of <caller>
+ you must specify 2 so the access rights of <caller>
are checked.
RETURN VALUE:
*******************************************************************************/
-bool access_check_field(fieldinfo *f, s4 calldepth)
+#if defined(ENABLE_JAVASE)
+bool access_check_field(fieldinfo *f, int callerdepth)
{
- java_handle_objectarray_t *oa;
- classinfo *callerclass;
- char *msg;
- s4 msglen;
- utf *u;
+ classinfo *callerclass;
+ char *msg;
+ int msglen;
+ utf *u;
- /* if everything is public, there is nothing to check */
+ /* If everything is public, there is nothing to check. */
- if ((f->class->flags & ACC_PUBLIC) && (f->flags & ACC_PUBLIC))
+ if ((f->clazz->flags & ACC_PUBLIC) && (f->flags & ACC_PUBLIC))
return true;
- /* get the caller's class */
+ /* Get the caller's class. */
- oa = stacktrace_getClassContext();
+ callerclass = stacktrace_get_caller_class(callerdepth);
- if (oa == NULL)
+ if (callerclass == NULL)
return false;
- assert(calldepth >= 0 && calldepth < LLNI_array_size(oa));
+ /* Check access rights. */
- callerclass = (classinfo *) LLNI_array_direct(oa, calldepth);
-
- /* check access rights */
-
- if (!access_is_accessible_member(callerclass, f->class, f->flags)) {
+ if (!access_is_accessible_member(callerclass, f->clazz, f->flags)) {
msglen =
- utf_bytes(f->class->name) +
+ utf_bytes(f->clazz->name) +
strlen(".") +
utf_bytes(f->name) +
strlen(" not accessible from ") +
msg = MNEW(char, msglen);
- utf_copy_classname(msg, f->class->name);
+ utf_copy_classname(msg, f->clazz->name);
strcat(msg, ".");
utf_cat_classname(msg, f->name);
strcat(msg, " not accessible from ");
return true;
}
+#endif
/* access_check_method *********************************************************
IN:
m................the method to check
- calldepth........number of callers to ignore
+ callerdepth......number of callers to ignore
For example if the stacktrace looks like this:
- java.lang.reflect.Method.invokeNative (Native Method)
- [0] java.lang.reflect.Method.invoke (Method.java:329)
- [1] <caller>
+ [1] java.lang.reflect.Method.invokeNative (Native Method)
+ [1] java.lang.reflect.Method.invoke
+ [2] <caller>
- you must specify 1 so the access rights of <caller>
+ you must specify 2 so the access rights of <caller>
are checked.
RETURN VALUE:
*******************************************************************************/
-bool access_check_method(methodinfo *m, s4 calldepth)
+#if defined(ENABLE_JAVASE)
+bool access_check_method(methodinfo *m, int callerdepth)
{
- java_handle_objectarray_t *oa;
- classinfo *callerclass;
- char *msg;
- s4 msglen;
- utf *u;
+ classinfo *callerclass;
+ char *msg;
+ int msglen;
+ utf *u;
- /* if everything is public, there is nothing to check */
+ /* If everything is public, there is nothing to check. */
- if ((m->class->flags & ACC_PUBLIC) && (m->flags & ACC_PUBLIC))
+ if ((m->clazz->flags & ACC_PUBLIC) && (m->flags & ACC_PUBLIC))
return true;
- /* get the caller's class */
+ /* Get the caller's class. */
- oa = stacktrace_getClassContext();
+ callerclass = stacktrace_get_caller_class(callerdepth);
- if (oa == NULL)
+ if (callerclass == NULL)
return false;
- assert(calldepth >= 0 && calldepth < LLNI_array_size(oa));
+ /* Check access rights. */
- callerclass = (classinfo *) LLNI_array_direct(oa, calldepth);
-
- /* check access rights */
-
- if (!access_is_accessible_member(callerclass, m->class, m->flags)) {
+ if (!access_is_accessible_member(callerclass, m->clazz, m->flags)) {
msglen =
- utf_bytes(m->class->name) +
+ utf_bytes(m->clazz->name) +
strlen(".") +
utf_bytes(m->name) +
utf_bytes(m->descriptor) +
msg = MNEW(char, msglen);
- utf_copy_classname(msg, m->class->name);
+ utf_copy_classname(msg, m->clazz->name);
strcat(msg, ".");
utf_cat_classname(msg, m->name);
utf_cat_classname(msg, m->descriptor);
return true;
}
+#endif
/*
/* src/vm/access.h - checking access rights
- 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 _ACCESS_H
#include "config.h"
-#include "vm/types.h"
+
+#include <stdint.h>
#include "vm/global.h"
bool access_is_accessible_class(classinfo *referer, classinfo *cls);
bool access_is_accessible_member(classinfo *referer, classinfo *declarer,
- s4 memberflags);
+ int32_t memberflags);
-bool access_check_field(fieldinfo *f, s4 calldepth);
-bool access_check_method(methodinfo *m, s4 calldepth);
+#if defined(ENABLE_JAVASE)
+bool access_check_field(fieldinfo *f, int callerdepth);
+bool access_check_method(methodinfo *m, int callerdepth);
+#endif
#endif /* _ACCESS_H */
/* src/vm/array.c - Java array functions
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
imm_union value;
java_handle_t *o;
+ if (a == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
v = LLNI_vftbl_direct(a);
type = v->arraydesc->arraytype;
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;
vftbl_t *v;
int type;
+ if (a == NULL) {
+ exceptions_throw_nullpointerexception();
+ return;
+ }
+
v = LLNI_vftbl_direct(a);
type = v->arraydesc->arraytype;
\
size = LLNI_array_size(a); \
\
- if ((index < 0) || (index > size)) { \
+ if ((index < 0) || (index >= size)) { \
exceptions_throw_arrayindexoutofboundsexception(); \
return (type) 0; \
} \
size = LLNI_array_size(a);
- if ((index < 0) || (index > size)) {
+ if ((index < 0) || (index >= size)) {
exceptions_throw_arrayindexoutofboundsexception();
return NULL;
}
\
size = LLNI_array_size(a); \
\
- if ((index < 0) || (index > size)) { \
+ if ((index < 0) || (index >= size)) { \
exceptions_throw_arrayindexoutofboundsexception(); \
return; \
} \
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)) {
+ if ((index < 0) || (index >= size)) {
exceptions_throw_arrayindexoutofboundsexception();
return;
}
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)
if (a == NULL) {
exceptions_throw_nullpointerexception();
- return 0;
+ return -1;
}
LLNI_class_get(a, c);
if (!class_is_array(c)) {
/* exceptions_throw_illegalargumentexception("Argument is not an array"); */
exceptions_throw_illegalargumentexception();
- return 0;
+ return -1;
}
size = LLNI_array_size(a);
/* src/vm/array.h - Java array functions
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* src/vm/assertion.c - assertion options
- Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
*/
+
#include "config.h"
+
#include <stdint.h>
#include <errno.h>
-#if defined(HAVE_STRING_H)
-# include <string.h>
-#endif
-
#include "mm/memory.h"
+#include "toolbox/list.h"
+
+#include "vm/assertion.h"
#include "vm/global.h"
#include "vm/vm.h"
-#include "toolbox/list.h"
+#include "vmcore/system.h"
-#include "vm/assertion.h"
/* -ea/-da options ************************************************************/
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) {
+void assertion_ea_da(const char *name, bool enabled)
+{
bool package;
size_t len;
char *buf;
}
package = false;
- len = strlen(name);
+ len = system_strlen(name);
if (name[len - 1] == '/') {
return;
}
- buf = strdup(name);
+ buf = system_strdup(name);
+
if (buf == NULL) {
vm_abort("assertion_ea_da: strdup failed: %s", strerror(errno));
}
assertion_class_count += 1;
}
- len = strlen(buf);
+ len = system_strlen(buf);
+
for (i = 0; i < len; i++) {
#if defined(WITH_CLASSPATH_SUN)
if (buf[i] == '.') {
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
/* src/vm/assertion.h - assertion options
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* src/vm/builtin.c - functions for unsupported operations
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/llni.h"
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
#include "toolbox/util.h"
static bool builtintable_init(void)
{
descriptor_pool *descpool;
- s4 dumpsize;
builtintable_entry *bte;
methodinfo *m;
+ int32_t dumpmarker;
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
/* create a new descriptor pool */
if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
return false;
}
bte->descriptor = utf_new_char(bte->cdescriptor);
if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
- dump_release(dumpsize);
+ DRELEASE;
return false;
}
}
bte->descriptor = utf_new_char(bte->cdescriptor);
if (!descriptor_pool_add(descpool, bte->descriptor, NULL)) {
- dump_release(dumpsize);
+ DRELEASE;
return false;
}
}
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
return true;
}
bool builtin_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("builtin_init");
+
/* initialize the builtin tables */
if (!builtintable_init())
*******************************************************************************/
-s4 builtin_instanceof(java_handle_t *o, classinfo *class)
+bool builtin_instanceof(java_handle_t *o, classinfo *class)
{
classinfo *c;
*******************************************************************************/
-s4 builtin_checkcast(java_handle_t *o, classinfo *class)
+bool builtin_checkcast(java_handle_t *o, classinfo *class)
{
classinfo *c;
*******************************************************************************/
-static s4 builtin_descriptorscompatible(arraydescriptor *desc,
- arraydescriptor *target)
+static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
{
if (desc == target)
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)*/
(target->elementvftbl->baseval == 1))
return 1;
- return class_isanysubclass(desc->elementvftbl->class,
- target->elementvftbl->class);
+ return class_isanysubclass(desc->elementvftbl->clazz,
+ target->elementvftbl->clazz);
}
if (desc->dimension < target->dimension)
/* {desc has higher dimension than target} */
return class_isanysubclass(pseudo_class_Arraystub,
- target->elementvftbl->class);
+ target->elementvftbl->clazz);
}
*******************************************************************************/
-s4 builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
+bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
{
arraydescriptor *desc;
*******************************************************************************/
-s4 builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
+bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass)
{
if (o == NULL)
return 0;
*******************************************************************************/
-s4 builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
+bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass)
{
- s4 result;
+ bool result;
LLNI_CRITICAL_START;
*******************************************************************************/
-s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
+bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o)
{
- int result;
+ bool result;
LLNI_CRITICAL_START;
*******************************************************************************/
-s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
+bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
{
arraydescriptor *desc;
arraydescriptor *valuedesc;
vftbl_t *valuevftbl;
int32_t baseval;
uint32_t diffval;
- int result;
+ bool result;
if (o == NULL)
return 1;
/* This is an optimized version where a is guaranteed to be one-dimensional */
-s4 builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
+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;
- int result;
+ bool result;
if (o == NULL)
return 1;
/* This is an optimized version where a is guaranteed to be a
* one-dimensional array of a class type */
-s4 builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
+bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
{
vftbl_t *elementvftbl;
vftbl_t *valuevftbl;
uint32_t diffval;
- int result;
+ bool result;
if (o == NULL)
return 1;
*******************************************************************************/
-java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass)
+java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass)
{
arraydescriptor *desc;
s4 dataoffset;
*******************************************************************************/
-java_handle_t *builtin_java_newarray(s4 size, java_handle_t *arrayclazz)
+java_handle_t *builtin_java_newarray(int32_t size, java_handle_t *arrayclazz)
{
return builtin_newarray(size, LLNI_classinfo_unwrap(arrayclazz));
}
*******************************************************************************/
-java_handle_objectarray_t *builtin_anewarray(s4 size, classinfo *componentclass)
+java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass)
{
classinfo *arrayclass;
*******************************************************************************/
#define BUILTIN_NEWARRAY_TYPE(type, arraytype) \
-java_handle_##type##array_t *builtin_newarray_##type(s4 size) \
+java_handle_##type##array_t *builtin_newarray_##type(int32_t size) \
{ \
return (java_handle_##type##array_t *) \
builtin_newarray(size, primitivetype_table[arraytype].arrayclass); \
/* get the class of the components to create */
- componentclass = arrayclass->vftbl->arraydesc->componentvftbl->class;
+ componentclass = arrayclass->vftbl->arraydesc->componentvftbl->clazz;
/* The verifier guarantees that the dimension count is in the range. */
/* src/vm/builtin.h - prototypes of builtin functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
* ICMD_BUILTIN3.)
*/
-s4 builtin_instanceof(java_handle_t *obj, classinfo *class);
+bool builtin_instanceof(java_handle_t *obj, classinfo *class);
/* NOT AN OP */
-s4 builtin_checkcast(java_handle_t *obj, classinfo *class);
+bool builtin_checkcast(java_handle_t *obj, classinfo *class);
/* NOT AN OP */
-s4 builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass);
+bool builtin_arrayinstanceof(java_handle_t *h, classinfo *targetclass);
/* NOT AN OP */
-s4 builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass);
+bool builtin_fast_arrayinstanceof(java_object_t *o, classinfo *targetclass);
#define BUILTIN_arrayinstanceof (functionptr) builtin_fast_arrayinstanceof
-s4 builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass);
+bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass);
#define BUILTIN_arraycheckcast (functionptr) builtin_fast_arraycheckcast
-s4 builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o);
+bool builtin_canstore(java_handle_objectarray_t *oa, java_handle_t *o);
/* NOT AN OP */
-s4 builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o);
+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);
java_object_t *builtin_fast_new(classinfo *c);
#define BUILTIN_FAST_new (functionptr) builtin_fast_new
-java_handle_t *builtin_newarray(s4 size, classinfo *arrayclass);
+java_handle_t *builtin_newarray(int32_t size, classinfo *arrayclass);
/* NOT AN OP */
-java_handle_t *builtin_java_newarray(s4 size, java_handle_t *arrayclass);
+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(s4 size, classinfo *componentclass);
+java_handle_objectarray_t *builtin_anewarray(int32_t size, classinfo *componentclass);
/* NOT AN OP */
-java_handle_booleanarray_t *builtin_newarray_boolean(s4 size);
+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(s4 size);
+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(s4 size);
+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(s4 size);
+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(s4 size);
+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(s4 size);
+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(s4 size);
+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(s4 size);
+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,
/* src/vm/builtintable.inc - tables of builtin functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "arch.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "threads/lock-common.h"
#include "vm/builtin.h"
+
#include "vm/jit/jit.h"
/* src/vm/exceptions.c - exception related functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/native.h"
#include "native/include/java_lang_String.h"
+#include "native/include/java_lang_Thread.h"
#include "native/include/java_lang_Throwable.h"
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/util.h"
#endif
-/* exceptions_init *************************************************************
-
- Initialize the exceptions subsystem.
-
-*******************************************************************************/
-
-void exceptions_init(void)
-{
-#if !(defined(__ARM__) && defined(__LINUX__))
- /* On arm-linux the first memory page can't be mmap'ed, as it
- contains the exception vectors. */
-
- int pagesize;
-
- /* mmap a memory page at address 0x0, so our hardware-exceptions
- work. */
-
- pagesize = system_getpagesize();
-
- (void) system_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
-#endif
-
- /* check if we get into trouble with our hardware-exceptions */
-
- if (OFFSET(java_bytearray_t, data) <= EXCEPTION_HARDWARE_LARGEST)
- vm_abort("signal_init: array-data offset is less or equal the maximum hardware-exception displacement: %d <= %d", OFFSET(java_bytearray_t, data), EXCEPTION_HARDWARE_LARGEST);
-}
-
-
/* exceptions_get_exception ****************************************************
Returns the current exception pointer of the current thread.
if (opt_DebugExceptions) {
printf("[exceptions_set_exception : t=%p, o=%p, class=",
(void *) t, (void *) o);
- class_print(o->vftbl->class);
+ class_print(o->vftbl->clazz);
printf("]\n");
}
#endif
}
+/* exceptions_new_class_utf ****************************************************
+
+ Creates an exception object with the given class and initalizes it
+ with the given utf message.
+
+ IN:
+ c ......... exception class
+ message ... the message as an utf *
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly
+ created exception, or an exception thrown while trying to create
+ it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_class_utf(classinfo *c, utf *message)
+{
+ java_handle_t *s;
+ java_handle_t *o;
+
+ if (vm_initializing) {
+ /* This can happen when global class variables are used which
+ are not initialized yet. */
+
+ if (c == NULL)
+ exceptions_abort(NULL, message);
+ else
+ exceptions_abort(c->name, message);
+ }
+
+ s = javastring_new(message);
+
+ if (s == NULL)
+ return exceptions_get_exception();
+
+ o = native_new_and_init_string(c, s);
+
+ if (o == NULL)
+ return exceptions_get_exception();
+
+ return o;
+}
+
+
/* exceptions_new_utf **********************************************************
Creates an exception object with the given name and initalizes it.
}
+/* exceptions_new_utf_javastring ***********************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given java/lang/String message.
+
+ IN:
+ classname....class name in UTF-8
+ message......the message as a java.lang.String
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly created
+ exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_javastring(utf *classname,
+ java_handle_t *message)
+{
+ java_handle_t *o;
+ classinfo *c;
+
+ if (vm_initializing)
+ exceptions_abort(classname, NULL);
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return exceptions_get_exception();
+
+ o = native_new_and_init_string(c, message);
+
+ if (o == NULL)
+ return exceptions_get_exception();
+
+ return o;
+}
+
+
+/* exceptions_new_utf_utf ******************************************************
+
+ Creates an exception object with the given name and initalizes it
+ with the given utf message.
+
+ IN:
+ classname....class name in UTF-8
+ message......the message as an utf *
+
+ RETURN VALUE:
+ an exception pointer (in any case -- either it is the newly created
+ exception, or an exception thrown while trying to create it).
+
+*******************************************************************************/
+
+static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
+{
+ classinfo *c;
+ java_handle_t *o;
+
+ if (vm_initializing)
+ exceptions_abort(classname, message);
+
+ c = load_class_bootstrap(classname);
+
+ if (c == NULL)
+ return exceptions_get_exception();
+
+ o = exceptions_new_class_utf(c, message);
+
+ return o;
+}
+
+
+/* exceptions_throw_class_utf **************************************************
+
+ Creates an exception object with the given class, initalizes and
+ throws it with the given utf message.
+
+ IN:
+ c ......... exception class
+ message ... the message as an utf *
+
+*******************************************************************************/
+
+static void exceptions_throw_class_utf(classinfo *c, utf *message)
+{
+ java_handle_t *o;
+
+ o = exceptions_new_class_utf(c, message);
+
+ exceptions_set_exception(o);
+}
+
+
/* exceptions_throw_utf ********************************************************
Creates an exception object with the given name, initalizes and
}
-/* exceptions_new_utf_javastring ***********************************************
-
- Creates an exception object with the given name and initalizes it
- with the given java/lang/String message.
-
- IN:
- classname....class name in UTF-8
- message......the message as a java.lang.String
-
- RETURN VALUE:
- an exception pointer (in any case -- either it is the newly created
- exception, or an exception thrown while trying to create it).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_javastring(utf *classname,
- java_handle_t *message)
-{
- java_handle_t *o;
- classinfo *c;
-
- if (vm_initializing)
- exceptions_abort(classname, NULL);
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return exceptions_get_exception();
-
- o = native_new_and_init_string(c, message);
-
- if (o == NULL)
- return exceptions_get_exception();
-
- return o;
-}
-
-
-/* exceptions_new_utf_utf ******************************************************
-
- Creates an exception object with the given name and initalizes it
- with the given utf message.
-
- IN:
- classname....class name in UTF-8
- message......the message as an utf *
-
- RETURN VALUE:
- an exception pointer (in any case -- either it is the newly created
- exception, or an exception thrown while trying to create it).
-
-*******************************************************************************/
-
-static java_handle_t *exceptions_new_utf_utf(utf *classname, utf *message)
-{
- classinfo *c;
- java_handle_t *s;
- java_handle_t *o;
-
- if (vm_initializing)
- exceptions_abort(classname, message);
-
- c = load_class_bootstrap(classname);
-
- if (c == NULL)
- return exceptions_get_exception();
-
- s = javastring_new(message);
-
- if (s == NULL)
- return exceptions_get_exception();
-
- o = native_new_and_init_string(c, s);
-
- if (o == NULL)
- return exceptions_get_exception();
-
- return o;
-}
-
-
/* exceptions_throw_utf_utf ****************************************************
Creates an exception object with the given name, initalizes and
void exceptions_throw_classnotfoundexception(utf *name)
{
- exceptions_throw_utf_utf(utf_java_lang_ClassNotFoundException, name);
+ exceptions_throw_class_utf(class_java_lang_ClassNotFoundException, name);
}
if (m != NULL)
msglen =
- strlen("(class: ") + utf_bytes(m->class->name) +
+ strlen("(class: ") + utf_bytes(m->clazz->name) +
strlen(", method: ") + utf_bytes(m->name) +
strlen(" signature: ") + utf_bytes(m->descriptor) +
strlen(") ") + strlen("0");
if (m != NULL) {
strcpy(msg, "(class: ");
- utf_cat_classname(msg, m->class->name);
+ utf_cat_classname(msg, m->clazz->name);
strcat(msg, ", method: ");
utf_cat(msg, m->name);
strcat(msg, " signature: ");
msglen = 0;
if (m != NULL)
- msglen = strlen("(class: ") + utf_bytes(m->class->name) +
+ msglen = strlen("(class: ") + utf_bytes(m->clazz->name) +
strlen(", method: ") + utf_bytes(m->name) +
strlen(" signature: ") + utf_bytes(m->descriptor) +
strlen(") Expecting to find longest-------typename on stack")
if (m != NULL) {
strcpy(msg, "(class: ");
- utf_cat_classname(msg, m->class->name);
+ utf_cat_classname(msg, m->clazz->name);
strcat(msg, ", method: ");
utf_cat(msg, m->name);
strcat(msg, " signature: ");
}
-/* exceptions_classnotfoundexception_to_noclassdeffounderror *******************
-
- Check the exception for a ClassNotFoundException. If it is one,
- convert it to a NoClassDefFoundError.
-
-*******************************************************************************/
-
-void exceptions_classnotfoundexception_to_noclassdeffounderror(void)
-{
- classinfo *c;
- java_handle_t *o;
- java_handle_t *cause;
- java_lang_Throwable *object;
- java_lang_String *s;
-
- /* Load java/lang/ClassNotFoundException for the instanceof
- check. */
-
- c = load_class_bootstrap(utf_java_lang_ClassNotFoundException);
-
- if (c == NULL)
- return;
-
- /* Get the cause. */
-
- cause = exceptions_get_exception();
-
- /* Convert ClassNotFoundException's to NoClassDefFoundError's. */
-
- if (builtin_instanceof(cause, c)) {
- /* clear exception, because we are calling jit code again */
-
- exceptions_clear_exception();
-
- /* create new error */
-
- object = (java_lang_Throwable *) cause;
- LLNI_field_get_ref(object, detailMessage, s);
-
- o = exceptions_new_utf_javastring(utf_java_lang_NoClassDefFoundError,
- (java_handle_t *) s);
-
- /* we had an exception while creating the error */
-
- if (exceptions_get_exception())
- return;
-
- /* set new exception */
-
- exceptions_set_exception(o);
- }
-}
-
-
/* exceptions_fillinstacktrace *************************************************
Calls the fillInStackTrace-method of the currently thrown
if (!(c->state & CLASS_LOADED))
/* use the methods' classloader */
if (!load_class_from_classloader(c->name,
- m->class->classloader))
+ m->clazz->classloader))
goto exceptions_handle_exception_return;
/* XXX I think, if it is not linked, we can be sure
void exceptions_print_stacktrace(void)
{
- java_handle_t *oxptr;
- java_handle_t *xptr;
- classinfo *c;
- methodinfo *m;
+ java_handle_t *e;
+ java_handle_t *ne;
+ classinfo *c;
+ methodinfo *m;
- /* get original exception */
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+ java_lang_Thread *to;
+#endif
- oxptr = exceptions_get_and_clear_exception();
+ /* Get and clear exception because we are calling Java code
+ again. */
- if (oxptr == NULL)
- vm_abort("exceptions_print_stacktrace: no exception thrown");
+ e = exceptions_get_and_clear_exception();
- /* clear exception, because we are calling jit code again */
+ if (e == NULL)
+ return;
- LLNI_class_get(oxptr, c);
+#if 0
+ /* FIXME Enable me. */
+ if (builtin_instanceof(e, class_java_lang_ThreadDeath)) {
+ /* Don't print anything if we are being killed. */
+ }
+ else
+#endif
+ {
+ /* Get the exception class. */
- /* find the printStackTrace() method */
+ LLNI_class_get(e, c);
- m = class_resolveclassmethod(c,
- utf_printStackTrace,
- utf_void__void,
- class_java_lang_Object,
- false);
+ /* Find the printStackTrace() method. */
- if (m == NULL)
- vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+ m = class_resolveclassmethod(c,
+ utf_printStackTrace,
+ utf_void__void,
+ class_java_lang_Object,
+ false);
+
+ if (m == NULL)
+ vm_abort("exceptions_print_stacktrace: printStackTrace()V not found");
+
+ /* Print message. */
+
+ fprintf(stderr, "Exception ");
- /* print compatibility message */
+#if defined(ENABLE_THREADS)
+ /* Print thread name. We get the thread here explicitly as we
+ need it afterwards. */
- fprintf(stderr, "Exception in thread \"main\" ");
+ t = thread_get_current();
+ to = (java_lang_Thread *) thread_get_object(t);
- /* print the stacktrace */
+ if (to != NULL) {
+ fprintf(stderr, "in thread \"");
+ thread_fprint_name(t, stderr);
+ fprintf(stderr, "\" ");
+ }
+#endif
- (void) vm_call_method(m, oxptr);
+ /* Print the stacktrace. */
- /* This normally means, we are EXTREMLY out of memory or
- have a serious problem while printStackTrace. But may
- be another exception, so print it. */
+ if (builtin_instanceof(e, class_java_lang_Throwable)) {
+ (void) vm_call_method(m, e);
- xptr = exceptions_get_exception();
+ /* If this happens we are EXTREMLY out of memory or have a
+ serious problem while printStackTrace. But may be
+ another exception, so print it. */
- if (xptr != NULL) {
- fprintf(stderr, "Exception while printStackTrace(): ");
+ ne = exceptions_get_exception();
- /* now print original exception */
+ if (ne != NULL) {
+ fprintf(stderr, "Exception while printStackTrace(): ");
- exceptions_print_exception(xptr);
- stacktrace_print_exception(xptr);
+ /* Print the current exception. */
- /* now print original exception */
+ exceptions_print_exception(ne);
+ stacktrace_print_exception(ne);
- fprintf(stderr, "Original exception was: ");
- exceptions_print_exception(oxptr);
- stacktrace_print_exception(oxptr);
- }
+ /* Now print the original exception. */
- fflush(stderr);
+ fprintf(stderr, "Original exception was: ");
+ exceptions_print_exception(e);
+ stacktrace_print_exception(e);
+ }
+ }
+ else {
+ fprintf(stderr, ". Uncaught exception of type ");
+#if !defined(NDEBUG)
+ /* FIXME This prints to stdout. */
+ class_print(c);
+#else
+ fprintf(stderr, "UNKNOWN");
+#endif
+ fprintf(stderr, ".");
+ }
+
+ fflush(stderr);
+ }
}
/* src/vm/exceptions.h - exception related functions prototypes
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#ifndef _EXCEPTIONS_H
#define _EXCEPTIONS_H
-/* forward typedefs ***********************************************************/
-
#include "config.h"
#include "vm/types.h"
#include "vm/global.h"
-#include "vm/jit/stacktrace.h"
-
#include "vmcore/references.h"
#include "vmcore/method.h"
-/* hardware-exception defines **************************************************
-
- These defines define an internal number for the various hardware
- exceptions.
-
- ATTENTION: These values are also used as load-displacements on some
- architectures. Thus, these values must NOT be aligned to 4 or
- 8-byte boundaries, since normal loads could have such offsets with
- a base of NULL which should result in a NullPointerException.
-
- NOTE: In exceptions_init() we have a check whether the offset of
- java_arrayheader.data[0] is greater than the largest displacement
- defined below. Otherwise normal array loads/stores could trigger
- an exception.
-
-*******************************************************************************/
-
-#define EXCEPTION_HARDWARE_NULLPOINTER 0
-#define EXCEPTION_HARDWARE_ARITHMETIC 1
-#define EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS 2
-#define EXCEPTION_HARDWARE_ARRAYSTORE 3
-
-#define EXCEPTION_HARDWARE_CLASSCAST 5
-#define EXCEPTION_HARDWARE_EXCEPTION 6
-#define EXCEPTION_HARDWARE_PATCHER 7
-
-#define EXCEPTION_HARDWARE_COMPILER 9
-
-#define EXCEPTION_HARDWARE_LARGEST 9
-
-
/* function prototypes ********************************************************/
-void exceptions_init(void);
-
java_handle_t *exceptions_get_exception(void);
void exceptions_set_exception(java_handle_t *o);
void exceptions_clear_exception(void);
void exceptions_throw_privilegedactionexception(java_handle_t *cause);
void exceptions_throw_stringindexoutofboundsexception(void);
-void exceptions_classnotfoundexception_to_noclassdeffounderror(void);
-
java_handle_t *exceptions_fillinstacktrace(void);
void exceptions_print_exception(java_handle_t *xptr);
/* src/vm/finalizer.c - finalizer linked list and thread
- 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/threads-common.h"
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
bool finalizer_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("finalizer_init");
+
#if defined(ENABLE_THREADS)
lock_thread_finalizer = NEW(java_object_t);
/* src/vm/global.h - global definitions
- Copyright (C) 1996-2005, 2007, 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, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#define true 1
#define false 0
-
#if defined(ENABLE_SSA)
/* immediate to get an addidional target Local Var Index */
/* for IINC in Combination with SSA */
#define ALIGN_2(a) ALIGN_EVEN(a)
+/* printf format defines ******************************************************/
+
+/* Define printf formats which change size between 32- and 64-bit. */
+
+#if SIZEOF_VOID_P == 8
+# define PRINTF_FORMAT_INT64_T "%ld"
+#else
+# define PRINTF_FORMAT_INT64_T "%lld"
+#endif
+
+
+/* convenience macros *********************************************************/
+
+/* Makes a string of the argument (which is not macro-expanded). */
+
+#define STR(a) #a
+
+
/* forward typedefs ***********************************************************/
typedef struct java_object_t java_object_t;
*******************************************************************************/
-#define HDRFLAG_FLC 0x01
#define HDRFLAG_MARK1 0x02
#define HDRFLAG_MARK2 0x04
#define HDRFLAG_UNCOLLECTABLE 0x08
#if defined(ENABLE_THREADS)
uintptr_t lockword;
#endif
-#if defined(ENABLE_THREADS) || defined(ENABLE_GC_CACAO)
- uintptr_t hdrflags; /* word containing the FLC and GC bits */
+#if defined(ENABLE_GC_CACAO)
+ uintptr_t hdrflags; /* word containing the GC bits */
#endif
};
/* src/vm/initialize.c - static class initializer functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
static bool initialize_class_intern(classinfo *c);
+/* initialize_init *************************************************************
+
+ Initialize important system classes.
+
+*******************************************************************************/
+
+void initialize_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("initialize_init");
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_CLASSPATH_GNU)
+
+ /* Nothing. */
+
+# elif defined(WITH_CLASSPATH_SUN)
+
+ if (!initialize_class(class_java_lang_String))
+ vm_abort("initialize_init: Initialization failed: java.lang.String");
+
+ if (!initialize_class(class_java_lang_System))
+ vm_abort("initialize_init: Initialization failed: java.lang.System");
+
+ if (!initialize_class(class_java_lang_ThreadGroup))
+ vm_abort("initialize_init: Initialization failed: java.lang.ThreadGroup");
+
+ if (!initialize_class(class_java_lang_Thread))
+ vm_abort("initialize_init: Initialization failed: java.lang.Thread");
+
+# else
+# error unknown classpath configuration
+# endif
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ /* Nothing. */
+
+#else
+# error unknown Java configuration
+#endif
+}
+
/* initialize_class ************************************************************
In Java, every class can have a static initialization
/* src/vm/initialize.h - static class initializer functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/global.h"
-#include "vmcore/references.h"
+#include "vmcore/class.h"
/* function prototypes ********************************************************/
-/* call initializer of class */
+void initialize_init(void);
bool initialize_class(classinfo *c);
#endif /* _INITIALIZE_H */
## src/vm/jit/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.
##
DIST_SUBDIRS = \
allocator \
inline \
+ ir \
loop \
optimizing \
schedule \
x86_64
SUBDIRS = \
+ ir \
optimizing \
$(ARCH_DIR)
STACK_SOURCES = \
stack.c \
stack.h
+
+TRAP_SOURCES = \
+ trap.c \
+ trap.h
endif
if ENABLE_REPLACEMENT
emit-common.h \
exceptiontable.c \
exceptiontable.h \
+ executionstate.c \
+ executionstate.h \
icmdtable.inc \
jit.c \
jit.h \
linenumbertable.c \
linenumbertable.h \
+ methodtree.c \
+ methodtree.h \
parse.c \
parse.h \
patcher-common.c \
stacktrace.c \
stacktrace.h \
trace.c \
- trace.h
+ trace.h \
+ $(TRAP_SOURCES)
libjit_la_SOURCES += \
cfg.c \
libjit_la_LIBADD = \
allocator/liballocator.la \
- $(ALLOCATOR_LIB) \
$(INLINE_LIB) \
+ ir/libir.la \
$(LOOP_LIB) \
$(OPTIMIZING_LIB) \
$(PROFILE_LIB) \
$(INTRP_LIB) \
$(ARCH_LIB)
+if ENABLE_PYTHON
+libjit_la_SOURCES += \
+ python.c
+AM_CPPFLAGS += \
+ @PYTHON_CSPEC@
+LIBS += \
+ @PYTHON_LSPEC@
+endif
+
## Local variables:
## mode: Makefile
/* src/vm/jit/abi.h - common ABI defines
- 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 "arch.h"
+
#include "vm/jit/abi-asm.h"
#include "vm/jit/jit.h"
+#include "vm/jit/stack.h"
-#include "arch.h"
/* ABI externs ****************************************************************/
void md_param_alloc_native(methoddesc *md);
/* machine dependent return value handling function */
-void md_return_alloc(jitdata *jd, stackptr stackslot);
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot);
#endif /* _ABI_H */
/* src/vm/jit/allocator/liveness.c - liveness analysis for lsra
- Copyright (C) 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) 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: Christian Ullrich
-
-
*/
/* function prototypes */
void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
- stackptr src, lv_sets *sets);
-void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
+ stackelement_t* src, lv_sets *sets);
+void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackelement_t* s,
lv_sets *sets, int op);
void liveness_set_local(lsradata *ls, int block, int g_iindex, s4 v_index,
int type, lv_sets *sets, int op);
-void liveness_add_ss(struct lifetime *lt, stackptr s) {
+void liveness_add_ss(struct lifetime *lt, stackelement_t* s) {
struct stackslot *ss;
/* Stackslot noch nicht eingetragen? */
void liveness_setup(jitdata *jd) {
int i, icount, b_index;
- stackptr src;
+ stackelement_t* src;
methodinfo *m;
lsradata *ls;
void liveness_init(jitdata *jd) {
int i, b_index, len;
int lifetimes;
- stackptr src, dst;
+ stackelement_t* src, dst;
instruction *iptr;
methodinfo *m;
lsradata *ls;
void liveness_scan_basicblock(jitdata *jd, int b_index,
lv_sets *sets, int lifetimes) {
int iindex;
- stackptr src;
+ stackelement_t* src;
instruction *iptr;
int i;
methodinfo *m;
int i, p, t;
methoddesc *md;
#ifdef LV_DEBUG_CHECK
- stackptr s;
+ stackelement_t* s;
#endif
methodinfo *m;
registerdata *rd;
}
-struct lifetime *liveness_get_ss_lifetime(lsradata *ls, stackptr s) {
+struct lifetime *liveness_get_ss_lifetime(lsradata *ls, stackelement_t* s) {
struct lifetime *n;
if (s->varnum >= 0) { /* new stackslot lifetime */
return n;
}
-void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackptr s,
+void liveness_set_stack(lsradata *ls, int block, int g_iindex, stackelement_t* s,
lv_sets *sets,
int op) {
struct lifetime *n;
}
void liveness_scan_registers_canditates(jitdata *jd, int b_index, int iindex,
- stackptr src, lv_sets *sets)
+ stackelement_t* src, lv_sets *sets)
{
/* methodinfo *lm; */
builtintable_entry *bte;
methoddesc *md;
int i, g_iindex;
instruction *iptr;
- stackptr dst;
+ stackelement_t* dst;
methodinfo *m;
lsradata *ls;
/* src/vm/jit/allocator/lsra.c - linear scan register allocator
- Copyright (C) 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) 2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
void lsra_setflags(int *, int);
#ifdef LSRA_DEBUG_VERBOSE
-void lsra_dump_stack(stackptr );
+void lsra_dump_stack(stackelement_t* );
void print_lifetimes(jitdata *, int *, int);
#endif
void lsra_scan_registers_canditates(jitdata *, int);
void lsra_join_lifetimes(jitdata *, int);
-void _lsra_new_stack( lsradata *, stackptr , int , int, int);
-void _lsra_from_stack(lsradata *, stackptr , int , int, int);
-void lsra_add_ss(struct lifetime *, stackptr );
+void _lsra_new_stack( lsradata *, stackelement_t* , int , int, int);
+void _lsra_from_stack(lsradata *, stackelement_t* , int , int, int);
+void lsra_add_ss(struct lifetime *, stackelement_t* );
void lsra_usage_local(lsradata *, s4 , int , int , int , int );
#endif
#if defined(LSRA_DEBUG_CHECK)
methodinfo *m;
int b_index;
- stackptr in,out;
+ stackelement_t* in,out;
int ind, outd;
#endif
}
}
-struct stackslot *lsra_make_ss(stackptr s, int bb_index)
+struct stackslot *lsra_make_ss(stackelement_t* s, int bb_index)
{
struct stackslot *ss;
return ss;
}
-void lsra_add_ss(struct lifetime *lt, stackptr s) {
+void lsra_add_ss(struct lifetime *lt, stackelement_t* s) {
struct stackslot *ss;
/* Stackslot not in list? */
}
}
-struct lifetime *get_ss_lifetime(lsradata *ls, stackptr s) {
+struct lifetime *get_ss_lifetime(lsradata *ls, stackelement_t* s) {
struct lifetime *n;
if (s->varnum >= 0) { /* new stackslot lifetime */
#define lsra_new_stack(ls, s, block, instr) \
if ((s)->varkind != ARGVAR) _lsra_new_stack(ls, s, block, instr, LSRA_STORE)
-void _lsra_new_stack(lsradata *ls, stackptr s, int block, int instr, int store)
+void _lsra_new_stack(lsradata *ls, stackelement_t* s, int block, int instr, int store)
{
struct lifetime *n;
if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_LOAD)
#define lsra_pop_from_stack(ls, s, block, instr) \
if ((s)->varkind != ARGVAR) _lsra_from_stack(ls, s, block, instr, LSRA_POP)
-void _lsra_from_stack(lsradata *ls, stackptr s, int block, int instr, int store)
+void _lsra_from_stack(lsradata *ls, stackelement_t* s, int block, int instr, int store)
{
struct lifetime *n;
}
#ifdef LSRA_DEBUG_VERBOSE
-void lsra_dump_stack(stackptr s)
+void lsra_dump_stack(stackelement_t* s)
{
while (s!=NULL) {
printf("%p(R%3i N%3i K%3i T%3i F%3i) ",(void *)s,s->regoff, s->varnum,
int i;
int opcode;
int iindex;
- stackptr src;
- stackptr dst;
+ stackelement_t* src;
+ stackelement_t* dst;
instruction *iptr;
bool join_ret; /* for lsra_join* Macros */
methodinfo *m;
/* src/vm/jit/allocator/lsra.h - linear scan register allocator 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., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Ullrich
-
- Changes: Edwin Steiner
-
*/
struct stackslot {
- stackptr s;
+ stackelement_t* s;
int bb;
struct stackslot *next;
};
/* src/vm/jit/allocator/simplereg.c - register allocator
- Copyright (C) 1996-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) 1996-2005, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* assert that all copy counts are zero */
-#if !defined(NDEBUG)
+#if !defined(NDEBUG) && !defined(ENABLE_SSA)
for (i=0; i < TOTAL_REG_CNT; ++i)
assert(rd->regcopycount[i] == 0);
#endif
int i;
s4 len;
#if 0
- stackptr src, src_old;
- stackptr dst;
+ stackelement_t* src, src_old;
+ stackelement_t* dst;
instruction *iptr;
#endif
basicblock *bptr;
## src/vm/jit/alpha/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.
-##
-##
+
+
DIST_SUBDIRS = \
freebsd \
linux
\
md-abi.c \
md-abi.h \
+ md-trap.h \
md.c \
md.h
/* src/vm/jit/alpha/asmpart.S - Java-C interface functions for alpha
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007, 2008 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
J. Wenninger, Institut f. Computersprachen - TU Wien
L_asm_vm_call_method_recompute_pv:
lda pv,(asm_vm_call_method - L_asm_vm_call_method_recompute_pv)(ra)
+L_asm_vm_call_method_recompute_return:
mov s0,sp /* restore stack pointer */
-L_asm_vm_call_method_recompute_return:
ldq ra,0*8(sp) /* restore RA */
ldq gp,1*8(sp) /* restore global pointer */
ldq s0,3*8(sp)
/* src/vm/jit/alpha/codegen.c - machine code generator 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, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
-#if defined(ENABLE_LSRA)
+#if defined(ENABLE_SSA)
+# include "vm/jit/optimizing/lsra.h"
+# include "vm/jit/optimizing/ssa.h"
+#elif defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
/* decide which monitor enter function to call */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_ALD(REG_A0, REG_PV, disp);
}
else {
M_BNEZ(REG_A0, 1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
M_AST(REG_A0, REG_SP, s1 * 8);
case ICMD_L2F:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_LST(s1, REG_PV, disp);
M_DLD(d, REG_PV, disp);
M_CVTLF(d, d);
case ICMD_L2D:
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_FTMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_LST(s1, REG_PV, disp);
M_DLD(d, REG_PV, disp);
M_CVTLD(d, d);
case ICMD_D2I:
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_CVTDL_C(s1, REG_FTMP2);
M_CVTLI(REG_FTMP2, REG_FTMP3);
M_DST(REG_FTMP3, REG_PV, disp);
case ICMD_D2L:
s1 = emit_load_s1(jd, iptr, REG_FTMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP3);
- disp = dseg_add_unique_double(cd, 0.0);
+ disp = dseg_add_unique_double(cd, 0.0); /* FIXME Not thread safe! */
M_CVTDL_C(s1, REG_FTMP2);
M_DST(REG_FTMP2, REG_PV, disp);
M_LLD(d, REG_PV, disp);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
/* src/vm/jit/alpha/emit.c - Alpha code emitter functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "threads/lock-common.h"
-#include "vm/exceptions.h"
-
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
#include "vm/jit/trace.h"
+#include "vm/jit/trap.h"
#include "vmcore/options.h"
M_BNEZ(reg, 1);
/* Destination register must not be REG_ZERO, because then no
SIGSEGV is thrown. */
- M_ALD_INTERN(reg, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+ M_ALD_INTERN(reg, REG_ZERO, TRAP_ArithmeticException);
}
}
M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
M_BNEZ(REG_ITMP3, 1);
- M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_ALD_INTERN(s2, REG_ZERO, TRAP_ArrayIndexOutOfBoundsException);
}
}
M_BNEZ(REG_RESULT, 1);
/* Destination register must not be REG_ZERO, because then no
SIGSEGV is thrown. */
- M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_ArrayStoreException);
}
}
default:
vm_abort("emit_classcast_check: unknown condition %d", condition);
}
- M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+ M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
}
}
M_BNEZ(reg, 1);
/* Destination register must not be REG_ZERO, because then no
SIGSEGV is thrown. */
- M_ALD_INTERN(reg, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(reg, REG_ZERO, TRAP_NullPointerException);
}
}
M_BNEZ(REG_RESULT, 1);
/* Destination register must not be REG_ZERO, because then no
SIGSEGV is thrown. */
- M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+ M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
- M_ALD_INTERN(REG_METHODPTR, REG_ZERO, EXCEPTION_HARDWARE_COMPILER);
+ M_ALD_INTERN(REG_METHODPTR, REG_ZERO, TRAP_COMPILER);
}
/* Get machine code which is patched back in later. The
trap is 1 instruction word long. */
- mcode = *((u4 *) 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, EXCEPTION_HARDWARE_PATCHER);
+ M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_PATCHER);
return mcode;
}
/* src/vm/jit/alpha/linux/md-os.c - machine dependent Alpha Linux functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/alpha/md.h"
#include "vm/jit/alpha/md-abi.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
+
+#include "vmcore/system.h"
/* md_signal_handler_sigsegv ***************************************************
type = disp;
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
/* The XPC is the RA minus 1, because the RA points to the
instruction after the call. */
type = (int) addr;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* Set registers. */
switch (type) {
- case EXCEPTION_HARDWARE_COMPILER:
+ case TRAP_COMPILER:
if (p != NULL) {
_mc->sc_regs[REG_PV] = (uintptr_t) p;
_mc->sc_pc = (uintptr_t) p;
/* fall-through */
- case EXCEPTION_HARDWARE_PATCHER:
+ case TRAP_PATCHER:
if (p == NULL)
break;
#endif
-/* md_replace_executionstate_read **********************************************
+/* md_executionstate_read ******************************************************
- Read the given context into an executionstate for Replacement.
+ Read the given context into an executionstate.
*******************************************************************************/
-#if defined(ENABLE_REPLACEMENT)
-void md_replace_executionstate_read(executionstate_t *es, void *context)
+void md_executionstate_read(executionstate_t *es, void *context)
{
ucontext_t *_uc;
mcontext_t *_mc;
- s4 i;
+ int i;
_uc = (ucontext_t *) context;
_mc = &_uc->uc_mcontext;
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];
/* read integer registers */
for (i = 0; i < INT_REG_CNT; i++)
es->intregs[i] = _mc->sc_regs[i];
/* read float registers */
- for (i = 0; i < FLT_REG_CNT; i++)
- es->fltregs[i] = _mc->sc_fpregs[i];
+ /* 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));
+ system_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
}
-#endif
-/* md_replace_executionstate_write *********************************************
+/* md_executionstate_write *****************************************************
- Write the given executionstate back to the context for Replacement.
+ Write the given executionstate back to the context.
*******************************************************************************/
-#if defined(ENABLE_REPLACEMENT)
-void md_replace_executionstate_write(executionstate_t *es, void *context)
+void md_executionstate_write(executionstate_t *es, void *context)
{
ucontext_t *_uc;
mcontext_t *_mc;
- s4 i;
+ int i;
_uc = (ucontext_t *) context;
_mc = &_uc->uc_mcontext;
_mc->sc_regs[i] = es->intregs[i];
/* write float registers */
- for (i = 0; i < FLT_REG_CNT; i++)
- _mc->sc_fpregs[i] = es->fltregs[i];
+ /* 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));
+ system_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
/* 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
/* md_critical_section_restart *************************************************
#ifndef _MACHINE_INSTR_H
#define _MACHINE_INSTR_H
-static inline void
-__attribute__ ((unused))
-atomic_add (volatile int *mem, int val)
-{
- int temp;
-
- __asm__ __volatile__ (
- "1:\t"
- "ldl_l %1,%3\n\t"
- "addl %1,%2,%1\n\t"
- "stl_c %1,%0\n\t"
- "beq %1,1b\n\t"
- : "=m"(*mem), "=&r"(temp)
- : "r"(val), "m"(*mem));
-}
-
static inline long
__attribute__ ((unused))
compare_and_swap (volatile long *p, long oldval, long newval)
}
#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("wmb" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
#define MEMORY_BARRIER() __asm__ __volatile__ ( \
"mb" : : : "memory" );
/* src/vm/jit/alpha/md-abi.c - functions for Alpha ABI
- 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.
NOTE: Do not pass a LOCALVAR in stackslot->varnum.
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
methodinfo *m;
methoddesc *md;
--- /dev/null
+/* src/vm/jit/alpha/md-trap.h - Alpha hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (alpha) the trap numbers are used as load
+ * displacements and thus must not be 4- or 8-byte aligned.
+ *
+ * NOTE: In trap_init() we have a check whether the offset of
+ * java_arrayheader.data[0] is greater than the largest displacement
+ * defined below. Otherwise normal array loads/stores could trigger
+ * an exception.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 1
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+
+ /* Don't use 4 (could be a normal load offset). */
+
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+
+ /* Don't use 8 (could be a normal load offset). */
+
+ TRAP_COMPILER = 9,
+ TRAP_END
+};
+
+#endif /* _MD_TRAP_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:
+ */
/* src/vm/jit/alpha/md.c - machine dependent Alpha functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
-#include <assert.h>
#include <stdint.h>
#include <ucontext.h>
#include "vm/jit/alpha/codegen.h"
#include "vm/jit/alpha/md.h"
-#include "vm/exceptions.h"
-
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
+#include "vm/jit/trap.h"
/* global variables ***********************************************************/
*(u4*)(savedmcode) = *(u4*)(pc);
/* build the machine code for the patch */
- mcode = (0xa41f0000 | (EXCEPTION_HARDWARE_PATCHER));
+ mcode = (0xa41f0000 | (TRAP_PATCHER));
/* write the new machine code */
*(u4*)(pc) = mcode;
/* src/vm/jit/alpha/patcher.c - Alpha code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
PATCH_BACK_ORIGINAL_MCODE;
/* patch interfacetable index */
*((s4 *) (ra + 4)) |= (s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->class->index) & 0x0000ffff);
+ sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
/* patch method offset */
*((s4 *) (ra + 4 + 4)) |=
- (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
+ (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
md_icacheflush(NULL, 0);
## src/vm/jit/arm/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.
##
codegen.h \
$(DISASS_SOURCES) \
emit.c \
- md.c \
+ patcher.c \
+ \
md-abi.c \
md-abi.h \
- patcher.c
+ md-trap.h \
+ md.c \
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
/* src/vm/jit/arm/asmpart.S - Java-C interface functions 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.
* *
*******************************************************************************/
-.equ sys_cacheflush,__ARM_NR_cacheflush /* syscall number for cache flushing */
+L___ARM_NR_cacheflush:
+ .align 2
+ .word __ARM_NR_cacheflush
asm_cacheflush:
add a1, a0, a1
see "http://wiki.debian.org/ArmEabiPort" for additional details. */
stmfd sp!, {r7}
- mov r7, #0x0f0000
- add r7, r7, #0x000002
-#endif
-
-#if 0
+ ldr r7, L___ARM_NR_cacheflush
+ swi 0x0
+ ldmfd sp!, {r7}
+#else
+# if 0
/* TWISTI: required on iyonix, maybe a linux-2.4 bug */
mov a0, #0x0
mov a1, #0xff000000
-#endif
-
- swi sys_cacheflush
+# endif
-#if defined(__ARM_EABI__)
- ldmfd sp!, {r7}
+ swi __ARM_NR_cacheflush
#endif
mov pc, lr
/* src/vm/jit/arm/codegen.c - machine code generator 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.
/* get the correct lock object */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_DSEG_LOAD(REG_A0, disp);
}
else {
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, 0);
+ fi->clazz, 0);
}
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, 0);
+ fi->clazz, 0);
}
}
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ sizeof(methodptr*) * lm->clazz->index;
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
our ENABLE_SOFTFLOAT define */
if (iptr->opc == ICMD_BUILTIN && d != TYPE_VOID && IS_FLT_DBL_TYPE(d)) {
#if 0 && !defined(NDEBUG)
- dolog("BUILTIN that returns float or double (%s.%s)", m->class->name->text, m->name->text);
+ dolog("BUILTIN that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
#endif
/* we cannot use this macro, since it is not defined
in ENABLE_SOFTFLOAT M_CAST_FLT_TO_INT_TYPED(d,
/* this depends on gcc; it is independent from our ENABLE_SOFTFLOAT define */
if (md->returntype.type != TYPE_VOID && IS_FLT_DBL_TYPE(md->returntype.type)) {
#if 0 && !defined(NDEBUG)
- dolog("NATIVESTUB that returns float or double (%s.%s)", m->class->name->text, m->name->text);
+ dolog("NATIVESTUB that returns float or double (%s.%s)", m->clazz->name->text, m->name->text);
#endif
/* we cannot use this macro, since it is not defined in ENABLE_SOFTFLOAT */
/* M_CAST_FLT_TO_INT_TYPED(md->returntype.type, REG_FRESULT, REG_RESULT_TYPED(md->returntype.type)); */
/******************************************************************************/
#if defined(__ARMEL__)
-#define SPLIT_OPEN(type, reg, tmpreg) \
+
+# define SPLIT_OPEN(type, reg, tmpreg) \
if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==REG_SPLIT) { \
/*dolog("SPLIT_OPEN({R%d;SPL} > {R%d;R%d})", GET_LOW_REG(reg), GET_LOW_REG(reg), tmpreg);*/ \
/*assert(GET_LOW_REG(reg) == 3);*/ \
(reg) = PACK_REGS(GET_LOW_REG(reg), tmpreg); \
}
-#define SPLIT_LOAD(type, reg, offset) \
- if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==3) { \
- /*dolog("SPLIT_LOAD({R%d;R%d} from [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \
- M_LDR(GET_HIGH_REG(reg), REG_SP, 4 * (offset)); \
- }
-#define SPLIT_STORE_AND_CLOSE(type, reg, offset) \
+
+# define SPLIT_STORE_AND_CLOSE(type, reg, offset) \
if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==3) { \
/*dolog("SPLIT_STORE({R%d;R%d} to [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \
M_STR(GET_HIGH_REG(reg), REG_SP, 4 * (offset)); \
(reg) = PACK_REGS(GET_LOW_REG(reg), REG_SPLIT); \
}
+
#else /* defined(__ARMEB__) */
-#define SPLIT_OPEN(type, reg, tmpreg) \
+
+# define SPLIT_OPEN(type, reg, tmpreg) \
if (IS_2_WORD_TYPE(type) && GET_LOW_REG(reg)==REG_SPLIT) { \
/*dolog("SPLIT_OPEN({SPL;R%d} > {R%d;R%d})", GET_HIGH_REG(reg), tmpreg, GET_HIGH_REG(reg));*/ \
/*assert(GET_HIGH_REG(reg) == 3);*/ \
(reg) = PACK_REGS(tmpreg, GET_HIGH_REG(reg)); \
}
-#define SPLIT_LOAD(type, reg, offset) \
- if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==3) { \
- /*dolog("SPLIT_LOAD({R%d;R%d} from [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \
- M_LDR(GET_LOW_REG(reg), REG_SP, 4 * (offset)); \
- }
-#define SPLIT_STORE_AND_CLOSE(type, reg, offset) \
+
+# define SPLIT_STORE_AND_CLOSE(type, reg, offset) \
if (IS_2_WORD_TYPE(type) && GET_HIGH_REG(reg)==3) { \
/*dolog("SPLIT_STORE({R%d;R%d} to [%x])", GET_LOW_REG(reg), GET_HIGH_REG(reg), offset);*/ \
M_STR(GET_LOW_REG(reg), REG_SP, 4 * (offset)); \
(reg) = PACK_REGS(REG_SPLIT, GET_HIGH_REG(reg)); \
}
+
#endif
/* src/vm/jit/arm/emit.c - Arm code emitter functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
#include "vm/jit/trace.h"
+#include "vm/jit/trap.h"
#include "toolbox/logging.h" /* XXX for debugging only */
if (INSTRUCTION_MUST_CHECK(iptr)) {
CHECK_INT_REG(reg);
M_TEQ_IMM(reg, 0);
- M_TRAPEQ(0, EXCEPTION_HARDWARE_ARITHMETIC);
+ M_TRAPEQ(0, TRAP_ArithmeticException);
}
}
{
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TST(reg, reg);
- M_TRAPEQ(0, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_TRAPEQ(0, TRAP_NullPointerException);
}
}
void emit_nullpointer_check_force(codegendata *cd, instruction *iptr, s4 reg)
{
M_TST(reg, reg);
- M_TRAPEQ(0, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_TRAPEQ(0, TRAP_NullPointerException);
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_ILD_INTERN(REG_ITMP3, s1, OFFSET(java_array_t, size));
M_CMP(s2, REG_ITMP3);
- M_TRAPHS(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_TRAPHS(s2, TRAP_ArrayIndexOutOfBoundsException);
}
}
{
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TST(REG_RESULT, REG_RESULT);
- M_TRAPEQ(0, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_TRAPEQ(0, TRAP_ArrayStoreException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
switch (condition) {
case BRANCH_EQ:
- M_TRAPEQ(s1, EXCEPTION_HARDWARE_CLASSCAST);
+ M_TRAPEQ(s1, TRAP_ClassCastException);
break;
case BRANCH_LE:
- M_TRAPLE(s1, EXCEPTION_HARDWARE_CLASSCAST);
+ M_TRAPLE(s1, TRAP_ClassCastException);
break;
case BRANCH_UGT:
- M_TRAPHI(s1, EXCEPTION_HARDWARE_CLASSCAST);
+ M_TRAPHI(s1, TRAP_ClassCastException);
break;
default:
{
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TST(REG_RESULT, REG_RESULT);
- M_TRAPEQ(0, EXCEPTION_HARDWARE_EXCEPTION);
+ M_TRAPEQ(0, TRAP_CHECK_EXCEPTION);
}
}
/* Get machine code which is patched back in later. The
trap is 1 instruction word long. */
- mcode = *((u4 *) cd->mcodeptr);
+ mcode = *((uint32_t *) cd->mcodeptr);
- M_TRAP(0, EXCEPTION_HARDWARE_PATCHER);
+ M_TRAP(0, TRAP_PATCHER);
return mcode;
}
-/* src/vm/jit/arm/linux/md-os.c - machine dependent arm linux functions
+/* src/vm/jit/arm/linux/md-os.c - machine dependent ARM Linux functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
-#include <assert.h>
#include <stdint.h>
#include "vm/types.h"
#define scontext_t struct sigcontext
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
+#include "vm/vm.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
/* md_signal_handler_sigsegv ***************************************************
mcode = *((s4 *) xpc);
- /* this is a NullPointerException */
+ /* This is a NullPointerException. */
addr = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + ((mcode >> 16) & 0x0f));
- type = EXCEPTION_HARDWARE_NULLPOINTER;
+ type = addr;
val = 0;
- if (addr != 0)
- vm_abort("md_signal_handler_sigsegv: faulting address is not NULL: addr=%p", addr);
+ /* Handle the trap. */
- /* Handle the type. */
-
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* set registers */
- _sc->arm_r10 = (intptr_t) p;
- _sc->arm_fp = (intptr_t) xpc;
- _sc->arm_pc = (intptr_t) asm_handle_exception;
+ _sc->arm_r10 = (uintptr_t) p;
+ _sc->arm_fp = (uintptr_t) xpc;
+ _sc->arm_pc = (uintptr_t) asm_handle_exception;
}
#if defined(ENABLE_DISASSEMBLER)
DISASSINSTR(xpc);
#endif
- assert(0);
+ vm_abort("Aborting...");
}
type = (mcode >> 8) & 0x0fff;
val = *((s4 *) _sc + OFFSET(scontext_t, arm_r0)/4 + (mcode & 0x0f));
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* set registers if we have an exception, continue execution
otherwise (this is needed for patchers to work) */
if (p != NULL) {
- _sc->arm_r10 = (intptr_t) p;
- _sc->arm_fp = (intptr_t) xpc;
- _sc->arm_pc = (intptr_t) asm_handle_exception;
+ _sc->arm_r10 = (uintptr_t) p;
+ _sc->arm_fp = (uintptr_t) xpc;
+ _sc->arm_pc = (uintptr_t) asm_handle_exception;
}
}
#endif
+/**
+ * Read the given context into an executionstate.
+ *
+ * @param es execution state
+ * @param context machine context
+ */
+void md_executionstate_read(executionstate_t *es, void *context)
+{
+ vm_abort("md_executionstate_read: IMPLEMENT ME!");
+
+#if 0
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ int i;
+
+ _uc = (ucontext_t *) context;
+ _mc = &_uc->uc_mcontext;
+
+ /* 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];
+
+ /* read integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ es->intregs[i] = _mc->sc_regs[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));
+ system_memcpy(&es->fltregs, &_mc->sc_fpregs, sizeof(_mc->sc_fpregs));
+#endif
+}
+
+
+/**
+ * Write the given executionstate back to the context.
+ *
+ * @param es execution state
+ * @param context machine context
+ */
+void md_executionstate_write(executionstate_t *es, void *context)
+{
+ vm_abort("md_executionstate_write: IMPLEMENT ME!");
+
+#if 0
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ int i;
+
+ _uc = (ucontext_t *) context;
+ _mc = &_uc->uc_mcontext;
+
+ /* write integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ _mc->sc_regs[i] = es->intregs[i];
+
+ /* write 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));
+ system_memcpy(&_mc->sc_fpregs, &es->fltregs, sizeof(_mc->sc_fpregs));
+
+ /* 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
+}
+
+
/* md_critical_section_restart *************************************************
Search the critical sections tree for a matching section and set
#ifndef _MACHINE_INSTR_H
#define _MACHINE_INSTR_H
-static inline void atomic_add(int *mem, int val)
-{
- int temp, temp2, temp3;
- /*dolog("atomic_add(%p [%d], %d)", mem, *mem, val);*/
-
- /* TODO: improve this one! */
- __asm__ __volatile__ (
- "1:\t"
- "ldr %0,[%3]\n\t"
- "add %1,%0,%4\n\t"
- "swp %2,%1,[%3]\n\t"
- "cmp %0,%2\n\t"
- "swpne %1,%2,[%3]\n\t"
- "bne 1b"
- : "=&r" (temp), "=&r" (temp2), "=&r" (temp3)
- : "r" (mem), "r"(val)
- : "cc", "memory"
- );
-
- /*dolog("atomic_add() mem=%d", *mem);*/
-}
-
static inline long compare_and_swap(long *p, long oldval, long newval)
{
long ret, temp;
}
#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
#define MEMORY_BARRIER() __asm__ __volatile__ ("" : : : "memory" );
/* src/vm/jit/arm/md-abi.c - functions for arm ABI
- 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.
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
methodinfo *m;
codeinfo *code;
--- /dev/null
+/* src/vm/jit/arm/md-trap.h - ARM hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (arm) we use illegal instructions as trap
+ * instructions. Since the illegal instruction with the value 1 is
+ * used by the kernel to generate a SIGTRAP, we skip this one.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 0
+
+enum {
+ TRAP_NullPointerException = 0,
+
+ /* Skip 1 because it's the SIGTRAP illegal instruction. */
+
+ TRAP_ArithmeticException = 2,
+ TRAP_ArrayIndexOutOfBoundsException = 3,
+ TRAP_ArrayStoreException = 4,
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+ TRAP_COMPILER = 8
+};
+
+#endif /* _MD_TRAP_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:
+ */
}
-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
/* src/vm/jit/arm/patcher.c - ARM code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
PATCH_BACK_ORIGINAL_MCODE;
/* patch interfacetable index */
- gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index));
+ gen_resolveload(*((s4 *) (ra + 1 * 4)), (s4) (OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index));
/* patch method offset */
- gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->class->methods)));
+ gen_resolveload(*((s4 *) (ra + 2 * 4)), (s4) (sizeof(methodptr) * (m - m->clazz->methods)));
/* synchronize instruction cache */
-/* src/vm/cfg.c - build a control-flow graph
+/* src/vm/jit/cfg.c - build a control-flow graph
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes: Edwin Steiner
-
*/
#include "config.h"
#include <assert.h>
-
-#include "vm/types.h"
+#include <stdint.h>
#include "mm/memory.h"
+
+#include "vm/global.h"
+
#include "vm/jit/jit.h"
#include "vm/jit/stack.h"
static void cfg_insert_predecessors(basicblock *bptr, basicblock *pbptr)
{
basicblock **tbptr;
- s4 i;
+ int i;
tbptr = bptr->predecessors;
bptr->predecessorcount++;
}
+static void cfg_insert_successors(basicblock *bptr, basicblock *pbptr)
+{
+ basicblock **tbptr;
+ int i;
+
+ tbptr = bptr->successors;
+
+ /* check if the successor is already stored in the array */
+
+ for (i = 0; i < bptr->successorcount; i++, tbptr++)
+ if (*tbptr == pbptr)
+ return;
+
+ /* not found, insert it */
+
+ bptr->successors[bptr->successorcount] = pbptr;
+ bptr->successorcount++;
+}
+
/* cfg_build *******************************************************************
instruction *iptr;
branch_target_t *table;
lookup_target_t *lookup;
- s4 i;
+ int i;
+ bool has_fallthrough;
/* process all basic blocks to find the predecessor/successor counts */
bptr = jd->basicblocks;
for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
+
+ if (bptr->type == BBTYPE_EXH) {
+ /* predecessorcount for exception handlers is initialized to -1,
+ so we need to fix it to 0. */
+ bptr->predecessorcount += 1;
+ }
+
if ((bptr->icount == 0) || (bptr->flags == BBUNDEF))
continue;
iptr--;
}
- switch (iptr->opc) {
- case ICMD_RETURN:
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- case ICMD_ATHROW:
+ if (iptr->opc == ICMD_GOTO) {
+
+ /*
+ This is needed for the following special case caused by
+ stack_reach_next_block:
+ I.e. there might be instructions causing control flow before
+ a GOTO:
+
+ ....
+ 129: 192: IFEQ Ti102 0 (0x00000000) --> L052
+ 131: 193: NOP
+ 0: 0: GOTO --> L060
+ */
+
+ bptr->successorcount++;
+
+ tbptr = iptr->dst.block;
+ tbptr->predecessorcount++;
+
+ if (iptr == bptr->iinstr) {
+ continue;
+ }
+
+ iptr--;
+
+ while (iptr->opc == ICMD_NOP) {
+ if (iptr == bptr->iinstr) {
+ break;
+ }
+ iptr--;
+ }
+
+ has_fallthrough = false;
+ } else {
+ has_fallthrough = true;
+ }
+
+ switch (icmd_table[iptr->opc].controlflow) {
+
+ case CF_END:
break;
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
-
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
-
- 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_ACMPEQ:
- case ICMD_IF_ACMPNE:
+ case CF_IF:
+
bptr->successorcount += 2;
tbptr = iptr->dst.block;
- ntbptr = bptr->next;
-
tbptr->predecessorcount++;
- ntbptr->predecessorcount++;
+
+ if (has_fallthrough) {
+ ntbptr = bptr->next;
+ ntbptr->predecessorcount++;
+ }
break;
- case ICMD_JSR:
+ case CF_JSR:
bptr->successorcount++;
tbptr = iptr->sx.s23.s3.jsrtarget.block;
tbptr->predecessorcount++;
break;
- case ICMD_GOTO:
- case ICMD_RET:
+ case CF_GOTO:
+ case CF_RET:
bptr->successorcount++;
tbptr = iptr->dst.block;
tbptr->predecessorcount++;
break;
- case ICMD_TABLESWITCH:
+ case CF_TABLE:
table = iptr->dst.table;
bptr->successorcount++;
}
break;
- case ICMD_LOOKUPSWITCH:
+ case CF_LOOKUP:
lookup = iptr->dst.lookup;
bptr->successorcount++;
break;
default:
- bptr->successorcount++;
+ if (has_fallthrough) {
+ bptr->successorcount++;
- tbptr = bptr->next;
+ tbptr = bptr->next;
- /* An exception handler has no predecessors. */
+ /* An exception handler has no predecessors. */
- if (tbptr->type != BBTYPE_EXH)
- tbptr->predecessorcount++;
+ if (tbptr->type != BBTYPE_EXH)
+ tbptr->predecessorcount++;
+ }
break;
}
}
iptr--;
}
- switch (iptr->opc) {
- case ICMD_RETURN:
- case ICMD_IRETURN:
- case ICMD_LRETURN:
- case ICMD_FRETURN:
- case ICMD_DRETURN:
- case ICMD_ARETURN:
- case ICMD_ATHROW:
+ if (iptr->opc == ICMD_GOTO) {
+ tbptr = iptr->dst.block;
+
+ cfg_allocate_successors(bptr);
+
+ cfg_insert_successors(bptr, tbptr);
+
+ cfg_allocate_predecessors(tbptr);
+
+ cfg_insert_predecessors(tbptr, bptr);
+
+ if (iptr == bptr->iinstr) {
+ continue;
+ }
+
+ iptr--;
+
+ while (iptr->opc == ICMD_NOP) {
+ if (iptr == bptr->iinstr) {
+ break;
+ }
+ iptr--;
+ }
+
+ has_fallthrough = false;
+
+ } else {
+ has_fallthrough = true;
+ }
+
+ switch (icmd_table[iptr->opc].controlflow) {
+
+ case CF_END:
break;
- case ICMD_IFEQ:
- case ICMD_IFNE:
- case ICMD_IFLT:
- case ICMD_IFGE:
- case ICMD_IFGT:
- case ICMD_IFLE:
-
- case ICMD_IFNULL:
- case ICMD_IFNONNULL:
-
- 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_ACMPEQ:
- case ICMD_IF_ACMPNE:
+ case CF_IF:
+
tbptr = iptr->dst.block;
ntbptr = bptr->next;
cfg_allocate_successors(bptr);
- bptr->successors[0] = tbptr;
- bptr->successors[1] = ntbptr;
- bptr->successorcount += 2;
+ cfg_insert_successors(bptr, tbptr);
+ if (has_fallthrough) {
+ cfg_insert_successors(bptr, ntbptr);
+ }
cfg_allocate_predecessors(tbptr);
- cfg_allocate_predecessors(ntbptr);
-
- tbptr->predecessors[tbptr->predecessorcount] = bptr;
- tbptr->predecessorcount++;
+ if (has_fallthrough) {
+ cfg_allocate_predecessors(ntbptr);
+ }
- ntbptr->predecessors[ntbptr->predecessorcount] = bptr;
- ntbptr->predecessorcount++;
+ cfg_insert_predecessors(tbptr, bptr);
+ if (has_fallthrough) {
+ cfg_insert_predecessors(ntbptr, bptr);
+ }
break;
- case ICMD_JSR:
+ case CF_JSR:
tbptr = iptr->sx.s23.s3.jsrtarget.block;
goto goto_tail;
- case ICMD_GOTO:
- case ICMD_RET:
+ case CF_GOTO:
+ case CF_RET:
+
tbptr = iptr->dst.block;
goto_tail:
cfg_allocate_successors(bptr);
- bptr->successors[0] = tbptr;
- bptr->successorcount++;
+ cfg_insert_successors(bptr, tbptr);
cfg_allocate_predecessors(tbptr);
- tbptr->predecessors[tbptr->predecessorcount] = bptr;
- tbptr->predecessorcount++;
+ cfg_insert_predecessors(tbptr, bptr);
break;
- case ICMD_TABLESWITCH:
+ case CF_TABLE:
table = iptr->dst.table;
tbptr = table->block;
cfg_allocate_successors(bptr);
- bptr->successors[0] = tbptr;
- bptr->successorcount++;
+ cfg_insert_successors(bptr, tbptr);
cfg_allocate_predecessors(tbptr);
- tbptr->predecessors[tbptr->predecessorcount] = bptr;
- tbptr->predecessorcount++;
+ cfg_insert_predecessors(tbptr, bptr);
i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
tbptr = table->block;
table++;
- bptr->successors[bptr->successorcount] = tbptr;
- bptr->successorcount++;
+ cfg_insert_successors(bptr, tbptr);
cfg_allocate_predecessors(tbptr);
cfg_insert_predecessors(tbptr, bptr);
}
break;
- case ICMD_LOOKUPSWITCH:
+ case CF_LOOKUP:
lookup = iptr->dst.lookup;
tbptr = iptr->sx.s23.s3.lookupdefault.block;
cfg_allocate_successors(bptr);
- bptr->successors[0] = tbptr;
- bptr->successorcount++;
+ cfg_insert_successors(bptr, tbptr);
cfg_allocate_predecessors(tbptr);
- tbptr->predecessors[tbptr->predecessorcount] = bptr;
- tbptr->predecessorcount++;
+ cfg_insert_predecessors(tbptr, bptr);
i = iptr->sx.s23.s2.lookupcount;
tbptr = lookup->target.block;
lookup++;
- bptr->successors[bptr->successorcount] = tbptr;
- bptr->successorcount++;
+ cfg_insert_successors(bptr, tbptr);
cfg_allocate_predecessors(tbptr);
cfg_insert_predecessors(tbptr, bptr);
break;
default:
- tbptr = bptr->next;
+ if (has_fallthrough) {
+ tbptr = bptr->next;
- cfg_allocate_successors(bptr);
+ cfg_allocate_successors(bptr);
- bptr->successors[0] = tbptr;
- bptr->successorcount++;
+ bptr->successors[0] = tbptr;
+ bptr->successorcount++;
- /* An exception handler has no predecessors. */
+ /* An exception handler has no predecessors. */
- if (tbptr->type != BBTYPE_EXH) {
- cfg_allocate_predecessors(tbptr);
+ if (tbptr->type != BBTYPE_EXH) {
+ cfg_allocate_predecessors(tbptr);
- tbptr->predecessors[tbptr->predecessorcount] = bptr;
- tbptr->predecessorcount++;
+ tbptr->predecessors[tbptr->predecessorcount] = bptr;
+ tbptr->predecessorcount++;
+ }
}
break;
}
return true;
}
+/* cfg_add_root ****************************************************************
+
+ Adds an empty root basicblock.
+ The numbers of all other basicblocks are set off by one.
+ Needed for some analyses that require the root basicblock to have no
+ predecessors and to perform special initializations.
+
+*******************************************************************************/
+
+void cfg_add_root(jitdata *jd) {
+ basicblock *root, *zero, *it;
+
+ zero = jd->basicblocks;
+
+ root = DNEW(basicblock);
+ MZERO(root, basicblock, 1);
+
+ root->successorcount = 1;
+ root->successors = DMNEW(basicblock *, 1);
+ root->successors[0] = zero;
+ root->next = zero;
+ root->nr = 0;
+ root->type = BBTYPE_STD;
+
+ if (zero->predecessorcount == 0) {
+ zero->predecessors = DNEW(basicblock *);
+ } else {
+ zero->predecessors = DMREALLOC(zero->predecessors, basicblock *, zero->predecessorcount, zero->predecessorcount + 1);
+ }
+ zero->predecessors[zero->predecessorcount] = root;
+ zero->predecessorcount += 1;
+
+ jd->basicblocks = root;
+ jd->basicblockcount += 1;
+
+ for (it = zero; it; it = it->next) {
+ it->nr += 1;
+ }
+}
+
+#if defined(ENABLE_SSA)
+
+/* cfg_add_exceptional_edges ***************************************************
+
+ Edges from basicblocks to their exception handlers and from exception
+ handlers to the blocks they handle exceptions for are added. Further
+ the number of potentially throwing instructions in the basicblocks are
+ counted.
+
+ We don't consider nor do we determine the types of exceptions thrown. Edges
+ are added from every block to every potential handler.
+
+*******************************************************************************/
+
+void cfg_add_exceptional_edges(jitdata *jd) {
+ basicblock *bptr;
+ instruction *iptr;
+ exception_entry *ee;
+
+ /* Count the number of exceptional exits for every block.
+ * Every PEI is an exceptional out.
+ */
+
+ FOR_EACH_BASICBLOCK(jd, bptr) {
+
+ if (bptr->flags == BBUNDEF) {
+ continue;
+ }
+
+ FOR_EACH_INSTRUCTION(bptr, iptr) {
+ if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
+ bptr->exouts += 1;
+ }
+ }
+ }
+
+ /* Count the number of exception handlers for every block. */
+
+ for (ee = jd->exceptiontable; ee; ee = ee->down) {
+ for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
+ /* Linking a block with a handler, even if there are no exceptional exits
+ breaks stuff in other passes. */
+ if (bptr->exouts > 0) {
+ bptr->exhandlercount += 1;
+ ee->handler->expredecessorcount += 1;
+ }
+ }
+ }
+
+ /* Allocate and fill exception handler arrays. */
+
+ for (ee = jd->exceptiontable; ee; ee = ee->down) {
+ for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
+ if (bptr->exouts > 0) {
+
+ if (bptr->exhandlers == NULL) {
+ bptr->exhandlers = DMNEW(basicblock *, bptr->exhandlercount);
+ /* Move pointer past the end of the array,
+ * It will be filled in the reverse order.
+ */
+ bptr->exhandlers += bptr->exhandlercount;
+ }
+
+ bptr->exhandlers -= 1;
+ *(bptr->exhandlers) = ee->handler;
+
+ if (ee->handler->expredecessors == NULL) {
+ ee->handler->expredecessors = DMNEW(basicblock *, ee->handler->expredecessorcount);
+ ee->handler->expredecessors += ee->handler->expredecessorcount;
+ }
+
+ ee->handler->expredecessors -= 1;
+ *(ee->handler->expredecessors) = bptr;
+ }
+ }
+ }
+}
+
+#endif
/*
* These are local overrides for various environment variables in Emacs.
-/* src/vm/cfg.h - build a control-flow graph
+/* src/vm/jit/cfg.h - build a control-flow graph
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#define _CFG_H
#include "config.h"
-#include "vm/types.h"
+
+#include "vm/global.h"
#include "vm/jit/jit.h"
bool cfg_build(jitdata *jd);
+void cfg_add_root(jitdata *jd);
+
#endif /* _CFG_H */
/* src/vm/jit/code.c - codeinfo struct for representing compiled code
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include <assert.h>
-
-#include "vm/types.h"
+#include <stdint.h>
#include "arch.h"
#include "mm/memory.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "vm/vm.h"
#include "vm/jit/code.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/patcher-common.h"
+#include "vm/jit/methodtree.h"
#include "vmcore/options.h"
*******************************************************************************/
-bool code_init(void)
+void code_init(void)
{
- /* check for offset of code->m == 0 (see comment in code.h) */
-
- assert(OFFSET(codeinfo, m) == 0);
+ /* Check if offset of codeinfo.m == 0 (see comment in code.h). */
- /* everything's ok */
-
- return true;
+ if (OFFSET(codeinfo, m) != 0)
+ vm_abort("code_init: offset of codeinfo.m != 0: %d != 0", OFFSET(codeinfo, m));
}
Return the codeinfo for the compilation unit that contains the
given PC.
- IN:
+ ARGUMENTS:
pc...............machine code position
RETURN VALUE:
*******************************************************************************/
-codeinfo *code_find_codeinfo_for_pc(u1 *pc)
+codeinfo *code_find_codeinfo_for_pc(void *pc)
{
- u1 *pv;
+ void *pv;
- pv = codegen_get_pv_from_pc(pc);
- assert(pv);
+ pv = methodtree_find(pc);
return code_get_codeinfo_for_pv(pv);
}
*******************************************************************************/
-codeinfo *code_find_codeinfo_for_pc_nocheck(u1 *pc)
+codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc)
{
- u1 *pv;
+ void *pv;
- pv = codegen_get_pv_from_pc_nocheck(pc);
+ pv = methodtree_find_nocheck(pc);
if (pv == NULL)
return NULL;
*******************************************************************************/
-methodinfo *code_get_methodinfo_for_pv(u1 *pv)
+methodinfo *code_get_methodinfo_for_pv(void *pv)
{
codeinfo *code;
/* src/vm/jit/code.h - codeinfo struct for representing compiled code
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
list_t *patchers;
/* replacement */
+ s4 stackframesize; /* size of the stackframe in slots */
+
#if defined(ENABLE_REPLACEMENT)
rplpoint *rplpoints; /* replacement points */
rplalloc *regalloc; /* register allocation info */
s4 globalcount; /* number of global allocations */
s4 regalloccount; /* number of total allocations */
s4 memuse; /* number of arg + local slots */
- s4 stackframesize; /* size of the stackframe in slots */
u1 savedintcount; /* number of callee saved int regs */
u1 savedfltcount; /* number of callee saved flt regs */
# if defined(HAS_ADDRESS_REGISTER_FILE)
/* function prototypes ********************************************************/
-bool code_init(void);
+void code_init(void);
codeinfo *code_codeinfo_new(methodinfo *m);
void code_codeinfo_free(codeinfo *code);
-codeinfo *code_find_codeinfo_for_pc(u1 *pc);
-codeinfo *code_find_codeinfo_for_pc_nocheck(u1 *pc);
+codeinfo *code_find_codeinfo_for_pc(void *pc);
+codeinfo *code_find_codeinfo_for_pc_nocheck(void *pc);
-methodinfo *code_get_methodinfo_for_pv(u1 *pv);
+methodinfo *code_get_methodinfo_for_pv(void *pv);
#if defined(ENABLE_REPLACEMENT)
int code_get_sync_slot_count(codeinfo *code);
/* src/vm/jit/codegen-common.c - architecture independent code generator stuff
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#if defined(WITH_CLASSPATH_SUN)
# include "native/include/java_lang_Object.h"
-# include "native/include/java_lang_String.h"
+# include "native/include/java_lang_String.h" /* required by j.l.CL */
# include "native/include/java_nio_ByteBuffer.h" /* required by j.l.CL */
# include "native/include/java_lang_ClassLoader.h"
#endif
+#if defined(WITH_CLASSPATH_CLDC1_1)
+# include "native/include/java_lang_String.h"
+#endif
+
#include "native/include/java_lang_Class.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/exceptions.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 "show.h"
-/* in this tree we store all method addresses *********************************/
-
-static avl_tree_t *methodtree = NULL;
-static s4 methodtree_comparator(const void *treenode, const void *node);
-
/* codegen_init ****************************************************************
void codegen_init(void)
{
- /* this tree is global, not method specific */
-
- if (!methodtree) {
-#if defined(ENABLE_JIT)
- methodtree_element *mte;
-#endif
-
- methodtree = avl_create(&methodtree_comparator);
-
-#if defined(ENABLE_JIT)
- /* insert asm_vm_call_method */
-
- mte = NEW(methodtree_element);
-
- mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
- mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
-
- avl_insert(methodtree, mte);
-#endif /* defined(ENABLE_JIT) */
-
- }
-
}
void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
{
- list_t *list;
+ list_t *l;
branch_label_ref_t *br;
s4 mpc;
- /* get the label list */
+ /* Get the label list. */
- list = cd->brancheslabel;
+ l = cd->brancheslabel;
/* calculate the current mpc */
br->reg = reg;
br->options = options;
- /* add the branch to the list */
+ /* Add the branch to the list. */
- list_add_last_unsynced(list, br);
+ list_add_last(l, br);
}
#if defined(ENABLE_THREADS)
void codegen_critical_section_new(codegendata *cd)
{
- list_t *list;
+ list_t *l;
critical_section_ref_t *csr;
s4 mpc;
- /* get the critical section list */
+ /* Get the critical section list. */
- list = cd->listcritical;
+ l = cd->listcritical;
/* calculate the current mpc */
csr->end = -1;
csr->restart = mpc;
- /* add the branch to the list */
+ /* Add the branch to the list. */
- list_add_last_unsynced(list, csr);
+ list_add_last(l, csr);
}
#endif
#if defined(ENABLE_THREADS)
void codegen_critical_section_start(codegendata *cd)
{
- list_t *list;
+ list_t *l;
critical_section_ref_t *csr;
s4 mpc;
- /* get the critical section list */
+ /* Get the critical section list. */
- list = cd->listcritical;
+ l = cd->listcritical;
/* calculate the current mpc */
mpc = cd->mcodeptr - cd->mcodebase;
- /* get the current critical section */
+ /* Get the current critical section. */
- csr = list_last_unsynced(list);
+ csr = list_last(l);
/* set the start point */
#if defined(ENABLE_THREADS)
void codegen_critical_section_end(codegendata *cd)
{
- list_t *list;
+ list_t *l;
critical_section_ref_t *csr;
s4 mpc;
- /* get the critical section list */
+ /* Get the critical section list. */
- list = cd->listcritical;
+ l = cd->listcritical;
/* calculate the current mpc */
mpc = cd->mcodeptr - cd->mcodebase;
- /* get the current critical section */
+ /* Get the current critical section. */
- csr = list_last_unsynced(list);
+ csr = list_last(l);
/* set the end point */
{
codeinfo *code;
codegendata *cd;
- list_t *list;
+ list_t *l;
critical_section_ref_t *csr;
critical_section_node_t *csn;
code = jd->code;
cd = jd->cd;
- /* get the critical section list */
+ /* Get the critical section list. */
- list = cd->listcritical;
+ l = cd->listcritical;
/* iterate over all critical sections */
- for (csr = list_first_unsynced(list); csr != NULL;
- csr = list_next_unsynced(list, csr)) {
+ for (csr = list_first(l); csr != NULL; csr = list_next(l, csr)) {
/* check if all points are set */
assert(csr->start != -1);
#endif
-/* methodtree_comparator *******************************************************
-
- Comparator function used for the AVL tree of methods.
-
- ARGUMENTS:
- treenode....the node from the tree
- node........the node to compare to the tree-node
-
-*******************************************************************************/
-
-static s4 methodtree_comparator(const void *treenode, const void *node)
-{
- methodtree_element *mte;
- methodtree_element *mtepc;
-
- mte = (methodtree_element *) treenode;
- mtepc = (methodtree_element *) node;
-
- /* compare both startpc and endpc of pc, even if they have the same value,
- otherwise the avl_probe sometimes thinks the element is already in the
- tree */
-
-#ifdef __S390__
- /* On S390 addresses are 31 bit. Compare only 31 bits of value.
- */
-# define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
-#else
-# define ADDR_MASK(a) (a)
-#endif
-
- if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
- ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
- ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
- ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
- return 0;
-
- } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
- return -1;
-
- } else {
- return 1;
- }
-
-# undef ADDR_MASK
-}
-
-
-/* codegen_insertmethod ********************************************************
-
- Insert the machine code range of a method into the AVL tree of methods.
-
-*******************************************************************************/
-
-void codegen_insertmethod(u1 *startpc, u1 *endpc)
-{
- methodtree_element *mte;
-
- /* allocate new method entry */
-
- mte = NEW(methodtree_element);
-
- mte->startpc = startpc;
- mte->endpc = endpc;
-
- /* this function does not return an error, but asserts for
- duplicate entries */
-
- avl_insert(methodtree, mte);
-}
-
-
-/* codegen_get_pv_from_pc ******************************************************
-
- Find the PV for the given PC by searching in the AVL tree of
- methods.
-
-*******************************************************************************/
-
-u1 *codegen_get_pv_from_pc(u1 *pc)
-{
- methodtree_element mtepc;
- methodtree_element *mte;
-
- /* allocation of the search structure on the stack is much faster */
-
- mtepc.startpc = pc;
- mtepc.endpc = pc;
-
- mte = avl_find(methodtree, &mtepc);
-
- if (mte == NULL) {
- /* No method was found. Let's dump a stacktrace. */
-
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_signl("SIGSEGV");
-#endif
-
- log_println("We received a SIGSEGV and tried to handle it, but we were");
- log_println("unable to find a Java method at:");
- log_println("");
-#if SIZEOF_VOID_P == 8
- log_println("PC=0x%016lx", pc);
-#else
- log_println("PC=0x%08x", pc);
-#endif
- log_println("");
- assert(0);
- log_println("Dumping the current stacktrace:");
-
-#if defined(ENABLE_THREADS)
- /* XXX michi: This should be available even without threads! */
- threads_print_stacktrace();
-#endif
-
- vm_abort("Exiting...");
- }
-
- return mte->startpc;
-}
-
-
-/* codegen_get_pv_from_pc_nocheck **********************************************
-
- Find the PV for the given PC by searching in the AVL tree of
- methods. This method does not check the return value and is used
- by the profiler.
-
-*******************************************************************************/
-
-u1 *codegen_get_pv_from_pc_nocheck(u1 *pc)
-{
- methodtree_element mtepc;
- methodtree_element *mte;
-
- /* allocation of the search structure on the stack is much faster */
-
- mtepc.startpc = pc;
- mtepc.endpc = pc;
-
- mte = avl_find(methodtree, &mtepc);
-
- if (mte == NULL)
- return NULL;
- else
- return mte->startpc;
-}
-
-
/* codegen_set_replacement_point_notrap ****************************************
Record the position of a non-trappable replacement point.
#endif
s4 alignedmcodelen;
jumpref *jr;
- patchref_t *pr;
u1 *epoint;
s4 alignedlen;
/* patcher resolving */
- pr = list_first_unsynced(code->patchers);
- while (pr) {
- pr->mpc += (ptrint) epoint;
- pr->datap = (ptrint) (pr->disp + epoint);
- pr = list_next_unsynced(code->patchers, pr);
- }
+ patcher_resolve(jd);
#if defined(ENABLE_REPLACEMENT)
/* replacement point resolving */
}
#endif /* defined(ENABLE_REPLACEMENT) */
- /* add method into methodtree to find the entrypoint */
+ /* Insert method into methodtree to find the entrypoint. */
- codegen_insertmethod(code->entrypoint, code->entrypoint + mcodelen);
+ methodtree_insert(code->entrypoint, code->entrypoint + mcodelen);
#if defined(__I386__) || defined(__X86_64__) || defined(__XDSPCORE__) || defined(__M68K__) || defined(ENABLE_INTRP)
/* resolve data segment references */
codegendata *cd;
ptrint *d; /* pointer to data memory */
u1 *c; /* pointer to code memory */
- s4 dumpsize;
+ int32_t dumpmarker;
/* mark dump memory */
- dumpsize = dump_size();
+ DMARKER;
/* allocate required data structures */
/* release dump memory */
- dump_release(dumpsize);
+ DRELEASE;
/* return native stub code */
jitdata *jd;
codeinfo *code;
int skipparams;
- s4 dumpsize;
+ int32_t dumpmarker;
/* mark dump memory */
- dumpsize = dump_size();
+ DMARKER;
/* Create JIT data structure. */
code = jd->code;
+ /* Stubs are non-leaf methods. */
+
+ code_unflag_leafmethod(code);
+
/* setup code generation stuff */
codegen_setup(jd);
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
}
{
jitdata *jd;
codeinfo *code;
- s4 dumpsize;
methoddesc *md;
methoddesc *nmd;
int skipparams;
+ int32_t dumpmarker;
/* mark dump memory */
- dumpsize = dump_size();
+ DMARKER;
/* Create JIT data structure. */
code = jd->code;
+ /* Stubs are non-leaf methods. */
+
+ code_unflag_leafmethod(code);
+
/* set the flags for the current JIT run */
#if defined(ENABLE_PROFILING)
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
/* return native stub code */
void codegen_disassemble_stub(methodinfo *m, u1 *start, u1 *end)
{
printf("Stub code: ");
- if (m->class != NULL)
- utf_fprint_printable_ascii_classname(stdout, m->class->name);
+ if (m->clazz != NULL)
+ utf_fprint_printable_ascii_classname(stdout, m->clazz->name);
else
printf("NULL");
printf(".");
#endif
#if !defined(NDEBUG)
-# if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) || defined(__S390__)
+# 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 */
/* Return a wrapped classinfo for static methods. */
if (m->flags & ACC_STATIC)
- return LLNI_classinfo_wrap(m->class);
+ return (java_handle_t *) LLNI_classinfo_wrap(m->clazz);
else
return NULL;
}
#elif defined(__I386__)
datasp = sp + framesize;
ret_regs = (uint64_t *) (sp + 2 * SIZEOF_VOID_P);
-#elif defined(__M68K__) || defined(__X86_64__)
+#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__)
#endif
#if !defined(NDEBUG)
-# if defined(__ALPHA__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__) || defined(__S390__)
+# 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 */
s4 codegen_reg_of_var(u2 opcode, varinfo *v, s4 tempregnum)
{
-
-#if 0
- /* Do we have to generate a conditional move? Yes, then always
- return the temporary register. The real register is identified
- during the store. */
-
- if (opcode & ICMD_CONDITION_MASK)
- return tempregnum;
-#endif
-
if (!(v->flags & INMEMORY))
return v->vv.regoff;
if (compileverbose)
printf("...returning - phi lifetimes where joined\n");
#endif
- return;
+ continue;
}
if (s->type == -1) {
if (compileverbose)
printf("...returning - phi lifetimes where joined\n");
#endif
- return;
+ continue;
}
tmp_i.opc = 0;
};
-/* methodtree_element *********************************************************/
-
-typedef struct methodtree_element methodtree_element;
-
-struct methodtree_element {
- u1 *startpc;
- u1 *endpc;
-};
-
-
/* function prototypes ********************************************************/
void codegen_init(void);
void codegen_branch_label_add(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options);
-void codegen_insertmethod(u1 *startpc, u1 *endpc);
-u1 *codegen_get_pv_from_pc(u1 *pc);
-u1 *codegen_get_pv_from_pc_nocheck(u1 *pc);
-
#if defined(ENABLE_REPLACEMENT)
#if !defined(NDEBUG)
void codegen_set_replacement_point_notrap(codegendata *cd, s4 type);
/* src/vm/jit/emit-common.c - 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
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* generate patcher traps code */
- for (pr = list_first_unsynced(code->patchers); pr != NULL; pr = list_next_unsynced(code->patchers, pr)) {
+ 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. */
/* search if the label is already in the list */
- for (br = list_first_unsynced(list); br != NULL;
- br = list_next_unsynced(list, br)) {
+ for (br = list_first(list); br != NULL; br = list_next(list, br)) {
/* is this entry the correct label? */
if (br->label == label)
break;
}
- /* a branch reference was found */
+ if (br == NULL) {
+ /* current mcodeptr is the correct position,
+ afterwards emit the NOPs */
- if (br != NULL) {
- /* calculate the mpc of the branch instruction */
+ 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;
+ 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++;
+ 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++;
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
# endif
#endif
- emit_branch(cd, disp, condition, reg, options);
+ emit_branch(cd, disp, condition, reg, options);
- /* now remove the branch reference */
-
- list_remove_unsynced(list, br);
- }
- else {
- /* current mcodeptr is the correct position,
- afterwards emit the NOPs */
+ /* now remove the branch reference */
- codegen_branch_label_add(cd, label, condition, reg, options);
-
- /* generate NOPs as placeholder for branch code */
-
- BRANCH_NOPS;
- }
+ list_remove(list, br);
}
/* search if the label is already in the list */
- for (br = list_first_unsynced(list); br != NULL;
- br = list_next_unsynced(list, br)) {
+ for (br = list_first(list); br != NULL; br = list_next(list, br)) {
/* is this entry the correct label? */
if (br->label == label)
break;
}
- /* a branch reference was found */
+ if (br == NULL) {
+ /* No branch reference found, add the label to the list (use
+ invalid values for condition and register). */
- if (br != NULL) {
- /* calculate the mpc of the branch instruction */
+ 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;
+ mpc = cd->mcodeptr - cd->mcodebase;
+ disp = mpc - br->mpc;
- /* temporary set the mcodeptr */
+ /* temporary set the mcodeptr */
- mcodeptr = cd->mcodeptr;
- cd->mcodeptr = cd->mcodebase + br->mpc;
+ 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++;
+ 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++;
+ else if ((int64_t)disp == disp) count_emit_branch_64bit++;
# endif
#endif
- emit_branch(cd, disp, br->condition, br->reg, br->options);
+ emit_branch(cd, disp, br->condition, br->reg, br->options);
- /* restore mcodeptr */
+ /* restore mcodeptr */
- cd->mcodeptr = mcodeptr;
+ cd->mcodeptr = mcodeptr;
- /* now remove the branch reference */
+ /* now remove the branch reference */
- list_remove_unsynced(list, br);
- }
- else {
- /* add the label to the list (use invalid values for condition
- and register) */
-
- codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
- }
+ list_remove(list, br);
}
/* src/vm/jit/exceptiontable.c - method exception table
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* src/vm/jit/exceptiontable.h - method exception table
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
--- /dev/null
+/* src/vm/jit/executionstate.c - execution-state handling
+
+ 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 <stdio.h>
+
+#include "md-abi.h"
+
+#include "vm/jit/abi.h"
+#include "vm/jit/executionstate.h"
+
+#include "vmcore/descriptor.h"
+#include "vmcore/system.h"
+
+
+/* executionstate_sanity_check *************************************************
+
+ Perform some sanity checks for the md_executionstate_read and
+ md_executionstate_write functions.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void executionstate_sanity_check(void *context)
+{
+ /* estimate a minimum for the context size */
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+#define MINIMUM_CONTEXT_SIZE (SIZEOF_VOID_P * ADR_REG_CNT \
+ + sizeof(double) * FLT_REG_CNT \
+ + sizeof(int) * INT_REG_CNT)
+#else
+#define MINIMUM_CONTEXT_SIZE (SIZEOF_VOID_P * INT_REG_CNT \
+ + sizeof(double) * FLT_REG_CNT)
+#endif
+
+ executionstate_t es1;
+ executionstate_t es2;
+ executionstate_t es3;
+ unsigned int i;
+ unsigned char reference[MINIMUM_CONTEXT_SIZE];
+
+ /* keep a copy of (a prefix of) the context for reference */
+
+ system_memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
+
+ /* different poisons */
+
+ system_memset(&es1, 0xc9, sizeof(executionstate_t));
+ system_memset(&es2, 0xb5, sizeof(executionstate_t));
+ system_memset(&es3, 0x6f, sizeof(executionstate_t));
+
+ md_executionstate_read(&es1, context);
+
+ /* verify that item-by-item copying preserves the state */
+
+ es2.pc = es1.pc;
+ es2.sp = es1.sp;
+ es2.pv = es1.pv;
+ es2.ra = es1.ra;
+ es2.code = es1.code;
+ for (i = 0; i < INT_REG_CNT; ++i)
+ es2.intregs[i] = es1.intregs[i];
+ for (i = 0; i < FLT_REG_CNT; ++i)
+ es2.fltregs[i] = es1.fltregs[i];
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ for (i = 0; i < ADR_REG_CNT; ++i)
+ es2.adrregs[i] = es1.adrregs[i];
+#endif
+
+ /* write it back - this should not change the context */
+ /* We cannot check that completely, unfortunately, as we don't know */
+ /* the size of the (OS-dependent) context. */
+
+ md_executionstate_write(&es2, context);
+
+ /* Read it again, Sam! */
+
+ md_executionstate_read(&es3, context);
+
+ /* Compare. Note: Because of the NAN madness, we cannot compare
+ * doubles using '=='. */
+
+ assert(es3.pc == es1.pc);
+ assert(es3.sp == es1.sp);
+ assert(es3.pv == es1.pv);
+ for (i = 0; i < INT_REG_CNT; ++i)
+ assert(es3.intregs[i] == es1.intregs[i]);
+ for (i = 0; i < FLT_REG_CNT; ++i)
+ assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ for (i = 0; i < ADR_REG_CNT; ++i)
+ assert(es3.adrregs[i] == es1.adrregs[i]);
+#endif
+
+ /* i386 and x86_64 do not have an RA register */
+
+#if defined(__I386__) || defined(__X86_64__)
+ assert(es3.ra != es1.ra);
+#else
+ assert(es3.ra == es1.ra);
+#endif
+
+ /* "code" is not set by the md_* functions */
+
+ assert(es3.code != es1.code);
+
+ /* assert that we have not messed up the context */
+
+ assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
+}
+#endif
+
+
+/* executionstate_println ******************************************************
+
+ Print execution state
+
+ IN:
+ es...............the execution state to print
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void executionstate_println(executionstate_t *es)
+{
+ uint64_t *sp;
+ int slots;
+ int extraslots;
+ int i;
+
+ if (!es) {
+ printf("(executionstate_t *)NULL\n");
+ return;
+ }
+
+ printf("executionstate_t:\n");
+ printf("\tpc = %p", es->pc);
+ printf(" sp = %p", es->sp);
+ printf(" pv = %p", es->pv);
+ printf(" ra = %p\n", es->ra);
+
+#if defined(ENABLE_DISASSEMBLER)
+ for (i=0; i<INT_REG_CNT; ++i) {
+ if (i%4 == 0)
+ printf("\t");
+ else
+ printf(" ");
+# if SIZEOF_VOID_P == 8
+ printf("%-3s = %016lx", abi_registers_integer_name[i], es->intregs[i]);
+# else
+ printf("%-3s = %08x", abi_registers_integer_name[i], (unsigned) es->intregs[i]);
+# endif
+ if (i%4 == 3)
+ printf("\n");
+ }
+
+ for (i=0; i<FLT_REG_CNT; ++i) {
+ if (i%4 == 0)
+ printf("\t");
+ else
+ printf(" ");
+ printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
+ if (i%4 == 3)
+ printf("\n");
+ }
+
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+ for (i=0; i<ADR_REG_CNT; ++i) {
+ if (i%4 == 0)
+ printf("\t");
+ else
+ printf(" ");
+ printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
+ if (i%4 == 3)
+ printf("\n");
+ }
+# endif
+#endif
+
+ sp = (uint64_t *) es->sp;
+
+ extraslots = 2;
+
+ if (es->code) {
+ methoddesc *md = es->code->m->parseddesc;
+ slots = es->code->stackframesize;
+ extraslots = 1 + md->memuse;
+ }
+ else
+ slots = 0;
+
+
+ if (slots) {
+ printf("\tstack slots(+%d) at sp:", extraslots);
+ for (i=0; i<slots+extraslots; ++i) {
+ 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");
+ }
+
+ printf("\tcode: %p", (void*)es->code);
+ if (es->code != NULL) {
+ printf(" stackframesize=%d ", es->code->stackframesize);
+ method_print(es->code->m);
+ }
+ printf("\n");
+
+ 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/jit/executionstate.h - execution-state handling
+
+ 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 _EXECUTIONSTATE_H
+#define _EXECUTIONSTATE_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct executionstate_t executionstate_t;
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "arch.h"
+#include "md-abi.h"
+
+#include "vm/jit/code.h"
+
+
+/* executionstate_t ************************************************************
+
+ An execution-state represents the state of a thread containing all
+ registers that are important. This structure is an internal
+ structure similar to mcontext_t.
+
+*******************************************************************************/
+
+struct executionstate_t {
+ uint8_t *pc; /* program counter */
+ uint8_t *sp; /* stack pointer within method */
+ uint8_t *pv; /* procedure value. NULL means */
+ /* search the AVL tree */
+ uint8_t *ra; /* return address / link register */
+
+ uintptr_t intregs[INT_REG_CNT]; /* register values */
+ double fltregs[FLT_REG_CNT]; /* register values */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ uintptr_t adrregs[ADR_REG_CNT]; /* register values */
+#endif
+
+ codeinfo *code; /* codeinfo corresponding to the pv */
+};
+
+
+/* prototypes *****************************************************************/
+
+#if !defined(NDEBUG)
+void executionstate_sanity_check(void *context);
+void executionstate_println(executionstate_t *es);
+#endif
+
+/* Machine and OS dependent functions (code in ARCH_DIR/OS_DIR/md-os.c) */
+
+void md_executionstate_read(executionstate_t *es, void *ucontext);
+void md_executionstate_write(executionstate_t *es, void *ucontext);
+
+#endif /* _EXECUTIONSTATE_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:
+ */
## src/vm/jit/i386/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.
##
$(DISASS_SOURCES) \
emit.c \
emit.h \
- md.c \
patcher.c \
\
md-abi.c \
- md-abi.h
+ md-abi.h \
+ md-trap.h \
+ md.c \
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
/* src/vm/jit/i386/asmpart.S - Java-C interface functions 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.
asm_vm_call_method_float:
asm_vm_call_method_double:
push bp
- mov sp,bp /* save stackptr */
+ mov sp,bp /* save stack pointer */
sub $(4*4),sp /* create stackframe */
and $0xfffffff0,sp /* align stack to 16-byte */
mov t0,8*4(sp) /* save maybe-leaf flag */
mov xpc,0*4(sp) /* pass exception pc */
- call codegen_get_pv_from_pc
+ call methodtree_find
mov v0,6*4(sp) /* save data segment pointer */
mov 4*4(sp),itmp3 /* pass exception pointer */
cmp $2,itmp1
je int2
- mov -3*8(itmp2),s0
+ mov -4-3*8(itmp2),s0
int2:
- mov -2*8(itmp2),s1
+ mov -4-2*8(itmp2),s1
int1:
- mov -1*8(itmp2),s2
+ mov -4-1*8(itmp2),s2
shl $2,itmp1 /* multiply by 4 bytes */
sub itmp1,itmp2
/* src/vm/jit/i386/codegen.c - machine code generator 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/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
#if defined(ENABLE_SSA)
# include "vm/jit/optimizing/lsra.h"
codegendata *cd;
registerdata *rd;
s4 len, s1, s2, s3, d, disp;
+ int align_off; /* offset for alignment compensation */
varinfo *var, *var1;
basicblock *bptr;
instruction *iptr;
/* Keep stack of non-leaf functions 16-byte aligned. */
if (!code_is_leafmethod(code)) {
- ALIGN_ODD(cd->stackframesize); /* XXX this is wrong, +4 is missing */
+ ALIGN_ODD(cd->stackframesize);
}
+ align_off = cd->stackframesize ? 4 : 0;
+
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
- (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
+ (void) dseg_add_unique_s4(
+ cd, cd->stackframesize * 8 + align_off); /* FrameSize */
code->synchronizedoffset = rd->memuse * 8;
/* create stack frame (if necessary) */
if (cd->stackframesize)
- M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
+ /* align_off == 4 */
+ M_ASUB_IMM(cd->stackframesize * 8 + 4, REG_SP);
/* save return address and used callee saved registers */
}
else {
if (!(var->flags & INMEMORY)) {
- M_ILD(d, REG_SP, cd->stackframesize * 8 + 4 + s1);
+ M_ILD(d, REG_SP,
+ cd->stackframesize * 8 + 4 + align_off + s1);
}
else {
if (!IS_2_WORD_TYPE(t)) {
/* no copy avoiding by now possible with SSA */
if (ls != NULL) {
emit_mov_membase_reg( /* + 4 for return address */
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4,
- REG_ITMP1);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + align_off,
+ REG_ITMP1);
emit_mov_reg_membase(
- cd, REG_ITMP1, REG_SP, var->vv.regoff);
+ cd, REG_ITMP1, REG_SP, var->vv.regoff);
}
else
#endif /*defined(ENABLE_SSA)*/
/* reuse stackslot */
- var->vv.regoff = cd->stackframesize * 8 + 4 + s1;
+ var->vv.regoff = cd->stackframesize * 8 + 4 +
+ align_off + s1;
}
else {
/* no copy avoiding by now possible with SSA */
if (ls != NULL) {
emit_mov_membase_reg( /* + 4 for return address */
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4,
- REG_ITMP1);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + align_off,
+ REG_ITMP1);
emit_mov_reg_membase(
- cd, REG_ITMP1, REG_SP, var->vv.regoff);
+ cd, REG_ITMP1, REG_SP, var->vv.regoff);
emit_mov_membase_reg( /* + 4 for return address */
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4 + 4,
- REG_ITMP1);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + 4 + align_off,
+ REG_ITMP1);
emit_mov_reg_membase(
- cd, REG_ITMP1, REG_SP, var->vv.regoff + 4);
+ cd, REG_ITMP1, REG_SP, var->vv.regoff + 4);
}
else
#endif /*defined(ENABLE_SSA)*/
/* reuse stackslot */
- var->vv.regoff = cd->stackframesize * 8 + 4 + s1;
+ var->vv.regoff = cd->stackframesize * 8 + 8 + s1;
}
}
}
if (!(var->flags & INMEMORY)) { /* stack-arg -> register */
if (t == TYPE_FLT) {
emit_flds_membase(
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + align_off);
assert(0);
/* emit_fstp_reg(cd, var->vv.regoff + fpu_st_offset); */
}
else {
emit_fldl_membase(
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + align_off);
assert(0);
/* emit_fstp_reg(cd, var->vv.regoff + fpu_st_offset); */
}
/* no copy avoiding by now possible with SSA */
if (ls != NULL) {
emit_mov_membase_reg(
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4, REG_ITMP1);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + align_off,
+ REG_ITMP1);
emit_mov_reg_membase(
- cd, REG_ITMP1, REG_SP, var->vv.regoff);
+ cd, REG_ITMP1, REG_SP, var->vv.regoff);
if (t == TYPE_FLT) {
emit_flds_membase(
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + align_off);
emit_fstps_membase(cd, REG_SP, var->vv.regoff);
}
else {
emit_fldl_membase(
- cd, REG_SP, cd->stackframesize * 8 + s1 + 4);
+ cd, REG_SP,
+ cd->stackframesize * 8 + s1 + 4 + align_off);
emit_fstpl_membase(cd, REG_SP, var->vv.regoff);
}
}
else
#endif /*defined(ENABLE_SSA)*/
/* reuse stackslot */
- var->vv.regoff = cd->stackframesize * 8 + 4 + s1;
+ var->vv.regoff = cd->stackframesize * 8 + 4 +
+ align_off + s1;
}
}
}
s1 = rd->memuse;
if (m->flags & ACC_STATIC) {
- M_MOV_IMM(&m->class->object.header, REG_ITMP1);
+ M_MOV_IMM(&m->clazz->object.header, REG_ITMP1);
}
else {
- M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + 4);
+ M_ALD(REG_ITMP1, REG_SP, cd->stackframesize * 8 + 4 + align_off);
M_TEST(REG_ITMP1);
M_BNE(6);
- M_ALD_MEM(REG_ITMP1, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_MEM(REG_ITMP1, TRAP_NullPointerException);
}
M_AST(REG_ITMP1, REG_SP, s1 * 8);
fieldtype = fi->type;
disp = (intptr_t) fi->value;
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
}
M_MOV_IMM(disp, REG_ITMP1);
fieldtype = fi->type;
disp = (intptr_t) fi->value;
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
}
M_MOV_IMM(disp, REG_ITMP1);
fieldtype = fi->type;
disp = (intptr_t) fi->value;
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
}
M_MOV_IMM(disp, REG_ITMP1);
/* deallocate stack */
if (cd->stackframesize)
- M_AADD_IMM(cd->stackframesize * 8, REG_SP);
+ M_AADD_IMM(cd->stackframesize * 8 + 4, REG_SP);
M_RET;
}
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr) * lm->class->index;
+ sizeof(methodptr) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
d = md->returntype.type;
}
/* keep stack 16-byte aligned */
- ALIGN_ODD(cd->stackframesize); /* XXX this is wrong, +4 is missing */
+ ALIGN_ODD(cd->stackframesize);
/* create method header */
(void) dseg_add_unique_address(cd, code); /* CodeinfoPointer */
- (void) dseg_add_unique_s4(cd, cd->stackframesize * 8); /* FrameSize */
+ (void) dseg_add_unique_s4(cd, cd->stackframesize * 8 + 4); /* FrameSize */
(void) dseg_add_unique_s4(cd, 0); /* IsLeaf */
(void) dseg_add_unique_s4(cd, 0); /* IntSave */
(void) dseg_add_unique_s4(cd, 0); /* FltSave */
/* calculate stackframe size for native function */
- M_ASUB_IMM(cd->stackframesize * 8, REG_SP);
+ M_ASUB_IMM(cd->stackframesize * 8 + 4, REG_SP);
/* Mark the whole fpu stack as free for native functions (only for saved */
/* register count == 0). */
if (!md->params[i].inmemory)
assert(0);
- s1 = md->params[i].regoff + cd->stackframesize * 8 + 4;
+ s1 = md->params[i].regoff + cd->stackframesize * 8 + 8;
s2 = nmd->params[j].regoff;
/* float/double in memory can be copied like int/longs */
M_ALD(abi_registers_integer_saved[i], REG_SP, disp + i * 4);
#endif
- M_AADD_IMM(cd->stackframesize * 8, REG_SP);
+ M_AADD_IMM(cd->stackframesize * 8 + 4, REG_SP);
/* check for exception */
/* src/vm/jit/i386/cygwin/md-asm.h - assembler defines for Cygwin i386 ABI
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Michael Starzinger
-
- Changes:
-
*/
#define asm_builtin_d2i _asm_builtin_d2i
#define asm_builtin_d2l _asm_builtin_d2l
-#define asm_criticalsections _asm_criticalsections
-#define asm_getclassvalues_atomic _asm_getclassvalues_atomic
-
/* external defines ***********************************************************/
#define exceptions_get_and_clear_exception _exceptions_get_and_clear_exception
#define builtin_throw_exception _builtin_throw_exception
-#define codegen_get_pv_from_pc _codegen_get_pv_from_pc
+#define methodtree_find _methodtree_find
#define exceptions_handle_exception _exceptions_handle_exception
#define jit_asm_compile _jit_asm_compile
/* src/vm/jit/i386/darwin/md-asm.h - assembler defines for i386 Darwin ABI
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
#define asm_builtin_d2i _asm_builtin_d2i
#define asm_builtin_d2l _asm_builtin_d2l
-#define asm_criticalsections _asm_criticalsections
-#define asm_getclassvalues_atomic _asm_getclassvalues_atomic
-
/* external defines ***********************************************************/
#define exceptions_get_and_clear_exception _exceptions_get_and_clear_exception
#define builtin_throw_exception _builtin_throw_exception
-#define codegen_get_pv_from_pc _codegen_get_pv_from_pc
+#define methodtree_find _methodtree_find
#define exceptions_handle_exception _exceptions_handle_exception
#define jit_asm_compile _jit_asm_compile
/* src/vm/jit/i386/darwin/md-os.c - machine dependent i386 Darwin functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
#include "vm/jit/i386/codegen.h"
+#include "vm/jit/i386/md.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
-#include "vm/exceptions.h"
+#include "vm/builtin.h"
#include "vm/global.h"
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
#include "vm/jit/i386/codegen.h"
intptr_t val;
int type;
void *p;
+ java_object_t *o;
_uc = (ucontext_t *) _p;
_mc = _uc->uc_mcontext;
((d == 4) ? _ss->esp :
((d == 5) ? _ss->ebp :
((d == 6) ? _ss->esi : _ss->edi))))));
+
+ 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 = EXCEPTION_HARDWARE_NULLPOINTER;
+ type = TRAP_NullPointerException;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- /* set registers */
+ /* Set registers. */
- _ss->eax = (intptr_t) p;
- _ss->ecx = (intptr_t) xpc;
- _ss->eip = (intptr_t) asm_handle_exception;
+ if (type == TRAP_COMPILER) {
+ if (p == NULL) {
+ o = builtin_retrieve_exception();
+
+ _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;
+ }
}
xpc = (u1 *) _ss->eip;
ra = xpc; /* return address is equal to xpc */
- /* this is an ArithmeticException */
+ /* This is an ArithmeticException */
- type = EXCEPTION_HARDWARE_ARITHMETIC;
+ type = TRAP_ArithmeticException;
val = 0;
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- _ss->eax = (intptr_t) p;
- _ss->ecx = (intptr_t) xpc;
- _ss->eip = (intptr_t) asm_handle_exception;
+ /* Set registers. */
+
+ _ss->eax = (uintptr_t) p;
+ _ss->ecx = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _ss->eip = (uintptr_t) asm_handle_exception;
}
}
+/* md_signal_handler_sigill ****************************************************
+
+ Signal handler for hardware patcher traps (ud2).
+
+*******************************************************************************/
+
+void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
+{
+ ucontext_t *_uc;
+ mcontext_t _mc;
+ u1 *pv;
+ i386_thread_state_t *_ss;
+ u1 *sp;
+ u1 *ra;
+ u1 *xpc;
+ int type;
+ intptr_t val;
+ void *p;
+
+
+ _uc = (ucontext_t *) _p;
+ _mc = _uc->uc_mcontext;
+ _ss = &_mc->ss;
+
+ pv = NULL; /* is resolved during stackframeinfo creation */
+ sp = (u1 *) _ss->esp;
+ xpc = (u1 *) _ss->eip;
+ ra = xpc; /* return address is equal to xpc */
+
+ type = TRAP_PATCHER;
+ val = 0;
+
+ /* Handle the trap. */
+
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
+
+ /* Set registers. */
+
+ if (p != NULL) {
+ _ss->eax = (uintptr_t) p;
+ _ss->ecx = (uintptr_t) xpc; /* REG_ITMP2_XPC */
+ _ss->eip = (uintptr_t) asm_handle_exception;
+ }
+}
+
+/* md_executionstate_read ******************************************************
+
+ Read the given context into an executionstate.
+
+*******************************************************************************/
+
+void md_executionstate_read(executionstate_t *es, void *context)
+{
+ ucontext_t *_uc;
+ mcontext_t _mc;
+ i386_thread_state_t *_ss;
+ int i;
+
+ _uc = (ucontext_t *) context;
+ _mc = _uc->uc_mcontext;
+ _ss = &_mc->ss;
+
+ /* read special registers */
+ es->pc = (u1 *) _ss->eip;
+ es->sp = (u1 *) _ss->esp;
+ es->pv = NULL; /* pv must be looked up via AVL tree */
+
+ /* read integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ es->intregs[i] = (i == 0) ? _ss->eax :
+ ((i == 1) ? _ss->ecx :
+ ((i == 2) ? _ss->edx :
+ ((i == 3) ? _ss->ebx :
+ ((i == 4) ? _ss->esp :
+ ((i == 5) ? _ss->ebp :
+ ((i == 6) ? _ss->esi : _ss->edi))))));
+
+ /* read float registers */
+ for (i = 0; i < FLT_REG_CNT; i++)
+ es->fltregs[i] = 0xdeadbeefdeadbeefULL;
+}
+
+
+/* md_executionstate_write *****************************************************
+
+ Write the given executionstate back to the context.
+
+*******************************************************************************/
+
+void md_executionstate_write(executionstate_t *es, void *context)
+{
+ ucontext_t* _uc;
+ mcontext_t _mc;
+ i386_thread_state_t* _ss;
+ int i;
+
+ _uc = (ucontext_t *) context;
+ _mc = _uc->uc_mcontext;
+ _ss = &_mc->ss;
+
+ /* write integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ *((i == 0) ? &_ss->eax :
+ ((i == 1) ? &_ss->ecx :
+ ((i == 2) ? &_ss->edx :
+ ((i == 3) ? &_ss->ebx :
+ ((i == 4) ? &_ss->esp :
+ ((i == 5) ? &_ss->ebp :
+ ((i == 6) ? &_ss->esi : &_ss->edi))))))) = es->intregs[i];
+
+ /* write special registers */
+ _ss->eip = (ptrint) es->pc;
+ _ss->esp = (ptrint) es->sp;
+}
+
+
/* md_critical_section_restart *************************************************
Search the critical sections tree for a matching section and set
/* src/vm/jit/i386/emit.c - i386 code emitter functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
#include "vm/jit/trace.h"
+#include "vm/jit/trap.h"
#include "vmcore/options.h"
#include "vmcore/statistics.h"
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(reg);
M_BNE(6);
- M_ALD_MEM(reg, EXCEPTION_HARDWARE_ARITHMETIC);
+ M_ALD_MEM(reg, TRAP_ArithmeticException);
}
}
M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
M_CMP(REG_ITMP3, s2);
M_BB(6);
- M_ALD_MEM(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_ALD_MEM(s2, TRAP_ArrayIndexOutOfBoundsException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(REG_RESULT);
M_BNE(6);
- M_ALD_MEM(REG_RESULT, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_ALD_MEM(REG_RESULT, TRAP_ArrayStoreException);
}
}
default:
vm_abort("emit_classcast_check: unknown condition %d", condition);
}
- M_ALD_MEM(s1, EXCEPTION_HARDWARE_CLASSCAST);
+ M_ALD_MEM(s1, TRAP_ClassCastException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(reg);
M_BNE(6);
- M_ALD_MEM(reg, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_MEM(reg, TRAP_NullPointerException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(REG_RESULT);
M_BNE(6);
- M_ALD_MEM(REG_RESULT, EXCEPTION_HARDWARE_EXCEPTION);
+ M_ALD_MEM(REG_RESULT, TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
- M_ALD_MEM(REG_METHODPTR, EXCEPTION_HARDWARE_COMPILER);
+ M_ALD_MEM(REG_METHODPTR, TRAP_COMPILER);
}
methoddesc *md;
int32_t stackframesize;
int i;
+ int align_off; /* offset for alignment compensation */
if (!JITDATA_HAS_FLAG_VERBOSECALL(jd))
return;
/* no argument registers to save */
+ align_off = cd->stackframesize ? 4 : 0;
M_AST_IMM(m, REG_SP, 0 * 4);
M_AST_IMM(0, REG_SP, 1 * 4);
M_AST(REG_SP, REG_SP, 2 * 4);
- M_IADD_IMM_MEMBASE(stackframesize * 8 + cd->stackframesize * 8 + 4, REG_SP, 2 * 4);
+ M_IADD_IMM_MEMBASE(stackframesize * 8 + cd->stackframesize * 8 + 4 + align_off, REG_SP, 2 * 4);
M_MOV_IMM(trace_java_call_enter, REG_ITMP1);
M_CALL(REG_ITMP1);
/* src/vm/jit/i386/linux/md-os.c - machine dependent i386 Linux functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/i386/codegen.h"
#include "vm/jit/i386/md.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
/* md_signal_handler_sigsegv ***************************************************
val = _mc->gregs[REG_EAX - d];
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
/* The PV from the compiler stub is equal to the XPC. */
pv = xpc;
else {
/* this was a normal NPE */
- type = EXCEPTION_HARDWARE_NULLPOINTER;
+ type = TRAP_NullPointerException;
val = 0;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* Set registers. */
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
if (p == NULL) {
o = builtin_retrieve_exception();
}
}
else {
- _mc->gregs[REG_EAX] = (intptr_t) p;
- _mc->gregs[REG_ECX] = (intptr_t) xpc; /* REG_ITMP2_XPC */
- _mc->gregs[REG_EIP] = (intptr_t) asm_handle_exception;
+ _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;
}
}
xpc = (u1 *) _mc->gregs[REG_EIP];
ra = xpc; /* return address is equal to xpc */
- /* this is an ArithmeticException */
+ /* This is an ArithmeticException. */
- type = EXCEPTION_HARDWARE_ARITHMETIC;
+ type = TRAP_ArithmeticException;
val = 0;
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- /* set registers */
+ /* Set registers. */
- _mc->gregs[REG_EAX] = (intptr_t) p;
- _mc->gregs[REG_ECX] = (intptr_t) xpc; /* REG_ITMP2_XPC */
- _mc->gregs[REG_EIP] = (intptr_t) asm_handle_exception;
+ _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;
}
xpc = (u1 *) _mc->gregs[REG_EIP];
ra = xpc; /* return address is equal to xpc */
- /* this is an ArithmeticException */
-
- type = EXCEPTION_HARDWARE_PATCHER;
+ type = TRAP_PATCHER;
val = 0;
- /* generate appropriate exception */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- /* set registers (only if exception object ready) */
+ /* Set registers. */
if (p != NULL) {
- _mc->gregs[REG_EAX] = (ptrint) p;
- _mc->gregs[REG_ECX] = (ptrint) xpc; /* REG_ITMP2_XPC */
- _mc->gregs[REG_EIP] = (ptrint) asm_handle_exception;
+ _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;
}
}
#endif
-/* md_replace_executionstate_read **********************************************
+/* md_executionstate_read ******************************************************
Read the given context into an executionstate for Replacement.
*******************************************************************************/
-#if defined(ENABLE_REPLACEMENT)
-void md_replace_executionstate_read(executionstate_t *es, void *context)
+void md_executionstate_read(executionstate_t *es, void *context)
{
ucontext_t *_uc;
mcontext_t *_mc;
for (i = 0; i < FLT_REG_CNT; i++)
es->fltregs[i] = 0xdeadbeefdeadbeefULL;
}
-#endif
-/* md_replace_executionstate_write *********************************************
+/* md_executionstate_write *****************************************************
Write the given executionstate back to the context for Replacement.
*******************************************************************************/
-#if defined(ENABLE_REPLACEMENT)
-void md_replace_executionstate_write(executionstate_t *es, void *context)
+void md_executionstate_write(executionstate_t *es, void *context)
{
ucontext_t *_uc;
mcontext_t *_mc;
_mc->gregs[REG_EIP] = (ptrint) es->pc;
_mc->gregs[REG_ESP] = (ptrint) es->sp;
}
-#endif
/* md_critical_section_restart *************************************************
#ifndef _MACHINE_INSTR_H
#define _MACHINE_INSTR_H
-static inline void
-__attribute__ ((unused))
-atomic_add (volatile int *mem, int val)
-{
- __asm__ __volatile__ ("lock; addl %1,%0"
- : "=m" (*mem)
- : "ir" (val), "m" (*mem));
-}
-
-/* compare_and_swap ********************************************************
-
- Atomically do the following: Check if the location still contains
- `oldval`. If so, replace it by `newval` and return `oldval`.
-
- RETURN VALUE:
- the old value at *p
-
-***************************************************************************/
-
static inline long
__attribute__ ((unused))
compare_and_swap (volatile long *p, long oldval, long newval)
}
#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER_AFTER_ATOMIC() /* nothing */
#define MEMORY_BARRIER() __asm__ __volatile__ ( \
"lock; add $0, 0(%%esp)" : : : "memory" );
/* src/vm/jit/i386/md-abi.c - functions for i386 Linux ABI
- 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.
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
/* nothing */
}
--- /dev/null
+/* src/vm/jit/x86_64/md-trap.h - i386 hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (i386) the trap numbers are used as load
+ * displacements and thus must not be 4- or 8-byte aligned.
+ *
+ * NOTE: In trap_init() we have a check whether the offset of
+ * java_arrayheader.data[0] is greater than the largest displacement
+ * defined below. Otherwise normal array loads/stores could trigger
+ * an exception.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 1
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+
+ /* Don't use 4 (could be a normal load offset). */
+
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+
+ /* Don't use 8 (could be a normal load offset). */
+
+ TRAP_COMPILER = 9,
+ TRAP_END
+};
+
+#endif /* _MD_TRAP_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:
+ */
/* src/vm/jit/i386/md.h - machine dependent i386 functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
#include "vm/jit/codegen-common.h"
+#include "vm/jit/methodtree.h"
/* inline functions ***********************************************************/
/* md_codegen_get_pv_from_pc ***************************************************
On this architecture just a wrapper function to
- codegen_get_pv_from_pc.
+ methodtree_find.
*******************************************************************************/
/* Get the start address of the function which contains this
address from the method table. */
- pv = codegen_get_pv_from_pc(ra);
+ pv = methodtree_find(ra);
return pv;
}
/* src/vm/jit/i386/patcher.c - i386 code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
PATCH_BACK_ORIGINAL_MCODE;
/* patch interfacetable index */
*((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr) * m->class->index);
+ sizeof(methodptr) * m->clazz->index);
/* patch method offset */
*((s4 *) (ra + 2 + 6 + 2)) =
- (s4) (sizeof(methodptr) * (m - m->class->methods));
+ (s4) (sizeof(methodptr) * (m - m->clazz->methods));
return true;
}
/* src/vm/jit/inline/inline.c - method inlining
- 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/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
#if !defined(NDEBUG)
#define INLINE_VERBOSE
-#define DOLOG(code) do{ if (opt_inline_debug_log) { code; } }while(0)
+#define DOLOG(code) do{ if (opt_TraceInlining >= 2) { code; } }while(0)
+#define DOLOG_SHORT(code) do{ if (opt_TraceInlining >= 1) { code; } }while(0)
#else
#define DOLOG(code)
#endif
/* call parse pass */
- DOLOG( log_message_class("Parsing ", m->class) );
+ DOLOG( log_message_class("Parsing ", m->clazz) );
if (!parse(jd)) {
return false;
}
}
+#if 0
static void inline_add_blocknr_reference(inline_node *iln, s4 *nrp)
{
inline_target_ref *ref;
ref->next = iln->refs;
iln->refs = ref;
}
+#endif
static void inline_block_translation(inline_node *iln, basicblock *o_bptr, basicblock *n_bptr)
syncvar = inline_new_temp_variable(iln->ctx->resultjd, TYPE_ADR);
n_ins = inline_instruction(iln, ICMD_ACONST, o_iptr);
- n_ins->sx.val.c.cls = callee->m->class;
+ n_ins->sx.val.c.cls = callee->m->clazz;
n_ins->dst.varindex = syncvar;
n_ins->flags.bits |= INS_FLAG_CLASS;
}
n_ins = master->inlined_iinstr_cursor++;
if (iln->m->flags & ACC_STATIC) {
n_ins->opc = ICMD_ACONST;
- n_ins->sx.val.c.cls = iln->m->class;
+ n_ins->sx.val.c.cls = iln->m->clazz;
n_ins->flags.bits = INS_FLAG_CLASS;
}
else {
#endif
#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
- if ( (n_jd->instructioncount >= opt_inline_debug_min_size)
- && (n_jd->instructioncount <= opt_inline_debug_max_size))
+ if ( (n_jd->instructioncount >= opt_InlineMinSize)
+ && (n_jd->instructioncount <= opt_InlineMaxSize))
{
- if (debug_counter <= opt_inline_debug_end_counter)
+ if (debug_counter < opt_InlineCount)
#endif /* defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG) */
{
/* install the inlined result */
#if !defined(NDEBUG)
inline_stat_roots++;
- DOLOG(
+ DOLOG_SHORT(
printf("==== %d.INLINE ==================================================================\n",
debug_counter);
printf("\ninline tree:\n");
+#if 0
static void debug_dump_inline_context(inline_node *iln)
{
assert(iln->indent);
printf("%sinline_context @%p: \n",
iln->indent, (void*)iln->ctx);
}
+#endif
static void dump_inline_tree(inline_node *iln, s4 blocknr)
## src/vm/jit/intrp/Makefile.am
##
-## 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.
##
## 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
-##
-## Changes: Edwin Steiner
-## Process this file with automake to produce Makefile.in
AM_CFLAGS = $(INTRP_CFLAGS)
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR) -I$(top_builddir) -I$(top_builddir)/src
peephole.c
$(BUILT_SOURCES): $(srcdir)/java.vmg $(srcdir)/prims2x.fs $(srcdir)/vmgenx
- $(srcdir)/vmgenx $(srcdir)/java.vmg && touch java-peephole.i
+ $(SHELL) $(srcdir)/vmgenx $(srcdir)/java.vmg && touch java-peephole.i
true #GFORTHPATH=.:/nfs/nfstmp/anton/cacao/:/usr/lib/gforth/site-forth:/usr/share/gforth/site-forth:/usr/lib/gforth/0.6.2:/usr/share/gforth/0.6.2 $(srcdir)/vmgenx $(srcdir)/java.vmg && touch java-peephole.i
/* src/vm/jit/intrp/asmpart.c - Java-C interface functions for Interpreter
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "arch.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#else
-# include "threads/none/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
-#include "vm/jit/intrp/intrp.h"
+#include "vm/jit/methodtree.h"
#include "vm/jit/dseg.h"
+#include "vm/jit/intrp/intrp.h"
+
#include "vmcore/class.h"
#include "vmcore/linker.h"
#include "vmcore/loader.h"
/* for a description of the stack see IRETURN in java.vmg */
for (; fp != NULL; ) {
- u1 *f = codegen_get_pv_from_pc((u1 *) (ip - 1));
+ u1 *f = methodtree_find((u1 *) (ip - 1));
/* get methodinfo pointer from method header */
/* get synchronization object */
if (m->flags & ACC_STATIC) {
- syncobj = (java_objectheader *) m->class;
+ syncobj = (java_objectheader *) m->clazz;
}
else {
syncobj = (java_objectheader *) access_local_cell(-framesize + SIZEOF_VOID_P);
}
-void intrp_asm_getclassvalues_atomic(vftbl_t *super, vftbl_t *sub, castinfo *out)
-{
- s4 sbv, sdv, sv;
-
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
- sbv = super->baseval;
- sdv = super->diffval;
- sv = sub->baseval;
-
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-
- out->super_baseval = sbv;
- out->super_diffval = sdv;
- out->sub_baseval = sv;
-}
-
-
/*
* These are local overrides for various environment variables in Emacs.
* Please do not remove this and leave it at the end of the file, where
/* src/vm/jit/intrp/codegen.c - code generator for Interpreter
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#if defined(ENABLE_THREADS)
if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(cd, (java_objectheader *) m->class);
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
}
else {
gen_ALOAD(cd, 0);
case TYPE_INT:
if (fi == NULL)
gen_PATCHER_GETSTATIC_INT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_INT(cd, 0, fi);
else
gen_GETSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_FLT:
if (fi == NULL)
gen_PATCHER_GETSTATIC_FLOAT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_FLOAT(cd, 0, fi);
else
gen_GETSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_DBL:
if (fi == NULL)
gen_PATCHER_GETSTATIC_LONG(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_LONG(cd, 0, fi);
else
gen_GETSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
case TYPE_ADR:
if (fi == NULL)
gen_PATCHER_GETSTATIC_CELL(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_GETSTATIC_CLINIT_CELL(cd, 0, fi);
else
gen_GETSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
case TYPE_INT:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_INT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_INT(cd, 0, fi);
else
gen_PUTSTATIC_INT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_FLT:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_FLOAT(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_FLOAT(cd, 0, fi);
else
gen_PUTSTATIC_FLOAT(cd, (u1 *) &(fi->value.i), fi);
case TYPE_DBL:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_LONG(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_LONG(cd, 0, fi);
else
gen_PUTSTATIC_LONG(cd, (u1 *) &(fi->value.l), fi);
case TYPE_ADR:
if (fi == NULL)
gen_PATCHER_PUTSTATIC_CELL(cd, 0, uf);
- else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ else if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
gen_PATCHER_PUTSTATIC_CLINIT_CELL(cd, 0, fi);
else
gen_PUTSTATIC_CELL(cd, (u1 *) &(fi->value.a), fi);
#if defined(ENABLE_THREADS)
if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(cd, (java_objectheader *) m->class);
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
} else {
gen_ALOAD(cd, index2offset(m->maxlocals));
}
#if defined(ENABLE_THREADS)
if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(cd, (java_objectheader *) m->class);
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
} else {
gen_ALOAD(cd, index2offset(m->maxlocals));
}
#if defined(ENABLE_THREADS)
if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- gen_ACONST(cd, (java_objectheader *) m->class);
+ gen_ACONST(cd, (java_objectheader *) m->clazz);
} else {
gen_ALOAD(cd, index2offset(m->maxlocals));
}
md = lm->parseddesc;
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
gen_INVOKEINTERFACE(cd, s1, s2, md->paramslots, lm);
}
Inst *s;
Inst *d;
codegendata *cd;
- s4 dumpsize;
s4 stackframesize;
+ int32_t dumpmarker;
s = CNEW(Inst, COMPILERSTUB_SIZE);
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
cd = DNEW(codegendata);
cd->mcodeptr = (u1 *) s;
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
return (u1 *) s;
}
av_ptr(alist, _Jv_JNIEnv *, _Jv_env);
if (m->flags & ACC_STATIC)
- av_ptr(alist, classinfo *, m->class);
+ av_ptr(alist, classinfo *, m->clazz);
for (i = 0, p = sp + md->paramslots; i < md->paramcount; i++) {
switch (md->paramtypes[i].type) {
/* for static methods, pass class pointer */
if (m->flags & ACC_STATIC)
- *pvalues++ = &m->class;
+ *pvalues++ = &m->clazz;
/* pass parameter to native function */
jitdata *jd;
codegendata *cd;
registerdata *rd;
- s4 dumpsize;
methoddesc *md;
+ int32_t dumpmarker;
/* mark dump memory */
- dumpsize = dump_size();
+ DMARKER;
/* allocate memory */
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
return entrypoint;
}
/* src/vm/jit/intrp/disass.c - disassembler wrapper for interpreter
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Reinhard Grafl
-
- Changes: Christian Thalinger
- Anton Ertl
- Edwin Steiner
-
*/
void printarg_afi (fieldinfo * afi )
{
if (afi) {
- utf_fprint_printable_ascii_classname(vm_out, afi->class->name);
+ utf_fprint_printable_ascii_classname(vm_out, afi->clazz->name);
fprintf(vm_out, ".");
utf_fprint_printable_ascii(vm_out, afi->name);
utf_fprint_printable_ascii(vm_out, afi->descriptor);
void printarg_am (methodinfo * am )
{
if (am) {
- utf_fprint_printable_ascii_classname(vm_out, am->class->name);
+ utf_fprint_printable_ascii_classname(vm_out, am->clazz->name);
fprintf(vm_out, ".");
utf_fprint_printable_ascii(vm_out, am->name);
utf_fprint_printable_ascii(vm_out, am->descriptor);
#include "mm/memory.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#else
-# include "threads/none/lock.h"
-#endif
+#include "threads/lock-common.h"
#include "toolbox/hashtable.h"
#include "toolbox/logging.h"
/* src/vm/jit/intrp/engine.c - #included by engine1.c and engine2.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#else
-# include "threads/none/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
# ifndef USE_FAKE_ATOMIC_INSTRUCTIONS
# include "machine-instr.h"
# else
-# include "threads/native/generic-primitives.h"
+# include "threads/posix/generic-primitives.h"
# endif
#endif
/* src/vm/jit/intrp/patcher.c - Interpreter code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
/* patch the field's address */
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
/* patch the field's address */
/* patch interfacetable index */
ip[1] = (OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->class->index);
+ sizeof(methodptr*) * m->clazz->index);
/* patch methodinfo and method offset */
ip[4] = (ptrint) m;
- ip[2] = (sizeof(methodptr) * (m - m->class->methods));
+ ip[2] = (sizeof(methodptr) * (m - m->clazz->methods));
return true;
}
--- /dev/null
+## src/vm/jit/ir/Makefile.am
+##
+## 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.
+
+## 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)
+
+LIBS =
+
+noinst_LTLIBRARIES = \
+ libir.la
+
+libir_la_SOURCES = \
+ bytecode.c \
+ bytecode.h
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+/* src/vm/jit/ir/bytecode.c - Java byte code handling
+
+ 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 "vm/jit/ir/bytecode.h"
+
+
+/* bytecodes ******************************************************************/
+
+bytecode_t bytecode[256] = {
+ { 1, 0, "nop" },
+ { 1, 1, "aconst_null" },
+ { 1, 1, "iconst_m1" },
+ { 1, 1, "iconst" },
+ { 1, 1, "iconst_1" },
+ { 1, 1, "iconst_2" },
+ { 1, 1, "iconst_3" },
+ { 1, 1, "iconst_4" },
+ { 1, 1, "iconst_5" },
+ { 1, 1, "lconst_0" },
+ { 1, 1, "lconst_1" },
+ { 1, 1, "fconst_0" },
+ { 1, 1, "fconst_1" },
+ { 1, 1, "fconst_2" },
+ { 1, 1, "dconst_0" },
+ { 1, 1, "dconst_1" },
+ { 2, 1, "bipush" },
+ { 3, 1, "sipush" },
+ { 2, 1, "ldc" },
+ { 3, 1, "ldc_w" },
+ { 3, 1, "ldc2_w" },
+ { 2, 1, "iload" },
+ { 2, 1, "lload" },
+ { 2, 1, "fload" },
+ { 2, 1, "dload" },
+ { 2, 1, "aload" },
+ { 1, 1, "iload_0" },
+ { 1, 1, "iload_1" },
+ { 1, 1, "iload_2" },
+ { 1, 1, "iload_3" },
+ { 1, 1, "lload_0" },
+ { 1, 1, "lload_1" },
+ { 1, 1, "lload_2" },
+ { 1, 1, "lload_3" },
+ { 1, 1, "fload_0" },
+ { 1, 1, "fload_1" },
+ { 1, 1, "fload_2" },
+ { 1, 1, "fload_3" },
+ { 1, 1, "dload_0" },
+ { 1, 1, "dload_1" },
+ { 1, 1, "dload_2" },
+ { 1, 1, "dload_3" },
+ { 1, 1, "aload_0" },
+ { 1, 1, "aload_1" },
+ { 1, 1, "aload_2" },
+ { 1, 1, "aload_3" },
+ { 1, 1, "iaload" },
+ { 1, 1, "laload" },
+ { 1, 1, "faload" },
+ { 1, 1, "daload" },
+ { 1, 1, "aaload" },
+ { 1, 1, "baload" },
+ { 1, 1, "caload" },
+ { 1, 1, "saload" },
+ { 2, 0, "istore" },
+ { 2, 0, "lstore" },
+ { 2, 0, "fstore" },
+ { 2, 0, "dstore" },
+ { 2, 0, "astore" },
+ { 1, 0, "istore_0" },
+ { 1, 0, "istore_1" },
+ { 1, 0, "istore_2" },
+ { 1, 0, "istore_3" },
+ { 1, 0, "lstore_0" },
+ { 1, 0, "lstore_1" },
+ { 1, 0, "lstore_2" },
+ { 1, 0, "lstore_3" },
+ { 1, 0, "fstore_0" },
+ { 1, 0, "fstore_1" },
+ { 1, 0, "fstore_2" },
+ { 1, 0, "fstore_3" },
+ { 1, 0, "dstore_0" },
+ { 1, 0, "dstore_1" },
+ { 1, 0, "dstore_2" },
+ { 1, 0, "dstore_3" },
+ { 1, 0, "astore_0" },
+ { 1, 0, "astore_1" },
+ { 1, 0, "astore_2" },
+ { 1, 0, "astore_3" },
+ { 1, 0, "iastore" },
+ { 1, 0, "lastore" },
+ { 1, 0, "fastore" },
+ { 1, 0, "dastore" },
+ { 1, 0, "aastore" },
+ { 1, 0, "bastore" },
+ { 1, 0, "castore" },
+ { 1, 0, "sastore" },
+ { 1, 0, "pop" },
+ { 1, 0, "pop2" },
+ { 1, 1, "dup" },
+ { 1, 1+3, "dup_x1" },
+ { 1, 2+4, "dup_x2" },
+ { 1, 2, "dup2" },
+ { 1, 2+5, "dup2_x1" },
+ { 1, 3+6, "dup2_x2" },
+ { 1, 1+2, "swap" },
+ { 1, 1, "iadd" },
+ { 1, 1, "ladd" },
+ { 1, 1, "fadd" },
+ { 1, 1, "dadd" },
+ { 1, 1, "isub" },
+ { 1, 1, "lsub" },
+ { 1, 1, "fsub" },
+ { 1, 1, "dsub" },
+ { 1, 1, "imul" },
+ { 1, 1, "lmul" },
+ { 1, 1, "fmul" },
+ { 1, 1, "dmul" },
+ { 1, 1, "idiv" },
+ { 1, 1, "ldiv" },
+ { 1, 1, "fdiv" },
+ { 1, 1, "ddiv" },
+ { 1, 1, "irem" },
+ { 1, 1, "lrem" },
+ { 1, 1, "frem" },
+ { 1, 1, "drem" },
+ { 1, 1, "ineg" },
+ { 1, 1, "lneg" },
+ { 1, 1, "fneg" },
+ { 1, 1, "dneg" },
+ { 1, 1, "ishl" },
+ { 1, 1, "lshl" },
+ { 1, 1, "ishr" },
+ { 1, 1, "lshr" },
+ { 1, 1, "iushr" },
+ { 1, 1, "lushr" },
+ { 1, 1, "iand" },
+ { 1, 1, "land" },
+ { 1, 1, "ior" },
+ { 1, 1, "lor" },
+ { 1, 1, "ixor" },
+ { 1, 1, "lxor" },
+ { 3, 0, "iinc" },
+ { 1, 1, "i2l" },
+ { 1, 1, "i2f" },
+ { 1, 1, "i2d" },
+ { 1, 1, "l2i" },
+ { 1, 1, "l2f" },
+ { 1, 1, "l2d" },
+ { 1, 1, "f2i" },
+ { 1, 1, "f2l" },
+ { 1, 1, "f2d" },
+ { 1, 1, "d2i" },
+ { 1, 1, "d2l" },
+ { 1, 1, "d2f" },
+ { 1, 1, "int2byte" },
+ { 1, 1, "int2char" },
+ { 1, 1, "int2short" },
+ { 1, 1, "lcmp" },
+ { 1, 1, "fcmpl" },
+ { 1, 1, "fcmpg" },
+ { 1, 1, "dcmpl" },
+ { 1, 1, "dcmpg" },
+ { 3, 0, "ifeq" },
+ { 3, 0, "ifne" },
+ { 3, 0, "iflt" },
+ { 3, 0, "ifge" },
+ { 3, 0, "ifgt" },
+ { 3, 0, "ifle" },
+ { 3, 0, "if_icmpe" },
+ { 3, 0, "if_icmpne" },
+ { 3, 0, "if_icmplt" },
+ { 3, 0, "if_icmpge" },
+ { 3, 0, "if_icmpgt" },
+ { 3, 0, "if_icmple" },
+ { 3, 0, "if_acmpeq" },
+ { 3, 0, "if_acmpne" },
+ { 3, 0, "goto" },
+ { 3, 1, "jsr" },
+ { 2, 0, "ret" },
+ { 0, 0, "tableswitch" },
+ { 0, 0, "lookupswitch" },
+ { 1, 0, "ireturn" },
+ { 1, 0, "lreturn" },
+ { 1, 0, "freturn" },
+ { 1, 0, "dreturn" },
+ { 1, 0, "areturn" },
+ { 1, 0, "return" },
+ { 3, 1, "getstatic" },
+ { 3, 0, "putstatic" },
+ { 3, 1, "getfield" },
+ { 3, 0, "putfield" },
+ { 3, 1, "invokevirtual" },
+ { 3, 1, "invokespecial" },
+ { 3, 1, "invokestatic" },
+ { 5, 1, "invokeinterface" },
+ { 1, 1, "undef186" }, /* XXX */
+ { 3, 1, "new" },
+ { 2, 1, "newarray" },
+ { 3, 1, "anewarray" },
+ { 1, 1, "arraylength" },
+ { 1, 1, "athrow" },
+ { 3, 1, "checkcast" },
+ { 3, 1, "instanceof" },
+ { 1, 0, "monitorenter" },
+ { 1, 0, "monitorexit" },
+ { 0, 0, "wide" },
+ { 4, 1, "multianewarray" },
+ { 3, 0, "ifnull" },
+ { 3, 0, "ifnonnull" },
+ { 5, 0, "goto_w" },
+ { 5, 1, "jsr_w" },
+ { 1, 0, "breakpoint" },
+};
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically 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/bytecode.h - Java byte code definitions
+
+ 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_JIT_IR_BYTECODE_H
+#define _VM_JIT_IR_BYTECODE_H
+
+#include "config.h"
+
+
+/* bytecode_t *****************************************************************/
+
+typedef struct bytecode_t bytecode_t;
+
+struct bytecode_t {
+ int length; /* length of the instruction in bytes */
+ int slots; /* required stack slots */
+ char *mnemonic;
+};
+
+extern bytecode_t bytecode[256];
+
+
+/* Java bytecodes *************************************************************/
+
+enum {
+ BC_nop = 0,
+
+ BC_aconst_null = 1,
+
+ BC_iconst_m1 = 2,
+ BC_iconst_0 = 3,
+ BC_iconst_1 = 4,
+ BC_iconst_2 = 5,
+ BC_iconst_3 = 6,
+ BC_iconst_4 = 7,
+ BC_iconst_5 = 8,
+
+ BC_lconst_0 = 9,
+ BC_lconst_1 = 10,
+
+ BC_fconst_0 = 11,
+ BC_fconst_1 = 12,
+ BC_fconst_2 = 13,
+
+ BC_dconst_0 = 14,
+ BC_dconst_1 = 15,
+
+ BC_bipush = 16,
+ BC_sipush = 17,
+
+ BC_ldc1 = 18,
+ BC_ldc2 = 19,
+ BC_ldc2w = 20,
+
+ BC_iload = 21,
+ BC_lload = 22,
+ BC_fload = 23,
+ BC_dload = 24,
+ BC_aload = 25,
+
+ BC_iload_0 = 26,
+ BC_iload_1 = 27,
+ BC_iload_2 = 28,
+ BC_iload_3 = 29,
+
+ BC_lload_0 = 30,
+ BC_lload_1 = 31,
+ BC_lload_2 = 32,
+ BC_lload_3 = 33,
+
+ BC_fload_0 = 34,
+ BC_fload_1 = 35,
+ BC_fload_2 = 36,
+ BC_fload_3 = 37,
+
+ BC_dload_0 = 38,
+ BC_dload_1 = 39,
+ BC_dload_2 = 40,
+ BC_dload_3 = 41,
+
+ BC_aload_0 = 42,
+ BC_aload_1 = 43,
+ BC_aload_2 = 44,
+ BC_aload_3 = 45,
+
+ BC_iaload = 46,
+ BC_laload = 47,
+ BC_faload = 48,
+ BC_daload = 49,
+ BC_aaload = 50,
+ BC_baload = 51,
+ BC_caload = 52,
+ BC_saload = 53,
+
+ BC_istore = 54,
+ BC_lstore = 55,
+ BC_fstore = 56,
+ BC_dstore = 57,
+ BC_astore = 58,
+
+ BC_istore_0 = 59,
+ BC_istore_1 = 60,
+ BC_istore_2 = 61,
+ BC_istore_3 = 62,
+
+ BC_lstore_0 = 63,
+ BC_lstore_1 = 64,
+ BC_lstore_2 = 65,
+ BC_lstore_3 = 66,
+
+ BC_fstore_0 = 67,
+ BC_fstore_1 = 68,
+ BC_fstore_2 = 69,
+ BC_fstore_3 = 70,
+
+ BC_dstore_0 = 71,
+ BC_dstore_1 = 72,
+ BC_dstore_2 = 73,
+ BC_dstore_3 = 74,
+
+ BC_astore_0 = 75,
+ BC_astore_1 = 76,
+ BC_astore_2 = 77,
+ BC_astore_3 = 78,
+
+ BC_iastore = 79,
+ BC_lastore = 80,
+ BC_fastore = 81,
+ BC_dastore = 82,
+ BC_aastore = 83,
+ BC_bastore = 84,
+ BC_castore = 85,
+ BC_sastore = 86,
+
+ BC_pop = 87,
+ BC_pop2 = 88,
+ BC_dup = 89,
+ BC_dup_x1 = 90,
+ BC_dup_x2 = 91,
+ BC_dup2 = 92,
+ BC_dup2_x1 = 93,
+ BC_dup2_x2 = 94,
+ BC_swap = 95,
+
+ BC_iadd = 96,
+ BC_ladd = 97,
+ BC_fadd = 98,
+ BC_dadd = 99,
+
+ BC_isub = 100,
+ BC_lsub = 101,
+ BC_fsub = 102,
+ BC_dsub = 103,
+
+ BC_imul = 104,
+ BC_lmul = 105,
+ BC_fmul = 106,
+ BC_dmul = 107,
+
+ BC_idiv = 108,
+ BC_ldiv = 109,
+ BC_fdiv = 110,
+ BC_ddiv = 111,
+
+ BC_irem = 112,
+ BC_lrem = 113,
+ BC_frem = 114,
+ BC_drem = 115,
+
+ BC_ineg = 116,
+ BC_lneg = 117,
+ BC_fneg = 118,
+ BC_dneg = 119,
+
+ BC_ishl = 120,
+ BC_lshl = 121,
+ BC_ishr = 122,
+ BC_lshr = 123,
+ BC_iushr = 124,
+ BC_lushr = 125,
+
+ BC_iand = 126,
+ BC_land = 127,
+ BC_ior = 128,
+ BC_lor = 129,
+ BC_ixor = 130,
+ BC_lxor = 131,
+
+ BC_iinc = 132,
+
+ BC_i2l = 133,
+ BC_i2f = 134,
+ BC_i2d = 135,
+ BC_l2i = 136,
+ BC_l2f = 137,
+ BC_l2d = 138,
+ BC_f2i = 139,
+ BC_f2l = 140,
+ BC_f2d = 141,
+ BC_d2i = 142,
+ BC_d2l = 143,
+ BC_d2f = 144,
+
+ BC_int2byte = 145,
+ BC_int2char = 146,
+ BC_int2short = 147,
+
+ BC_lcmp = 148,
+ BC_fcmpl = 149,
+ BC_fcmpg = 150,
+ BC_dcmpl = 151,
+ BC_dcmpg = 152,
+
+ BC_ifeq = 153,
+ BC_ifne = 154,
+ BC_iflt = 155,
+ BC_ifge = 156,
+ BC_ifgt = 157,
+ BC_ifle = 158,
+
+ BC_if_icmpeq = 159,
+ BC_if_icmpne = 160,
+ BC_if_icmplt = 161,
+ BC_if_icmpge = 162,
+ BC_if_icmpgt = 163,
+ BC_if_icmple = 164,
+ BC_if_acmpeq = 165,
+ BC_if_acmpne = 166,
+
+ BC_goto = 167,
+ BC_jsr = 168,
+ BC_ret = 169,
+
+ BC_tableswitch = 170,
+ BC_lookupswitch = 171,
+
+ BC_ireturn = 172,
+ BC_lreturn = 173,
+ BC_freturn = 174,
+ BC_dreturn = 175,
+ BC_areturn = 176,
+ BC_return = 177,
+
+ BC_getstatic = 178,
+ BC_putstatic = 179,
+ BC_getfield = 180,
+ BC_putfield = 181,
+
+ BC_invokevirtual = 182,
+ BC_invokespecial = 183,
+ BC_invokestatic = 184,
+ BC_invokeinterface = 185,
+
+ /* xxxunusedxxx 186 */
+
+ BC_new = 187,
+ BC_newarray = 188,
+ BC_anewarray = 189,
+
+ BC_arraylength = 190,
+
+ BC_athrow = 191,
+
+ BC_checkcast = 192,
+ BC_instanceof = 193,
+
+ BC_monitorenter = 194,
+ BC_monitorexit = 195,
+
+ BC_wide = 196,
+
+ BC_multianewarray = 197,
+
+ BC_ifnull = 198,
+ BC_ifnonnull = 199,
+
+ BC_goto_w = 200,
+ BC_jsr_w = 201,
+
+ /* Reserved opcodes. */
+
+ BC_breakpoint = 202,
+
+ BC_impdep1 = 254,
+ BC_impdep2 = 255
+};
+
+#endif /* _VM_JIT_IR_BYTECODE_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:
+ */
/* src/vm/jit/jit.c - calls the code generation functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "toolbox/logging.h"
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
#include "vm/global.h"
#include "vm/initialize.h"
#include "vm/jit/asmpart.h"
-# include "vm/jit/cfg.h"
+#include "vm/jit/cfg.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/disass.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"
# 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"
#include "vm/jit/optimizing/reorder.h"
+#if defined(ENABLE_PYTHON)
+# include "vm/jit/python.h"
+#endif
+
#include "vm/jit/verify/typecheck.h"
#include "vmcore/class.h"
#define PEI 1
-/* stackelement requirements of Java opcodes **********************************/
-
-int stackreq[256] = {
- 0, /* JAVA_NOP 0 */
- 1, /* JAVA_ACONST 1 */
- 1, /* JAVA_ICONST_M1 2 */
- 1, /* JAVA_ICONST_0 3 */
- 1, /* JAVA_ICONST_1 4 */
- 1, /* JAVA_ICONST_2 5 */
- 1, /* JAVA_ICONST_3 6 */
- 1, /* JAVA_ICONST_4 7 */
- 1, /* JAVA_ICONST_5 8 */
- 1, /* JAVA_LCONST_0 9 */
- 1, /* JAVA_LCONST_1 10 */
- 1, /* JAVA_FCONST_0 11 */
- 1, /* JAVA_FCONST_1 12 */
- 1, /* JAVA_FCONST_2 13 */
- 1, /* JAVA_DCONST_0 14 */
- 1, /* JAVA_DCONST_1 15 */
- 1, /* JAVA_BIPUSH 16 */
- 1, /* JAVA_SIPUSH 17 */
- 1, /* JAVA_LDC 18 */
- 1, /* JAVA_LDC_W 19 */
- 1, /* JAVA_LDC2_W 20 */
- 1, /* JAVA_ILOAD 21 */
- 1, /* JAVA_LLOAD 22 */
- 1, /* JAVA_FLOAD 23 */
- 1, /* JAVA_DLOAD 24 */
- 1, /* JAVA_ALOAD 25 */
- 1, /* JAVA_ILOAD_0 26 */
- 1, /* JAVA_ILOAD_1 27 */
- 1, /* JAVA_ILOAD_2 28 */
- 1, /* JAVA_ILOAD_3 29 */
- 1, /* JAVA_LLOAD_0 30 */
- 1, /* JAVA_LLOAD_1 31 */
- 1, /* JAVA_LLOAD_2 32 */
- 1, /* JAVA_LLOAD_3 33 */
- 1, /* JAVA_FLOAD_0 34 */
- 1, /* JAVA_FLOAD_1 35 */
- 1, /* JAVA_FLOAD_2 36 */
- 1, /* JAVA_FLOAD_3 37 */
- 1, /* JAVA_DLOAD_0 38 */
- 1, /* JAVA_DLOAD_1 39 */
- 1, /* JAVA_DLOAD_2 40 */
- 1, /* JAVA_DLOAD_3 41 */
- 1, /* JAVA_ALOAD_0 42 */
- 1, /* JAVA_ALOAD_1 43 */
- 1, /* JAVA_ALOAD_2 44 */
- 1, /* JAVA_ALOAD_3 45 */
- 1, /* JAVA_IALOAD 46 */
- 1, /* JAVA_LALOAD 47 */
- 1, /* JAVA_FALOAD 48 */
- 1, /* JAVA_DALOAD 49 */
- 1, /* JAVA_AALOAD 50 */
- 1, /* JAVA_BALOAD 51 */
- 1, /* JAVA_CALOAD 52 */
- 1, /* JAVA_SALOAD 53 */
- 0, /* JAVA_ISTORE 54 */
- 0, /* JAVA_LSTORE 55 */
- 0, /* JAVA_FSTORE 56 */
- 0, /* JAVA_DSTORE 57 */
- 0, /* JAVA_ASTORE 58 */
- 0, /* JAVA_ISTORE_0 59 */
- 0, /* JAVA_ISTORE_1 60 */
- 0, /* JAVA_ISTORE_2 61 */
- 0, /* JAVA_ISTORE_3 62 */
- 0, /* JAVA_LSTORE_0 63 */
- 0, /* JAVA_LSTORE_1 64 */
- 0, /* JAVA_LSTORE_2 65 */
- 0, /* JAVA_LSTORE_3 66 */
- 0, /* JAVA_FSTORE_0 67 */
- 0, /* JAVA_FSTORE_1 68 */
- 0, /* JAVA_FSTORE_2 69 */
- 0, /* JAVA_FSTORE_3 70 */
- 0, /* JAVA_DSTORE_0 71 */
- 0, /* JAVA_DSTORE_1 72 */
- 0, /* JAVA_DSTORE_2 73 */
- 0, /* JAVA_DSTORE_3 74 */
- 0, /* JAVA_ASTORE_0 75 */
- 0, /* JAVA_ASTORE_1 76 */
- 0, /* JAVA_ASTORE_2 77 */
- 0, /* JAVA_ASTORE_3 78 */
- 0, /* JAVA_IASTORE 79 */
- 0, /* JAVA_LASTORE 80 */
- 0, /* JAVA_FASTORE 81 */
- 0, /* JAVA_DASTORE 82 */
- 0, /* JAVA_AASTORE 83 */
- 0, /* JAVA_BASTORE 84 */
- 0, /* JAVA_CASTORE 85 */
- 0, /* JAVA_SASTORE 86 */
- 0, /* JAVA_POP 87 */
- 0, /* JAVA_POP2 88 */
- 1, /* JAVA_DUP 89 */
- 1+3, /* JAVA_DUP_X1 90 */
- 2+4, /* JAVA_DUP_X2 91 */
- 2, /* JAVA_DUP2 92 */
- 2+5, /* JAVA_DUP2_X1 93 */
- 3+6, /* JAVA_DUP2_X2 94 */
- 1+2, /* JAVA_SWAP 95 */
- 1, /* JAVA_IADD 96 */
- 1, /* JAVA_LADD 97 */
- 1, /* JAVA_FADD 98 */
- 1, /* JAVA_DADD 99 */
- 1, /* JAVA_ISUB 100 */
- 1, /* JAVA_LSUB 101 */
- 1, /* JAVA_FSUB 102 */
- 1, /* JAVA_DSUB 103 */
- 1, /* JAVA_IMUL 104 */
- 1, /* JAVA_LMUL 105 */
- 1, /* JAVA_FMUL 106 */
- 1, /* JAVA_DMUL 107 */
- 1, /* JAVA_IDIV 108 */
- 1, /* JAVA_LDIV 109 */
- 1, /* JAVA_FDIV 110 */
- 1, /* JAVA_DDIV 111 */
- 1, /* JAVA_IREM 112 */
- 1, /* JAVA_LREM 113 */
- 1, /* JAVA_FREM 114 */
- 1, /* JAVA_DREM 115 */
- 1, /* JAVA_INEG 116 */
- 1, /* JAVA_LNEG 117 */
- 1, /* JAVA_FNEG 118 */
- 1, /* JAVA_DNEG 119 */
- 1, /* JAVA_ISHL 120 */
- 1, /* JAVA_LSHL 121 */
- 1, /* JAVA_ISHR 122 */
- 1, /* JAVA_LSHR 123 */
- 1, /* JAVA_IUSHR 124 */
- 1, /* JAVA_LUSHR 125 */
- 1, /* JAVA_IAND 126 */
- 1, /* JAVA_LAND 127 */
- 1, /* JAVA_IOR 128 */
- 1, /* JAVA_LOR 129 */
- 1, /* JAVA_IXOR 130 */
- 1, /* JAVA_LXOR 131 */
- 0, /* JAVA_IINC 132 */
- 1, /* JAVA_I2L 133 */
- 1, /* JAVA_I2F 134 */
- 1, /* JAVA_I2D 135 */
- 1, /* JAVA_L2I 136 */
- 1, /* JAVA_L2F 137 */
- 1, /* JAVA_L2D 138 */
- 1, /* JAVA_F2I 139 */
- 1, /* JAVA_F2L 140 */
- 1, /* JAVA_F2D 141 */
- 1, /* JAVA_D2I 142 */
- 1, /* JAVA_D2L 143 */
- 1, /* JAVA_D2F 144 */
- 1, /* JAVA_INT2BYTE 145 */
- 1, /* JAVA_INT2CHAR 146 */
- 1, /* JAVA_INT2SHORT 147 */
- 1, /* JAVA_LCMP 148 */
- 1, /* JAVA_FCMPL 149 */
- 1, /* JAVA_FCMPG 150 */
- 1, /* JAVA_DCMPL 151 */
- 1, /* JAVA_DCMPG 152 */
- 0, /* JAVA_IFEQ 153 */
- 0, /* JAVA_IFNE 154 */
- 0, /* JAVA_IFLT 155 */
- 0, /* JAVA_IFGE 156 */
- 0, /* JAVA_IFGT 157 */
- 0, /* JAVA_IFLE 158 */
- 0, /* JAVA_IF_ICMPEQ 159 */
- 0, /* JAVA_IF_ICMPNE 160 */
- 0, /* JAVA_IF_ICMPLT 161 */
- 0, /* JAVA_IF_ICMPGE 162 */
- 0, /* JAVA_IF_ICMPGT 163 */
- 0, /* JAVA_IF_ICMPLE 164 */
- 0, /* JAVA_IF_ACMPEQ 165 */
- 0, /* JAVA_IF_ACMPNE 166 */
- 0, /* JAVA_GOTO 167 */
- 1, /* JAVA_JSR 168 */
- 0, /* JAVA_RET 169 */
- 0, /* JAVA_TABLESWITCH 170 */
- 0, /* JAVA_LOOKUPSWITCH 171 */
- 0, /* JAVA_IRETURN 172 */
- 0, /* JAVA_LRETURN 173 */
- 0, /* JAVA_FRETURN 174 */
- 0, /* JAVA_DRETURN 175 */
- 0, /* JAVA_ARETURN 176 */
- 0, /* JAVA_RETURN 177 */
- 1, /* JAVA_GETSTATIC 178 */
- 0, /* JAVA_PUTSTATIC 179 */
- 1, /* JAVA_GETFIELD 180 */
- 0, /* JAVA_PUTFIELD 181 */
- 1, /* JAVA_INVOKEVIRTUAL 182 */
- 1, /* JAVA_INVOKESPECIAL 183 */
- 1, /* JAVA_INVOKESTATIC 184 */
- 1, /* JAVA_INVOKEINTERFACE 185 */
- 1, /* JAVA_UNDEF186 186 */
- 1, /* JAVA_NEW 187 */
- 1, /* JAVA_NEWARRAY 188 */
- 1, /* JAVA_ANEWARRAY 189 */
- 1, /* JAVA_ARRAYLENGTH 190 */
- 1, /* JAVA_ATHROW 191 */
- 1, /* JAVA_CHECKCAST 192 */
- 1, /* JAVA_INSTANCEOF 193 */
- 0, /* JAVA_MONITORENTER 194 */
- 0, /* JAVA_MONITOREXIT 195 */
- 0, /* JAVA_WIDE 196 */
- 1, /* JAVA_MULTIANEWARRAY 197 */
- 0, /* JAVA_IFNULL 198 */
- 0, /* JAVA_IFNONNULL 199 */
- 0, /* JAVA_GOTO_W 200 */
- 1, /* JAVA_JSR_W 201 */
- 0, /* JAVA_BREAKPOINT 202 */
- 1, /* JAVA_UNDEF203 203 */
- 1, /* JAVA_UNDEF204 204 */
- 1, /* JAVA_UNDEF205 205 */
- 1, /* JAVA_UNDEF206 206 */
- 1, /* JAVA_UNDEF207 207 */
- 1, /* JAVA_UNDEF208 208 */
- 1, /* JAVA_UNDEF209 209 */
- 1, /* JAVA_UNDEF210 210 */
- 1, /* JAVA_UNDEF211 211 */
- 1, /* JAVA_UNDEF212 212 */
- 1, /* JAVA_UNDEF213 213 */
- 1, /* JAVA_UNDEF214 214 */
- 1, /* JAVA_UNDEF215 215 */
- 1, /* JAVA_UNDEF216 216 */
- 1, /* JAVA_UNDEF217 217 */
- 1, /* JAVA_UNDEF218 218 */
- 1, /* JAVA_UNDEF219 219 */
- 1, /* JAVA_UNDEF220 220 */
- 1, /* JAVA_UNDEF221 221 */
- 1, /* JAVA_UNDEF222 222 */
- 1, /* JAVA_UNDEF223 223 */
- 1, /* JAVA_UNDEF224 224 */
- 1, /* JAVA_UNDEF225 225 */
- 1, /* JAVA_UNDEF226 226 */
- 1, /* JAVA_UNDEF227 227 */
- 1, /* JAVA_UNDEF228 228 */
- 1, /* JAVA_UNDEF229 229 */
- 1, /* JAVA_UNDEF230 230 */
- 1, /* JAVA_UNDEF231 231 */
- 1, /* JAVA_UNDEF232 232 */
- 1, /* JAVA_UNDEF233 233 */
- 1, /* JAVA_UNDEF234 234 */
- 1, /* JAVA_UNDEF235 235 */
- 1, /* JAVA_UNDEF236 236 */
- 1, /* JAVA_UNDEF237 237 */
- 1, /* JAVA_UNDEF238 238 */
- 1, /* JAVA_UNDEF239 239 */
- 1, /* JAVA_UNDEF240 240 */
- 1, /* JAVA_UNDEF241 241 */
- 1, /* JAVA_UNDEF242 242 */
- 1, /* JAVA_UNDEF243 243 */
- 1, /* JAVA_UNDEF244 244 */
- 1, /* JAVA_UNDEF245 245 */
- 1, /* JAVA_UNDEF246 246 */
- 1, /* JAVA_UNDEF247 247 */
- 1, /* JAVA_UNDEF248 248 */
- 1, /* JAVA_UNDEF249 249 */
- 1, /* JAVA_UNDEF250 250 */
- 1, /* JAVA_UNDEF251 251 */
- 1, /* JAVA_UNDEF252 252 */
- 1, /* JAVA_UNDEF253 253 */
- 1, /* JAVA_UNDEF254 254 */
- 1, /* JAVA_UNDEF255 255 */
-};
-
-
-/* size in bytes of Java opcodes **********************************************/
-
-int jcommandsize[256] = {
-
- 1, /* JAVA_NOP 0 */
- 1, /* JAVA_ACONST_NULL 1 */
- 1, /* JAVA_ICONST_M1 2 */
- 1, /* JAVA_ICONST_0 3 */
- 1, /* JAVA_ICONST_1 4 */
- 1, /* JAVA_ICONST_2 5 */
- 1, /* JAVA_ICONST_3 6 */
- 1, /* JAVA_ICONST_4 7 */
- 1, /* JAVA_ICONST_5 8 */
- 1, /* JAVA_LCONST_0 9 */
- 1, /* JAVA_LCONST_1 10 */
- 1, /* JAVA_FCONST_0 11 */
- 1, /* JAVA_FCONST_1 12 */
- 1, /* JAVA_FCONST_2 13 */
- 1, /* JAVA_DCONST_0 14 */
- 1, /* JAVA_DCONST_1 15 */
- 2, /* JAVA_BIPUSH 16 */
- 3, /* JAVA_SIPUSH 17 */
- 2, /* JAVA_LDC1 18 */
- 3, /* JAVA_LDC2 19 */
- 3, /* JAVA_LDC2W 20 */
- 2, /* JAVA_ILOAD 21 */
- 2, /* JAVA_LLOAD 22 */
- 2, /* JAVA_FLOAD 23 */
- 2, /* JAVA_DLOAD 24 */
- 2, /* JAVA_ALOAD 25 */
- 1, /* JAVA_ILOAD_0 26 */
- 1, /* JAVA_ILOAD_1 27 */
- 1, /* JAVA_ILOAD_2 28 */
- 1, /* JAVA_ILOAD_3 29 */
- 1, /* JAVA_LLOAD_0 30 */
- 1, /* JAVA_LLOAD_1 31 */
- 1, /* JAVA_LLOAD_2 32 */
- 1, /* JAVA_LLOAD_3 33 */
- 1, /* JAVA_FLOAD_0 34 */
- 1, /* JAVA_FLOAD_1 35 */
- 1, /* JAVA_FLOAD_2 36 */
- 1, /* JAVA_FLOAD_3 37 */
- 1, /* JAVA_DLOAD_0 38 */
- 1, /* JAVA_DLOAD_1 39 */
- 1, /* JAVA_DLOAD_2 40 */
- 1, /* JAVA_DLOAD_3 41 */
- 1, /* JAVA_ALOAD_0 42 */
- 1, /* JAVA_ALOAD_1 43 */
- 1, /* JAVA_ALOAD_2 44 */
- 1, /* JAVA_ALOAD_3 45 */
- 1, /* JAVA_IALOAD 46 */
- 1, /* JAVA_LALOAD 47 */
- 1, /* JAVA_FALOAD 48 */
- 1, /* JAVA_DALOAD 49 */
- 1, /* JAVA_AALOAD 50 */
- 1, /* JAVA_BALOAD 51 */
- 1, /* JAVA_CALOAD 52 */
- 1, /* JAVA_SALOAD 53 */
- 2, /* JAVA_ISTORE 54 */
- 2, /* JAVA_LSTORE 55 */
- 2, /* JAVA_FSTORE 56 */
- 2, /* JAVA_DSTORE 57 */
- 2, /* JAVA_ASTORE 58 */
- 1, /* JAVA_ISTORE_0 59 */
- 1, /* JAVA_ISTORE_1 60 */
- 1, /* JAVA_ISTORE_2 61 */
- 1, /* JAVA_ISTORE_3 62 */
- 1, /* JAVA_LSTORE_0 63 */
- 1, /* JAVA_LSTORE_1 64 */
- 1, /* JAVA_LSTORE_2 65 */
- 1, /* JAVA_LSTORE_3 66 */
- 1, /* JAVA_FSTORE_0 67 */
- 1, /* JAVA_FSTORE_1 68 */
- 1, /* JAVA_FSTORE_2 69 */
- 1, /* JAVA_FSTORE_3 70 */
- 1, /* JAVA_DSTORE_0 71 */
- 1, /* JAVA_DSTORE_1 72 */
- 1, /* JAVA_DSTORE_2 73 */
- 1, /* JAVA_DSTORE_3 74 */
- 1, /* JAVA_ASTORE_0 75 */
- 1, /* JAVA_ASTORE_1 76 */
- 1, /* JAVA_ASTORE_2 77 */
- 1, /* JAVA_ASTORE_3 78 */
- 1, /* JAVA_IASTORE 79 */
- 1, /* JAVA_LASTORE 80 */
- 1, /* JAVA_FASTORE 81 */
- 1, /* JAVA_DASTORE 82 */
- 1, /* JAVA_AASTORE 83 */
- 1, /* JAVA_BASTORE 84 */
- 1, /* JAVA_CASTORE 85 */
- 1, /* JAVA_SASTORE 86 */
- 1, /* JAVA_POP 87 */
- 1, /* JAVA_POP2 88 */
- 1, /* JAVA_DUP 89 */
- 1, /* JAVA_DUP_X1 90 */
- 1, /* JAVA_DUP_X2 91 */
- 1, /* JAVA_DUP2 92 */
- 1, /* JAVA_DUP2_X1 93 */
- 1, /* JAVA_DUP2_X2 94 */
- 1, /* JAVA_SWAP 95 */
- 1, /* JAVA_IADD 96 */
- 1, /* JAVA_LADD 97 */
- 1, /* JAVA_FADD 98 */
- 1, /* JAVA_DADD 99 */
- 1, /* JAVA_ISUB 100 */
- 1, /* JAVA_LSUB 101 */
- 1, /* JAVA_FSUB 102 */
- 1, /* JAVA_DSUB 103 */
- 1, /* JAVA_IMUL 104 */
- 1, /* JAVA_LMUL 105 */
- 1, /* JAVA_FMUL 106 */
- 1, /* JAVA_DMUL 107 */
- 1, /* JAVA_IDIV 108 */
- 1, /* JAVA_LDIV 109 */
- 1, /* JAVA_FDIV 110 */
- 1, /* JAVA_DDIV 111 */
- 1, /* JAVA_IREM 112 */
- 1, /* JAVA_LREM 113 */
- 1, /* JAVA_FREM 114 */
- 1, /* JAVA_DREM 115 */
- 1, /* JAVA_INEG 116 */
- 1, /* JAVA_LNEG 117 */
- 1, /* JAVA_FNEG 118 */
- 1, /* JAVA_DNEG 119 */
- 1, /* JAVA_ISHL 120 */
- 1, /* JAVA_LSHL 121 */
- 1, /* JAVA_ISHR 122 */
- 1, /* JAVA_LSHR 123 */
- 1, /* JAVA_IUSHR 124 */
- 1, /* JAVA_LUSHR 125 */
- 1, /* JAVA_IAND 126 */
- 1, /* JAVA_LAND 127 */
- 1, /* JAVA_IOR 128 */
- 1, /* JAVA_LOR 129 */
- 1, /* JAVA_IXOR 130 */
- 1, /* JAVA_LXOR 131 */
- 3, /* JAVA_IINC 132 */
- 1, /* JAVA_I2L 133 */
- 1, /* JAVA_I2F 134 */
- 1, /* JAVA_I2D 135 */
- 1, /* JAVA_L2I 136 */
- 1, /* JAVA_L2F 137 */
- 1, /* JAVA_L2D 138 */
- 1, /* JAVA_F2I 139 */
- 1, /* JAVA_F2L 140 */
- 1, /* JAVA_F2D 141 */
- 1, /* JAVA_D2I 142 */
- 1, /* JAVA_D2L 143 */
- 1, /* JAVA_D2F 144 */
- 1, /* JAVA_INT2BYTE 145 */
- 1, /* JAVA_INT2CHAR 146 */
- 1, /* JAVA_INT2SHORT 147 */
- 1, /* JAVA_LCMP 148 */
- 1, /* JAVA_FCMPL 149 */
- 1, /* JAVA_FCMPG 150 */
- 1, /* JAVA_DCMPL 151 */
- 1, /* JAVA_DCMPG 152 */
- 3, /* JAVA_IFEQ 153 */
- 3, /* JAVA_IFNE 154 */
- 3, /* JAVA_IFLT 155 */
- 3, /* JAVA_IFGE 156 */
- 3, /* JAVA_IFGT 157 */
- 3, /* JAVA_IFLE 158 */
- 3, /* JAVA_IF_ICMPEQ 159 */
- 3, /* JAVA_IF_ICMPNE 160 */
- 3, /* JAVA_IF_ICMPLT 161 */
- 3, /* JAVA_IF_ICMPGE 162 */
- 3, /* JAVA_IF_ICMPGT 163 */
- 3, /* JAVA_IF_ICMPLE 164 */
- 3, /* JAVA_IF_ACMPEQ 165 */
- 3, /* JAVA_IF_ACMPNE 166 */
- 3, /* JAVA_GOTO 167 */
- 3, /* JAVA_JSR 168 */
- 2, /* JAVA_RET 169 */
- 0, /* JAVA_TABLESWITCH 170 */ /* variable length */
- 0, /* JAVA_LOOKUPSWITCH 171 */ /* variable length */
- 1, /* JAVA_IRETURN 172 */
- 1, /* JAVA_LRETURN 173 */
- 1, /* JAVA_FRETURN 174 */
- 1, /* JAVA_DRETURN 175 */
- 1, /* JAVA_ARETURN 176 */
- 1, /* JAVA_RETURN 177 */
- 3, /* JAVA_GETSTATIC 178 */
- 3, /* JAVA_PUTSTATIC 179 */
- 3, /* JAVA_GETFIELD 180 */
- 3, /* JAVA_PUTFIELD 181 */
- 3, /* JAVA_INVOKEVIRTUAL 182 */
- 3, /* JAVA_INVOKESPECIAL 183 */
- 3, /* JAVA_INVOKESTATIC 184 */
- 5, /* JAVA_INVOKEINTERFACE 185 */
- 1, /* UNDEF186 */
- 3, /* JAVA_NEW 187 */
- 2, /* JAVA_NEWARRAY 188 */
- 3, /* JAVA_ANEWARRAY 189 */
- 1, /* JAVA_ARRAYLENGTH 190 */
- 1, /* JAVA_ATHROW 191 */
- 3, /* JAVA_CHECKCAST 192 */
- 3, /* JAVA_INSTANCEOF 193 */
- 1, /* JAVA_MONITORENTER 194 */
- 1, /* JAVA_MONITOREXIT 195 */
- 0, /* JAVA_WIDE 196 */ /* variable length */
- 4, /* JAVA_MULTIANEWARRAY 197 */
- 3, /* JAVA_IFNULL 198 */
- 3, /* JAVA_IFNONNULL 199 */
- 5, /* JAVA_GOTO_W 200 */
- 5, /* JAVA_JSR_W 201 */
- 1, /* JAVA_BREAKPOINT 202 */
-
- 1, /* UNDEF203 */
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1, /* UNDEF210 */
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1, /* UNDEF220 */
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1, /* UNDEF230 */
- 1,
- 1,
- 1,
- 1,
-
- /* unused */
- 1,1,1,1,1,1,
- 1,1,1,1,1,1,1,1,1,1,
- 1,1,1,1,1
-};
-
-
-/* Java opcode names *********************************************************/
-
-char *opcode_names[256] = {
- "NOP ", /* 0 */
- "ACONST ", /* 1 */
- "ICONST_M1 ", /* ICONST_M1 2 */
- "ICONST_0 ", /* ICONST_0 3 */
- "ICONST_1 ", /* ICONST_1 4 */
- "ICONST_2 ", /* ICONST_2 5 */
- "ICONST_3 ", /* ICONST_3 6 */
- "ICONST_4 ", /* ICONST_4 7 */
- "ICONST_5 ", /* ICONST_5 8 */
- "LCONST_0 ", /* LCONST_0 9 */
- "LCONST_1 ", /* LCONST_1 10 */
- "FCONST_0 ", /* FCONST_0 11 */
- "FCONST_1 ", /* FCONST_1 12 */
- "FCONST_2 ", /* FCONST_2 13 */
- "DCONST_0 ", /* DCONST_0 14 */
- "DCONST_1 ", /* DCONST_1 15 */
- "BIPUSH ", /* BIPUSH 16 */
- "SIPUSH ", /* SIPUSH 17 */
- "LDC ", /* LDC 18 */
- "LDC_W ", /* LDC_W 19 */
- "LDC2_W ", /* LDC2_W 20 */
- "ILOAD ", /* 21 */
- "LLOAD ", /* 22 */
- "FLOAD ", /* 23 */
- "DLOAD ", /* 24 */
- "ALOAD ", /* 25 */
- "ILOAD_0 ", /* ILOAD_0 26 */
- "ILOAD_1 ", /* ILOAD_1 27 */
- "ILOAD_2 ", /* ILOAD_2 28 */
- "ILOAD_3 ", /* ILOAD_3 29 */
- "LLOAD_0 ", /* LLOAD_0 30 */
- "LLOAD_1 ", /* LLOAD_1 31 */
- "LLOAD_2 ", /* LLOAD_2 32 */
- "LLOAD_3 ", /* LLOAD_3 33 */
- "FLOAD_0 ", /* FLOAD_0 34 */
- "FLOAD_1 ", /* FLOAD_1 35 */
- "FLOAD_2 ", /* FLOAD_2 36 */
- "FLOAD_3 ", /* FLOAD_3 37 */
- "DLOAD_0 ", /* DLOAD_0 38 */
- "DLOAD_1 ", /* DLOAD_1 39 */
- "DLOAD_2 ", /* DLOAD_2 40 */
- "DLOAD_3 ", /* DLOAD_3 41 */
- "ALOAD_0 ", /* ALOAD_0 42 */
- "ALOAD_1 ", /* ALOAD_1 43 */
- "ALOAD_2 ", /* ALOAD_2 44 */
- "ALOAD_3 ", /* ALOAD_3 45 */
- "IALOAD ", /* 46 */
- "LALOAD ", /* 47 */
- "FALOAD ", /* 48 */
- "DALOAD ", /* 49 */
- "AALOAD ", /* 50 */
- "BALOAD ", /* 51 */
- "CALOAD ", /* 52 */
- "SALOAD ", /* 53 */
- "ISTORE ", /* 54 */
- "LSTORE ", /* 55 */
- "FSTORE ", /* 56 */
- "DSTORE ", /* 57 */
- "ASTORE ", /* 58 */
- "ISTORE_0 ", /* ISTORE_0 59 */
- "ISTORE_1 ", /* ISTORE_1 60 */
- "ISTORE_2 ", /* ISTORE_2 61 */
- "ISTORE_3 ", /* ISTORE_3 62 */
- "LSTORE_0 ", /* LSTORE_0 63 */
- "LSTORE_1 ", /* LSTORE_1 64 */
- "LSTORE_2 ", /* LSTORE_2 65 */
- "LSTORE_3 ", /* LSTORE_3 66 */
- "FSTORE_0 ", /* FSTORE_0 67 */
- "FSTORE_1 ", /* FSTORE_1 68 */
- "FSTORE_2 ", /* FSTORE_2 69 */
- "FSTORE_3 ", /* FSTORE_3 70 */
- "DSTORE_0 ", /* DSTORE_0 71 */
- "DSTORE_1 ", /* DSTORE_1 72 */
- "DSTORE_2 ", /* DSTORE_2 73 */
- "DSTORE_3 ", /* DSTORE_3 74 */
- "ASTORE_0 ", /* ASTORE_0 75 */
- "ASTORE_1 ", /* ASTORE_1 76 */
- "ASTORE_2 ", /* ASTORE_2 77 */
- "ASTORE_3 ", /* ASTORE_3 78 */
- "IASTORE ", /* 79 */
- "LASTORE ", /* 80 */
- "FASTORE ", /* 81 */
- "DASTORE ", /* 82 */
- "AASTORE ", /* 83 */
- "BASTORE ", /* 84 */
- "CASTORE ", /* 85 */
- "SASTORE ", /* 86 */
- "POP ", /* 87 */
- "POP2 ", /* 88 */
- "DUP ", /* 89 */
- "DUP_X1 ", /* 90 */
- "DUP_X2 ", /* 91 */
- "DUP2 ", /* 92 */
- "DUP2_X1 ", /* 93 */
- "DUP2_X2 ", /* 94 */
- "SWAP ", /* 95 */
- "IADD ", /* 96 */
- "LADD ", /* 97 */
- "FADD ", /* 98 */
- "DADD ", /* 99 */
- "ISUB ", /* 100 */
- "LSUB ", /* 101 */
- "FSUB ", /* 102 */
- "DSUB ", /* 103 */
- "IMUL ", /* 104 */
- "LMUL ", /* 105 */
- "FMUL ", /* 106 */
- "DMUL ", /* 107 */
- "IDIV ", /* 108 */
- "LDIV ", /* 109 */
- "FDIV ", /* 110 */
- "DDIV ", /* 111 */
- "IREM ", /* 112 */
- "LREM ", /* 113 */
- "FREM ", /* 114 */
- "DREM ", /* 115 */
- "INEG ", /* 116 */
- "LNEG ", /* 117 */
- "FNEG ", /* 118 */
- "DNEG ", /* 119 */
- "ISHL ", /* 120 */
- "LSHL ", /* 121 */
- "ISHR ", /* 122 */
- "LSHR ", /* 123 */
- "IUSHR ", /* 124 */
- "LUSHR ", /* 125 */
- "IAND ", /* 126 */
- "LAND ", /* 127 */
- "IOR ", /* 128 */
- "LOR ", /* 129 */
- "IXOR ", /* 130 */
- "LXOR ", /* 131 */
- "IINC ", /* 132 */
- "I2L ", /* 133 */
- "I2F ", /* 134 */
- "I2D ", /* 135 */
- "L2I ", /* 136 */
- "L2F ", /* 137 */
- "L2D ", /* 138 */
- "F2I ", /* 139 */
- "F2L ", /* 140 */
- "F2D ", /* 141 */
- "D2I ", /* 142 */
- "D2L ", /* 143 */
- "D2F ", /* 144 */
- "INT2BYTE ", /* 145 */
- "INT2CHAR ", /* 146 */
- "INT2SHORT ", /* 147 */
- "LCMP ", /* 148 */
- "FCMPL ", /* 149 */
- "FCMPG ", /* 150 */
- "DCMPL ", /* 151 */
- "DCMPG ", /* 152 */
- "IFEQ ", /* 153 */
- "IFNE ", /* 154 */
- "IFLT ", /* 155 */
- "IFGE ", /* 156 */
- "IFGT ", /* 157 */
- "IFLE ", /* 158 */
- "IF_ICMPEQ ", /* 159 */
- "IF_ICMPNE ", /* 160 */
- "IF_ICMPLT ", /* 161 */
- "IF_ICMPGE ", /* 162 */
- "IF_ICMPGT ", /* 163 */
- "IF_ICMPLE ", /* 164 */
- "IF_ACMPEQ ", /* 165 */
- "IF_ACMPNE ", /* 166 */
- "GOTO ", /* 167 */
- "JSR ", /* 168 */
- "RET ", /* 169 */
- "TABLESWITCH ", /* 170 */
- "LOOKUPSWITCH ", /* 171 */
- "IRETURN ", /* 172 */
- "LRETURN ", /* 173 */
- "FRETURN ", /* 174 */
- "DRETURN ", /* 175 */
- "ARETURN ", /* 176 */
- "RETURN ", /* 177 */
- "GETSTATIC ", /* 178 */
- "PUTSTATIC ", /* 179 */
- "GETFIELD ", /* 180 */
- "PUTFIELD ", /* 181 */
- "INVOKEVIRTUAL ", /* 182 */
- "INVOKESPECIAL ", /* 183 */
- "INVOKESTATIC ", /* 184 */
- "INVOKEINTERFACE", /* 185 */
- "UNDEF186 ", /* 186 */
- "NEW ", /* 187 */
- "NEWARRAY ", /* 188 */
- "ANEWARRAY ", /* 189 */
- "ARRAYLENGTH ", /* 190 */
- "ATHROW ", /* 191 */
- "CHECKCAST ", /* 192 */
- "INSTANCEOF ", /* 193 */
- "MONITORENTER ", /* 194 */
- "MONITOREXIT ", /* 195 */
- "WIDE ", /* WIDE 196 */
- "MULTIANEWARRAY ", /* 197 */
- "IFNULL ", /* 198 */
- "IFNONNULL ", /* 199 */
- "GOTO_W ", /* GOTO_W 200 */
- "JSR_W ", /* JSR_W 201 */
- "BREAKPOINT ", /* BREAKPOINT 202 */
-
- "UNDEF203", "UNDEF204", "UNDEF205",
- "UNDEF206", "UNDEF207", "UNDEF208", "UNDEF209", "UNDEF210",
- "UNDEF211", "UNDEF212", "UNDEF213", "UNDEF214", "UNDEF215",
- "UNDEF216", "UNDEF217", "UNDEF218", "UNDEF219", "UNDEF220",
- "UNDEF221", "UNDEF222", "UNDEF223", "UNDEF224", "UNDEF225",
- "UNDEF226", "UNDEF227", "UNDEF228", "UNDEF229", "UNDEF230",
- "UNDEF231", "UNDEF232", "UNDEF233", "UNDEF234", "UNDEF235",
- "UNDEF236", "UNDEF237", "UNDEF238", "UNDEF239", "UNDEF240",
- "UNDEF241", "UNDEF242", "UNDEF243", "UNDEF244", "UNDEF245",
- "UNDEF246", "UNDEF247", "UNDEF248", "UNDEF249", "UNDEF250",
- "UNDEF251", "UNDEF252", "UNDEF253", "UNDEF254", "UNDEF255"
-};
-
-
/* jit_init ********************************************************************
Initializes the JIT subsystem.
void jit_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("jit_init");
+
#if defined(ENABLE_JIT)
/* initialize stack analysis subsystem */
{
u1 *r;
jitdata *jd;
- s4 dumpsize;
+ int32_t dumpmarker;
STATISTICS(count_jit_calls++);
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->class->state & CLASS_INITIALIZED)) {
+ if ((m->flags & ACC_STATIC) && !(m->clazz->state & CLASS_INITIALIZED)) {
#if !defined(NDEBUG)
if (initverbose)
- log_message_class("Initialize class ", m->class);
+ log_message_class("Initialize class ", m->clazz);
#endif
- if (!initialize_class(m->class))
+ if (!initialize_class(m->clazz))
return NULL;
/* check if the method has been compiled during initialization */
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
/* create jitdata structure */
#endif
#if defined(ENABLE_INLINING) && defined(ENABLE_INLINING_DEBUG)
- if (opt_inlining && opt_inline_debug_all)
+ if (opt_Inline && opt_InlineAll)
jd->flags |= JITDATA_FLAG_INLINE;
#endif
jd->flags |= JITDATA_FLAG_VERBOSECALL;
#if defined(ENABLE_REPLACEMENT) && defined(ENABLE_INLINING)
- if (opt_inlining)
+ if (opt_Inline)
jd->flags |= JITDATA_FLAG_COUNTDOWN;
#endif
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
#if defined(ENABLE_STATISTICS)
/* measure time */
u1 *r;
jitdata *jd;
u1 optlevel;
- s4 dumpsize;
+ int32_t dumpmarker;
/* check for max. optimization level */
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
/* create jitdata structure */
jd->flags |= JITDATA_FLAG_VERBOSECALL;
#if defined(ENABLE_INLINING)
- if (opt_inlining)
+ if (opt_Inline)
jd->flags |= JITDATA_FLAG_INLINE;
#endif
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
#if defined(ENABLE_STATISTICS)
/* measure time */
return r;
}
+#if defined(ENABLE_PM_HACKS)
+#include "vm/jit/jit_pm_1.inc"
+#endif
/* jit_compile_intern **********************************************************
show_filters_apply(jd->m);
#endif
- /* handle native methods and create a native stub */
+ /* Handle native methods and create a native stub. */
if (m->flags & ACC_NATIVE) {
functionptr f;
dynamically-generated bytecodes. */
# if defined(ENABLE_VERIFIER)
- if (class_issubclass(m->class, class_sun_reflect_MagicAccessorImpl))
+ if (class_issubclass(m->clazz, class_sun_reflect_MagicAccessorImpl))
jd->flags &= ~JITDATA_FLAG_VERIFY;
# endif
#endif
}
#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)
# endif /* defined(ENABLE_LSRA) && !defined(ENABLE_SSA) */
#if defined(ENABLE_SSA)
/* allocate registers */
- if ((opt_lsra) && (jd->exceptiontablelength == 0)) {
+ if ((opt_lsra) /*&& (strcmp(jd->m->name->text, "findClass") == 0 || jd->exceptiontablelength == 0)*/) {
jd->ls = DNEW(lsradata);
- lsra(jd);
-
+ jd->ls = NULL;
+ ssa(jd);
+ /*lsra(jd);*/ regalloc(jd);
+ eliminate_subbasicblocks(jd);
STATISTICS(count_methods_allocated_by_lsra++);
} else
}
#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.
/* src/vm/jit/jit.h - code generation header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* forward typedefs ***********************************************************/
typedef struct jitdata jitdata;
-typedef struct stackelement stackelement;
-typedef stackelement *stackptr;
typedef struct basicblock basicblock;
typedef struct instruction instruction;
typedef struct insinfo_inline insinfo_inline;
#include "vm/jit/codegen-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
+#include "vm/jit/stack.h"
#include "vm/jit/stacktrace.h"
#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
instruction *instructions; /* ICMDs, valid between parse and stack */
basicblock *basicblocks; /* start of basic block list */
- stackelement *stack; /* XXX should become stack.c internal */
+ 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 */
/* >= 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) */
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
((jd)->flags & JITDATA_FLAG_VERBOSECALL)
-/* 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))
-
-
/* exception_entry ************************************************************/
struct exception_entry {
};
-/* stack element structure ****************************************************/
-
-/* flags */
+/* 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 SAVEDVAR 1 /* variable has to survive method invocations */
-#define INMEMORY 2 /* variable stored in memory */
-#define SAVREG 4 /* allocated to a saved register */
-#define ARGREG 8 /* allocated to an arg register */
-#define PASSTHROUGH 32 /* stackslot was passed-through by an ICMD */
-#define PREALLOC 64 /* preallocated var like for ARGVARS. Used */
- /* with the new var system */
-#define INOUT 128 /* variable is an invar or/and an outvar */
+******************************************************************************/
-#define IS_SAVEDVAR(x) ((x) & SAVEDVAR)
-#define IS_INMEMORY(x) ((x) & INMEMORY)
+#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);
+}
-/* variable kinds */
+static inline bool var_is_prealloc(const jitdata *jd, s4 i) {
+ return ((i >= jd->localcount) && (jd->var[i].flags & PREALLOC));
+}
-#define UNDEFVAR 0 /* stack slot will become temp during regalloc*/
-#define TEMPVAR 1 /* stack slot is temp register */
-#define STACKVAR 2 /* stack slot is numbered stack slot */
-#define LOCALVAR 3 /* stack slot is local variable */
-#define ARGVAR 4 /* stack slot is argument variable */
+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));
+}
+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));
+}
-struct stackelement {
- stackptr prev; /* pointer to next element towards bottom */
- instruction *creator; /* instruction that created this element */
- s4 type; /* slot type of stack element */
- s4 flags; /* flags (SAVED, INMEMORY) */
- s4 varkind; /* kind of variable or register */
- s4 varnum; /* number of variable */
-};
+static inline bool var_is_saved(const jitdata *jd, s4 i) {
+ return (jd->var[i].flags & SAVEDVAR);
+}
/**************************** instruction structure ***************************/
md = iptr->sx.s23.s3.fmiref->parseddesc.md; \
} while (0)
-
/* additional info structs for special instructions ***************************/
/* for ICMD_INLINE_START and ICMD_INLINE_END */
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 */
+
+ basicblock *subbasicblocks;
+
+ 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))
+
+#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 */
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 ************************************/
/********** JavaVM operation codes (sorted) and instruction lengths ***********/
-extern char *opcode_names[256];
-extern int jcommandsize[256];
-extern int stackreq[256];
-
-#define JAVA_NOP 0
-#define ICMD_NOP 0
-
-#define JAVA_ACONST_NULL 1
-#define ICMD_ACONST 1 /* val.a = constant */
-
-#define JAVA_ICONST_M1 2
-#define ICMD_CHECKNULL 2
-
-#define JAVA_ICONST_0 3
-#define ICMD_ICONST 3 /* val.i = constant */
-
-#define JAVA_ICONST_1 4
-
-#define JAVA_ICONST_2 5
-#define ICMD_IDIVPOW2 5 /* val.i = constant */
-
-#define JAVA_ICONST_3 6
-#define ICMD_LDIVPOW2 6 /* val.l = constant */
-
-#define JAVA_ICONST_4 7
-
-#define JAVA_ICONST_5 8
-
-#define JAVA_LCONST_0 9
-#define ICMD_LCONST 9 /* val.l = constant */
-
-#define JAVA_LCONST_1 10
-#define ICMD_LCMPCONST 10 /* val.l = constant */
-
-#define JAVA_FCONST_0 11
-#define ICMD_FCONST 11 /* val.f = constant */
-
-#define JAVA_FCONST_1 12
-
-#define JAVA_FCONST_2 13
-
-#define JAVA_DCONST_0 14
-#define ICMD_DCONST 14 /* val.d = constant */
-
-#define JAVA_DCONST_1 15
-#define ICMD_COPY 15
-
-#define JAVA_BIPUSH 16
-#define ICMD_MOVE 16
-
-#define JAVA_SIPUSH 17
-
-#define JAVA_LDC1 18
-
-#define JAVA_LDC2 19
-
-#define JAVA_LDC2W 20
-
- /* order of LOAD instructions must be */
- /* equal to order of TYPE_* defines */
-#define JAVA_ILOAD 21
-#define ICMD_ILOAD 21 /* op1 = local variable */
-
-#define JAVA_LLOAD 22
-#define ICMD_LLOAD 22 /* op1 = local variable */
-
-#define JAVA_FLOAD 23
-#define ICMD_FLOAD 23 /* op1 = local variable */
-
-#define JAVA_DLOAD 24
-#define ICMD_DLOAD 24 /* op1 = local variable */
-
-#define JAVA_ALOAD 25
-#define ICMD_ALOAD 25 /* op1 = local variable */
-
-#define JAVA_ILOAD_0 26
-#define ICMD_IADDCONST 26 /* val.i = constant */
-
-#define JAVA_ILOAD_1 27
-#define ICMD_ISUBCONST 27 /* val.i = constant */
-
-#define JAVA_ILOAD_2 28
-#define ICMD_IMULCONST 28 /* val.i = constant */
-
-#define JAVA_ILOAD_3 29
-#define ICMD_IANDCONST 29 /* val.i = constant */
-
-#define JAVA_LLOAD_0 30
-#define ICMD_IORCONST 30 /* val.i = constant */
-
-#define JAVA_LLOAD_1 31
-#define ICMD_IXORCONST 31 /* val.i = constant */
-
-#define JAVA_LLOAD_2 32
-#define ICMD_ISHLCONST 32 /* val.i = constant */
-
-#define JAVA_LLOAD_3 33
-#define ICMD_ISHRCONST 33 /* val.i = constant */
-
-#define JAVA_FLOAD_0 34
-#define ICMD_IUSHRCONST 34 /* val.i = constant */
-
-#define JAVA_FLOAD_1 35
-#define ICMD_IREMPOW2 35 /* val.i = constant */
-
-#define JAVA_FLOAD_2 36
-#define ICMD_LADDCONST 36 /* val.l = constant */
-
-#define JAVA_FLOAD_3 37
-#define ICMD_LSUBCONST 37 /* val.l = constant */
-
-#define JAVA_DLOAD_0 38
-#define ICMD_LMULCONST 38 /* val.l = constant */
-
-#define JAVA_DLOAD_1 39
-#define ICMD_LANDCONST 39 /* val.l = constant */
-
-#define JAVA_DLOAD_2 40
-#define ICMD_LORCONST 40 /* val.l = constant */
-
-#define JAVA_DLOAD_3 41
-#define ICMD_LXORCONST 41 /* val.l = constant */
-
-#define JAVA_ALOAD_0 42
-#define ICMD_LSHLCONST 42 /* val.l = constant */
-
-#define JAVA_ALOAD_1 43
-#define ICMD_LSHRCONST 43 /* val.l = constant */
-
-#define JAVA_ALOAD_2 44
-#define ICMD_LUSHRCONST 44 /* val.l = constant */
-
-#define JAVA_ALOAD_3 45
-#define ICMD_LREMPOW2 45 /* val.l = constant */
-
-#define JAVA_IALOAD 46
-#define ICMD_IALOAD 46
-
-#define JAVA_LALOAD 47
-#define ICMD_LALOAD 47
-
-#define JAVA_FALOAD 48
-#define ICMD_FALOAD 48
-
-#define JAVA_DALOAD 49
-#define ICMD_DALOAD 49
-
-#define JAVA_AALOAD 50
-#define ICMD_AALOAD 50
-
-#define JAVA_BALOAD 51
-#define ICMD_BALOAD 51
-
-#define JAVA_CALOAD 52
-#define ICMD_CALOAD 52
-
-#define JAVA_SALOAD 53
-#define ICMD_SALOAD 53
-
- /* order of STORE instructions must be*/
- /* equal to order of TYPE_* defines */
-#define JAVA_ISTORE 54
-#define ICMD_ISTORE 54 /* op1 = local variable */
-
-#define JAVA_LSTORE 55
-#define ICMD_LSTORE 55 /* op1 = local variable */
-
-#define JAVA_FSTORE 56
-#define ICMD_FSTORE 56 /* op1 = local variable */
-
-#define JAVA_DSTORE 57
-#define ICMD_DSTORE 57 /* op1 = local variable */
-
-#define JAVA_ASTORE 58
-#define ICMD_ASTORE 58 /* op1 = local variable */
-
-#define JAVA_ISTORE_0 59
-#define ICMD_IF_LEQ 59 /* op1 = target JavaVM pc, val.l */
-
-#define JAVA_ISTORE_1 60
-#define ICMD_IF_LNE 60 /* op1 = target JavaVM pc, val.l */
-
-#define JAVA_ISTORE_2 61
-#define ICMD_IF_LLT 61 /* op1 = target JavaVM pc, val.l */
-
-#define JAVA_ISTORE_3 62
-#define ICMD_IF_LGE 62 /* op1 = target JavaVM pc, val.l */
-
-#define JAVA_LSTORE_0 63
-#define ICMD_IF_LGT 63 /* op1 = target JavaVM pc, val.l */
-
-#define JAVA_LSTORE_1 64
-#define ICMD_IF_LLE 64 /* op1 = target JavaVM pc, val.l */
-
-#define JAVA_LSTORE_2 65
-#define ICMD_IF_LCMPEQ 65 /* op1 = target JavaVM pc */
-
-#define JAVA_LSTORE_3 66
-#define ICMD_IF_LCMPNE 66 /* op1 = target JavaVM pc */
-
-#define JAVA_FSTORE_0 67
-#define ICMD_IF_LCMPLT 67 /* op1 = target JavaVM pc */
-
-#define JAVA_FSTORE_1 68
-#define ICMD_IF_LCMPGE 68 /* op1 = target JavaVM pc */
-
-#define JAVA_FSTORE_2 69
-#define ICMD_IF_LCMPGT 69 /* op1 = target JavaVM pc */
-
-#define JAVA_FSTORE_3 70
-#define ICMD_IF_LCMPLE 70 /* op1 = target JavaVM pc */
-
-#define JAVA_DSTORE_0 71
-
-#define JAVA_DSTORE_1 72
-
-#define JAVA_DSTORE_2 73
-
-#define JAVA_DSTORE_3 74
-
-#define JAVA_ASTORE_0 75
-
-#define JAVA_ASTORE_1 76
-
-#define JAVA_ASTORE_2 77
+enum {
+ ICMD_NOP = BC_nop,
-#define JAVA_ASTORE_3 78
+ ICMD_ACONST = BC_aconst_null,
-#define JAVA_IASTORE 79
-#define ICMD_IASTORE 79
+ ICMD_CHECKNULL = 2,
-#define JAVA_LASTORE 80
-#define ICMD_LASTORE 80
+ ICMD_ICONST = BC_iconst_0,
-#define JAVA_FASTORE 81
-#define ICMD_FASTORE 81
+ /* 3 */
+ /* 4 */
-#define JAVA_DASTORE 82
-#define ICMD_DASTORE 82
+ ICMD_IDIVPOW2 = 5,
+ ICMD_LDIVPOW2 = 6,
-#define JAVA_AASTORE 83
-#define ICMD_AASTORE 83
+ /* 7 */
+ /* 8 */
-#define JAVA_BASTORE 84
-#define ICMD_BASTORE 84
+ ICMD_LCONST = BC_lconst_0,
+
+ ICMD_LCMPCONST = 10,
-#define JAVA_CASTORE 85
-#define ICMD_CASTORE 85
-
-#define JAVA_SASTORE 86
-#define ICMD_SASTORE 86
-
-#define JAVA_POP 87
-#define ICMD_POP 87
-
-#define JAVA_POP2 88
-#define ICMD_POP2 88
-
-#define JAVA_DUP 89
-#define ICMD_DUP 89
-
-#define JAVA_DUP_X1 90
-#define ICMD_DUP_X1 90
-
-#define JAVA_DUP_X2 91
-#define ICMD_DUP_X2 91
-
-#define JAVA_DUP2 92
-#define ICMD_DUP2 92
-
-#define JAVA_DUP2_X1 93
-#define ICMD_DUP2_X1 93
-
-#define JAVA_DUP2_X2 94
-#define ICMD_DUP2_X2 94
-
-#define JAVA_SWAP 95
-#define ICMD_SWAP 95
-
-#define JAVA_IADD 96
-#define ICMD_IADD 96
-
-#define JAVA_LADD 97
-#define ICMD_LADD 97
-
-#define JAVA_FADD 98
-#define ICMD_FADD 98
-
-#define JAVA_DADD 99
-#define ICMD_DADD 99
-
-#define JAVA_ISUB 100
-#define ICMD_ISUB 100
-
-#define JAVA_LSUB 101
-#define ICMD_LSUB 101
-
-#define JAVA_FSUB 102
-#define ICMD_FSUB 102
-
-#define JAVA_DSUB 103
-#define ICMD_DSUB 103
-
-#define JAVA_IMUL 104
-#define ICMD_IMUL 104
-
-#define JAVA_LMUL 105
-#define ICMD_LMUL 105
-
-#define JAVA_FMUL 106
-#define ICMD_FMUL 106
-
-#define JAVA_DMUL 107
-#define ICMD_DMUL 107
-
-#define JAVA_IDIV 108
-#define ICMD_IDIV 108
-
-#define JAVA_LDIV 109
-#define ICMD_LDIV 109
-
-#define JAVA_FDIV 110
-#define ICMD_FDIV 110
-
-#define JAVA_DDIV 111
-#define ICMD_DDIV 111
-
-#define JAVA_IREM 112
-#define ICMD_IREM 112
-
-#define JAVA_LREM 113
-#define ICMD_LREM 113
-
-#define JAVA_FREM 114
-#define ICMD_FREM 114
-
-#define JAVA_DREM 115
-#define ICMD_DREM 115
-
-#define JAVA_INEG 116
-#define ICMD_INEG 116
-
-#define JAVA_LNEG 117
-#define ICMD_LNEG 117
-
-#define JAVA_FNEG 118
-#define ICMD_FNEG 118
-
-#define JAVA_DNEG 119
-#define ICMD_DNEG 119
-
-#define JAVA_ISHL 120
-#define ICMD_ISHL 120
-
-#define JAVA_LSHL 121
-#define ICMD_LSHL 121
-
-#define JAVA_ISHR 122
-#define ICMD_ISHR 122
-
-#define JAVA_LSHR 123
-#define ICMD_LSHR 123
-
-#define JAVA_IUSHR 124
-#define ICMD_IUSHR 124
-
-#define JAVA_LUSHR 125
-#define ICMD_LUSHR 125
-
-#define JAVA_IAND 126
-#define ICMD_IAND 126
-
-#define JAVA_LAND 127
-#define ICMD_LAND 127
-
-#define JAVA_IOR 128
-#define ICMD_IOR 128
-
-#define JAVA_LOR 129
-#define ICMD_LOR 129
-
-#define JAVA_IXOR 130
-#define ICMD_IXOR 130
-
-#define JAVA_LXOR 131
-#define ICMD_LXOR 131
-
-#define JAVA_IINC 132
-#define ICMD_IINC 132 /* op1 = local variable, val.i = constant */
-
-#define JAVA_I2L 133
-#define ICMD_I2L 133
-
-#define JAVA_I2F 134
-#define ICMD_I2F 134
-
-#define JAVA_I2D 135
-#define ICMD_I2D 135
-
-#define JAVA_L2I 136
-#define ICMD_L2I 136
-
-#define JAVA_L2F 137
-#define ICMD_L2F 137
-
-#define JAVA_L2D 138
-#define ICMD_L2D 138
-
-#define JAVA_F2I 139
-#define ICMD_F2I 139
-
-#define JAVA_F2L 140
-#define ICMD_F2L 140
-
-#define JAVA_F2D 141
-#define ICMD_F2D 141
-
-#define JAVA_D2I 142
-#define ICMD_D2I 142
-
-#define JAVA_D2L 143
-#define ICMD_D2L 143
-
-#define JAVA_D2F 144
-#define ICMD_D2F 144
-
-#define JAVA_INT2BYTE 145
-#define ICMD_INT2BYTE 145
-
-#define JAVA_INT2CHAR 146
-#define ICMD_INT2CHAR 146
-
-#define JAVA_INT2SHORT 147
-#define ICMD_INT2SHORT 147
-
-#define JAVA_LCMP 148
-#define ICMD_LCMP 148
-
-#define JAVA_FCMPL 149
-#define ICMD_FCMPL 149
-
-#define JAVA_FCMPG 150
-#define ICMD_FCMPG 150
-
-#define JAVA_DCMPL 151
-#define ICMD_DCMPL 151
-
-#define JAVA_DCMPG 152
-#define ICMD_DCMPG 152
-
-#define JAVA_IFEQ 153
-#define ICMD_IFEQ 153 /* op1 = target JavaVM pc, val.i */
-
-#define JAVA_IFNE 154
-#define ICMD_IFNE 154 /* op1 = target JavaVM pc, val.i */
-
-#define JAVA_IFLT 155
-#define ICMD_IFLT 155 /* op1 = target JavaVM pc, val.i */
-
-#define JAVA_IFGE 156
-#define ICMD_IFGE 156 /* op1 = target JavaVM pc, val.i */
-
-#define JAVA_IFGT 157
-#define ICMD_IFGT 157 /* op1 = target JavaVM pc, val.i */
-
-#define JAVA_IFLE 158
-#define ICMD_IFLE 158 /* op1 = target JavaVM pc, val.i */
-
-#define JAVA_IF_ICMPEQ 159
-#define ICMD_IF_ICMPEQ 159 /* op1 = target JavaVM pc */
-
-#define JAVA_IF_ICMPNE 160
-#define ICMD_IF_ICMPNE 160 /* op1 = target JavaVM pc */
-
-#define JAVA_IF_ICMPLT 161
-#define ICMD_IF_ICMPLT 161 /* op1 = target JavaVM pc */
-
-#define JAVA_IF_ICMPGE 162
-#define ICMD_IF_ICMPGE 162 /* op1 = target JavaVM pc */
-
-#define JAVA_IF_ICMPGT 163
-#define ICMD_IF_ICMPGT 163 /* op1 = target JavaVM pc */
-
-#define JAVA_IF_ICMPLE 164
-#define ICMD_IF_ICMPLE 164 /* op1 = target JavaVM pc */
-
-#define JAVA_IF_ACMPEQ 165
-#define ICMD_IF_ACMPEQ 165 /* op1 = target JavaVM pc */
-
-#define JAVA_IF_ACMPNE 166
-#define ICMD_IF_ACMPNE 166 /* op1 = target JavaVM pc */
-
-#define JAVA_GOTO 167
-#define ICMD_GOTO 167 /* op1 = target JavaVM pc */
-
-#define JAVA_JSR 168
-#define ICMD_JSR 168 /* op1 = target JavaVM pc */
-
-#define JAVA_RET 169
-#define ICMD_RET 169 /* op1 = local variable */
-
-#define JAVA_TABLESWITCH 170
-#define ICMD_TABLESWITCH 170 /* val.a = pointer to s4 table */
- /* length must be computed */
-#define JAVA_LOOKUPSWITCH 171
-#define ICMD_LOOKUPSWITCH 171 /* val.a = pointer to s4 table */
- /* length must be computed */
-#define JAVA_IRETURN 172
-#define ICMD_IRETURN 172
-
-#define JAVA_LRETURN 173
-#define ICMD_LRETURN 173
-
-#define JAVA_FRETURN 174
-#define ICMD_FRETURN 174
-
-#define JAVA_DRETURN 175
-#define ICMD_DRETURN 175
-
-#define JAVA_ARETURN 176
-#define ICMD_ARETURN 176
-
-#define JAVA_RETURN 177
-#define ICMD_RETURN 177
-
-#define JAVA_GETSTATIC 178
-#define ICMD_GETSTATIC 178 /* op1 = type, val.a = field address */
-
-#define JAVA_PUTSTATIC 179
-#define ICMD_PUTSTATIC 179 /* op1 = type, val.a = field address */
-
-#define JAVA_GETFIELD 180
-#define ICMD_GETFIELD 180 /* op1 = type, val.i = field offset */
-
-#define JAVA_PUTFIELD 181
-#define ICMD_PUTFIELD 181 /* op1 = type, val.i = field offset */
-
-#define JAVA_INVOKEVIRTUAL 182
-#define ICMD_INVOKEVIRTUAL 182 /* val.a = method info pointer */
-
-#define JAVA_INVOKESPECIAL 183
-#define ICMD_INVOKESPECIAL 183 /* val.a = method info pointer */
-
-#define JAVA_INVOKESTATIC 184
-#define ICMD_INVOKESTATIC 184 /* val.a = method info pointer */
-
-#define JAVA_INVOKEINTERFACE 185
-#define ICMD_INVOKEINTERFACE 185 /* val.a = method info pointer */
-
-/* UNDEF186 */
-
-#define JAVA_NEW 187
-#define ICMD_NEW 187 /* op1 = 1, val.a = class pointer */
-
-#define JAVA_NEWARRAY 188
-#define ICMD_NEWARRAY 188 /* op1 = basic type */
-
-#define JAVA_ANEWARRAY 189
-#define ICMD_ANEWARRAY 189 /* op1 = 0, val.a = array pointer */
- /* op1 = 1, val.a = class pointer */
-#define JAVA_ARRAYLENGTH 190
-#define ICMD_ARRAYLENGTH 190
-
-#define JAVA_ATHROW 191
-#define ICMD_ATHROW 191
-
-#define JAVA_CHECKCAST 192
-#define ICMD_CHECKCAST 192 /* op1 = 0, val.a = array pointer */
- /* op1 = 1, val.a = class pointer */
-#define JAVA_INSTANCEOF 193
-#define ICMD_INSTANCEOF 193 /* op1 = 0, val.a = array pointer */
- /* op1 = 1, val.a = class pointer */
-#define JAVA_MONITORENTER 194
-#define ICMD_MONITORENTER 194
-
-#define JAVA_MONITOREXIT 195
-#define ICMD_MONITOREXIT 195
-
-#define JAVA_WIDE 196
-
-#define JAVA_MULTIANEWARRAY 197
-#define ICMD_MULTIANEWARRAY 197 /* op1 = dimension, val.a = array */
- /* pointer */
-#define JAVA_IFNULL 198
-#define ICMD_IFNULL 198 /* op1 = target JavaVM pc */
-
-#define JAVA_IFNONNULL 199
-#define ICMD_IFNONNULL 199 /* op1 = target JavaVM pc */
-
-#define JAVA_GOTO_W 200
-
-#define JAVA_JSR_W 201
-
-#define JAVA_BREAKPOINT 202
-
-/* UNDEF203 */
-
-#define ICMD_IASTORECONST 204
-#define ICMD_LASTORECONST 205
-#define ICMD_FASTORECONST 206
-#define ICMD_DASTORECONST 207
-#define ICMD_AASTORECONST 208
-#define ICMD_BASTORECONST 209
-#define ICMD_CASTORECONST 210
-#define ICMD_SASTORECONST 211
-
-#define ICMD_PUTSTATICCONST 212
-#define ICMD_PUTFIELDCONST 213
-
-#define ICMD_IMULPOW2 214
-#define ICMD_LMULPOW2 215
+ 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_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 */
+};
-#define ICMD_INLINE_START 251 /* instruction before inlined method */
-#define ICMD_INLINE_END 252 /* instruction after inlined method */
-#define ICMD_INLINE_BODY 253 /* start of inlined body */
+/* Additional instruction accessors */
-#define ICMD_BUILTIN 255 /* internal opcode */
+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 *********************************/
/* src/vm/jit/linenumbertable.c - linenumber handling stuff
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* 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_last_unsynced(l); le != NULL;
- le = list_prev_unsynced(l, le), lnte++) {
+ 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). */
le->linenumber = linenumber;
le->mpc = cd->mcodeptr - cd->mcodebase;
- list_add_last_unsynced(cd->linenumbers, le);
+ list_add_first(cd->linenumbers, le);
}
le->linenumber = (-2); /* marks start of inlined method */
le->mpc = (mpc = cd->mcodeptr - cd->mcodebase);
- list_add_last_unsynced(cd->linenumbers, le);
+ list_add_first(cd->linenumbers, le);
insinfo = iptr->sx.s23.s3.inlineinfo;
le->linenumber = (-3) - iptr->line;
le->mpc = (uintptr_t) insinfo->method;
- list_add_last_unsynced(cd->linenumbers, le);
+ list_add_first(cd->linenumbers, le);
le = DNEW(linenumbertable_list_entry_t);
le->linenumber = (-1);
le->mpc = insinfo->startmpc;
- list_add_last_unsynced(cd->linenumbers, le);
+ list_add_first(cd->linenumbers, le);
}
/* src/vm/jit/linenumbertable.h - linenumber table
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* src/vm/jit/loop/analyze.c - bound check removal functions
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christopher Kruegel
-
- Changes: Christian Thalinger
-
- Contains the functions which perform the bound check removals. With
- the loops identified, these functions scan the code for array
- accesses that take place in loops and try to guarantee that their
- bounds are never violated. The function to call is
- optimize_loops().
-
*/
#include "mm/memory.h"
#include "toolbox/logging.h"
+
#include "vm/jit/jit.h"
+#include "vm/jit/stack.h"
+
#include "vm/jit/loop/analyze.h"
#include "vm/jit/loop/graph.h"
#include "vm/jit/loop/loop.h"
/* copy a stack and return the start pointer of the newly created one
*/
-stackptr copy_stack_from(stackptr source) {
- stackptr current, top;
+stackelement_t* copy_stack_from(stackelement_t* source) {
+ stackelement_t* current, top;
if (source == NULL)
return NULL;
inst: pointer to the new instruction
tos: stackpointer before this operation is executed
- newstack: temporary stackptr
+ newstack: temporary stackelement_t*
stackdepth: counts the current stackdepth
original start: blockpointer to the head of the new, optimized loop
*/
/* tos and newstack are needed by the macros, that insert instructions into */
/* the new loop head */
- stackptr newstack, tos;
+ stackelement_t* newstack, tos;
exceptiontable *ex;
/* prevent some compiler warnings */
## src/vm/jit/m68k/Makefile.am
##
-## Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
+## Copyright (C) 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
##
## This file is part of CACAO.
##
LIBS =
noinst_HEADERS = \
- arch.h \
- machine-instr.h
+ arch.h \
+ machine-instr.h
noinst_LTLIBRARIES = \
libarch.la
if ENABLE_DISASSEMBLER
DISASS_SOURCES = \
- disass.c
+ disass.c
endif
libarch_la_SOURCES = \
codegen.h \
$(DISASS_SOURCES) \
emit.c \
+ patcher.c \
+ \
+ md-trap.h \
md.c \
- patcher.c
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
#define SPECIALMEMUSE
#define JIT_COMPILER_VIA_SIGNAL
-/* #define HAS_4BYTE_STACKSLOT */
/* #define SUPPORT_COMBINE_INTEGER_REGISTERS */
#endif /* _ARCH_H */
movel %sp@(12*4+2*4),%a2 /* arg array */
movel %sp@(12*4+3*4),%d2 /* arg count */
- movel %a3, %sp@(12*4) /* copy method address to stackslot */
- leal %sp@(12*4), %a3 /* and store that address in %a3 */
+ movel %a3, %sp@(11*4) /* copy method address to stackslot */
+ leal %sp@(11*4), %a3 /* and store that address in %a3 */
#else
addal #(-12*4-6*8), %sp
moveml %d2/%d3/%d4/%d5/%d6/%d7/%a2/%a3/%a4/%a5/%fp,%sp@ /* save registers */
movel %sp@(12*4+6*8+2*4),%a2 /* arg array */
movel %sp@(12*4+6*8+3*4),%d2 /* arg count */
- movel %a3, %sp@(12*4+6*8) /* copy method address to stackslot */
- leal %sp@(12*4+6*8), %a3 /* and store that address in %a3 */
+ movel %a3, %sp@(11*4+6*8) /* copy method address to stackslot */
+ leal %sp@(11*4+6*8), %a3 /* and store that address in %a3 */
#endif
moveal %sp, %a5 /* memorize stack */
/* src/vm/jit/m68k/codegen.c
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
#include "md-abi.h"
-#include "md-os.h"
#include "vm/types.h"
#include "vm/jit/m68k/codegen.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
/* call lock_monitor_enter function */
if (checksync && code_is_synchronized(code)) {
if (m->flags & ACC_STATIC) {
- M_AMOV_IMM((&m->class->object.header), REG_ATMP1);
+ M_AMOV_IMM((&m->clazz->object.header), REG_ATMP1);
} else {
/* for non-static case the first arg is the object */
M_ALD(REG_ATMP1, REG_SP, cd->stackframesize + 4);
M_ATST(REG_ATMP1);
M_BNE(2);
- M_TRAP(M68K_EXCEPTION_HARDWARE_NULLPOINTER);
+ M_TRAP(TRAP_NullPointerException);
}
M_AST(REG_ATMP1, REG_SP, rd->memuse * 8);
fieldtype = fi->type;
disp = (intptr_t) fi->value;
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
}
fieldtype = fi->type;
disp = (intptr_t) fi->value;
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class,
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz,
0);
}
s1 = 0;
s2 = 0;
} else {
- s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->class->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s1 = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * lm->clazz->index;
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* load object pointer (==argument 0) */
M_ALD(REG_ATMP1, REG_SP, 0);
(void) dseg_add_unique_s4(cd, 0); /* IntSave */
(void) dseg_add_unique_s4(cd, 0); /* FltSave */
- /* print call trace */
-#if !defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
- emit_verbosecall_enter(jd);
- }
-#endif
-
/* generate code */
M_AADD_IMM(-(cd->stackframesize*8), REG_SP);
- /* get function address (this must happen before the stackframeinfo) */
- if (f == NULL) {
- patcher_add_patch_ref(jd, PATCHER_resolve_native_function, m, 0);
- }
-
- M_AMOV_IMM(f, REG_ATMP2); /* do not move this line, the patcher is needed */
-
- M_AST(REG_ATMP2, REG_SP, 4 * 4);
-
/* put arguments for codegen_start_native_call onto stack */
/* void codegen_start_native_call(u1 *datasp, u1 *pv, u1 *sp, u1 *ra) */
if (m->flags & ACC_STATIC)
M_INT2ADRMOVE(REG_RESULT, REG_ATMP3);
- /* load function pointer */
- M_ALD(REG_ATMP2, REG_SP, 4 * 4);
-
/* copy arguments into stackframe */
for (i = md->paramcount -1, j = i + skipparams; i >= 0; --i, --j) {
t = md->paramtypes[i].type;
}
}
- /* for static function class as second arg */
- if (m->flags & ACC_STATIC)
- M_AST(REG_ATMP3, REG_SP, 1 * 4);
+ /* builtins are not invoked like natives, environemtn and clazz are only needed for natives */
+ if (m->flags & ACC_NATIVE) {
+ /* for static function class as second arg */
+ if (m->flags & ACC_STATIC)
+ M_AST(REG_ATMP3, REG_SP, 1 * 4);
- /* env ist first argument */
- M_AMOV_IMM(_Jv_env, REG_ATMP1);
- M_AST(REG_ATMP1, REG_SP, 0 * 4);
+ /* env ist first argument */
+ M_AMOV_IMM(_Jv_env, REG_ATMP1);
+ M_AST(REG_ATMP1, REG_SP, 0 * 4);
+ }
/* call the native function */
+ M_AMOV_IMM(f, REG_ATMP2);
M_JSR(REG_ATMP2);
/* save return value */
default: assert(0);
}
-
- /* print call trace */
-#if ! defined(NDEBUG)
- if (JITDATA_HAS_FLAG_VERBOSECALL(jd)) {
- emit_verbosecall_exit(jd);
- }
-#endif
+
/* remove native stackframe info */
/* therefore we call: java_objectheader *codegen_finish_native_call(u1 *datasp) */
/* should never be reached from within jit code*/
M_JSR_IMM(0);
-
- /* generate patcher stub call code */
- emit_patcher_traps(jd);
}
/* stub defines ***************************************************************/
-#define COMPILERSTUB_CODESIZE (6+6+2)
+#define COMPILERSTUB_CODESIZE (2+2)
/* coldfire instruction format:
#include <assert.h>
-#include "emit.h"
-#include "vm/jit/emit-common.h"
-#include "vm/exceptions.h"
-#include "vm/jit/asmpart.h"
-#include "vm/builtin.h"
-#include "vm/jit/trace.h"
+#include "vm/jit/m68k/codegen.h"
+#include "vm/jit/m68k/emit.h"
#include "mm/memory.h"
-#include "threads/lock-common.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/emit-common.h"
+#include "vm/jit/trace.h"
+#include "vm/jit/trap.h"
-#include "codegen.h"
-#include "md-os.h"
/* emit_mov_imm_reg **************************************************************************
*
*******************************************************************************/
-inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
{
codegendata *cd;
vm_abort("emit_classcast_check: unknown condition %d", condition);
}
M_TRAP_SETREGISTER(s1);
- M_TRAP(EXCEPTION_HARDWARE_CLASSCAST);
+ M_TRAP(TRAP_ClassCastException);
}
}
M_ICMP(s2, REG_ITMP3);
M_BHI(4);
M_TRAP_SETREGISTER(s2);
- M_TRAP(EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_TRAP(TRAP_ArrayIndexOutOfBoundsException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_ITST(REG_RESULT);
M_BNE(2);
- /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARRAYSTORE);*/
- M_TRAP(EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_TRAP(TRAP_ArrayStoreException);
}
}
Emit a NullPointerException check.
*******************************************************************************/
+
void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
{
if (INSTRUCTION_MUST_CHECK(iptr)) {
* invocation at the beginning of codegen.c */
M_ATST(reg);
M_BNE(2);
- M_TRAP(M68K_EXCEPTION_HARDWARE_NULLPOINTER);
+ M_TRAP(TRAP_NullPointerException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_ITST(reg);
M_BNE(2);
- M_TRAP(EXCEPTION_HARDWARE_ARITHMETIC);
+ M_TRAP(TRAP_ArithmeticException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_ITST(REG_RESULT);
M_BNE(2);
- /*M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);*/
- M_TRAP(EXCEPTION_HARDWARE_EXCEPTION);
+ M_TRAP(TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
M_TRAP_SETREGISTER(REG_METHODPTR);
- M_TRAP(EXCEPTION_HARDWARE_COMPILER);
+ M_TRAP(TRAP_COMPILER);
}
mcode = *((uint32_t *) cd->mcodeptr);
- M_TRAP(EXCEPTION_HARDWARE_PATCHER);
+ M_TRAP(TRAP_PATCHER);
return mcode;
}
-## src/vm/jit/powerpc64/linux/Makefile.am
+## src/vm/jit/m68k/linux/Makefile.am
##
-## 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.
##
## 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
-##
-## Changes:
-## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)
noinst_HEADERS = \
md-asm.h
-noinst_LTLIBRARIES = libmd.la
+noinst_LTLIBRARIES = \
+ libmd.la
libmd_la_SOURCES = \
md-abi.c \
md-abi.h \
- md-os.h \
md-os.c
/* src/vm/jit/m68k/linux/md-abi.c - linux specific abi functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
void md_param_alloc_native(methoddesc *md)
{
- /* For now use system ABI */
- md_param_alloc(md);
+ paramdesc *pd;
+ s4 stacksize;
+ s4 i;
+
+ pd = md->params;
+ stacksize = 0;
+
+ for (i=0; i<md->paramcount; i++, pd++) {
+ pd->inmemory = true;
+ pd->regoff = stacksize * 4;
+ pd->index = stacksize;
+ stacksize += IS_2_WORD_TYPE(md->paramtypes[i].type) ? 2:1;
+ }
+
+ md->memuse = stacksize;
+ md->argintreguse = 0;
+ md->argfltreguse = 0;
+ md->argadrreguse = 0;
+
}
for (i=0; i<md->paramcount; i++, pd++) {
pd->inmemory = true;
pd->regoff = stacksize * 8;
-/* stacksize += IS_2_WORD_TYPE(md->paramtypes[i].type) ? 2:1;*/
+ pd->index = stacksize;
+ stacksize ++;
}
md->memuse = stacksize;
%d0 for all word types %d0-%d1 for 2 word types. %f0-%f1 for floats/doubles
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
/* The Problem: %a0, %a1, %d0 and %d1 are scratch registers by platform abi
-/* src/vm/jit/m68k/linux/md-os.c - linux specific functions
+/* src/vm/jit/m68k/linux/md-os.c - m68k linux specific functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
*/
+
#include "config.h"
-#include "md-os.h"
-#include "md-abi.h"
+#include "vm/jit/m68k/md.h"
+#include "vm/jit/m68k/linux/md-abi.h"
-#include "vm/vm.h"
#include "vm/exceptions.h"
-#include "vm/jit/asmpart.h"
#include "vm/signallocal.h"
+#include "vm/vm.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/trap.h"
#include <assert.h>
#include <stdlib.h>
* Invoked when a Nullpointerexception occured, or when the vm
* crashes, hard to tell the difference.
**********************************************************************/
+
void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
{
uint32_t xpc, sp;
void *p;
actual_mcontext_t *_mc;
actual_ucontext_t *_uc;
-
+ int type;
_uc = (actual_ucontext_t*)_p;
_mc = &_uc->uc_mcontext;
/* val is now register number, adreg == true if it is an address regsiter */
regval = _mc->gregs[adrreg ? GREGS_ADRREG_OFF + val : val];
- /*
- if (regval != 0) {
- vm_abort("md_signal_handler_sigsegv: faulting address is not NULL: addr=%p", regval);
- }*/
-
-
- /*fprintf(stderr, "SEGV: sp=%x, xpc=%x, regval=%x\n", sp, xpc, regval);
- */
+ type = regval;
/* Handle the type. */
- p = signal_handle(EXCEPTION_HARDWARE_NULLPOINTER, regval, NULL, (void*)sp, (void*)xpc, (void*)xpc, _p);
+ p = trap_handle(type, regval, NULL, (void*)sp, (void*)xpc, (void*)xpc, _p);
_mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (intptr_t) p;
_mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (intptr_t) xpc;
_mc->gregs[R_PC] = (intptr_t) asm_handle_exception;
}
+
/* md_signal_handler_sigill *******************************************
*
* This handler is used to generate hardware exceptions.
* been created directly before the trap instruction (2 bytes long).
* the last 3 bit of this tst instruction contain the register number.
**********************************************************************/
+
void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
{
uint32_t xpc, sp, ra, pv;
/* Figure out in which register the object causing the exception resides for appropiate exceptions
*/
switch (type) {
- case EXCEPTION_HARDWARE_ARITHMETIC:
- case EXCEPTION_HARDWARE_EXCEPTION:
+ case TRAP_NullPointerException:
+ case TRAP_ArithmeticException:
+ case TRAP_CHECK_EXCEPTION:
/* nothing */
break;
- case EXCEPTION_HARDWARE_CLASSCAST:
+
+ case TRAP_ClassCastException:
regval = *(uint16_t*)(xpc-4);
assert( (regval&0xfff0) == 0x4a00 );
/* was in a address register */
regval = _mc->gregs[ GREGS_ADRREG_OFF + (regval & 0x7) ];
break;
- case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
+
+ case TRAP_ArrayIndexOutOfBoundsException:
regval = *(uint16_t*)(xpc-4);
assert( (regval&0xfff0) == 0x4a00 );
/* was a data register */
regval = _mc->gregs[regval & 0x7];
break;
- case M68K_EXCEPTION_HARDWARE_NULLPOINTER:
- type = EXCEPTION_HARDWARE_NULLPOINTER;
- break;
- case EXCEPTION_HARDWARE_COMPILER:
+
+ case TRAP_COMPILER:
regval = *(uint16_t*)(xpc-4);
assert( (regval&0xfff0) == 0x4a00 );
/* was in a address register */
sp = sp + SIZEOF_VOID_P;
xpc = ra - 2;
break;
- case EXCEPTION_HARDWARE_PATCHER:
+
+ case TRAP_PATCHER:
xpc -= 2;
ra = xpc;
break;
-
- default: assert(0);
}
- /*fprintf(stderr, "NEW HWE: sp=%x, xpc=%x, tpye=%x, regval=%x\n", sp, xpc, type, regval);
- */
-
- /* Handle the type. */
- p = signal_handle(type, regval, pv, (void*)sp, (void*)ra, (void*)xpc, _p);
+ /* Handle the trap. */
+ p = trap_handle(type, regval, pv, (void*)sp, (void*)ra, (void*)xpc, _p);
switch (type) {
- case EXCEPTION_HARDWARE_COMPILER:
- if (p == NULL) {
- /* exception when compiling the method */
- java_object_t *o = exceptions_get_and_clear_exceptions();
+ case TRAP_COMPILER:
+ if (p == NULL) {
+ /* exception when compiling the method */
+ java_object_t *o = builtin_retrieve_exception();
- _mc->gregs[R_SP] = sp; /* remove RA from stack */
+ _mc->gregs[R_SP] = sp; /* remove RA from stack */
- _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (intptr_t) o;
- _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (intptr_t) xpc;
- _mc->gregs[R_PC] = (intptr_t) asm_handle_exception;
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (uintptr_t) o;
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (uintptr_t) xpc;
+ _mc->gregs[R_PC] = (uintptr_t) asm_handle_exception;
+ }
+ else {
+ /* compilation ok, execute */
+ _mc->gregs[R_PC] = p;
+ }
+ break;
- } else {
- /* compilation ok, execute */
- _mc->gregs[R_PC] = p;
- }
- break;
+ case TRAP_PATCHER:
+ if (p == NULL) {
+ /* No exception while patching, continue. */
+ _mc->gregs[R_PC] = xpc;
+ return;
+ }
+ /* fall-through in case of exception */
- case EXCEPTION_HARDWARE_PATCHER:
- if (p == NULL) {
- /* no expcetion while patching, continue */
- _mc->gregs[R_PC] = xpc;
- return;
- }
- /* fall-through in case of exception */
- default:
- /* a normal exception with normal expcetion handling */
- _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (intptr_t) p;
- _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (intptr_t) xpc;
- _mc->gregs[R_PC] = (intptr_t) asm_handle_exception;
+ default:
+ /* a normal exception with normal expcetion handling */
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP1] = (uintptr_t) p;
+ _mc->gregs[GREGS_ADRREG_OFF + REG_ATMP2_XPC] = (uintptr_t) xpc;
+ _mc->gregs[R_PC] = (uintptr_t) asm_handle_exception;
}
}
+
/* md_signal_handler_sigusr1 ***************************************************
Signal handler for suspending threads.
+++ /dev/null
-/* src/vm/jit/m68k/linux/md-os.h - linux specific functions
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-#include "config.h"
-
-/* XXX trap #0 is reserved and will not be delivered to signal handler */
-#define M68K_EXCEPTION_HARDWARE_NULLPOINTER 14
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically 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 STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
#define MEMORY_BARRIER() __asm__ __volatile__ ( "" : : : "memory" );
--- /dev/null
+/* src/vm/jit/m68k/md-trap.h - m68k hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * The trap #0 is reserved and will not be delivered to signal
+ * handler, so we skip this one.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 0
+
+enum {
+ /* Skip 0 because it's a reserved trap. */
+
+ TRAP_NullPointerException = 1,
+ TRAP_ArithmeticException = 2,
+ TRAP_ArrayIndexOutOfBoundsException = 3,
+ TRAP_ArrayStoreException = 4,
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+ TRAP_COMPILER = 8
+};
+
+#endif /* _MD_TRAP_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:
+ */
return pa;
}
+void *md_stacktrace_get_returnaddress(void *sp, int32_t stackframesize)
+{
+ void *ra;
+
+ /* return address is above stackpointer */
+
+ ra = *((void **) (((uintptr_t) sp) + stackframesize));
+
+ /* XXX: This helps for now, but it's a ugly hack
+ * the problem _may_ be: the link instruction is used
+ * by some gcc generated code, and we get an additional word
+ * on the stack, the old framepointer. Its address is somewhere
+ * near sp, but that all depends the code generated by the compiler.
+ * I'm unsure about a clean solution.
+ */
+#if 0
+ if (!(ra > 0x40000000 && ra < 0x80000000)) {
+ ra = *((u1**)(sp + framesize + 4));
+ }
+#endif
+
+ /* assert(ra > 0x40000000 && ra < 0x80000000);
+ printf("XXXXXX=%x\n", ra);
+ */
+
+ return ra;
+}
+
+
/*
* These are local overrides for various environment variables in Emacs.
#include <stdint.h>
#include "vm/jit/codegen-common.h"
+#include "vm/jit/methodtree.h"
/* md_stacktrace_get_returnaddress *********************************************
*******************************************************************************/
-inline static void *md_stacktrace_get_returnaddress(void *sp, int32_t stackframesize)
-{
- void *ra;
-
- /* return address is above stackpointer */
-
- ra = *((void **) (((uintptr_t) sp) + stackframesize));
-
- /* XXX: This helps for now, but it's a ugly hack
- * the problem _may_ be: the link instruction is used
- * by some gcc generated code, and we get an additional word
- * on the stack, the old framepointer. Its address is somewhere
- * near sp, but that all depends the code generated by the compiler.
- * I'm unsure about a clean solution.
- */
-#if 0
- if (!(ra > 0x40000000 && ra < 0x80000000)) {
- ra = *((u1**)(sp + framesize + 4));
- }
-#endif
-
- /* assert(ra > 0x40000000 && ra < 0x80000000);
- printf("XXXXXX=%x\n", ra);
- */
-
- return ra;
-}
+void *md_stacktrace_get_returnaddress(void *sp, int32_t stackframesize);
/* md_codegen_get_pv_from_pc ***************************************************
- On this architecture just a wrapper function to
- codegen_get_pv_from_pc.
+ On this architecture just a wrapper function to methodtree_find.
*******************************************************************************/
{
void *pv;
- pv = codegen_get_pv_from_pc(ra);
+ pv = methodtree_find(ra);
return pv;
}
/* src/vm/jit/m68k/patcher.c - m68k patcher functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
return false;
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
/* patch back original code */
assert( *((uint32_t*)ra) == 0x246f0000 );
/* patch interfacetable index (first #0) */
- disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->class->index;
+ disp = OFFSET(vftbl_t, interfacetable[0]) - sizeof(methodptr*) * m->clazz->index;
/* XXX this disp is negative, check!
* assert( (disp & 0x0000ffff) == disp);*/
*((uint16_t *) (ra + 5 * 2)) = disp;
/* patch method offset (second #0) */
- disp = sizeof(methodptr) * (m - m->class->methods);
+ disp = sizeof(methodptr) * (m - m->clazz->methods);
assert( (disp & 0x0000ffff) == disp);
*((uint16_t *) (ra + 7 * 2)) = disp;
--- /dev/null
+/* src/vm/jit/methodtree.c - AVL tree of methods
+
+ 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/thread.h"
+
+#include "toolbox/avl.h"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/methodtree.h"
+
+
+/* methodtree_element *********************************************************/
+
+typedef struct methodtree_element_t methodtree_element_t;
+
+struct methodtree_element_t {
+ void *startpc;
+ void *endpc;
+};
+
+
+/* in this tree we store all method addresses *********************************/
+
+static avl_tree_t *methodtree = NULL;
+
+
+/* static functions ***********************************************************/
+
+static int methodtree_comparator(const void *treenode, const void *node);
+
+
+/* methodtree_init *************************************************************
+
+ Initialize the global method tree.
+
+*******************************************************************************/
+
+void methodtree_init(void)
+{
+#if defined(ENABLE_JIT)
+ methodtree_element_t *mte;
+#endif
+
+ methodtree = avl_create(&methodtree_comparator);
+
+#if defined(ENABLE_JIT)
+ /* Insert asm_vm_call_method. */
+
+ mte = NEW(methodtree_element_t);
+
+ mte->startpc = (u1 *) (ptrint) asm_vm_call_method;
+ mte->endpc = (u1 *) (ptrint) asm_vm_call_method_end;
+
+ avl_insert(methodtree, mte);
+#endif
+}
+
+
+/* methodtree_comparator *******************************************************
+
+ Comparator function used for the AVL tree of methods.
+
+ ARGUMENTS:
+ treenode ... the node from the tree
+ node ....... the node to compare to the tree-node
+
+ RETURN VALUE:
+ 0 .... found
+ -1 ... go left
+ 1 .... go right
+
+*******************************************************************************/
+
+static int methodtree_comparator(const void *treenode, const void *node)
+{
+ methodtree_element_t *mte;
+ methodtree_element_t *mtepc;
+
+ mte = (methodtree_element_t *) treenode;
+ mtepc = (methodtree_element_t *) node;
+
+ /* compare both startpc and endpc of pc, even if they have the same value,
+ otherwise the avl_probe sometimes thinks the element is already in the
+ tree */
+
+#ifdef __S390__
+ /* On S390 addresses are 31 bit. Compare only 31 bits of value.
+ */
+# define ADDR_MASK(a) ((a) & 0x7FFFFFFF)
+#else
+# define ADDR_MASK(a) (a)
+#endif
+
+ if (ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->startpc) &&
+ ADDR_MASK((long) mtepc->startpc) <= ADDR_MASK((long) mte->endpc) &&
+ ADDR_MASK((long) mte->startpc) <= ADDR_MASK((long) mtepc->endpc) &&
+ ADDR_MASK((long) mtepc->endpc) <= ADDR_MASK((long) mte->endpc)) {
+ return 0;
+
+ } else if (ADDR_MASK((long) mtepc->startpc) < ADDR_MASK((long) mte->startpc)) {
+ return -1;
+
+ } else {
+ return 1;
+ }
+
+# undef ADDR_MASK
+}
+
+
+/* methodtree_insert ***********************************************************
+
+ Insert the machine code range of a method into the AVL tree of
+ methods.
+
+ ARGUMENTS:
+ startpc ... start address of the method
+ endpc ..... end address of the method
+
+*******************************************************************************/
+
+void methodtree_insert(void *startpc, void *endpc)
+{
+ methodtree_element_t *mte;
+
+ /* Allocate new method entry. */
+
+ mte = NEW(methodtree_element_t);
+
+ mte->startpc = startpc;
+ mte->endpc = endpc;
+
+ /* This function does not return an error, but asserts for
+ duplicate entries. */
+
+ avl_insert(methodtree, mte);
+}
+
+
+/* methodtree_find *************************************************************
+
+ Find the PV for the given PC by searching in the AVL tree of
+ methods.
+
+*******************************************************************************/
+
+void *methodtree_find(void *pc)
+{
+ void *pv;
+
+ /* Try to find a method. */
+
+ pv = methodtree_find_nocheck(pc);
+
+ if (pv == NULL) {
+ /* No method was found. Let's dump a stacktrace. */
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_signl("SIGSEGV");
+#endif
+
+ log_println("We received a SIGSEGV and tried to handle it, but we were");
+ log_println("unable to find a Java method at:");
+ log_println("");
+#if SIZEOF_VOID_P == 8
+ log_println("PC=0x%016lx", pc);
+#else
+ log_println("PC=0x%08x", pc);
+#endif
+ log_println("");
+
+ log_println("Dumping the current stacktrace:");
+
+ stacktrace_print_current();
+
+ vm_abort("Exiting...");
+ }
+
+ return pv;
+}
+
+
+/* methodtree_find_nocheck *****************************************************
+
+ Find the PV for the given PC by searching in the AVL tree of
+ methods. This method does not check the return value and is used
+ by the profiler.
+
+*******************************************************************************/
+
+void *methodtree_find_nocheck(void *pc)
+{
+ methodtree_element_t mtepc;
+ methodtree_element_t *mte;
+
+ mtepc.startpc = pc;
+ mtepc.endpc = pc;
+
+ mte = avl_find(methodtree, &mtepc);
+
+ if (mte == NULL)
+ return NULL;
+ else
+ return mte->startpc;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically 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/methodtree.h - AVL tree of methods
+
+ 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 _METHODTREE_H
+#define _METHODTREE_H
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "toolbox/avl.h"
+
+
+/* function prototypes ********************************************************/
+
+void methodtree_init(void);
+void methodtree_insert(void *startpc, void *endpc);
+void *methodtree_find(void *pc);
+void *methodtree_find_nocheck(void *pc);
+
+#endif /* _METHODTREE_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:
+ */
## src/vm/jit/mips/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.
##
\
md-abi.c \
md-abi.h \
- md.c
+ md-trap.h \
+ md.c \
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
/* src/vm/jit/mips/asmpart.S - Java-C interface functions for MIPS
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007, 2008 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
J. Wenninger, Institut f. Computersprachen - TU Wien
.set reorder /* XXX we need to recompute pv */
+calljava_return2:
move sp,s0 /* restore stack pointer */
-calljava_return2:
ald ra,0*8(sp) /* restore return address */
ald pv,1*8(sp) /* restore procedure vector */
ald s0,3*8(sp)
/* src/vm/jit/mips/codegen.c - machine code generator 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 "vm/jit/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
+#include "vm/jit/trap.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
/* get correct lock object */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_ALD(REG_A0, REG_PV, disp);
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
M_ALD(REG_ITMP3, REG_PV, disp);
M_BNEZ(REG_A0, 2);
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
M_JSR(REG_RA, REG_ITMP3);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, disp);
+ fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, disp);
+ fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, disp);
+ fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
/* src/vm/jit/mips/emit.c - MIPS code emitter functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
+#include "vm/jit/trap.h"
#include "vmcore/options.h"
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(reg, 2);
M_NOP;
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_ArithmeticException);
}
}
M_CMPULT(s2, REG_ITMP3, REG_ITMP3);
M_BNEZ(REG_ITMP3, 2);
M_NOP;
- M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_ALD_INTERN(s2, REG_ZERO, TRAP_ArrayIndexOutOfBoundsException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(REG_RESULT, 2);
M_NOP;
- M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_ArrayStoreException);
}
}
}
M_NOP;
- M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+ M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(reg, 2);
M_NOP;
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(REG_RESULT, 2);
M_NOP;
- M_ALD_INTERN(REG_RESULT, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+ M_ALD_INTERN(REG_RESULT, REG_ZERO, TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
- M_ALD_INTERN(REG_METHODPTR, REG_ZERO, EXCEPTION_HARDWARE_COMPILER);
+ M_ALD_INTERN(REG_METHODPTR, REG_ZERO, TRAP_COMPILER);
}
/* Get machine code which is patched back in later. The
trap is 1 instruction word long. */
- mcode = *((u4 *) cd->mcodeptr);
+ mcode = *((uint32_t *) cd->mcodeptr);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_PATCHER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
return mcode;
}
/* src/vm/jit/mips/linux/md-os.c - machine dependent MIPS Linux functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
/* md_init *********************************************************************
sp = (u1 *) (ptrint) _gregs[REG_SP];
ra = (u1 *) (ptrint) _gregs[REG_RA]; /* this is correct for leafs */
-#if !defined(__UCLIBC__) && ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 5))
+#if !defined(__UCLIBC__)
+# if ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 5))
/* NOTE: We only need this for pre glibc-2.5. */
xpc = (u1 *) (ptrint) _mc->pc;
xpc = xpc - 4;
break;
}
+# else
+ xpc = (u1 *) (ptrint) _mc->pc;
+# endif
#else
xpc = (u1 *) (ptrint) _gregs[CTX_EPC];
#endif
type = disp;
val = _gregs[d];
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
/* The XPC is the RA minus 4, because the RA points to the
instruction after the call. */
define is 0. */
addr = _gregs[s1];
- type = (s4) addr;
+ type = (int) addr;
val = 0;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* Set registers. */
switch (type) {
- case EXCEPTION_HARDWARE_COMPILER:
+ case TRAP_COMPILER:
if (p != NULL) {
_gregs[REG_PV] = (uintptr_t) p;
#if defined(__UCLIBC__)
/* fall-through */
- case EXCEPTION_HARDWARE_PATCHER:
+ case TRAP_PATCHER:
if (p == NULL) {
/* We set the PC again because the cause may have changed
the XPC. */
* It is outdated, too.
*/
-static inline long
-__attribute__ ((unused))
-atomic_swap (volatile long *p, long val)
-{
- long ret, temp;
-
- __asm__ __volatile__
- ("1:\n\t"
- ".set push\n\t"
- ".set mips2\n\t"
- "lld %2,%4\n\t"
- "move %0,%3\n\t"
- "scd %0,%1\n\t"
- ".set pop\n\t"
- "beqz %0,1b\n"
- : "=&r" (temp), "=m" (*p), "=&r" (ret)
- : "r" (val), "m" (*p)
- : "memory");
-
- return ret;
-}
static inline int
__attribute__ ((unused))
compare_and_swap (volatile long *p, long oldval, long newval)
#else
-static inline void
-atomic_add(int *mem, int val)
-{
- *mem += val;
-}
-
long compare_and_swap (long *p, long oldval, long newval);
#define STORE_ORDER_BARRIER()
-#define MEMORY_BARRIER_BEFORE_ATOMIC()
#define MEMORY_BARRIER_AFTER_ATOMIC()
#define MEMORY_BARRIER()
/* src/vm/jit/mips/md-abi.c - functions for MIPS ABI
- 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 <stdarg.h>
+#include <stdint.h>
#include "vm/types.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
+#include "vm/jit/stack.h"
#include "vmcore/descriptor.h"
#include "vmcore/method.h"
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
methodinfo *m;
methoddesc *md;
--- /dev/null
+/* src/vm/jit/mips/md-trap.h - MIPS hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (mips) the trap numbers are used as load
+ * displacements and thus must not be 4- or 8-byte aligned.
+ *
+ * NOTE: In trap_init() we have a check whether the offset of
+ * java_arrayheader.data[0] is greater than the largest displacement
+ * defined below. Otherwise normal array loads/stores could trigger
+ * an exception.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 1
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+
+ /* Don't use 4 (could be a normal load offset). */
+
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+
+ /* Don't use 8 (could be a normal load offset). */
+
+ TRAP_COMPILER = 9,
+ TRAP_END
+};
+
+#endif /* _MD_TRAP_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:
+ */
/* src/vm/jit/mips/patcher.c - MIPS code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
PATCH_BACK_ORIGINAL_MCODE;
*((s4 *) (ra + 1 * 4)) |=
(s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->class->index) & 0x0000ffff);
+ sizeof(methodptr*) * m->clazz->index) & 0x0000ffff);
/* patch method offset */
*((s4 *) (ra + 2 * 4)) |=
- (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x0000ffff);
+ (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x0000ffff);
/* synchronize instruction cache */
lsra.h \
ssa.c \
ssa.h \
+ ssa_phi.c \
+ ssa_phi.h \
+ ssa_rename.c \
+ ssa_rename.h \
graph.c \
graph.h \
dominators.c \
dominators.h \
lifetimes.c \
- lifetimes.h
+ lifetimes.h \
+ ssa2.c \
+ ssa3.c
endif
noinst_LTLIBRARIES = \
/* src/vm/jit/optimizing/dominators.c - dominators and dominance frontier
- 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
+*/
-*/
#include "mm/memory.h"
#include "toolbox/bitvector.h"
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
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 */
/*
Authors: Christian Ullrich
+ $Id: graph.c$
*/
int graph_get_first_(graph_element *ge, graphiterator *i);
void transform_CFG(jitdata *, graphdata *);
+void graph_phi_moves(jitdata *jd, basicblock *bptr, basicblock *dst_goto);
+
#ifdef GRAPH_DEBUG_VERBOSE
void graph_print(lsradata *ls, graphdata *gd);
#endif
/*********************************************************************+
After the "original" CFG has been created, it has to be adopted for
-SSA. (inluding insertion of new Basic Blocks)
+SSA. (inluding insertion of new Basic Blocks - edge splitting)
-TODO: Do not insert blocks right now - just adopt the call graph!
- After the phi moves are determined create only the needed Blocks
**********************************************************************/
void transform_CFG(jitdata *jd, graphdata *gd) {
int i, j, k, n, num_new_blocks;
/* copy Basic Block References to ls->basicblocks */
for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
-/* if (bptr->flags >= BBREACHED) { */
- _GRAPH_ASSERT(bptr->nr < jd->basicblockcount);
- ls->basicblocks[bptr->nr + 1] = bptr;
- bptr->nr = bptr->nr+1;
-/* } */
+ _GRAPH_ASSERT(bptr->nr < jd->basicblockcount);
+ ls->basicblocks[bptr->nr + 1] = bptr;
+ bptr->nr = bptr->nr+1;
}
/* Create new Basic Blocks:
- 0, [jd->new_basicblockcount..ls->basicblockcount[ */
+ 0, [jd->basicblockcount..ls->basicblockcount[ */
/* num_new_blocks have to be inserted*/
tmp = DMNEW( basicblock, num_new_blocks);
ls->basicblocks[0]->next = ls->basicblocks[1];
if (ls->basicblockcount > jd->basicblockcount + 1) {
+
/* new Blocks have to be inserted */
+
num_succ = DMNEW(int, ls->basicblockcount);
successor = DMNEW(graph_element *, ls->basicblockcount);
/* regard the + 1 for the already inserted new BB 0 */
/* So recreate ls->var_def */
+
var_def = DMNEW(int *, ls->basicblockcount);
for(i = 0; i < jd->basicblockcount + 1; i++) {
var_def[i] = ls->var_def[i];
}
/* Now Split the edges */
+
num_new_blocks = jd->basicblockcount + 1; /* first free new block index */
for(i = 0; i < jd->basicblockcount + 1; i++) {
if (graph_has_multiple_successors(gd, i)) {/* more than one successor */
/* splite the edge from BB i to j with the new BB */
/* num_new_blocks ( i->j --> i->nnb->j)*/
/* iter_succ shows the edge from i to j */
+
graph_split_edge(gd, i, &iter, num_new_blocks);
ls->basicblocks[num_new_blocks]->indepth =
_GRAPH_ASSERT(ls->basicblocks[num_new_blocks]->outdepth ==
ls->basicblocks[j]->indepth );
-#if 0
- /* !!!! There can't be inoutvar definitions in one of these */
- /* newly inserted basicblocks !!!! */
-
- /* Add Definition */
- /* decrease nr temporarly, because ssa_set_interface*/
- /* adds 1 since it is called from stack.c, where there is */
- /* no new BB 0 inserted like now */
-
- ls->basicblocks[num_new_blocks]->nr--;
- ssa_set_interface(jd, ls->basicblocks[num_new_blocks]);
- ls->basicblocks[num_new_blocks]->nr++;
-#endif
num_new_blocks++;
}
}
ls->basicblocks[pred]->next;
ls->basicblocks[pred]->next =
ls->basicblocks[n];
+#if 1
/* generate no instructions */
ls->basicblocks[n]->icount = 1;
ls->basicblocks[n]->iinstr = NEW(instruction);
ls->basicblocks[n]->iinstr[0].opc = ICMD_NOP;
+#else
+ graph_phi_moves(jd, ls->basicblocks[n], NULL);
+#endif
} else {
/* Block n is in the Branch path */
/* link Block at the end */
/* change the Branch Target to BB i */
-
-
switch(iptr->opc) {
case ICMD_LOOKUPSWITCH:
{
/* not handled by now -> fallback to regalloc */
exit(1);
}
-
+#if 1
/* Generate the ICMD_GOTO */
ls->basicblocks[n]->icount = 1;
ls->basicblocks[n]->iinstr =
ICMD_GOTO;
ls->basicblocks[n]->iinstr->dst.block =
ls->basicblocks[succ];
+#else
+ graph_phi_moves(jd, ls->basicblocks[n], ls->basicblocks[succ]);
+#endif
}
}
}
}
+/* graph_phi_moves *************************************************************
+
+generate the instruction array for Basicblock n (== ls->basicblocks[n])
+
+IN:
+basicblock *bptr Basicblock to change with ->iinstr == NULL
+basicblock *dst_goto Destination Block for ICMD_GOTO at end of Block, or
+ NULL for no ICMD_GOTO
+
+OUT:
+bptr->iinstr points to a newly allocated instruction array containing
+ the phi moves, the optional ICMD_GOTO at the end.
+bptr->icount Count of instructions in bptr->iinstr
+
+*******************************************************************************/
+
+void graph_phi_moves(jitdata *jd, basicblock *bptr, basicblock *dst_goto) {
+ int lt_d,lt_s,i;
+ lsradata *ls;
+ instruction *iptr;
+
+ ls = jd->ls;
+
+ _GRAPH_ASSERT(ls->num_phi_moves[bptr->nr] > 0);
+ bptr->icount = ls->num_phi_moves[bptr->nr];
+ if (dst_goto != NULL)
+ bptr->icount++;
+ bptr->iinstr = iptr = DMNEW(instruction, bptr->icount);
+
+ _GRAPH_ASSERT(iptr != NULL);
+
+ /* 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(GRAPH_DEBUG_VERBOSE)
+ if (compileverbose)
+ printf("graph_phi_moves: BB %3i Move %3i <- %3i\n", bptr->nr,
+ lt_d, lt_s);
+#endif
+ if (lt_s == UNUSED) {
+#if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose)
+ printf(" ... not processed \n");
+#endif
+ continue;
+ }
+
+ _GRAPH_ASSERT(d->type != -1);
+ _GRAPH_ASSERT(s->type == -1);
+
+ iptr->opc = ICMD_MOVE;
+ iptr->s1.varindex = ls->lifetime[lt_s].v_index;
+ iptr->dst.varindex = ls->lifetime[lt_d].v_index;
+ iptr++;
+ }
+
+ if (dst_goto != NULL) {
+ iptr->opc = ICMD_GOTO;
+ iptr->dst.block = dst_goto;
+ }
+}
+
#ifdef GRAPH_DEBUG_VERBOSE
void graph_print(lsradata *ls, graphdata *gd) {
int i,j;
/* src/vm/jit/lsra.inc - lifetime anaylsis
- 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
-
-
*/
+
#include <stdio.h>
#include <stdlib.h>
continue;
i = ls->var_0[i];
/* _LT_ASSERT( i < jd->cd->maxlocals); */
-#ifdef LT_DEBUG_VERBOSE
- if (compileverbose)
- printf("param %3i -> L %3i/%3i",p,i,t);
-#endif
+/* printf("param %3i -> L %3i/%3i\n",p,i,t); */
_LT_ASSERT(t == VAR(i)->type);
/* Param to Local init happens before normal Code */
atime++;
diff += 1000000;
}
- printf("%8li %s.%s.%s\n",diff, m->class->name->text, m->name->text,
+ printf("%8li %s.%s.%s\n",diff, m->clazz->name->text, m->name->text,
m->descriptor->text);
}
#endif
/* real ICMD, no phi-function, no param initialisation */
_LT_ASSERT(ls->basicblocks[b_index]->iinstr != NULL);
+
iptr = ls->basicblocks[b_index]->iinstr + iindex;
if (icmd_table[iptr->opc].flags & ICMDTABLE_CALLS)
lt->savedvar = SAVEDVAR;
lt_is_live(ls, lt, b_index, iindex);
- if (iindex == -ls->varcount-1) {
+ if (iindex == -ls->ssavarcount-1) {
#ifdef LT_DEBUG_VERBOSE
if ((compileverbose))
lt->v_index, b_index, iindex);
#endif
/* iindex is the first statement of b_index */
- /* Statements -ls->max_vars-1 .. -1 are possible phi functions*/
+ /* Statements -ls->ssavarcounts-1 .. -1 are possible phi functions*/
/* lt->v_index is live-in at b_index */
pred = graph_get_first_predecessor(gd, b_index, &pred_iter);
/* look through phi functions */
- for(; prev_iindex > -ls->varcount-1; prev_iindex--)
+ for(; prev_iindex > -ls->ssavarcount-1; prev_iindex--)
if (ls->phi[b_index][-prev_iindex-1] != NULL)
break;
void lt_move_use_sites(struct lifetime *from, struct lifetime *to) {
struct site *s;
+#if 0
+ /* not anymore true for copy propagated lifetimes */
_LT_ASSERT(from->use != NULL);
+#endif
if (from->use == NULL)
return;
for(s = from->use; s->next != NULL; s = s->next);
}
}
-
if (bptr->iinstr != NULL) {
/* set iptr to last instruction of BB */
iptr = bptr->iinstr + iindex;
-/* src/vm/jit/lsra/graph.h - lifetimes header
+/* src/vm/jit/optimizing/lifetimes.h - lifetimes 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
-
-
*/
typedef struct site *lt_iterator;
void lt_scanlifetimes(jitdata *, graphdata *, dominatordata *);
-void lt_add_ss(struct lifetime *, stackptr );
+void lt_add_ss(struct lifetime *, stackelement_t *);
void lt_remove_use_site(struct lifetime *lt, int block, int iindex);
void lt_move_use_sites(struct lifetime *from, struct lifetime *to);
void lt_lifeness_analysis(jitdata *, graphdata *);
/* src/vm/jit/optimizing/lsra.inc - linear scan register allocator
- Copyright (C) 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) 2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/reg.h"
#include "vm/jit/jit.h"
-
#include "vm/jit/optimizing/graph.h"
#include "vm/jit/optimizing/lifetimes.h"
#include "vm/jit/optimizing/ssa.h"
#include "vm/jit/optimizing/lsra.h"
-#ifdef LSRA_TESTLT
-# include "vm/resolve.h"
-#include "vm/builtin.h"
-#endif
-
-
#include "toolbox/logging.h"
extern const char *string_java_lang_InternalError;
/* function prototypes */
-void lsra_init(jitdata *);
-graphdata *lsra_setup(jitdata *);
+void lsra_setup(jitdata *);
void lsra_main(jitdata *);
#ifdef LSRA_DEBUG_VERBOSE
-void lsra_dump_stack(stackptr );
+void lsra_dump_stack(stackelement_t*);
void print_lifetimes(jitdata *, int *, int);
void print_all_lifetimes(jitdata *);
#endif
codegendata *cd;
registerdata *rd;
lsradata *ls;
- graphdata *gd;
#if defined(ENABLE_STATISTICS)
int locals_start;
int i,j;
#if defined(LSRA_DEBUG_CHECK)
#if 0
int b_index;
- stackptr in,out;
+ stackelement_t* in,out;
int ind, outd;
#endif
#endif
#if defined(LSRA_DEBUG_CHECK) || defined(LSRA_DEBUG_VERBOSE)
#if defined(LSRA_DEBUG_VERBOSE)
if (compileverbose) {
- printf("%s %s ",m->class->name->text, m->name->text);
- if (code_is_leafmethod(code))
+ printf("%s %s ",m->clazz->name->text, m->name->text);
+ if (code_is_leafmethod(jd->code))
printf("**Leafmethod**");
printf("\n");
}
#endif
- if (strcmp(m->class->name->text,"java/lang/String")==0)
+ if (strcmp(m->clazz->name->text,"java/lang/String")==0)
if (strcmp(m->name->text,"toLowerCase")==0)
#if defined(LSRA_DEBUG_VERBOSE)
if (compileverbose)
{ int dummy=1; dummy++; }
#endif
#endif
-
- lsra_init(jd);
- gd = lsra_setup(jd);
+
+ lsra_setup(jd);
#if defined(ENABLE_STATISTICS)
/* find conflicts between locals for statistics */
#endif
/* Run LSRA */
lsra_main(jd);
-#ifdef LSRA_TESTLT
- test_lifetimes( jd, gd );
-#endif
+
fflush(stdout);
}
-void lsra_init(jitdata *jd)
-{
- lsradata *ls = jd->ls;
-
- /* Init LSRA Data Structures */
- /* allocate lifetimes for all Basicblocks */
-
- ls->v_index = -1;
-}
-
-graphdata *lsra_setup(jitdata *jd)
+void lsra_setup(jitdata *jd)
{
methodinfo *m;
codegendata *cd;
registerdata *rd;
lsradata *ls;
- graphdata *gd;
#if defined(ENABLE_LOOPS)
/* Loop optimization "destroys" the basicblock array */
rd = jd->rd;
ls = jd->ls;
- ssa_init(jd);
-
- /* Setup LSRA Data structures */
-
- /* Generate the Control Flow Graph */
- /* Add one for a Basic Block 0 to be inserted, so lateron */
- /* with SSA Parameter initialization is handled right */
- gd = graph_init(jd->basicblockcount + 1);
- graph_make_cfg(jd, gd);
- ssa(jd, gd);
- lt_lifeness_analysis(jd, gd);
-
#ifdef LSRA_DEBUG_VERBOSE
if (compileverbose) {
printf("Lifetimes after LifenessAnalyse: \n");
printf("Basicblockcount: %4i\n",ls->basicblockcount);
}
#endif
- return gd;
}
void lsra_reg_setup(jitdata *jd,
int_reg->nregdesc = nregdescint;
flt_reg->nregdesc = nregdescfloat;
- if (code_is_leafmethod(code)) {
+ if (code_is_leafmethod(jd->code)) {
/* Temp and Argumentregister can be used as saved registers */
int_reg->sav_top = INT_ARG_CNT + INT_TMP_CNT + INT_SAV_CNT;
int param_count;
int i,j,tmp;
- /* count number of parameters ( .i_start == -1) */
+ /* count number of parameters ( .i_start == 0) */
for (param_count=0; (param_count < lifetime_count) &&
-/* (ls->lifetime[lifetime[param_count]].i_start == -1); param_count++); */
(ls->lifetime[lifetime[param_count]].i_start == 0); param_count++);
if (param_count > 0) {
for (p=fmem; (p->next!=NULL) && (p->next->end < fm->end); p=p->next);
fm->next=p->next;
p->next=fm;
- return fm->off;
+ /* HACK: stackslots are 8 bytes on all architectures for now, I hope.
+ * -- pm
+ */
+ return fm->off * 8;
}
struct freemem *lsra_getnewmem(int *mem_use)
#ifdef LSRA_SAVEDVAR
lt->savedvar = SAVEDVAR;
#endif
- if (lt->savedvar || code_is_leafmethod(code)) {
+ if (lt->savedvar || code_is_leafmethod(jd->code)) {
/* use Saved Reg (in case of leafmethod all regs are saved regs) */
if (reg->sav_top > regsneeded) {
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
if (active[i]->i_end > lt->i_start) break;
/* make active[i]->reg available again */
- if (code_is_leafmethod(code)) {
+ if (code_is_leafmethod(jd->code)) {
/* leafmethod -> don't care about type -> put all again into */
/* reg->sav_reg */
#if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
ls = jd->ls;
- if (lt->savedvar || code_is_leafmethod(code)) {
+ if (lt->savedvar || code_is_leafmethod(jd->code)) {
_spill_at_intervall(lt, ls->active_sav, &(ls->active_sav_top));
} else {
_spill_at_intervall(lt, ls->active_tmp, &(ls->active_tmp_top));
switch (lt->type) {
case TYPE_LNG:
-#if defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
+#if (defined(HAS_4BYTE_STACKSLOT) && !defined(SUPPORT_COMBINE_INTEGER_REGISTERS)) || defined (__I386__)
flags = 0;
#else
flags = 1;
Authors: Christian Ullrich
+ $Id: lsra.h,v 1.17 2005/11/22 14:36:16 christian Exp $
*/
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)<(b)?(b):(a))
-struct _backedge {
- int start;
- int end;
- int nesting;
- struct _backedge *next;
-};
-
struct site {
int b_index;
int iindex;
int nesting;
};
-/*
-struct stackslot {
- stackptr s;
- int bb;
- struct stackslot *next;
-};
-*/
-
struct lsra_register {
int *sav_reg;
int *tmp_reg;
int use;
};
-struct igraph_lookup {
- int var;
- int igraph;
-};
-
-struct igraph_interference {
- int v1;
- int v2;
- struct igraph_interference *next;
-};
-
-struct igraph_vars {
- int v;
- struct igraph_vars *next;
-};
-
-struct igraph {
- struct igraph_interference *inter;
- struct igraph_vars *vars;
-};
-
-
struct lsradata {
- /* int *var; */ /* unused entries are set to UNUSED */
- /* maps to jd->vars array */
int varcount; /* size of vars array */
int ssavarcount; /* ls->vars[0..ssavarcount[ are all locals and iovars */
/* they are regarded for ssa renaming */
int *sorted; /* BB sorted in reverse post order */
int *sorted_rev; /* BB reverse lookup of sorted */
- struct _backedge **backedge; /* backedge data structure */
- int backedge_count; /* number of backedges */
-
long *nesting; /* Nesting level of BB*/
struct lifetime *lifetime; /* array of lifetimes */
int active_tmp_top, active_sav_top;
struct lsra_exceptiontable *ex;
- int v_index; /* next free index for stack slot lifetimes */
- /* decrements from -1 */
/* SSA fields */
bitvector *var_def; /* LocalVar Definition Bitvector [0..ls->bbcount] */
int **stack;
int *stack_top;
- /* structures for phi var interference graphs */
- struct igraph_lookup **igraph_lookup; /* var to igraph index */
- int igraph_lookup_top; /* number of entries in above table */
- struct igraph *igraph; /* interference graphs */
- int igraph_top;
};
/* src/vm/jit/optimizing/profile.c - runtime profiling
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
-#include "threads/threads-common.h"
+#include "threads/threadlist.h"
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/stringlocal.h"
#include "vm/jit/jit.h"
#include "vm/jit/methodheader.h"
+#include "vm/jit/methodtree.h"
+
#include "vm/jit/optimizing/recompile.h"
#include "vmcore/class.h"
/* lock the threads lists */
- threads_list_lock();
+ threadlist_lock();
/* iterate over all started threads */
- for (t = threads_list_first(); t != NULL; t = threads_list_next(t)) {
+ for (t = threadlist_first(); t != NULL; t = threadlist_next(t)) {
/* is this a Java thread? */
if (!(t->flags & THREAD_FLAG_JAVA))
pc = t->pc;
- /* get the PV for the current PC */
+ /* Get the PV for the current PC. */
- pv = codegen_get_pv_from_pc_nocheck(pc);
+ pv = methodtree_find_nocheck(pc);
/* get methodinfo pointer from data segment */
/* unlock the threads lists */
- threads_list_unlock();
+ threadlist_unlock();
}
}
#endif
/* src/vm/jit/optimizing/recompile.c - recompilation system
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
#include "threads/lock-common.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/list.h"
#include "vm/jit/optimizing/recompile.h"
#include "vmcore/classcache.h"
+#include "vmcore/options.h"
/* global variables ***********************************************************/
bool recompile_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("recompile_init");
+
/* initialize the recompile lock object */
lock_thread_recompile = NEW(java_object_t);
/* src/vm/jit/optimizing/ssa.c - static single-assignment form
- Copyright (C) 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) 2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/jit.h" /* icmd_table */
+#include "vm/jit/ir/bytecode.h"
+
#include "vm/jit/optimizing/dominators.h"
#include "vm/jit/optimizing/graph.h"
#include "vm/jit/optimizing/lifetimes.h"
#include "vm/jit/optimizing/lsra.h"
#include "vm/jit/optimizing/ssa.h"
+#include "vm/jit/optimizing/ssa_rename.h"
+#include "vm/jit/optimizing/ssa_phi.h"
+
+#include "vm/jit/python.h"
#if defined(SSA_DEBUG_VERBOSE)
#include "vmcore/options.h" /* compileverbose */
void copy_propagation(jitdata *jd, graphdata *gd);
void ssa_replace_use_sites(jitdata *, graphdata *, struct lifetime *,
int , worklist *);
-void ssa_place_phi_functions(jitdata *jd, graphdata *gd, dominatordata *dd);
-void ssa_rename_init(jitdata *jd, graphdata *gd);
-void ssa_rename(jitdata *jd, graphdata *gd, dominatordata *dd);
-void ssa_rename_(jitdata *jd, graphdata *gd, dominatordata *dd, int n);
void ssa_set_def(lsradata *, int , int );
void ssa_set_local_def(lsradata *, int , int );
void ssa_set_iovar(lsradata *, s4 , int , s4 *);
void ssa_set_interface(jitdata *, basicblock *, s4 *);
-void ssa_generate_phi_moves(jitdata *, graphdata *);
-int ssa_rename_def_(lsradata *ls, int a);
#ifdef SSA_DEBUG_VERBOSE
void ssa_print_trees(jitdata *jd, graphdata *gd, dominatordata *dd);
void ssa_print_lt(lsradata *ls);
+void _ssa_print_lt(struct lifetime *lt);
void ssa_show_variable(jitdata *jd, int index, varinfo *v, int stage);
void ssa_print_phi(lsradata *, graphdata *);
#endif
SSA main procedure:
-******************************************************************************/
+SSA Algorithms are based on "modern compiler implementation in C" from andrew
+w. appel, edition 2004
+
+Corrections:
+page 441 Algorithm 19.6. Inserting phi-functions:
+
+...
+ for each Y in DF[n]
+- if Y not element of A phi [n]
++ if a not element of A phi [n]
+ insert the statment a <- ...
+...
+...
+- A phi [n] <- A phi [n] join {Y}
++ A phi [n] <- A phi [n] join {a}
+- if Y not element of A orig [n]
++ if a not element of A orig [Y]
+ W <- W join {Y}
-void ssa(jitdata *jd, graphdata *gd) {
+******************************************************************************/
+void xssa(jitdata *jd);
+void yssa(jitdata *jd);
+void ssa(jitdata *jd) {
struct dominatordata *dd;
lsradata *ls;
+ graphdata *gd;
+
+#if defined(ENABLE_LOOPS)
+ /* Loop optimization "destroys" the basicblock array */
+ /* TODO: work with the basicblock list */
+ if (opt_loops) {
+ log_text("lsra not possible with loop optimization\n");
+ exit(1);
+ }
+#endif
+
+ cfg_add_root(jd);
+ cfg_add_exceptional_edges(jd);
+ /*pythonpass_run(jd, "foo", "cfg_print");*/
+ /*dominator_tree_validate(jd, dd);*/
+ /*pythonpass_run(jd, "ssa2", "main");*/
+ /*pythonpass_run(jd, "alt_ssa", "main");*/
+ pythonpass_run(jd, "foo", "before");
+ if (getenv("XSSA")) {
+ dominator_tree_build(jd);
+ dominance_frontier_build(jd);
+ xssa(jd);
+ } else {
+ yssa(jd);
+ }
+ pythonpass_run(jd, "foo", "after");
+ return;
ls = jd->ls;
+ ssa_init(jd);
+ /* Generate the Control Flow Graph */
+ /* Add one for a Basic Block 0 to be inserted, so lateron */
+ /* with SSA Parameter initialization is handled right */
+
+ gd = graph_init(jd->basicblockcount + 1);
+ graph_make_cfg(jd, gd);
+
dd = compute_Dominators(gd, ls->basicblockcount);
computeDF(gd, dd, ls->basicblockcount, 0);
ssa_print_lt(ls);
}
#endif
-/* dead_code_elimination(jd, gd); */
+ if (opt_ssa_dce) {
+ dead_code_elimination(jd, gd);
#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
- printf("Phi after dead code elemination\n");
- ssa_print_phi(ls, gd);
- ssa_print_lt(ls);
- }
+ if (compileverbose) {
+ printf("Phi after dead code elemination\n");
+ ssa_print_phi(ls, gd);
+ ssa_print_lt(ls);
+ }
#endif
-/* copy_propagation(jd, gd); */
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
- printf("Phi after copy propagation\n");
- ssa_print_phi(ls, gd);
- ssa_print_lt(ls);
}
+ if (opt_ssa_cp) {
+ copy_propagation(jd, gd);
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("Phi after copy propagation\n");
+ ssa_print_phi(ls, gd);
+ ssa_print_lt(ls);
+ }
#endif
+ }
ssa_generate_phi_moves(jd, gd);
transform_BB(jd, gd);
+ lt_lifeness_analysis(jd, gd);
#ifdef SSA_DEBUG_CHECK
{
if ((in[in_d] != out[out_d]) ||
(VAR(in[in_d])->flags != VAR(out[out_d])->flags)) {
printf("Method: %s %s\n",
- m->class->name->text, m->name->text);
+ m->clazz->name->text, m->name->text);
printf("Error: Stack Varnum Mismatch BBin %3i BBout %3i Stackdepth %3i\n", i, pred, in_d);
if (compileverbose)
printf("Error: Stack Varnum Mismatch BBin %3i BBout %3i Stackdepth %3i\n", i, pred, in_d);
#endif
-
#ifdef SSA_DEBUG_VERBOSE
if (compileverbose)
ssa_print_trees(jd, gd, dd);
#endif
+
}
/* ssa_init *******************************************************************
#if defined(SSA_DEBUG_CHECK) || defined(SSA_DEBUG_VERBOSE)
# if defined(SSA_DEBUG_VERBOSE)
if (compileverbose) {
- printf("%s %s ",m->class->name->text, m->name->text);
- if (code_is_leafmethod(code))
+ printf("%s %s ",m->clazz->name->text, m->name->text);
+ if (code_is_leafmethod(jd->code))
printf("**Leafmethod**");
printf("\n");
}
# endif
- if (strcmp(m->class->name->text,"spec/benchmarks/_213_javac/Parser")==0)
+ if (strcmp(m->clazz->name->text,"spec/benchmarks/_213_javac/Parser")==0)
if (strcmp(m->name->text,"parseTerm")==0)
# if defined(SSA_DEBUG_VERBOSE)
if (compileverbose)
jd->basicblockcount, jd->localcount);
#endif
- /* As first step all definitions of local variables and in/out vars are */
- /* gathered. in/outvars are coalesced for same type and depth */
- /* "normal" tempvars (just living within one basicblock are) ignored */
-
- /* ls->var holds the index to jd->vars */
+ /* As first step all definitions of local variables and in/out vars are */
+ /* gathered. in/outvars are coalesced for same type and depth */
+ /* "normal" tempvars (just living within one basicblock are) ignored */
ls->num_defs = DMNEW(int, jd->varcount);
ls->new_varindex = DMNEW(int , jd->varcount);
ls->ssavarcount = 0;
- /* Add parameters first in right order, so the new local indices */
- /* 0..p will correspond to "their" parameters */
- /* They get defined at the artificial Block 0, the real method bbs will be*/
- /* moved to start at block 1 */
+ /* Add parameters first in right order, so the new local indices */
+ /* 0..p will correspond to "their" parameters */
+ /* They get defined at the artificial Block 0, the real method bbs will */
+ /* be ed to start at block 1 */
/* don't look at already eliminated (not used) parameters (locals) */
if (v != UNUSED) {
if (( v < jd->localcount) || ( VAR(v)->flags & INOUT )) {
+
/* !IS_TEMPVAR && !IS_PREALLOC == (IS_LOCALVAR || IS_INOUT) */
-/* _SSA_ASSERT(ls->new_varindex[v] != UNUSED); */
ssa_set_local_def(ls, b_index, v);
}
}
}
}
_SSA_ASSERT(ls->ssavarcount < jd->varcount);
+
#ifdef SSA_DEBUG_VERBOSE
if (compileverbose) {
-
printf("ssa_init: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
ls->ssavarcount);
for(i = 0; i < jd->varcount; i++) {
}
ssa_set_iovar(ls, out[out_d], o_map_index, interface_map);
if (in_d == out_d) {
- if (in[in_d] != out[out_d]) {
-
- /* out interface stackslot is defined in this basic block */
-
-/* ssa_set_def(ls, bptr->nr + 1, ls->new_varindex[out[out_d]]); */
- }
out_d--;
in_d--;
}
else {
-
- /* in_d < out_d */
- /* out interface stackslot is defined in this basic block */
-
-/* ssa_set_def(ls, bptr->nr + 1, ls->new_varindex[out[out_d]]); */
out_d--;
}
}
}
-/* ssa_place_phi_functions *****************************************************
-
-ls->phi[n][a][p] is created and populated.
-
-For each basicblock Y in the dominance frontier of a basicblock n (0 <= n <
-ls->basicblockcount)in which a variable (0 <= a < ls->ssavarcount) is defined an
-entry in ls->phi[Y][a] is created.
-This entry is an array with the number of predecessors of Y elements + 1 elements.
-This elements are all set to the variable a and represent the phi function which
-will get ai = phi(ai1, ai2, ..., aip) after ssa_rename.
-
-*******************************************************************************/
-
-
-void ssa_place_phi_functions(jitdata *jd, graphdata *gd, dominatordata *dd)
-{
- int a,i,j,n,Y;
- bitvector *def_sites;
- bitvector *A_phi; /* [0..ls->basicblockcount[ of ls->ssavarcount Bit */
- worklist *W;
- int num_pred;
-
- lsradata *ls;
-
- ls = jd->ls;
-
- W = wl_new(ls->basicblockcount);
-
- def_sites = DMNEW(bitvector, ls->ssavarcount);
- for(a = 0; a < ls->ssavarcount; a++)
- def_sites[a] = bv_new(ls->basicblockcount);
-
- ls->phi = DMNEW(int **, ls->basicblockcount);
- A_phi = DMNEW(bitvector, ls->basicblockcount);
- for(i = 0; i < ls->basicblockcount; i++) {
- ls->phi[i] = DMNEW(int *, ls->ssavarcount);
- for(j = 0; j < ls->ssavarcount; j++)
- ls->phi[i][j] = NULL;
- A_phi[i] = bv_new(ls->ssavarcount);
- }
-
- /* copy var_def to def_sites */
- /* var_def is valid for 0.. jd->basicblockcount (bb 0 for param init) */
-
- for(n = 0; n <= jd->basicblockcount; n++)
- for(a = 0; a < ls->ssavarcount; a++)
- if (bv_get_bit(ls->var_def[n], a))
- bv_set_bit(def_sites[a], n);
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
- printf("var Definitions:\n");
- for(i = 0; i < ls->ssavarcount; i++) {
- printf("def_sites[%3i]=%p:",i,(void *)def_sites[i]);
- for(j = 0; j < ls->basicblockcount; j++) {
- if ((j % 5) == 0) printf(" ");
- if (bv_get_bit(def_sites[i], j))
- printf("1");
- else
- printf("0");
- }
- printf(" (");
-
- printf("\n");
- }
- }
-#endif
-
- for(a = 0; a < ls->ssavarcount; a++) {
-
- /* W<-def_sites(a) */
-
- for(n = 0; n < ls->basicblockcount; n++)
- if (bv_get_bit(def_sites[a],n)) {
- wl_add(W, n);
- }
-
- while (!wl_is_empty(W)) { /* W not empty */
- n = wl_get(W);
-
- for(i = 0; i < dd->num_DF[n]; i++) {
- Y = dd->DF[n][i];
- /* Node Y is in Dominance Frontier of n -> */
- /* insert phi function for a at top of Y*/
- _SSA_CHECK_BOUNDS(Y, 0, ls->basicblockcount);
- if (bv_get_bit( A_phi[Y], a) == 0) {
- /* a is not a Element of A_phi[Y] */
- /* a <- phi(a,a...,a) to be inserted at top of Block Y */
- /* phi has as many arguments, as Y has predecessors */
-#if 0
-#if 0
- /* do not add a phi function for interface stackslots */
- /* if a predecessor is not a def site of a <==> */
- /* the block does not have the corresponding inslot*/
-
-/* if ((ls->var_to_index[a] >= 0) || */
-/* (bv_get_bit(def_sites[a], */
-/* graph_get_first_predecessor(gd, Y, &iter)))) */
-
-#endif
- /* for interface stackslots add a phi function only */
- /* if the basicblock has the corresponding incoming */
- /* stackslot -> it could be, that the stackslot is */
- /* not live anymore at Y */
-
-#endif
- num_pred = graph_get_num_predecessor(gd, Y);
- ls->phi[Y][a] = DMNEW(int, num_pred + 1);
- for (j = 0; j < num_pred + 1; j++)
- ls->phi[Y][a][j] = a;
- /* increment the number of definitions of a by one */
- /* for this phi function */
- ls->num_defs[a]++;
-
- bv_set_bit(A_phi[Y], a);
- if (bv_get_bit(ls->var_def[Y],a)==0) {
- /* Iterated Dominance Frontier Criterion:*/
- /* if Y had no definition for a insert it*/
- /* into the Worklist, since now it */
- /* defines a through the phi function */
- wl_add(W, Y);
- }
- }
- }
- }
- }
-}
-
-/* ssa_rename ******************************************************************
-
-Rename the variables a (0 <= a < ls->ssavarcount) so that each new variable
-has only one definition (SSA form).
-
-ls->def_count[0..ls->ssavarcount[ holds the number of definitions of each var.
-ls->var_0[0..ls->ssavarcount[ will be set to the new index of the first
- definition of each old var.
-ls->varcount_with_indices will be se to the new maximum varcount of LOCAL
- and IOVARS.
-
-All other vars (TEMPVAR and PREALLOC) will get a new unique index above
-ls->varcount_with_indices.
-
-jd->var and jd->varcount will be set for this renamed vars.
-
-*******************************************************************************/
-
-void ssa_rename(jitdata *jd, graphdata *gd, dominatordata *dd)
-{
- int i, mi, l, j, p, t;
- int type, flags;
- methoddesc *md = jd->m->parseddesc;
-
- varinfo *new_vars;
- lsradata *ls;
-
- ls = jd->ls;
-
- ssa_rename_init(jd, gd);
-
- /* Consider definition of Local Vars initialized with Arguments */
- /* in Block 0 */
- /* init is regarded as use too-> ssa_rename_use ->bullshit!!*/
- for (p = 0, l= 0; p < md->paramcount; p++) {
- t = md->paramtypes[p].type;
- mi = l * 5 + t;
- i = jd->local_map[mi];
- l++;
- if (IS_2_WORD_TYPE(t))
- l++;
- if (i == UNUSED)
- continue;
- /* !!!!! locals are now numbered as the parameters !!!! */
- /* !!!!! no additional increment for 2 word types !!!!! */
- /* this happens later on! here we still need the increment */
- /* index of var can be in the range from 0 up to not including */
- /* CD->maxlocals */
-
- /* ignore return value, since first definition gives 0 -> */
- /* no rename necessary */
-
- i = ls->new_varindex[i];
- j = ssa_rename_def_(ls, i);
- _SSA_ASSERT(j == 0);
- jd->local_map[mi] = i;
- }
- ssa_rename_(jd, gd, dd, 0);
-
-#if 0
- /* DO _NOT_ DO THIS! Look at java.util.stringtokenizer.counttokens! */
- /* if there is no use of the defined Var itself by the phi function */
- /* for a loop path, in which this var is not used, it will not be life */
- /* in this path and overwritten! */
-
- /* Invalidate all xij from phi(xi0)=xi1,xi2,xi3,..,xin with xij == xi0 */
- /* this happens if the phi function is the first definition of x or in a */
- /* path with a backedge xi has no definition */
- /* a phi(xij) = ...,xij,... with the only use and definition of xij by */
- /* this phi function would otherwise "deadlock" the dead code elemination */
- /* invalidate means set it to ls->max_vars_with_indices */
- /* a phi function phi(xi0)=xi1,xi2,...xin wiht xij == xi0 for all j in */
- /* [1,n] can be removed */
-
- for(i = 0; i < ls->ssavarcount; i++) {
- for(t = 0; t < ls->basicblockcount; t++) {
- if (ls->phi[t][i] != 0) {
- remove_phi = true;
- for(p = 1; p <= graph_get_num_predecessor(gd, t); p++) {
- if (ls->phi[t][i][0] == ls->phi[t][i][p])
- ls->phi[t][i][p] = ls->varcount_with_indices;
- else
- remove_phi = false;
- }
- }
- if (remove_phi)
- ls->phi[t][i] = NULL;
- }
- }
-#endif
-
-#if defined(SSA_DEBUG_CHECK) || defined(SSA_DEBUG_VERBOSE)
-# if defined(SSA_DEBUG_VERBOSE)
- if (compileverbose) {
- printf("%s %s ",jd->m->class->name->text, jd->m->name->text);
- if (code_is_leafmethod(code))
- printf("**Leafmethod**");
- printf("\n");
- }
-# endif
- if (strcmp(jd->m->class->name->text,"fp")==0)
- if (strcmp(jd->m->name->text,"testfloat")==0)
-# if defined(SSA_DEBUG_VERBOSE)
- if (compileverbose)
- printf("12-------------------12\n");
-# else
- { int dummy=1; dummy++; }
-# endif
-#endif
- /* recreate rd->locals[][] */
- /* now only one (local_index/type) pair exists anymore */
- /* all var[t][i] with var_to_index[var[t][i]] >= 0 are locals */
- /* max local index after SSA indexing is in ls->local_0[ls->max_locals] */
-
- new_vars = DMNEW(varinfo, ls->vartop);
- for(i = 0; i < ls->vartop ; i++)
- new_vars[i].type = UNUSED;
- for(i = 0; i < jd->varcount; i++) {
- p = ls->new_varindex[i];
- if (p != UNUSED) {
- if (p < ls->ssavarcount)
- p = ls->var_0[p];
- new_vars[p].type = VAR(i)->type;
- new_vars[p].flags = VAR(i)->flags;
- ls->lifetime[p].v_index = p;
- ls->lifetime[p].type = VAR(i)->type;
- }
- }
-
- /* take care of newly indexed local & in/out vars */
-
- for(i = 0; i < ls->ssavarcount; i++) {
- j = ls->var_0[i];
- type = new_vars[j].type;
- flags = new_vars[j].flags;
- j++;
- for (; j < ls->var_0[i + 1]; j++) {
- new_vars[j].type = type;
- new_vars[j].flags = flags;
- ls->lifetime[j].v_index = j;
- ls->lifetime[j].type = type;
- }
- }
-
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
-
- printf("ssa_rename: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
- ls->ssavarcount);
- for(i = 0; i < jd->varcount; i++) {
- printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
- ssa_show_variable(jd, i, VAR(i),0);
- j = ls->new_varindex[i];
- if ((j != UNUSED) && (j < ls->ssavarcount))
- printf(" -> %3i ... %3i", ls->var_0[j], ls->var_0[j + 1] - 1);
- else
- printf(" -> %3i", j);
- printf("\n");
- }
- }
-#endif
-
- jd->var = new_vars;
- jd->varcount = ls->vartop;
- jd->vartop = ls->vartop;
-
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
- printf("ssa_rename: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
- ls->ssavarcount);
- for(i = 0; i < jd->varcount; i++) {
- printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
- ssa_show_variable(jd, i, VAR(i),0);
- printf("\n");
- }
- }
-#endif
-}
-
-/* ssa_rename_init *************************************************************
-
-Setup the data structure for ssa_rename
-
-ls->def_count[0..ls->ssavarcount[ holds the number of definitions of each var.
-ls->var_0[0..ls->ssavarcount[ will be set to the new index of the first
- definition of each old var.
-ls->varcount_with_indices will be se to the new maximum varcount of LOCAL
- and IOVARS.
-
-All other vars (TEMPVAR and PREALLOC) will get a new unique index above
-ls->varcount_with_indices.
-
-jd->var and jd->varcount will be set for this renamed vars.
-
-*******************************************************************************/
-
-void ssa_rename_init(jitdata *jd, graphdata *gd)
-{
- int a, i, p;
- lsradata *ls;
-
- ls = jd->ls;
-
- /* set up new locals */
- /* ls->new_varindex[0..jd->varcount[ holds the new unique index */
- /* for locals and iovars */
-
- /* ls->num_defs[index] gives the number of indizes which will be created */
- /* from SSA */
-
- /* -> vars will be numbered in this sequence: L0(0)..L0(i) L1(0)..L1(j) ..*/
- /* ls->var_0[X] will point to each LX(0) */
- /* ls->var_0[ls->ssavarcount] will hold ls->varcount_with_indices */
-
- /* as first step cummulate the num_defs array for locals and iovars */
- /* last element is the maximum var count */
-
- ls->var_0 = DMNEW(int, max(1, ls->ssavarcount + 1));
- ls->var_0[0] = 0;
- ls->varcount_with_indices = 0;
- for(i = 0; i < ls->ssavarcount; i++) {
- ls->varcount_with_indices += ls->num_defs[i];
- ls->var_0[i+1] = ls->var_0[i] + ls->num_defs[i];
- }
-
-#if 0
- /* Change the var indices in phi from La to La(0) */
-
- for(i = 0; i < ls->basicblockcount; i++)
- for (a = 0; a < ls->ssavarcount; a++)
- if (ls->phi[i][a] != NULL)
- for(p = 0; p < graph_get_num_predecessor(gd, i) + 1; p++)
- ls->phi[i][a][p] = ls->var_0[a];
-#endif
-
- /* Initialization */
-
- ls->count = DMNEW(int, max(1, ls->ssavarcount));
- ls->stack = DMNEW(int *, max(1, ls->ssavarcount));
- ls->stack_top = DMNEW(int, max(1, ls->ssavarcount));
- for(a = 0; a < ls->ssavarcount; a++) {
- ls->count[a] = 0;
- ls->stack_top[a] = 0;
-
- /* stack a has to hold number of defs of a Elements + 1 */
-
- ls->stack[a] = DMNEW(int, ls->num_defs[a] + 1);
- ls->stack[a][ls->stack_top[a]++] = 0;
- }
-
- if (ls->ssavarcount > 0) {
-
- /* Create the num_var_use Array */
-
- ls->num_var_use = DMNEW(int *, ls->basicblockcount);
- for(i = 0; i < ls->basicblockcount; i++) {
- ls->num_var_use[i] =DMNEW(int, max(1, ls->varcount_with_indices));
- for(a = 0; a < ls->varcount_with_indices; a++)
- ls->num_var_use[i][a] = 0;
- }
-
- /* Create the use_sites Array of Bitvectors*/
- /* use max(1,..), to ensure that the array is created! */
-
- ls->use_sites = DMNEW(bitvector, max(1, ls->varcount_with_indices));
- for(a = 0; a < ls->varcount_with_indices; a++)
- ls->use_sites[a] = bv_new(ls->basicblockcount);
- }
-
- /* init lifetimes */
- /* count number of TEMPVARs */
-
- ls->lifetimecount = 0;
- for(i = 0; i < jd->varcount; i++)
- if ((i >= jd->localcount) || (!(jd->var[i].flags & (INOUT | PREALLOC))))
- ls->lifetimecount++;
-
- ls->varcount = ls->varcount_with_indices + ls->lifetimecount;
-
- ls->lifetimecount = ls->varcount;
- ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
- ls->lt_used = DMNEW(int, ls->lifetimecount);
- ls->lt_int = DMNEW(int, ls->lifetimecount);
- ls->lt_int_count = 0;
- ls->lt_flt = DMNEW(int, ls->lifetimecount);
- ls->lt_flt_count = 0;
- ls->lt_mem = DMNEW(int, ls->lifetimecount);
- ls->lt_mem_count = 0;
- for (i=0; i < ls->lifetimecount; i++) {
- ls->lifetime[i].type = UNUSED;
- ls->lifetime[i].savedvar = 0;
- ls->lifetime[i].flags = 0;
- ls->lifetime[i].usagecount = 0;
- ls->lifetime[i].bb_last_use = -1;
- ls->lifetime[i].bb_first_def = -1;
- ls->lifetime[i].use = NULL;
- ls->lifetime[i].def = NULL;
- ls->lifetime[i].last_use = NULL;
- }
-
- /* for giving TEMP and PREALLOC vars a new unique index */
-
- ls->vartop = ls->varcount_with_indices;
-
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
- printf("ssa_rename_init: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
- ls->ssavarcount);
- for(i = 0; i < jd->varcount; i++) {
- if ((i < jd->localcount) || ( VAR(i)->flags & INOUT)) {
- printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
- ssa_show_variable(jd, i, VAR(i),0);
- if ((i < ls->ssavarcount) || (VAR(i)->flags & INOUT)) {
- printf(" -> %3i", ls->new_varindex[i]);
- }
- printf("\n");
- }
- }
- ssa_print_phi(ls, gd);
- }
-#endif
-}
-
-int ssa_rename_def_(lsradata *ls, int a) {
- int i;
-
- _SSA_CHECK_BOUNDS(a,0,ls->ssavarcount);
- ls->count[a]++;
- i = ls->count[a] - 1;
- /* push i on stack[a] */
- _SSA_CHECK_BOUNDS(ls->stack_top[a], 0, ls->num_defs[a] + 1);
- ls->stack[a][ls->stack_top[a]++] = i;
- return i;
-}
-
-int ssa_rename_def(jitdata *jd, int *def_count, int a) {
- int i, a1, ret;
- lsradata *ls;
-
- ls = jd->ls;
-
- a1 = ls->new_varindex[a];
- _SSA_CHECK_BOUNDS(a1, UNUSED, ls->varcount);
- if ((a1 != UNUSED) && (a1 < ls->ssavarcount)) {
- /* local or inoutvar -> normal ssa renaming */
- _SSA_ASSERT((a < jd->localcount) || (VAR(a)->flags & INOUT));
- /* !IS_TEMPVAR && !IS_PREALLOC == (IS_LOCALVAR || IS_INOUT) */
-
- def_count[a1]++;
- i = ssa_rename_def_(ls, a1);
- ret = ls->var_0[a1] + i;
- }
- else {
- /* TEMP or PREALLOC var */
- if (a1 == UNUSED) {
- ls->new_varindex[a] = ls->vartop;
- ret = ls->vartop;
- ls->vartop++;
- _SSA_ASSERT( ls->vartop < ls->varcount);
- }
- else
- ret = a1;
- }
- return ret;
-}
-
-void ssa_rename_use_(lsradata *ls, int n, int a) {
- _SSA_CHECK_BOUNDS(a, 0, ls->varcount_with_indices);
- if (ls->ssavarcount > 0) {
- bv_set_bit(ls->use_sites[a], n);
- ls->num_var_use[n][a]++;
- }
-}
-
-int ssa_rename_use(lsradata *ls, int n, int a) {
- int a1, i;
- int ret;
-
- a1 = ls->new_varindex[a];
- _SSA_CHECK_BOUNDS(a1, UNUSED, ls->varcount);
- if ((a1 != UNUSED) && (a1 < ls->ssavarcount)) {
- /* local or inoutvar -> normal ssa renaming */
- /* i <- top(stack[a]) */
-
- _SSA_CHECK_BOUNDS(ls->stack_top[a1]-1, 0, ls->num_defs[a1]+1);
- i = ls->stack[a1][ls->stack_top[a1] - 1];
- _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a1]);
-
- ret = ls->var_0[a1] + i;
- }
- else {
- /* TEMP or PREALLOC var */
- if (a1 == UNUSED) {
- ls->new_varindex[a] = ls->vartop;
- ret = ls->vartop;
- ls->vartop++;
- _SSA_ASSERT( ls->vartop < ls->varcount);
- }
- else
- ret = a1;
- }
-
- return ret;
-}
-
-#ifdef SSA_DEBUG_VERBOSE
-void ssa_rename_print(instruction *iptr, char *op, int from, int to) {
- if (compileverbose) {
- printf("ssa_rename_: ");
- if (iptr != NULL)
- printf("%s ", opcode_names[iptr->opc]);
- else
- printf(" ");
-
- printf("%s: %3i->%3i\n", op, from, to);
- }
-}
-#endif
-
-void ssa_rename_(jitdata *jd, graphdata *gd, dominatordata *dd, int n) {
- int a, i, j, k, iindex, Y, v;
- int in_d, out_d;
- int *def_count;
- /* [0..ls->varcount[ Number of Definitions of this var in this */
- /* Basic Block. Used to remove the entries off the stack at the */
- /* end of the function */
- instruction *iptr;
- s4 *in, *out, *argp;
- graphiterator iter_succ, iter_pred;
- struct lifetime *lt;
-
- methoddesc *md;
- methodinfo *m;
- builtintable_entry *bte;
- lsradata *ls;
-
- ls = jd->ls;
- m = jd->m;
-
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose)
- printf("ssa_rename_: BB %i\n",n);
-#endif
-
- _SSA_CHECK_BOUNDS(n, 0, ls->basicblockcount);
-
- def_count = DMNEW(int, max(1, ls->ssavarcount));
- for(i = 0; i < ls->ssavarcount; i++)
- def_count[i] = 0;
-
- /* change Store of possible phi functions from a to ai*/
-
- for(a = 0; a < ls->ssavarcount; a++)
- if (ls->phi[n][a] != NULL) {
- def_count[a]++;
- /* do not mark this store as use - maybee this phi function */
- /* can be removed for unused Vars*/
- j = ls->var_0[a] + ssa_rename_def_(ls, a);
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( NULL, "phi-st", ls->phi[n][a][0], j);
-#endif
- ls->phi[n][a][0] = j;
- }
-
- in = ls->basicblocks[n]->invars;
- in_d = ls->basicblocks[n]->indepth - 1;
-
- /* change use of instack Interface stackslots except top SBR and EXH */
- /* stackslots */
-
- if ((ls->basicblocks[n]->type == BBTYPE_EXH) ||
- (ls->basicblocks[n]->type == BBTYPE_SBR)) {
- in_d--;
- }
-/* out = ls->basicblocks[n]->outvars; */
-/* out_d = ls->basicblocks[n]->outdepth - 1; */
-
-/* for(; out_d > in_d; out_d--); */
-
- for (; in_d >= 0; in_d--) {
- /* Possible Use of ls->new_varindex[jd->var[in_d]] */
- _SSA_ASSERT(ls->new_varindex[in[in_d]] != UNUSED);
-
- a = ls->new_varindex[in[in_d]];
- _SSA_CHECK_BOUNDS(a, 0, ls->ssavarcount);
-
- /* i <- top(stack[a]) */
-
- _SSA_CHECK_BOUNDS(ls->stack_top[a]-1, 0, ls->num_defs[a]+1);
- i = ls->stack[a][ls->stack_top[a]-1];
- _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a]);
-
- /* Replace use of x with xi */
-
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( NULL, "invar", in[in_d], ls->var_0[a]+i);
-#endif
- in[in_d] = ls->var_0[a] + i;
- lt = ls->lifetime + in[in_d];
-
- lt->v_index = in[in_d];
- lt->bb_last_use = -1;
- }
-
- iptr = ls->basicblocks[n]->iinstr;
-
- for(iindex = 0; iindex < ls->basicblocks[n]->icount; iindex++, iptr++) {
-
- /* check for use (s1, s2, s3 or special (argp) ) */
-
- switch (icmd_table[iptr->opc].dataflow) {
- case DF_3_TO_0:
- case DF_3_TO_1: /* icmd has s1, s2 and s3 */
- j = ssa_rename_use(ls, n, iptr->sx.s23.s3.varindex);
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( iptr, "s3 ", iptr->sx.s23.s3.varindex, j);
-#endif
- iptr->sx.s23.s3.varindex = j;
-
- /* now "fall through" for handling of s2 and s1 */
-
- case DF_2_TO_0:
- case DF_2_TO_1: /* icmd has s1 and s2 */
- j = ssa_rename_use(ls, n, iptr->sx.s23.s2.varindex);
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( iptr, "s2 ", iptr->sx.s23.s2.varindex, j);
-#endif
- iptr->sx.s23.s2.varindex = j;
-
- /* now "fall through" for handling of s1 */
-
- case DF_1_TO_0:
- case DF_1_TO_1:
- case DF_MOVE:
- case DF_COPY:
- j = ssa_rename_use(ls, n, iptr->s1.varindex);
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( iptr, "s1 ", iptr->s1.varindex, j);
-#endif
- iptr->s1.varindex = j;
- break;
-
- case DF_INVOKE:
- case DF_BUILTIN:
- case DF_N_TO_1:
- /* do not use md->paramcount, pass-through stackslots have */
- /* to be renamed, too */
- i = iptr->s1.argcount;
- argp = iptr->sx.s23.s2.args;
- while (--i >= 0) {
- j = ssa_rename_use(ls, n, *argp);
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( iptr, "arg", *argp, j);
-#endif
- *argp = j;
- argp++;
- }
- break;
- }
-
-
- /* Look for definitions (iptr->dst). INVOKE and BUILTIN have */
- /* an optional dst - so they to be checked first */
-
- v = UNUSED;
- if (icmd_table[iptr->opc].dataflow == DF_INVOKE) {
- INSTRUCTION_GET_METHODDESC(iptr,md);
- if (md->returntype.type != TYPE_VOID)
- v = iptr->dst.varindex;
- }
- else if (icmd_table[iptr->opc].dataflow == DF_BUILTIN) {
- bte = iptr->sx.s23.s3.bte;
- md = bte->md;
- if (md->returntype.type != TYPE_VOID)
- v = iptr->dst.varindex;
- }
- else if (icmd_table[iptr->opc].dataflow >= DF_DST_BASE) {
- v = iptr->dst.varindex;
- }
-
- if (v != UNUSED) {
- j = ssa_rename_def(jd, def_count, iptr->dst.varindex);
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( iptr, "dst", iptr->dst.varindex, j);
-#endif
- iptr->dst.varindex = j;
- }
-
- /* ?????????????????????????????????????????????????????????? */
- /* Mark Def as use, too. Since param initialisation is in */
- /* var_def and this would not remove this locals, if not used */
- /* elsewhere */
- /* ?????????????????????????????????????????????????????????? */
-
- }
-
- /* change outstack Interface stackslots */
- out = ls->basicblocks[n]->outvars;
- out_d = ls->basicblocks[n]->outdepth - 1;
-
- for (;out_d >= 0; out_d--) {
- /* Possible Use of ls->new_varindex[jd->var[out_d]] */
- _SSA_ASSERT(ls->new_varindex[out[out_d]] != UNUSED);
-
- a = ls->new_varindex[out[out_d]];
- _SSA_CHECK_BOUNDS(a, 0, ls->ssavarcount);
-
- /* i <- top(stack[a]) */
-
- _SSA_CHECK_BOUNDS(ls->stack_top[a]-1, 0, ls->num_defs[a]+1);
- i = ls->stack[a][ls->stack_top[a]-1];
- _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a]);
-
- /* Replace use of x with xi */
-
-#ifdef SSA_DEBUG_VERBOSE
- ssa_rename_print( NULL, "outvar", out[out_d], ls->var_0[a]+i);
-#endif
- out[out_d] = ls->var_0[a] + i;
- lt = ls->lifetime + out[out_d];
-
- lt->v_index = out[out_d];
- lt->bb_last_use = -1;
- }
-
- /* change use in phi Functions of Successors */
-
- Y = graph_get_first_successor(gd, n, &iter_succ);
- for(; Y != -1; Y = graph_get_next(&iter_succ)) {
- _SSA_CHECK_BOUNDS(Y, 0, ls->basicblockcount);
- k = graph_get_first_predecessor(gd, Y, &iter_pred);
- for (j = 0; (k != -1) && (k != n); j++)
- k = graph_get_next(&iter_pred);
- _SSA_ASSERT(k == n);
-
- /* n is jth Predecessor of Y */
-
- for(a = 0; a < ls->ssavarcount; a++)
- if (ls->phi[Y][a] != NULL) {
-
- /* i <- top(stack[a]) */
-
- if (ls->stack_top[a] == 1) {
- /* no definition till now in controll flow */
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
- printf("Succ %3i Arg %3i \n", Y, j);
- ssa_rename_print( NULL, "phi-use", ls->phi[Y][a][j+1], UNUSED);
- }
-#endif
- ls->phi[Y][a][j+1] = UNUSED;
- }
- else {
- _SSA_CHECK_BOUNDS(ls->stack_top[a]-1, 0, ls->num_defs[a]+1);
- i = ls->stack[a][ls->stack_top[a]-1];
- _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a]);
-
- /* change jth operand from a0 to ai */
-
- i = ls->var_0[a] + i;
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose) {
- printf("Succ %3i Arg %3i \n", Y, j);
- ssa_rename_print( NULL, "phi-use", ls->phi[Y][a][j+1], i);
- }
-#endif
- ls->phi[Y][a][j+1] = i;
- _SSA_CHECK_BOUNDS(ls->phi[Y][a][j+1], 0,
- ls->varcount_with_indices);
-
- /* use by phi function has to be remembered, too */
-
- ssa_rename_use_(ls, n, ls->phi[Y][a][j+1]);
- }
-
- /* ????????????????????????????????????????????? */
- /* why was this only for local vars before ? */
- /* ????????????????????????????????????????????? */
-
- }
- }
-
- /* Call ssa_rename_ for all Childs of n of the Dominator Tree */
- for(i = 0; i < ls->basicblockcount; i++)
- if (dd->idom[i] == n)
- ssa_rename_(jd, gd, dd, i);
-
- /* pop Stack[a] for each definition of a var a in the original S */
- for(a = 0; a < ls->ssavarcount; a++) {
- ls->stack_top[a] -= def_count[a];
- _SSA_ASSERT(ls->stack_top[a] >= 0);
- }
-}
-
-
-
#ifdef SSA_DEBUG_VERBOSE
void ssa_print_trees(jitdata *jd, graphdata *gd, dominatordata *dd) {
int i,j;
printf(")\n");
}
}
-
-void ssa_print_phi(lsradata *ls, graphdata *gd) {
- int i,j,k;
-
- printf("phi Functions (varcount_with_indices: %3i):\n",
- ls->varcount_with_indices);
- for(i = 0; i < ls->basicblockcount; i++) {
- for(j = 0; j < ls->ssavarcount; j++) {
- if (ls->phi[i][j] != NULL) {
- printf("BB %3i %3i = phi(", i, ls->phi[i][j][0]);
- for(k = 1; k <= graph_get_num_predecessor(gd, i); k++)
- printf("%3i ",ls->phi[i][j][k]);
- printf(")\n");
- }
- }
- }
-
-}
-
#endif
-void ssa_generate_phi_moves(jitdata *jd, graphdata *gd) {
- int a, i, j, pred;
- graphiterator iter;
- lsradata *ls;
-
- ls = jd->ls;
-
- /* count moves to be inserted at the end of each block in moves[] */
- ls->num_phi_moves = DMNEW(int, ls->basicblockcount);
- for(i = 0; i < ls->basicblockcount; i++)
- ls->num_phi_moves[i] = 0;
- for(i = 0; i < ls->basicblockcount; i++)
- for(a = 0; a < ls->ssavarcount; a++)
- if (ls->phi[i][a] != NULL) {
-#if 0
- if (ls->lifetime[ls->phi[i][a][0]].use == NULL) {
- /* Var defined (only <- SSA Form!) in this phi function */
- /* and not used anywhere -> delete phi function and set */
- /* var to unused */
-
- /* TODO: first delete use sites of arguments of phi */
- /* function */
- VAR(ls->lifetime[ls->phi[i][a][0]].v_index)->type = UNUSED;
- ls->lifetime[ls->phi[i][a][0]].def = NULL;
- ls->phi[i][a] = NULL;
- }
- else
-#endif
- {
- pred = graph_get_first_predecessor(gd, i, &iter);
- for(; pred != -1; pred = graph_get_next(&iter)) {
- ls->num_phi_moves[pred]++;
- }
- }
- }
-
- /* allocate ls->phi_moves */
- ls->phi_moves = DMNEW( int **, ls->basicblockcount);
- for(i = 0; i < ls->basicblockcount; i++) {
- ls->phi_moves[i] = DMNEW( int *, ls->num_phi_moves[i]);
- for(j = 0; j <ls->num_phi_moves[i]; j++)
- ls->phi_moves[i][j] = DMNEW(int, 2);
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose)
- printf("ssa_generate_phi_moves: ls_num_phi_moves[%3i] = %3i\n",
- i, ls->num_phi_moves[i]);
-#endif
- }
-
- /* populate ls->phi_moves */
- for(i = 0; i < ls->basicblockcount; i++)
- ls->num_phi_moves[i] = 0;
- for(i = 0; i < ls->basicblockcount; i++)
- for(a = 0; a < ls->ssavarcount; a++)
- if (ls->phi[i][a] != NULL) {
- pred = graph_get_first_predecessor(gd, i, &iter);
- for(j = 0; pred != -1; j++, pred = graph_get_next(&iter)) {
- /* target is phi[i][a][0] */
- /* source is phi[i][a][j+1] */
- if (ls->phi[i][a][j+1] != ls->varcount_with_indices) {
- /* valid move */
- if (ls->phi[i][a][0] != ls->phi[i][a][j+1]) {
- ls->phi_moves[pred][ls->num_phi_moves[pred]][0] =
- ls->phi[i][a][0];
- ls->phi_moves[pred][(ls->num_phi_moves[pred])++][1]=
- ls->phi[i][a][j+1];
- }
- }
- }
- }
-}
/****************************************************************************
Optimizations
W = wl_new(ls->lifetimecount);
if (ls->lifetimecount > 0) {
- /* put all lifetimes on Worklist */
+
+ /* put all lifetimes into Worklist W */
+
for(a = 0; a < ls->lifetimecount; a++) {
- if (ls->lifetime[a].type != -1) {
+ if (ls->lifetime[a].type != UNUSED) {
wl_add(W, a);
}
}
}
/* Remove unused lifetimes */
+
while(!wl_is_empty(W)) {
+
/* take a var out of Worklist */
+
a = wl_get(W);
lt = &(ls->lifetime[a]);
- if ((lt->def == NULL) || (lt->type == -1))
+ if ((lt->def == NULL) || (lt->type == UNUSED))
+
/* lifetime was already removed -> no defs anymore */
+
continue;
- /* Remove lifetimes, which are only used in a phi function, which
- defines them! */
+ /* Remove lifetimes, which are only used in the phi function which */
+ /* defines them! */
+
remove_statement = (lt->use != NULL) && (lt->use->iindex < 0);
for(use = lt->use; (remove_statement && (use != NULL));
use = use->next)
(use->b_index == lt->def->b_index) &&
(use->iindex == lt->def->iindex);
}
+
if (remove_statement) {
#ifdef SSA_DEBUG_CHECK
+
/* def == use can only happen in phi functions */
+
if (remove_statement)
_SSA_ASSERT(lt->use->iindex < 0);
#endif
+
/* give it free for removal */
+
lt->use = NULL;
}
if (lt->use == NULL) {
+
/* Look at statement of definition of a and remove it, */
/* if the Statement has no sideeffects other than the assignemnt */
/* of a */
+
if (lt->def->iindex < 0 ) {
+
/* phi function */
/* delete use of sources , delete phi functions */
NULL);
for (i = 1;i <= graph_get_num_predecessor(gd, lt->def->b_index);
- i++)
- {
- source =
- ls->phi[lt->def->b_index][-lt->def->iindex-1][i];
- if ((source != ls->varcount_with_indices) &&
- (source != lt->v_index)) {
+ i++) {
+ source =
+ ls->phi[lt->def->b_index][-lt->def->iindex-1][i];
+ if ((source != ls->varcount_with_indices) &&
+ (source != lt->v_index) &&
+ (source != UNUSED)) {
- /* phi Argument was not already removed (already in
- because of selfdefinition) */
+ /* phi Argument was not already removed (already in
+ because of "selfdefinition") */
- s_lt = &(ls->lifetime[source]);
+ s_lt = &(ls->lifetime[source]);
- /* remove it */
+ /* remove it */
- lt_remove_use_site(s_lt,lt->def->b_index,
- lt->def->iindex);
+ lt_remove_use_site(s_lt,lt->def->b_index,
+ lt->def->iindex);
- /* put it on the Worklist */
+ /* put it on the Worklist */
- wl_add(W, source);
- }
+ wl_add(W, source);
}
+ }
+
/* now delete phi function itself */
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("dce: BB%3i phi for var %3i=%3i removed \n",
+ lt->def->b_index, -lt->def->iindex - 1,
+ lt->v_index);
+ }
+#endif
+
ls->phi[lt->def->b_index][-lt->def->iindex-1] = NULL;
- } else {
+ }
+ else {
+
/* "normal" Use by ICMD */
+
remove_statement = false;
if (lt->def->b_index != 0) {
iptr = ls->basicblocks[lt->def->b_index]->iinstr +
lt->def->iindex;
- if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI)
- remove_statement = false;
+ if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
- /* if ICMD could throw an exception do not remove it! */
+ /* if ICMD could throw an exception do not remove it! */
- else {
+ remove_statement = false;
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("dce: PEI: BB%3i II%3i %s not removed \n",
+ lt->def->b_index, lt->def->iindex,
+ bytecode[iptr->opc].mnemonic);
+ }
+#endif
- /* ICMD_INVOKE*, ICMD_BUILTIN and ICMD_MULTIANEWARRAY */
- /* have possible sideeffects -> do not remove them */
-
-/* remove_statement = !(ICMD_HAS_SPECIAL(iptr->opc)); */
-
- remove_statement = !(
- (icmd_table[iptr->opc].dataflow == DF_INVOKE) ||
- (icmd_table[iptr->opc].dataflow == DF_BUILTIN) ||
- (icmd_table[iptr->opc].dataflow == DF_N_TO_1));
-
- if (remove_statement) {
- switch (icmd_table[iptr->opc].dataflow) {
- case DF_3_TO_0:
- case DF_3_TO_1: /* icmd has s1, s2 and s3 */
- a = iptr->sx.s23.s3.varindex;
- s_lt = ls->lifetime + a;
- lt_remove_use_site(s_lt, lt->def->b_index,
- lt->def->iindex);
- wl_add(W, a);
-
- /* now "fall through" for handling of s2 and s1 */
-
- case DF_2_TO_0:
- case DF_2_TO_1: /* icmd has s1 and s2 */
- a = iptr->sx.s23.s2.varindex;
- s_lt = ls->lifetime + a;
- lt_remove_use_site(s_lt, lt->def->b_index,
- lt->def->iindex);
- wl_add(W, a);
-
- /* now "fall through" for handling of s1 */
-
- case DF_1_TO_0:
- case DF_1_TO_1:
- case DF_MOVE:
- case DF_COPY:
- a = iptr->s1.varindex;
- s_lt = ls->lifetime + a;
- lt_remove_use_site(s_lt, lt->def->b_index,
- lt->def->iindex);
- wl_add(W, a);
- }
+ }
+ else {
+ remove_statement = true;
+
+ switch (icmd_table[iptr->opc].dataflow) {
+ case DF_3_TO_0:
+ case DF_3_TO_1: /* icmd has s1, s2 and s3 */
+ a = iptr->sx.s23.s3.varindex;
+ s_lt = ls->lifetime + a;
+ lt_remove_use_site(s_lt, lt->def->b_index,
+ lt->def->iindex);
+ wl_add(W, a);
+
+ /* "fall through" for handling of s2 and s1 */
+
+ case DF_2_TO_0:
+ case DF_2_TO_1: /* icmd has s1 and s2 */
+ a = iptr->sx.s23.s2.varindex;
+ s_lt = ls->lifetime + a;
+ lt_remove_use_site(s_lt, lt->def->b_index,
+ lt->def->iindex);
+ wl_add(W, a);
+
+ /* "fall through" for handling of s1 */
+
+ /* DF_{IINC,STORE,LOAD} are DF_{1_TO_1,MOVE,COPY} */
+
+ case DF_1_TO_0:
+ case DF_1_TO_1:
+ case DF_MOVE:
+ case DF_COPY:
+ a = iptr->s1.varindex;
+ s_lt = ls->lifetime + a;
+ lt_remove_use_site(s_lt, lt->def->b_index,
+ lt->def->iindex);
+ wl_add(W, a);
+ }
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("dce: BB%3i II%3i %s removed \n",
+ lt->def->b_index, lt->def->iindex,
+ bytecode[iptr->opc].mnemonic);
}
+#endif
}
if (remove_statement) {
#ifdef SSA_DEBUG_VERBOSE
if (compileverbose)
- printf("INFO: %s %s:at BB %3i II %3i NOP-<%s\n",
- m->class->name->text, m->name->text,
+ printf("dce: %s %s:at BB %3i II %3i NOP-<%s\n",
+ m->clazz->name->text, m->name->text,
lt->def->b_index, lt->def->iindex,
icmd_table[iptr->opc].name);
#endif
/* remove definition of a */
- VAR(lt->v_index)->type = -1;
- lt->type = -1;
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose)
+ printf("dce: var %3i removed\n", lt->v_index);
+#endif
+ VAR(lt->v_index)->type = UNUSED;
+ lt->type = UNUSED;
lt->def = NULL;
+/* jd->var */
} /* if (lt->use == NULL) */
} /* while(!wl_is_empty(W)) */
} /* dead_code_elimination */
instruction *iptr;
struct lifetime *lt, *s_lt;
- s4 *in;
lsradata *ls;
if (ls->lifetimecount > 0) {
/* put all lifetimes on Worklist */
for(a = 0; a < ls->lifetimecount; a++) {
- if (ls->lifetime[a].type != -1) {
+ if (ls->lifetime[a].type != UNUSED) {
wl_add(W, a);
}
}
a = wl_get(W);
lt = ls->lifetime + a;
- if (lt->type == -1)
+ if (lt->type == UNUSED)
continue;
_SSA_ASSERT(lt->def != NULL);
+#if 0
_SSA_ASSERT(lt->use != NULL);
+#endif
if (lt->def->iindex < 0 ) {
/* phi function */
for (i = 1; i <= graph_get_num_predecessor(gd, lt->def->b_index);
i++) {
source = ls->phi[lt->def->b_index][-lt->def->iindex-1][i];
- if (source != ls->varcount_with_indices) {
+ if ((source != ls->varcount_with_indices) &&
+ (source != UNUSED)) {
if (only_source == ls->varcount_with_indices) {
+
/* first valid source argument of phi function */
+
only_source = source;
} else {
+
/* second valid source argument of phi function */
/* exit for loop */
+
only_source = ls->varcount_with_indices;
break;
}
}
}
+
if (only_source != ls->varcount_with_indices) {
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose)
+ printf(
+ "-- copy propagation phi-func: BB %3i II %3i: %3i -> %3i\n",
+ lt->def->b_index, lt->def->iindex,
+ only_source, lt->v_index);
+#endif
+ s_lt = ls->lifetime + only_source;
+
/* replace all use sites of lt with the var_index only_source */
ssa_replace_use_sites( jd, gd, lt, only_source, W);
- /* delete def of lt and replace uses of lt with "only_source" */
+ /* delete def of lt */
ls->phi[lt->def->b_index][-lt->def->iindex-1] = NULL;
- s_lt = ls->lifetime + only_source;
+ /* remove this deleted use site of s_lt */
- VAR(lt->v_index)->type = -1;
lt_remove_use_site(s_lt, lt->def->b_index, lt->def->iindex);
+
lt->def = NULL;
+
/* move use sites from lt to s_lt */
+
lt_move_use_sites(lt, s_lt);
- lt->type = -1;
+
+ /* invalidate lt */
+
+ lt->type = UNUSED;
+ VAR(lt->v_index)->type = UNUSED;
+
+ /* add s_lt again to Worklist W */
+
+ wl_add(W, s_lt->v_index);
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose)
+ _ssa_print_lt(s_lt);
+#endif
} /* if (only_source != ls->varcount_with_indices) */
- } else { /* if (lt->def->iindex < 0 )*/
+ }
+ else { /* if (lt->def->iindex < 0 ) */
+
+ /* def in argument passing - no propagation possible */
+ /* (there is no ICMD for this... */
+
+ if (lt->def->b_index == 0)
+ continue;
+
/* def in "normal" ICMD */
-#if 0
+
iptr = ls->basicblocks[lt->def->b_index]->iinstr +
lt->def->iindex;
-
- if ( localvar ) {
- if (lt->def->b_index == 0)
- continue;
-
- switch(iptr->opc) {
- case ICMD_ISTORE:
- case ICMD_LSTORE:
- case ICMD_FSTORE:
- case ICMD_DSTORE:
+
+ switch(iptr->opc) {
+ case ICMD_ISTORE:
+ case ICMD_LSTORE:
+ case ICMD_FSTORE:
+ case ICMD_DSTORE:
case ICMD_ASTORE:
- if (lt->def->iindex == 0) {
- /* first instruction in bb -> instack==bb->instack */
- in = ls->basicblocks[lt->def->b_index]->instack;
- } else {
- /* instack is (iptr-1)->dst */
- in = (iptr-1)->dst;
- }
-
- if (in->varkind != LOCALVAR) {
+ case ICMD_ILOAD:
+ case ICMD_LLOAD:
+ case ICMD_FLOAD:
+ case ICMD_DLOAD:
+ case ICMD_ALOAD:
+ case ICMD_MOVE:
#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose)
- printf("copy propagation xstore: BB %3i I %3i: %3i -> %3i\n", lt->def->b_index, lt->def->iindex, iptr->op1, in->varnum);
+ if (compileverbose)
+ printf(
+ "-- copy propagation %3i %s: BB %3i II %3i: %3i -> %3i\n",
+ iptr->opc, bytecode[iptr->opc].mnemonic,
+ lt->def->b_index, lt->def->iindex,
+ iptr->s1.varindex, iptr->dst.varindex);
#endif
- s_lt = &(ls->lifetime[-in->varnum-1]);
-
- for (ss = s_lt->local_ss; ss != NULL; ss = ss->next) {
- ss->s->varkind = LOCALVAR;
- ss->s->varnum = iptr->op1;
- }
-
- /* replace all use sites of s_lt with the var_index */
- /* iptr->op1 */
-
- ssa_replace_use_sites(jd, gd, s_lt, iptr->op1, W);
+ s_lt = ls->lifetime + iptr->s1.varindex;
- /* s_lt->def is the new def site of lt */
- /* the old ->def site will get a use site of def */
- /* only one def site */
- _SSA_ASSERT(lt->def->next == NULL);
- _SSA_ASSERT(s_lt->def != NULL);
- _SSA_ASSERT(s_lt->def->next == NULL);
-
- /* replace def of s_lt with iptr->op1 */
- if (s_lt->def->iindex < 0) {
- /* phi function */
- _SSA_ASSERT(ls->phi[s_lt->def->b_index]
- [-s_lt->def->iindex-1]
- != NULL);
- ls->phi[s_lt->def->b_index][-s_lt->def->iindex-1][0]
- = iptr->op1;
- } else
- if (in->varnum != iptr->op1)
- printf("copy propagation: LOCALVAR ss->ISTORE BB %i II %i\n",
- lt->def->b_index, lt->def->iindex);
-
+ _SSA_ASSERT( lt->v_index == iptr->dst.varindex);
+
+ /* replace all use sites of lt with the var_index */
+ /* iptr->s1.varindex (==lt->v_index) */
+
+ ssa_replace_use_sites(jd, gd, lt, iptr->s1.varindex, W);
+
+ _SSA_ASSERT(lt->def->next == NULL);
+ _SSA_ASSERT(s_lt->def != NULL);
+ _SSA_ASSERT(s_lt->def->next == NULL);
- /* move def to use sites of lt */
- lt->def->next = lt->use;
- lt->use = lt->def;
-
- lt->def = s_lt->def;
+ /* this ICMD is not a PEI -> so no danger in deleting it! */
+ /* delete def of lt (ICMD_NOP) */
- s_lt->def = NULL;
+ /* lt->def->iindex > 0 -> ICMD */
+ iptr->opc = ICMD_NOP;
- /* move use sites from s_lt to lt */
- move_use_sites(s_lt, lt);
- move_stackslots(s_lt, lt);
- s_lt->type = -1;
- }
- break;
- }
- } else {
- /* Def Interface Stackslot */
-
- switch(iptr->opc) {
- case ICMD_ILOAD:
- case ICMD_LLOAD:
- case ICMD_FLOAD:
- case ICMD_DLOAD:
- case ICMD_ALOAD:
- only_source = lt->local_ss->s->varnum;
- if (lt->local_ss->s->varkind != LOCALVAR) {
-#ifdef SSA_DEBUG_VERBOSE
- if (compileverbose)
- printf("copy propagation xload: BB %3i I %3i: %3i -> %3i\n", lt->def->b_index, lt->def->iindex, iptr->op1, lt->local_ss->s->varnum);
-#endif
- _SSA_ASSERT(iptr->dst->varnum == lt->local_ss->s->varnum);
- for (ss = lt->local_ss; ss != NULL; ss = ss->next) {
- ss->s->varkind = LOCALVAR;
- ss->s->varnum = iptr->op1;
- }
+ /* remove this deleted use site of s_lt */
- /* replace all use sites of lt with the var_index iptr->op1*/
+ lt_remove_use_site(s_lt, lt->def->b_index, lt->def->iindex);
- ssa_replace_use_sites(jd, gd, lt, iptr->op1, W);
+ /* invalidate def site of lt */
- lt->def = NULL;
-
- s_lt = &(ls->lifetime[ls->maxlifetimes + iptr->op1]);
-
- /* move use sites from lt to s_lt */
- move_use_sites(lt, s_lt);
- move_stackslots(lt, s_lt);
- lt->type = -1;
- } else
- if (lt->local_ss->s->varnum != iptr->op1)
- printf("copy propagation: ILOAD -> LOCALVAR ss BB %i II %i\n",
- lt->def->b_index, lt->def->iindex);
-
- break;
- }
- } /* localvar or interface stackslot */
+ lt->def = NULL;
+
+ /* move use sites from lt to s_lt */
+
+ lt_move_use_sites(lt, s_lt);
+
+ /* invalidate lt */
+
+ lt->type = UNUSED;
+ VAR(lt->v_index)->type = UNUSED;
+
+ /* add s_lt again to Worklist W */
+ wl_add(W, s_lt->v_index);
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose)
+ _ssa_print_lt(s_lt);
#endif
- } /* i(lt->def->iindex < 0 ) */
-
+ break;
+ }
+ } /* if (lt->def->iindex < 0 ) */
} /* while(!wl_is_empty(W)) */
}
for (i = 1;i <= graph_get_num_predecessor(gd, s->b_index); i++) {
source = ls->phi[s->b_index][-s->iindex-1][i];
- if (source == lt->v_index) {
+ if (source == lt->v_index) {
+
+ /* check if this use in this phi function is a */
+ /* "selfdefinition" (x = phi(...,x,...)) */
+ /* if so replace the use with -1 (x=phi(...,-1,...)*/
+
+ if (new_v_index == ls->phi[s->b_index][-s->iindex-1][0]) {
#ifdef SSA_DEBUG_VERBOSE
- if (W != NULL) {
- if (compileverbose)
- printf("copy propagation phi: BB %3i I %3i: %3i -> \
- %3i\n", s->b_index, s->iindex,
- new_v_index, source);
+ if (W != NULL) {
+ if (compileverbose)
+ printf(
+ "copy propagation phi: BB %3i I %3i: %3i -> %3i\n",
+ s->b_index, s->iindex, -1, source);
+ }
+#endif
+ ls->phi[s->b_index][-s->iindex-1][i] = -1;
+
+ /* remove this use site of use site */
+ lt_remove_use_site(lt, s->b_index, s->iindex);
}
+ else {
+#ifdef SSA_DEBUG_VERBOSE
+ if (W != NULL) {
+ if (compileverbose)
+ printf(
+ "copy propagation phi: BB %3i I %3i: %3i -> %3i\n",
+ s->b_index, s->iindex, new_v_index, source);
+ }
#endif
- ls->phi[s->b_index][-s->iindex-1][i]
- = new_v_index;
+ ls->phi[s->b_index][-s->iindex-1][i] = new_v_index;
+ }
}
}
if (W != NULL) {
#ifdef SSA_DEBUG_VERBOSE
if (W != NULL) {
if (compileverbose)
- printf("copy propagation loc: BB %3i I %3i: %3i -> \
+ printf("copy propagation loc3: BB %3i I %3i: %3i -> \
%3i\n", s->b_index, s->iindex,
new_v_index, iptr->sx.s23.s3.varindex);
}
#ifdef SSA_DEBUG_VERBOSE
if (W != NULL) {
if (compileverbose)
- printf("copy propagation loc: BB %3i I %3i: %3i -> \
+ printf("copy propagation loc2: BB %3i I %3i: %3i -> \
%3i\n", s->b_index, s->iindex,
new_v_index, iptr->sx.s23.s2.varindex);
}
#ifdef SSA_DEBUG_VERBOSE
if (W != NULL) {
if (compileverbose)
- printf("copy propagation loc: BB %3i I %3i: %3i -> \
- %3i\n", s->b_index, s->iindex,
- new_v_index, iptr->s1.varindex);
+ printf(
+ "copy propagation loc1: BB %3i I %3i: %3i -> %3i\n",
+ s->b_index, s->iindex, new_v_index,
+ iptr->s1.varindex);
}
#endif
iptr->s1.varindex = new_v_index;
if (W != NULL) {
if (compileverbose)
printf(
- "copy propagation loc: BB %3i I %3i: %3i -> %3i\n"
+ "copy propagation locN: BB %3i I %3i: %3i -> %3i\n"
, s->b_index, s->iindex, new_v_index, *argp);
}
#endif
void ssa_print_lt(lsradata *ls) {
int i;
struct lifetime *lt;
- struct site *use;
printf("SSA LT Def/Use\n");
for(i = 0; i < ls->lifetimecount; i++) {
lt = ls->lifetime + i;
- if (lt->type != UNUSED) {
- printf("VI %3i Type %3i Def: ",lt->v_index, lt->type);
- if (lt->def != NULL)
- printf("%3i,%3i Use: ",lt->def->b_index, lt->def->iindex);
- else
- printf("%3i,%3i Use: ",0,0);
- for(use = lt->use; use != NULL; use = use->next)
- printf("%3i,%3i ",use->b_index, use->iindex);
- printf("\n");
- }
+ _ssa_print_lt(lt);
+ }
+}
+
+void _ssa_print_lt(struct lifetime *lt) {
+ struct site *use;
+
+ if (lt->type != UNUSED) {
+ printf("VI %3i Type %3i Def: ",lt->v_index, lt->type);
+ if (lt->def != NULL)
+ printf("%3i,%3i Use: ",lt->def->b_index, lt->def->iindex);
+ else
+ printf("%3i,%3i Use: ",0,0);
+ for(use = lt->use; use != NULL; use = use->next)
+ printf("%3i,%3i ",use->b_index, use->iindex);
+ printf("\n");
}
}
/* src/vm/jit/optimizing/ssa.h - static single assignment form header
- Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ 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
Authors: Christian Ullrich
+ $Id: ssa.h$
*/
/* function prototypes */
void ssa_init(jitdata *);
-void ssa(jitdata *, graphdata *);
+void ssa(jitdata */* , graphdata **/);
#endif /* _SSA_H */
--- /dev/null
+/* src/vm/optimizing/ssa2.c
+
+ Copyright (C) 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Reimplementation of code in ssa.c.
+ Uses the new dominator tree and the new CFG.
+*/
+
+#include "config.h"
+
+#include "mm/memory.h"
+
+#include "toolbox/bitvector.h"
+#include "toolbox/set.h"
+#include "toolbox/worklist.h"
+
+#include "vm/global.h"
+#include "vm/jit/jit.h"
+
+#if 1
+#define printf(...) do { if (getenv("VERB")) printf(__VA_ARGS__); } while (0)
+#define show_method(...) do { if (getenv("VERB")) show_method(__VA_ARGS__); } while (0)
+#endif
+
+typedef struct phi_function {
+ s4 dst;
+ s4 *args;
+} phi_function;
+
+typedef struct basicblock_info {
+ bitvector defines;
+ bitvector phi;
+ unsigned phi_count;
+ phi_function *phi_functions;
+} basicblock_info;
+
+typedef struct var_info {
+ set *work;
+ unsigned num_defs;
+
+ unsigned offset;
+
+ unsigned count;
+ unsigned *stack;
+ unsigned *stack_top;
+
+} var_info;
+
+typedef struct ssa_info {
+ jitdata *jd;
+ var_info *vars;
+ unsigned vars_count;
+ unsigned total_local_count;
+} ssa_info;
+
+static inline basicblock_info *bb_info(basicblock *bb) {
+ return (basicblock_info *)(bb->vp);
+}
+
+static ssa_info *ssa_init(jitdata *jd) {
+ unsigned i;
+ ssa_info *ssa;
+
+ ssa = DNEW(ssa_info);
+ ssa->jd = jd;
+ ssa->vars_count = jd->localcount;
+
+ ssa->vars = DMNEW(var_info, ssa->vars_count);
+ MZERO(ssa->vars, var_info, ssa->vars_count);
+ for (i = 0; i < ssa->vars_count; ++i) {
+ ssa->vars[i].work = set_new(jd->basicblockcount);
+ }
+
+ return ssa;
+}
+
+static void ssa_place_phi_functions(ssa_info *ssa) {
+
+ basicblock *bptr, *Y, *n, **itdf;
+ basicblock_info *bbi;
+ instruction *iptr;
+ s4 a;
+ set *work;
+
+ for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
+
+ bbi = DNEW(basicblock_info);
+ bbi->defines = bv_new(ssa->vars_count);
+ bbi->phi = bv_new(ssa->vars_count);
+ bbi->phi_count = 0;
+
+ bptr->vp = bbi;
+
+ for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
+ if (instruction_has_dst(iptr)) {
+ if (
+ var_is_local(ssa->jd, iptr->dst.varindex)
+ ) {
+ /* A_orig */
+ bv_set_bit(bbi->defines, iptr->dst.varindex);
+ /* defsites */
+ set_insert(ssa->vars[iptr->dst.varindex].work, bptr);
+ /* Accout definition */
+ ssa->vars[iptr->dst.varindex].num_defs += 1;
+ }
+ }
+ }
+ }
+
+ bptr = ssa->jd->basicblocks;
+ bbi = bb_info(bptr);
+ for (a = 0; a < ssa->vars_count; ++a) {
+ bv_set_bit(bbi->defines, a);
+ set_insert(ssa->vars[a].work, bptr);
+ ssa->vars[a].num_defs += 1;
+ }
+
+ for (a = 0; a < ssa->vars_count; ++a) {
+ work = ssa->vars[a].work;
+ while (! set_empty(work)) {
+ n = (basicblock *)set_pop(work);
+ for (
+ itdf = n->domfrontier;
+ itdf != n->domfrontier + n->domfrontiercount;
+ ++itdf
+ ) {
+ Y = *itdf;
+ if (! bv_get_bit(bb_info(Y)->phi, a)) {
+ bv_set_bit(bb_info(Y)->phi, a);
+ printf(" *** BB %d: phi for var %d\n", Y->nr, a);
+ bb_info(Y)->phi_count += 1;
+ ssa->vars[a].num_defs += 1;
+ if (! bv_get_bit(bb_info(Y)->defines, a)) {
+ set_insert(work, Y);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void ssa_create_phi_functions(ssa_info *ssa) {
+ unsigned i, j;
+ basicblock_info *bbi;
+ basicblock *bptr;
+ phi_function *itph;
+
+ for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
+
+ bbi = bb_info(bptr);
+ bbi->phi_functions = DMNEW(phi_function, bbi->phi_count);
+ itph = bbi->phi_functions;
+
+ for (i = 0; i < ssa->vars_count; ++i) {
+ if (bv_get_bit(bbi->phi, i)) {
+ itph->dst = i;
+ itph->args = DMNEW(s4, bptr->predecessorcount);
+ for (j = 0; j < bptr->predecessorcount; ++j) {
+ itph->args[j] = i;
+ }
+ itph += 1;
+ }
+ }
+ }
+}
+
+static void ssa_calculate_offsets(ssa_info *ssa) {
+ int i;
+ unsigned cur_offset = ssa->jd->localcount;
+
+ ssa->total_local_count = 0;
+
+ for (i = 0; i < ssa->vars_count; ++i) {
+
+ ssa->vars[i].offset = cur_offset;
+
+ ssa->total_local_count += ssa->vars[i].num_defs;
+
+ if (ssa->vars[i].num_defs > 1) {
+ cur_offset += (ssa->vars[i].num_defs - 1);
+ }
+ }
+}
+
+
+static s4 ssa_rename_var(ssa_info *ssa, s4 var, unsigned index) {
+ s4 ret;
+#define return ret=
+ if (var_is_local(ssa->jd, var)) {
+ assert(0 < index && index <= ssa->vars[var].num_defs);
+ if (index == 1) {
+ return var;
+ } else {
+ return ssa->vars[var].offset + (index - 2);
+ }
+ assert(ret < ssa->total_local_count);
+ } else {
+ return ssa->total_local_count + (var - ssa->vars_count);
+ }
+#undef return
+ printf(" *** rename %c %d vers %d => %d\n", var_is_local(ssa->jd, var) ? 'L' : 'O', var, index, ret);
+ return ret;
+}
+
+static void ssa_rename_uses(ssa_info *ssa, s4 *uses, unsigned uses_count) {
+ while (uses_count > 0) {
+ if (var_is_local(ssa->jd, *uses)) {
+ *uses = ssa_rename_var(ssa, *uses, *(ssa->vars[*uses].stack_top));
+ } else {
+ *uses = ssa_rename_var(ssa, *uses, 0);
+ }
+ uses_count -= 1;
+ uses += 1;
+ }
+}
+
+static void ssa_rename_definition(ssa_info *ssa, s4 *pdef) {
+ s4 def = *pdef;
+ unsigned i = 0;
+
+ if (var_is_local(ssa->jd, def)) {
+ ssa->vars[def].count += 1;
+ i = ssa->vars[def].count;
+ ssa->vars[def].stack_top += 1;
+ *(ssa->vars[def].stack_top) = i;
+ }
+
+ *pdef = ssa_rename_var(ssa, def, i);
+}
+
+static void ssa_rename_block(ssa_info *ssa, basicblock *bptr) {
+
+ basicblock_info *bbi = bb_info(bptr);
+ s4 s[3];
+ s4 *uses;
+ unsigned uses_count;
+ instruction *iptr;
+ basicblock **itsucc, **itpred, **itdsucc, *Y;
+ phi_function *itph;
+ unsigned j;
+ s4 i, tmp;
+ s4 a;
+ s4 **orig_stack_top;
+
+ /* XXX */
+ orig_stack_top = DMNEW(s4 *, ssa->vars_count);
+ for (a = 0; a < ssa->vars_count; ++a) orig_stack_top[a] = ssa->vars[a].stack_top;
+
+ int jj;
+
+printf(" *** === %d ===========\n", bptr->nr);
+
+ ssa_rename_uses(ssa, bptr->invars, bptr->indepth);
+
+ /* Phi functions are the first instructions in the block */
+printf(" *** --- phis ---------\n");
+ for (
+ itph = bbi->phi_functions;
+ itph != bbi->phi_functions + bbi->phi_count;
+ ++itph
+ ) {
+ ssa_rename_definition(ssa, &(itph->dst));
+ }
+
+printf(" *** --- vars ---------\n");
+
+ if (bptr == ssa->jd->basicblocks) {
+ for (i = 0; i < ssa->jd->localcount; ++i) {
+ tmp = i;
+ ssa_rename_definition(ssa, &tmp);
+ }
+ }
+
+ for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
+
+ /* Determine uses */
+
+ uses_count = 0;
+
+ switch (icmd_table[iptr->opc].dataflow) {
+ case DF_3_TO_0:
+ case DF_3_TO_1:
+ s[2] = iptr->sx.s23.s3.varindex;
+ uses_count += 1;
+
+ case DF_2_TO_0:
+ case DF_2_TO_1:
+ s[1] = iptr->sx.s23.s2.varindex;
+ uses_count += 1;
+
+ case DF_1_TO_0:
+ case DF_1_TO_1:
+ case DF_COPY:
+ case DF_MOVE:
+ s[0] = iptr->s1.varindex;
+ uses_count += 1;
+
+ uses = s;
+ break;
+
+ case DF_N_TO_1:
+ case DF_INVOKE:
+ case DF_BUILTIN:
+
+ uses = iptr->sx.s23.s2.args;
+ uses_count = iptr->s1.argcount;
+ break;
+
+ }
+
+ printf(" *** %s uses ", icmd_table[iptr->opc].name);
+ for (jj = 0; jj < uses_count; ++jj) printf("%d ",uses[jj]);
+ printf("\n");
+
+ if (uses_count > 0) {
+ /* Update uses, if there are any */
+
+ ssa_rename_uses(ssa, uses, uses_count);
+
+ /* If uses were s, then we need to update the instruction */
+
+ if (uses == s) {
+ switch (uses_count) {
+ case 3:
+ iptr->sx.s23.s3.varindex = s[2];
+ case 2:
+ iptr->sx.s23.s2.varindex = s[1];
+ case 1:
+ iptr->s1.varindex = s[0];
+ }
+ }
+ }
+
+ /* Rename definitions */
+
+ if (instruction_has_dst(iptr)) {
+ printf(" *** %s defines %d\n", icmd_table[iptr->opc].name, iptr->dst.varindex);
+ ssa_rename_definition(ssa, &(iptr->dst.varindex));
+ }
+
+ }
+
+ for (i = 0; i < bptr->outdepth; ++i) {
+ ssa_rename_definition(ssa, bptr->outvars + i);
+ }
+
+ /* Successors */
+
+ printf(" *** succs %d\n", bptr->successorcount);
+
+ for (
+ itsucc = bptr->successors;
+ itsucc != bptr->successors + bptr->successorcount;
+ ++itsucc
+ ) {
+ Y = *itsucc;
+
+ for (
+ itpred = Y->predecessors, j = 0;
+ itpred != Y->predecessors + Y->predecessorcount;
+ ++itpred, ++j
+ ) {
+ if (*itpred == bptr) break;
+ }
+
+ assert(j != Y->predecessorcount);
+
+ for (
+ itph = bb_info(Y)->phi_functions;
+ itph != bb_info(Y)->phi_functions + bb_info(Y)->phi_count;
+ ++itph
+ ) {
+ ssa_rename_uses(ssa, itph->args + j, 1);
+ }
+ }
+
+ /* Recurse */
+
+ for (
+ itdsucc = bptr->domsuccessors;
+ itdsucc != bptr->domsuccessors + bptr->domsuccessorcount;
+ ++itdsucc
+ ) {
+ ssa_rename_block(ssa, *itdsucc);
+ }
+
+ /* For each definition of some variable a in the original S, pop stack */
+
+ /* XXX */
+ for (a = 0; a < ssa->vars_count; ++a) ssa->vars[a].stack_top = orig_stack_top[a];
+}
+
+static void ssa_rename(ssa_info *ssa) {
+ unsigned i;
+
+ for (i = 0; i < ssa->vars_count; ++i) {
+ ssa->vars[i].stack = DMNEW(unsigned, ssa->vars[i].num_defs + 1);
+ ssa->vars[i].stack[0] = 0;
+ ssa->vars[i].stack_top = ssa->vars[i].stack;
+ }
+
+ ssa_rename_block(ssa, ssa->jd->basicblocks);
+}
+
+static void ssa_export(ssa_info *ssa) {
+ unsigned i, j;
+ jitdata *jd = ssa->jd;
+ methoddesc *md = jd->m->parseddesc;
+ varinfo *vars, *it;
+ s4 vartop, varindex;
+
+ vartop = ssa->total_local_count + jd->vartop - jd->localcount;
+ vars = DMNEW(varinfo, vartop);
+
+ printf(" *** vartop(%d) = ssa->total_local_count(%d) + jd->vartop(%d) - jd->localcount(%d)\n",
+ vartop , ssa->total_local_count , jd->vartop , jd->localcount);
+
+ it = vars;
+
+ /* Version 1 of each local */
+
+ for (i = 0; i < jd->localcount; ++i) {
+ *(it++) = jd->var[i];
+ }
+
+ /* Other versions of each local */
+
+ for (i = 0; i < jd->localcount; ++i) {
+ for (j = 1; j < ssa->vars[i].num_defs; ++j) {
+ *(it++) = jd->var[i];
+ }
+ }
+
+ /* Other vars */
+
+ for (i = jd->localcount; i < jd->vartop; ++i) {
+ *(it++) = jd->var[i];
+ }
+
+ jd->var = vars;
+ jd->vartop = jd->varcount = vartop;
+
+ jd->local_map = DMREALLOC(jd->local_map, s4, 5 * jd->maxlocals, 5 * (jd->maxlocals + ssa->total_local_count - jd->localcount));
+
+ for (i = 0; i < ssa->total_local_count - jd->localcount; ++i) {
+ for (j = 0; j < 5; ++j) {
+ varindex = jd->localcount + i;
+ if (jd->var[varindex].type != j) {
+ varindex = UNUSED;
+ }
+ jd->local_map[((jd->maxlocals + i) * 5) + j] = varindex;
+ }
+ }
+
+ jd->maxlocals += (ssa->total_local_count - jd->localcount);
+ jd->localcount = ssa->total_local_count;
+
+ printf(" *** jd->localcount %d, jd->maxlocals %d\n", jd->localcount , jd->maxlocals);
+}
+
+static unsigned get_predecessor_index(basicblock *from, basicblock *to) {
+ basicblock **itpred;
+ unsigned j = 0;
+
+ for (itpred = to->predecessors; itpred != to->predecessors + to->predecessorcount; ++itpred) {
+ if (*itpred == from) break;
+ j++;
+ }
+
+ if (j == to->predecessorcount) {
+ printf(" *** %d => %d\n", from->nr, to->nr);
+ assert(j != to->predecessorcount);
+ }
+
+ return j;
+}
+
+static basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
+ basicblock *mid;
+ basicblock_info *toi;
+ instruction *iptr;
+ phi_function *itph;
+ unsigned j = get_predecessor_index(from, to);
+
+ mid = DNEW(basicblock);
+ MZERO(mid, basicblock, 1);
+
+ toi = bb_info(to);
+ assert(toi);
+
+ mid->nr = ssa->jd->basicblockcount;
+ ssa->jd->basicblockcount += 1;
+ mid->mpc = -1;
+ mid->type = 666;
+ mid->icount = toi->phi_count + 1;
+ iptr = mid->iinstr = DMNEW(instruction, mid->icount);
+ MZERO(mid->iinstr, instruction, mid->icount);
+
+ for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
+ iptr->opc = ICMD_COPY;
+ iptr->dst.varindex = itph->dst;
+ iptr->s1.varindex = itph->args[j];
+ assert(itph->dst < ssa->total_local_count);
+ assert(itph->args[j] < ssa->total_local_count);
+ iptr++;
+ }
+
+ iptr->opc = ICMD_GOTO;
+ iptr->dst.block = to;
+
+ while (from->next) {
+ from = from->next;
+ }
+
+ from->next = mid;
+
+ return mid;
+}
+
+static void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
+ unsigned j;
+ basicblock_info *toi;
+ instruction *iptr;
+ phi_function *itph;
+
+ if (bptr->next == NULL) return;
+
+ j = get_predecessor_index(bptr, bptr->next);
+
+ toi = bb_info(bptr->next);
+ assert(toi);
+
+ bptr->iinstr = DMREALLOC(bptr->iinstr, instruction, bptr->icount, bptr->icount + toi->phi_count);
+ iptr = bptr->iinstr + bptr->icount;
+ bptr->icount += toi->phi_count;
+
+ for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
+ iptr->opc = ICMD_COPY;
+ iptr->dst.varindex = itph->dst;
+ iptr->s1.varindex = itph->args[j];
+ assert(itph->dst < ssa->total_local_count);
+ assert(itph->args[j] < ssa->total_local_count);
+ iptr++;
+ }
+
+}
+
+static void ssa_create_phi_moves(ssa_info *ssa) {
+ basicblock *bptr;
+ instruction *iptr;
+
+ s4 i, l;
+ branch_target_t *table;
+ lookup_target_t *lookup;
+ bool gt;
+
+ for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
+ if (bptr->type == 666) {
+ bptr->type = BBTYPE_STD;
+ continue;
+ }
+ if (! bptr->vp) continue;
+ if (! (bptr->flags >= BBREACHED)) continue;
+ gt = false;
+ for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
+ switch (icmd_table[iptr->opc].controlflow) {
+ case CF_IF:
+ case CF_RET:
+ case CF_GOTO:
+ iptr->dst.block = create_block(ssa, bptr, iptr->dst.block);
+ break;
+ case CF_TABLE:
+ table = iptr->dst.table;
+ l = iptr->sx.s23.s2.tablelow;
+ i = iptr->sx.s23.s3.tablehigh;
+ i = i - l + 1;
+ i += 1; /* default */
+ while (--i >= 0) {
+ table->block = create_block(ssa, bptr, table->block);
+ ++table;
+ }
+ break;
+ case CF_LOOKUP:
+ lookup = iptr->dst.lookup;
+ i = iptr->sx.s23.s2.lookupcount;
+ while (--i >= 0) {
+ lookup->target.block = create_block(ssa, bptr, lookup->target.block);
+ lookup++;
+ }
+ iptr->sx.s23.s3.lookupdefault.block = create_block(ssa, bptr, iptr->sx.s23.s3.lookupdefault.block);
+ break;
+ case CF_JSR:
+ iptr->sx.s23.s3.jsrtarget.block = create_block(ssa, bptr, iptr->sx.s23.s3.jsrtarget.block);
+ break;
+ }
+ if ((iptr->opc == ICMD_GOTO) || icmd_table[iptr->opc].controlflow == CF_END)
+ gt = true;
+ else if (iptr->opc != ICMD_NOP)
+ gt = false;
+ }
+ if (! bptr->next) continue;
+ if (! (bptr->next->flags >= BBREACHED)) continue;
+ if (bptr->next->type == 666) continue;
+ if (!gt) crate_fallthrough(ssa, bptr);
+ }
+}
+
+void xssa(jitdata *jd) {
+ ssa_info *ssa = ssa_init(jd);
+
+ printf("=============== [ before %s ] =========================\n", jd->m->name->text);
+ show_method(jd, 3);
+ printf("=============== [ /before ] =========================\n");
+
+ ssa_place_phi_functions(ssa);
+ ssa_create_phi_functions(ssa);
+ ssa_calculate_offsets(ssa);
+ ssa_rename(ssa);
+ ssa_export(ssa);
+ ssa_create_phi_moves(ssa);
+
+ printf("=============== [ after ] =========================\n");
+ show_method(jd, 3);
+ printf("=============== [ /after ] =========================\n");
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically 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/optimizing/ssa3.c
+
+ Copyright (C) 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ SSA transformation PROTOTYPE based on:
+
+ Moessenboeck, H.,
+ Adding Static Single Assignment Form and a Graph Coloring Register
+ Allocator to the Java Hotspot Client Compiler, 2000
+ (http://www.ssw.uni-linz.ac.at/Research/Reports/Report15.html)
+
+ TODO
+
+ * Adapt for exception handling [done]
+ * Eliminiation of redundand PHI functions
+ * Create PHI functions lazyly, when they are used for the first time
+ (I suspect that currently PHIs are created that are never used).
+ * REWRITE. The code was never designed for producion.
+*/
+
+#include "vm/jit/jit.h"
+#include "vm/global.h"
+#include "mm/memory.h"
+#include "mm/dumpmemory.h"
+#include "toolbox/list.h"
+
+#if 1
+static inline bool test_do_verbose(jitdata *jd) {
+ return strcmp(jd->m->name->text, "close") == 0 &&
+ strcmp(jd->m->clazz->name->text, "antlr/PreservingFileWriter") == 0;
+}
+static bool do_verbose = 0;
+#define WHEN do_verbose
+#define printf(...) do { if (WHEN) printf(__VA_ARGS__); } while (0)
+#define show_method(...) do { if (WHEN) show_method(__VA_ARGS__); } while (0)
+#define show_basicblock(...) do { if (WHEN) show_basicblock(__VA_ARGS__); } while (0)
+#endif
+
+/*
+TODO
+move set and get uses into jit.h
+*/
+
+#define ICMD_PHI 666
+
+#define eqi(a, b) (((a) && (b) || (!(a) && !(b)))
+
+#define nn(x) ((x) < 0 ? 0 : (x))
+
+#define ass(dst, src) *(dst) = *(src)
+
+static inline const char *instruction_name(const instruction *iptr) {
+ if (iptr == NULL) {
+ return "null";
+ } else if (iptr->opc == ICMD_PHI) {
+ return "phi";
+ } else {
+ return icmd_table[iptr->opc].name;
+ }
+}
+
+static inline s4 instruction_line(const instruction *iptr) {
+ if (iptr == NULL) {
+ return -1;
+ } else {
+ return iptr->line;
+ }
+}
+
+typedef struct phi_function {
+ s4 dst;
+ s4 *args;
+ s4 local;
+ instruction instr;
+} phi_function;
+
+typedef struct basicblock_info {
+ bool visited;
+ bool active;
+ bool traversed;
+ unsigned backward_branches;
+
+ instruction **state_array;
+
+ unsigned phi_count;
+ unsigned phi_max;
+ phi_function *phi_functions;
+ unsigned complete_predecessors;
+ bool cow;
+} basicblock_info;
+
+typedef struct ssa_info {
+ jitdata *jd;
+
+ varinfo locals[3000]; /* XXX hardcoded max */
+ unsigned max_locals;
+ unsigned locals_count;
+
+ s4 s_buf[3];
+} ssa_info;
+
+static unsigned get_predecessor_count(basicblock *bb) {
+ unsigned ret;
+ basicblock **itpred;
+
+ ret = nn(bb->predecessorcount);
+
+ FOR_EACH_EXPREDECESSOR(bb, itpred) {
+ ret += (*itpred)->exouts;
+ }
+
+ return ret;
+}
+
+static unsigned get_predecessor_index(basicblock *from, basicblock *to) {
+ basicblock **itpred;
+ unsigned j = 0;
+
+ for (itpred = to->predecessors; itpred != to->predecessors + nn(to->predecessorcount); ++itpred) {
+ if (*itpred == from) break;
+ j++;
+ }
+
+ if (j == nn(to->predecessorcount)) {
+ assert(j != nn(to->predecessorcount));
+ }
+
+ return j;
+}
+
+static void phi_set_argument(basicblock *bb, instruction *phi, unsigned j, instruction *value) {
+ phi_function *pf = (phi_function *)(
+ (char *)phi - OFFSET(phi_function, instr)
+ );
+ assert(j < phi->s1.argcount);
+ if (value == NULL) {
+ pf->args[j] = pf->local;
+ } else {
+ pf->args[j] = value->dst.varindex;
+ }
+ /*phi->sx.s23.s2.args[j] = value->dst.varindex;*/
+ printf(" *** in bb%d setting phi arg %d for local %d to %s@%d (%d)\n", bb->nr, j, pf->local, instruction_name(value), instruction_line(value), value ? value->dst.varindex : -1);
+}
+
+static inline basicblock_info *bb_info(basicblock *bb) {
+ return (basicblock_info *)(bb->vp);
+}
+
+static void mark_loops(basicblock *bb) {
+ basicblock_info *bbi = bb_info(bb);
+ basicblock **itsucc;
+
+ if (! bbi->visited) {
+ bbi->visited = true;
+ bbi->active = true;
+ FOR_EACH_SUCCESSOR(bb, itsucc) {
+ mark_loops(*itsucc);
+ }
+ FOR_EACH_EXHANDLER(bb, itsucc) {
+ mark_loops(*itsucc);
+ }
+ bbi->active = false;
+ } else if (bbi->active) {
+ bbi->backward_branches += 1;
+ }
+}
+
+static instruction *create_phi(ssa_info *ssa, basicblock *bb, s4 local) {
+ basicblock_info *bbi = bb_info(bb);
+ phi_function *phi;
+ s4 *itarg;
+ unsigned arg_count = get_predecessor_count(bb);
+
+ printf(" *** BB%d phi #%d for local %d\n", bb->nr, bbi->phi_count, local);
+
+ phi = bbi->phi_functions + bbi->phi_count;
+ assert(bbi->phi_count < bbi->phi_max);
+ bbi->phi_count += 1;
+
+
+ phi->local = local;
+ phi->args = DMNEW(s4, arg_count);
+ for (itarg = phi->args; itarg != phi->args + arg_count; ++itarg) {
+ /* Invalidate */
+ *itarg = 0x7fffffff;
+ }
+
+ assert(ssa->locals_count < ssa->max_locals);
+ ssa->locals[ssa->locals_count] = ssa->jd->var[local];
+ phi->dst = ssa->locals_count;
+ ssa->locals_count += 1;
+
+ phi->instr.opc = ICMD_PHI;
+ phi->instr.dst.varindex = phi->dst;
+ phi->instr.s1.argcount = arg_count;
+ phi->instr.sx.s23.s2.args = NULL;
+
+ return &(phi->instr);
+}
+
+static bool is_my_phi(basicblock *bb, instruction *iptr) {
+ basicblock_info *bbi = bb_info(bb);
+ if (iptr == NULL) {
+ return false;
+ }
+ if (iptr->opc != ICMD_PHI) {
+ return false;
+ }
+ if (
+ ((char *)bbi->phi_functions <= (char *)iptr) &&
+ ((char *)iptr < (char *)(bbi->phi_functions + bbi->phi_count))
+ ) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void rename_def(ssa_info *ssa, basicblock *bptr, instruction *iptr) {
+ basicblock_info *bbi = bb_info(bptr);
+ assert(bbi->state_array);
+
+ bbi->state_array[iptr->dst.varindex] = iptr;
+
+ assert(ssa->locals_count < ssa->max_locals);
+
+ ssa->locals[ssa->locals_count] = ssa->jd->var[iptr->dst.varindex];
+ iptr->dst.varindex = ssa->locals_count;
+ printf(" *** BB%d %s def %d => %d\n", bptr->nr, instruction_name(iptr), iptr->dst.varindex, ssa->locals_count);
+
+ ssa->locals_count += 1;
+}
+
+static void rename_use(ssa_info *ssa, basicblock *bptr, instruction *iptr, s4 *use) {
+ basicblock_info *bbi = bb_info(bptr);
+ assert(bbi->state_array);
+
+ if (bbi->state_array[*use] != NULL) {
+ printf(" *** BB%d %s use %d => %d (%s) \n", bptr->nr, instruction_name(iptr), *use, bbi->state_array[*use]->dst.varindex, instruction_name(bbi->state_array[*use]) );
+ *use = bbi->state_array[*use]->dst.varindex;
+ } else {
+ printf(" *** BB%d %s use keep\n", bptr->nr, instruction_name(iptr));
+ }
+}
+
+static void get_uses(ssa_info *ssa, instruction *iptr, s4 **puses, unsigned *puses_count) {
+ unsigned uses_count = 0;
+
+ switch (icmd_table[iptr->opc].dataflow) {
+ case DF_3_TO_0:
+ case DF_3_TO_1:
+ ssa->s_buf[2] = iptr->sx.s23.s3.varindex;
+ uses_count += 1;
+
+ case DF_2_TO_0:
+ case DF_2_TO_1:
+ ssa->s_buf[1] = iptr->sx.s23.s2.varindex;
+ uses_count += 1;
+
+ case DF_1_TO_0:
+ case DF_1_TO_1:
+ case DF_COPY:
+ case DF_MOVE:
+ ssa->s_buf[0] = iptr->s1.varindex;
+ uses_count += 1;
+
+ *puses_count = uses_count;
+ *puses = ssa->s_buf;
+ break;
+
+ case DF_N_TO_1:
+ case DF_INVOKE:
+ case DF_BUILTIN:
+
+ *puses = iptr->sx.s23.s2.args;
+ *puses_count = iptr->s1.argcount;
+ break;
+
+ default:
+
+ *puses_count = 0;
+ break;
+ }
+}
+
+static void set_uses(ssa_info *ssa, instruction *iptr, s4 *uses, unsigned uses_count) {
+ if (uses == ssa->s_buf) {
+ switch (uses_count) {
+ case 3:
+ iptr->sx.s23.s3.varindex = ssa->s_buf[2];
+ case 2:
+ iptr->sx.s23.s2.varindex = ssa->s_buf[1];
+ case 1:
+ iptr->s1.varindex = ssa->s_buf[0];
+ }
+ }
+}
+
+typedef void (*traverse_fun)(ssa_info *ssa, basicblock *bb);
+
+static void traverse(ssa_info *ssa, basicblock *bb, traverse_fun fun) {
+ basicblock_info *bbi = bb_info(bb);
+ basicblock **itsucc, **itpred;
+ basicblock_info *succi;
+ unsigned complete_preds;
+ unsigned j;
+
+ /*if (bbi->traversed) {
+ return;
+ }*/
+
+ /* Process block */
+
+ fun(ssa, bb);
+
+ /*bbi->traversed = true;*/
+
+ /* Recurse */
+
+ FOR_EACH_SUCCESSOR(bb, itsucc) {
+ merge(ssa, bbi->state_array, *itsucc, get_predecessor_index(bb, *itsucc));
+ succi = bb_info(*itsucc);
+ succi->complete_predecessors += 1;
+ if (succi->complete_predecessors == (/*nn((*itsucc)->predecessorcount)*/ get_predecessor_count(*itsucc) - succi->backward_branches)) {
+ printf(" *** Traverse bb%d => bb%d\n", bb->nr, (*itsucc)->nr);
+ traverse(ssa, *itsucc, fun);
+ }
+ }
+
+ FOR_EACH_EXHANDLER(bb, itsucc) {
+ succi = bb_info(*itsucc);
+ succi->complete_predecessors += bb->exouts; /* XXX this might be 0 */
+ if (succi->complete_predecessors == (/*nn((*itsucc)->predecessorcount)*/ get_predecessor_count(*itsucc) - succi->backward_branches)) {
+ printf(" *** Traverse bb%d => bb%d\n", bb->nr, (*itsucc)->nr);
+ traverse(ssa, *itsucc, fun);
+ }
+ }
+
+}
+
+void merge(ssa_info *ssa, instruction **state_array, basicblock *succ, unsigned j) {
+ basicblock_info *succi = bb_info(succ);
+ instruction *phi;
+ unsigned i;
+ unsigned a;
+
+#define mprintf(fmt, ...) printf(" *** merge bb? => bb%d > " fmt, succ->nr, __VA_ARGS__)
+
+ mprintf("(%d, %p)\n", j, succi->state_array);
+
+ if (succi->state_array == NULL) {
+
+ succi->state_array = DMNEW(instruction *, ssa->jd->localcount);
+
+ mprintf("creating state_array %p\n", succi->state_array );
+
+
+ if (succi->backward_branches > 0) {
+ mprintf("bb%d is loop header, creating phis\n", succ->nr);
+ for (i = 0; i < ssa->jd->localcount; ++i) {
+ succi->state_array[i] = create_phi(ssa, succ, i);
+ }
+ } else {
+ /*
+ printf(" *** merge bb%d cow state array\n", succ->nr);
+ succi->state_array = bbi->state_array;
+ succi->cow = true;
+ */
+ MCOPY(succi->state_array, state_array, instruction *, ssa->jd->localcount);
+ return;
+ }
+ }
+
+ for (i = 0; i < ssa->jd->localcount; ++i) {
+ mprintf("local %d bb: %s@%d, succ: %s@%d\n", i, instruction_name(state_array[i]), instruction_line(state_array[i]), instruction_name(succi->state_array[i]), instruction_line(succi->state_array[i]));
+
+ if (succi->traversed) {
+ /* Back edge, all phis already created */
+ /* Only fill in phi arguments */
+ /* We have created phis for *ALL* locals, so there is random access */
+ phi_set_argument(succ, &(succi->phi_functions[i].instr), j, state_array[i]);
+ } else if (state_array[i] != succi->state_array[i]) {
+ mprintf("merge bb%d need phi for local %d\n", succ->nr, i);
+ /* Create new state array if needed */
+
+ /*if (succi->cow) {
+ printf(" *** merge bb%d cloning cow state array\n", succ->nr);
+ state_array = DMNEW(instruction *, ssa->jd->localcount);
+ MCOPY(state_array, succi->state_array, instruction *, ssa->jd->localcount);
+ succi->state_array = state_array;
+ succi->cow = false;
+ }*/
+
+ if (is_my_phi(succ, succi->state_array[i])) {
+ /* State array is already phi function, just need to fill in argument */
+ phi_set_argument(succ, succi->state_array[i], j, state_array[i]);
+ } else {
+ /* Create phi and initialize all arguments with current state array value
+ * (We might have already merged this value from within several blocks).
+ */
+ phi = create_phi(ssa, succ, i);
+ for (a = 0; a < get_predecessor_count(succ); ++a) {
+ phi_set_argument(succ, phi, a, succi->state_array[i]);
+ }
+ phi_set_argument(succ, phi, j, state_array[i]);
+ succi->state_array[i] = phi;
+ }
+ }
+ }
+#undef mprintf
+}
+
+static unsigned get_ex_predecessor_index(basicblock *from, unsigned pei, basicblock *to) {
+ unsigned i, j;
+ basicblock **itpred;
+ instruction *iti;
+
+ j = nn(to->predecessorcount);
+
+ FOR_EACH_EXPREDECESSOR(to, itpred) {
+ if ((*itpred)->nr == from->nr) {
+ j += pei;
+ return j;
+ } else {
+ j += (*itpred)->exouts;
+ }
+ }
+
+ assert(0);
+}
+
+static void handle_pei(ssa_info *ssa, basicblock *bb, unsigned pei) {
+ basicblock_info *bbi = bb_info(bb);
+ basicblock **itsucc;
+
+ FOR_EACH_EXHANDLER(bb, itsucc) {
+ merge(ssa, bbi->state_array, *itsucc, get_ex_predecessor_index(bb, pei, *itsucc));
+ }
+}
+
+static void traverse_fun_impl(ssa_info *ssa, basicblock *bb) {
+ basicblock_info *bbi = bb_info(bb), *predi;
+ basicblock **itpred, *pred;
+ unsigned i;
+ bool need_phi;
+ instruction *iptr;
+ unsigned uses_count;
+ s4 *uses, *ituse;
+ unsigned pei = 0;
+
+ assert(! bbi->traversed);
+ bbi->traversed = true;
+
+ /*
+ if (bbi->state_array) {
+ return;
+ }
+ */
+
+ /* bb 0 */
+
+ if (bb->predecessorcount == 0) {
+ assert(! bbi->state_array);
+ bbi->state_array = DMNEW(instruction *, ssa->jd->localcount);
+ MZERO(bbi->state_array, instruction *, ssa->jd->localcount);
+ goto process_instructions;
+ }
+
+
+ /*
+ if ((bb->predecessorcount == 1) && (bb->predecessors[0]->successorcount == 1)) {
+ bbi->state_array = bb_info(bb->predecessors[0])->state_array;
+ assert(bbi->state_array);
+ goto process_instructions;
+ }
+ */
+
+ /*
+ bbi->state_array = DMNEW(instruction *, ssa->jd->localcount);
+ MZERO(bbi->state_array, instruction *, ssa->jd->localcount);
+ */
+
+ /*
+ if (bbi->backward_branches > 0) {
+ for (i = 0; i < ssa->jd->localcount; ++i) {
+ bbi->state_array[i] = create_phi(ssa, bb, i);
+ }
+ } else {
+ for (i = 0; i < ssa->jd->localcount; ++i) {
+ need_phi = false;
+ assert(bb_info(bb->predecessors[0])->state_array);
+
+ FOR_EACH_PREDECESSOR(bb, itpred) {
+ assert(bb_info(*itpred)->state_array);
+ if (bb_info(bb->predecessors[0])->state_array[i] != bb_info(*itpred)->state_array[i]) {
+ need_phi = true;
+ break;
+ }
+ }
+
+ if (need_phi) {
+ bbi->state_array[i] = create_phi(ssa, bb, i);
+ } else {
+ bbi->state_array[i] = bb_info(bb->predecessors[0])->state_array[i];
+ }
+
+ }
+ }
+ */
+
+process_instructions:
+
+ assert(bbi->state_array);
+
+ FOR_EACH_INSTRUCTION(bb, iptr) {
+
+ if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
+ handle_pei(ssa, bb, pei++);
+ }
+
+ get_uses(ssa, iptr, &uses, &uses_count);
+
+ for (ituse = uses; ituse != uses + uses_count; ++ituse) {
+ if (var_is_local(ssa->jd, *ituse)) {
+ rename_use(ssa, bb, iptr, ituse);
+ } else {
+ *ituse += 0xFFFF;
+ }
+ }
+
+ set_uses(ssa, iptr, uses, uses_count);
+
+ if (instruction_has_dst(iptr)) {
+ if (var_is_local(ssa->jd, iptr->dst.varindex)) {
+ rename_def(ssa, bb, iptr);
+ } else {
+ iptr->dst.varindex += 0xFFFF;
+ }
+ }
+ }
+}
+
+static void ssa_rename_others(ssa_info *ssa) {
+
+ basicblock *bb;
+ instruction *iptr;
+ s4 *itinout, *uses, *ituse;
+ unsigned uses_count;
+ unsigned off = ssa->locals_count - ssa->jd->localcount;
+
+ FOR_EACH_BASICBLOCK(ssa->jd, bb) {
+
+ if (! basicblock_reached(bb)) continue;
+
+ for (itinout = bb->invars; itinout != bb->invars + bb->indepth; ++itinout) {
+ *itinout += off;
+ }
+
+ for (itinout = bb->outvars; itinout != bb->outvars + bb->outdepth; ++itinout) {
+ *itinout += off;
+ }
+
+ FOR_EACH_INSTRUCTION(bb, iptr) {
+ if (instruction_has_dst(iptr)) {
+ if (iptr->dst.varindex >= 0xFFFF) {
+ iptr->dst.varindex += off;
+ iptr->dst.varindex -= 0xFFFF;
+ }
+ }
+ get_uses(ssa, iptr, &uses, &uses_count);
+ for (ituse = uses; ituse != uses + uses_count; ++ituse) {
+ if (*ituse >= 0xFFFF) {
+ *ituse += off;
+ *ituse -= 0xFFFF;
+ }
+ }
+ set_uses(ssa, iptr, uses, uses_count);
+ }
+ }
+}
+
+static void fill_in_phi_args(ssa_info *ssa) {
+ basicblock *bb;
+ basicblock_info *bbi;
+ phi_function *itphi;
+ unsigned j;
+ basicblock **itpred;
+ basicblock_info *predi;
+
+ FOR_EACH_BASICBLOCK(ssa->jd, bb) {
+ if (!(bb->flags >= BBREACHED)) continue;
+ bbi = bb_info(bb);
+ j = 0;
+ FOR_EACH_PREDECESSOR(bb, itpred) {
+ predi = bb_info(*itpred);
+ for (itphi = bbi->phi_functions; itphi != bbi->phi_functions + bbi->phi_count; ++itphi) {
+ if (predi->state_array[itphi->local]) {
+ itphi->args[j] = predi->state_array[itphi->local]->dst.varindex;
+ } else {
+ itphi->args[j] = itphi->local;
+ }
+ }
+ ++j;
+ }
+ }
+}
+
+static void ssa_export(ssa_info *ssa) {
+ unsigned i, j;
+ jitdata *jd = ssa->jd;
+ varinfo *vars, *it;
+ s4 vartop, varindex;
+
+ vartop = ssa->locals_count + jd->vartop - jd->localcount;
+ vars = DMNEW(varinfo, vartop);
+
+ MCOPY(vars, ssa->locals, varinfo, ssa->locals_count);
+ MCOPY(vars + ssa->locals_count, jd->var + jd->localcount, varinfo, jd->vartop - jd->localcount);
+
+ jd->var = vars;
+ jd->vartop = jd->varcount = vartop;
+
+ jd->local_map = DMREALLOC(jd->local_map, s4, 5 * jd->maxlocals, 5 * (jd->maxlocals + ssa->locals_count - jd->localcount));
+
+ for (i = 0; i < ssa->locals_count - jd->localcount; ++i) {
+ for (j = 0; j < 5; ++j) {
+ varindex = jd->localcount + i;
+ if (jd->var[varindex].type != j) {
+ varindex = UNUSED;
+ }
+ jd->local_map[((jd->maxlocals + i) * 5) + j] = varindex;
+ }
+ }
+
+ jd->maxlocals += (ssa->locals_count - jd->localcount);
+ jd->localcount = ssa->locals_count;
+}
+
+static basicblock *create_block_intern(ssa_info *ssa, basicblock *from, basicblock *to, unsigned j) {
+ basicblock *mid;
+ basicblock_info *toi;
+ instruction *iptr;
+ phi_function *itph;
+
+ mid = DNEW(basicblock);
+ MZERO(mid, basicblock, 1);
+
+ toi = bb_info(to);
+ assert(toi);
+
+ mid->nr = ssa->jd->basicblockcount;
+ ssa->jd->basicblockcount += 1;
+ mid->mpc = -1;
+ mid->type = 666;
+ mid->icount = toi->phi_count + 1;
+ iptr = mid->iinstr = DMNEW(instruction, mid->icount);
+ MZERO(mid->iinstr, instruction, mid->icount);
+
+ for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
+ iptr->opc = ICMD_COPY;
+ iptr->dst.varindex = itph->dst;
+ iptr->s1.varindex = itph->args[j];
+ assert(j < itph->instr.s1.argcount);
+ assert(itph->dst < ssa->locals_count);
+ assert(itph->args[j] < ssa->locals_count);
+ iptr++;
+ }
+
+ iptr->opc = ICMD_GOTO;
+ iptr->dst.block = to;
+
+ return mid;
+}
+
+static basicblock *create_block(ssa_info *ssa, basicblock *from, basicblock *to) {
+ basicblock *ret;
+ ret = create_block_intern(ssa, from, to, get_predecessor_index(from, to));
+
+ while (from->next) {
+ from = from->next;
+ }
+
+ from->next = ret;
+
+ return ret;
+}
+
+static void crate_fallthrough(ssa_info *ssa, basicblock *bptr) {
+ unsigned j;
+ basicblock_info *toi;
+ instruction *iptr;
+ phi_function *itph;
+
+ if (bptr->next == NULL) return;
+
+ j = get_predecessor_index(bptr, bptr->next);
+
+ toi = bb_info(bptr->next);
+ assert(toi);
+
+ bptr->iinstr = DMREALLOC(bptr->iinstr, instruction, bptr->icount, bptr->icount + toi->phi_count);
+ iptr = bptr->iinstr + bptr->icount;
+ bptr->icount += toi->phi_count;
+
+ for (itph = toi->phi_functions; itph != toi->phi_functions + toi->phi_count; ++itph) {
+ iptr->opc = ICMD_COPY;
+ iptr->dst.varindex = itph->dst;
+ iptr->s1.varindex = itph->args[j];
+ assert(itph->dst < ssa->locals_count);
+ assert(itph->args[j] < ssa->locals_count);
+ iptr++;
+ }
+
+}
+
+static void ssa_create_phi_moves(ssa_info *ssa) {
+ basicblock *bptr;
+ instruction *iptr;
+
+ s4 i, l;
+ branch_target_t *table;
+ lookup_target_t *lookup;
+ bool gt;
+
+ for (bptr = ssa->jd->basicblocks; bptr; bptr = bptr->next) {
+ if (bptr->type == 666) {
+ bptr->type = BBTYPE_STD;
+ continue;
+ }
+ if (! bptr->vp) continue;
+ if (! (bptr->flags >= BBREACHED)) continue;
+ gt = false;
+ for (iptr = bptr->iinstr; iptr != bptr->iinstr + bptr->icount; ++iptr) {
+ switch (icmd_table[iptr->opc].controlflow) {
+ case CF_IF:
+ case CF_RET:
+ case CF_GOTO:
+ iptr->dst.block = create_block(ssa, bptr, iptr->dst.block);
+ break;
+ case CF_TABLE:
+ table = iptr->dst.table;
+ l = iptr->sx.s23.s2.tablelow;
+ i = iptr->sx.s23.s3.tablehigh;
+ i = i - l + 1;
+ i += 1; /* default */
+ while (--i >= 0) {
+ table->block = create_block(ssa, bptr, table->block);
+ ++table;
+ }
+ break;
+ case CF_LOOKUP:
+ lookup = iptr->dst.lookup;
+ i = iptr->sx.s23.s2.lookupcount;
+ while (--i >= 0) {
+ lookup->target.block = create_block(ssa, bptr, lookup->target.block);
+ lookup++;
+ }
+ iptr->sx.s23.s3.lookupdefault.block = create_block(ssa, bptr, iptr->sx.s23.s3.lookupdefault.block);
+ break;
+ case CF_JSR:
+ iptr->sx.s23.s3.jsrtarget.block = create_block(ssa, bptr, iptr->sx.s23.s3.jsrtarget.block);
+ break;
+ }
+ if ((iptr->opc == ICMD_GOTO) || (iptr->opc == ICMD_JSR) || (iptr->opc == ICMD_RET) || icmd_table[iptr->opc].controlflow == CF_END || (iptr->opc == ICMD_TABLESWITCH) || (iptr->opc == ICMD_LOOKUPSWITCH))
+ gt = true;
+ else if (iptr->opc != ICMD_NOP)
+ gt = false;
+ }
+ if (! bptr->next) continue;
+ if (! (bptr->next->flags >= BBREACHED)) continue;
+ if (bptr->next->type == 666) continue;
+ if (!gt) crate_fallthrough(ssa, bptr);
+ }
+}
+
+static basicblock *split_basicblock_at(ssa_info *ssa, basicblock *bptr, instruction *iptr) {
+
+ basicblock *newblock;
+ basicblock *tosplit;
+ basicblock **pnext;
+ unsigned icount;
+ basicblock *it;
+ unsigned pos;
+
+ unsigned origidx = iptr - bptr->iinstr;
+
+ printf(" *** split basicblock bb%d at %s/%d/%d\n", bptr->nr, instruction_name(iptr), instruction_line(iptr), origidx);
+ assert(origidx < bptr->icount);
+
+
+ if (! bptr->subbasicblocks) {
+ bptr->subbasicblocks = DNEW(basicblock);
+ ass(bptr->subbasicblocks, bptr);
+ bptr->subbasicblocks->subbasicblocks = NULL;
+ bptr->subbasicblocks->next = NULL;
+ }
+
+ tosplit = bptr->subbasicblocks;
+ pos = 0;
+
+ while (tosplit->next && (origidx >= (pos + tosplit->icount))) {
+ assert(bptr->nr == tosplit->nr);
+ pos += tosplit->icount;
+ tosplit = tosplit->next;
+ }
+
+ assert(bptr->nr == tosplit->nr);
+
+ icount = iptr - tosplit->iinstr + 1;
+ assert(icount <= tosplit->icount);
+
+ if (icount < tosplit->icount) {
+ newblock = DNEW(basicblock);
+ ass(newblock, tosplit);
+
+ tosplit->next = newblock;
+ tosplit->icount = icount;
+
+ newblock->icount -= icount;
+ newblock->iinstr += icount;
+ newblock->next = NULL;
+
+ assert(tosplit->nr == bptr->nr);
+ assert(newblock->nr == bptr->nr);
+ assert(newblock->next == NULL);
+ } else {
+ printf("xx split\n");
+ }
+
+ /* To not break references to block bptr, we will replace
+ the block by the first fragment later. */
+
+ if (tosplit == bptr->subbasicblocks) tosplit = bptr;
+
+ return tosplit;
+}
+
+static exception_entry *create_exception_handler(ssa_info *ssa, basicblock *from, unsigned pei, basicblock *to, classref_or_classinfo catchtype) {
+ basicblock *it;
+ exception_entry *ee = DNEW(exception_entry);
+ basicblock *exh = create_block_intern(ssa, from, to, get_ex_predecessor_index(from, pei, to));
+ exh->type = BBTYPE_EXH;
+ to->type = BBTYPE_STD;
+
+ exh->indepth = exh->outdepth = 1;
+ exh->invars = exh->outvars = DNEW(s4);
+ /* assigned in caller */
+
+ ee->start = from;
+ /* XXX evil hack: if from is first fragment of BB, then from->next is not the next fragment */
+ ee->end = from->subbasicblocks ? from->subbasicblocks->next : from->next;
+ ee->handler = exh;
+ ee->catchtype = catchtype;
+ ee->next = NULL;
+ ee->down = NULL;
+
+ for (it = ssa->jd->basicblocks; it->next; it = it->next);
+
+ it->next = exh;
+
+ return ee;
+}
+
+static void ssa_create_ex_phi_moves(ssa_info *ssa) {
+ basicblock *bptr;
+ instruction *iptr;
+ basicblock_info *bbi;
+ exception_entry *ite;
+ exception_entry *firstee, *lastee, *ee;
+ basicblock *ittry, *try;
+ classref_or_classinfo catchtype;
+ unsigned pei;
+ unsigned exhandler_count = 0;
+ varinfo *v;
+
+ FOR_EACH_BASICBLOCK(ssa->jd, bptr) {
+ if (! bptr->vp) continue;
+ if (! (bptr->flags >= BBREACHED)) continue;
+ if (bptr->expredecessorcount == 0) continue;
+ bbi = bb_info(bptr);
+ if (bbi->phi_count == 0) continue;
+
+ for (ite = ssa->jd->exceptiontable; ite; ite = ite->down) {
+ /* Traverse all exhandlers */
+ if (bptr == ite->handler) {
+ printf(" *** mess with handler bb%d\n", bptr->nr);
+ catchtype = ite->catchtype;
+ firstee = lastee = NULL;
+ /* If bptr is handler, remove exhandler */
+ /* Traverse all guarded blocks */
+ for (ittry = ite->start; ittry != ite->end; ittry = ittry->next) {
+ pei = 0;
+ FOR_EACH_INSTRUCTION(ittry, iptr) {
+ if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
+ /* try is basicblock fragment till (including) the pei */
+ try = split_basicblock_at(ssa, ittry, iptr);
+ /* ee is handler for try */
+ ee = create_exception_handler(ssa, try, pei, bptr, catchtype);
+ ee->handler->invars[0] = ssa->jd->vartop + exhandler_count;
+ exhandler_count += 1;
+ ssa->jd->exceptiontablelength += 1;
+ if (firstee == NULL) {
+ firstee = lastee = ee;
+ } else {
+ lastee->next = ee;
+ lastee->down = ee;
+ lastee = ee;
+ }
+ pei += 1;
+ }
+ }
+ }
+ /* XXX
+ <------------------->
+ <---><--><--->missing */
+ if (firstee) {
+ lastee->next = ite->next;
+ lastee->down = ite->down;
+ *ite = *firstee;
+ ite = lastee;
+ }
+ }
+ }
+ }
+
+ /* Allocate interface vars */
+
+ ssa->jd->var = DMREALLOC(ssa->jd->var, varinfo, ssa->jd->vartop, ssa->jd->vartop + exhandler_count);
+ for (v = ssa->jd->var + ssa->jd->vartop; v != ssa->jd->var + ssa->jd->vartop + exhandler_count; ++v) {
+ v->type = TYPE_ADR;
+ v->flags = INOUT;
+ }
+ ssa->jd->vartop += exhandler_count;
+ ssa->jd->varcount += exhandler_count;
+}
+
+void yssa(jitdata *jd) {
+ basicblock *it;
+ basicblock_info *iti;
+ ssa_info *ssa;
+
+ if (jd->localcount == 0) return;
+
+ if (test_do_verbose(jd)) do_verbose = 1;
+
+ printf("=============== [ before %s ] =========================\n", jd->m->name->text);
+ show_method(jd, 3);
+ printf("=============== [ /before ] =========================\n");
+
+ ssa = DNEW(ssa_info);
+ ssa->jd = jd;
+ ssa->max_locals = sizeof(ssa->locals) / sizeof(ssa->locals[0]);
+ MCOPY(ssa->locals, jd->var, varinfo, jd->localcount);
+ ssa->locals_count = jd->localcount;
+
+ FOR_EACH_BASICBLOCK(jd, it) {
+ if (basicblock_reached(it)) {
+ iti = DNEW(basicblock_info);
+ MZERO(iti, basicblock_info, 1);
+ if (jd->localcount > 0) {
+ iti->phi_functions = DMNEW(phi_function, jd->localcount);
+ iti->phi_max = jd->localcount;
+ }
+ it->vp = iti;
+ } else {
+ it->vp = NULL;
+ }
+ }
+
+ mark_loops(jd->basicblocks);
+
+ traverse(ssa, jd->basicblocks, traverse_fun_impl);
+
+ ssa_rename_others(ssa);
+
+ /*fill_in_phi_args(ssa);*/
+
+ ssa_export(ssa);
+
+ ssa_create_phi_moves(ssa);
+ ssa_create_ex_phi_moves(ssa);
+
+ printf("=============== [ after ] =========================\n");
+ show_method(jd, 3);
+ printf("=============== [ /after ] =========================\n");
+
+ do_verbose = 0;
+}
+
+void eliminate_subbasicblocks(jitdata *jd) {
+ basicblock *bptr, *next;
+
+ FOR_EACH_BASICBLOCK(jd, bptr) {
+ if (bptr->subbasicblocks) {
+ next = bptr->next;
+ *bptr = *(bptr->subbasicblocks);
+ bptr->subbasicblocks = NULL;
+
+ /* *prev = bptr->subbasicblocks;
+ bptr = bptr->subbasicblocks; */
+
+ while (bptr->next) {
+ bptr = bptr->next;
+ }
+ bptr->next = next;
+ }
+ }
+
+ if (test_do_verbose(jd)) do_verbose = 1;
+ printf("=============== [ elim ] =========================\n");
+ show_method(jd, 3);
+ printf("=============== [ /elim ] =========================\n");
+ do_verbose = 0;
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/jit/optimizing/ssa.c - static single-assignment form
+
+ Copyright (C) 2005 - 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+ R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+ C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+ Institut f. Computersprachen - TU Wien
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You 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: $
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mm/memory.h"
+
+#include "toolbox/bitvector.h"
+#include "toolbox/worklist.h"
+
+#include "vm/builtin.h"
+
+#include "vm/jit/jit.h" /* icmd_table */
+
+#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/graph.h"
+#include "vm/jit/optimizing/lifetimes.h"
+#include "vm/jit/optimizing/lsra.h"
+#include "vm/jit/optimizing/ssa.h"
+#include "vm/jit/optimizing/ssa_phi.h"
+
+#if defined(SSA_DEBUG_VERBOSE)
+#include "vmcore/options.h" /* compileverbose */
+#endif
+
+/* ssa_place_phi_functions *****************************************************
+
+Algorithm is based on "modern compiler implementation in C" from andrew
+w. appel, edition 2004
+
+Corrections:
+page 441 Algorithm 19.6. Inserting phi-functions:
+
+...
+ for each Y in DF[n]
+- if Y not element of A phi [n]
++ if a not element of A phi [n]
+ insert the statment a <- ...
+...
+...
+- A phi [n] <- A phi [n] join {Y}
++ A phi [n] <- A phi [n] join {a}
+- if Y not element of A orig [n]
++ if a not element of A orig [Y]
+ W <- W join {Y}
+
+
+ls->phi[n][a][p] is created and populated.
+
+n in [0..ls->basicblockcount[
+a in [0..ls->ssavarcount[
+p in [1..Count of Predecessors of Basicblock n]
+
+For each basicblock Y in the dominance frontier of a basicblock n (0 <= n <
+ls->basicblockcount) in which a variable (0 <= a < ls->ssavarcount) is defined
+an entry in ls->phi[Y][a] is created.
+This entry is an array with the number of predecessors of Y elements + 1
+elements.
+This elements are all set to the variable a and represent the phi function which
+will get ai = phi(ai1, ai2, ..., aip) after ssa_rename.
+
+
+ls->phi[n][a] == NULL, if no phi function for Variable a for Basicblock n exists
+
+or
+
+ls->phi[n][a][0] == a, representing the result of the phi function and
+ls->phi[n][a][p] == a, representing the arguments of the phi function.
+
+*******************************************************************************/
+
+
+void ssa_place_phi_functions(jitdata *jd, graphdata *gd, dominatordata *dd)
+{
+ int a,i,j,n,Y;
+ bitvector *def_sites;
+ bitvector *A_phi; /* [0..ls->basicblockcount[ of */
+ /* ls->ssavarcount Bit */
+ worklist *W;
+ int num_pred;
+
+ lsradata *ls;
+
+ ls = jd->ls;
+
+ W = wl_new(ls->basicblockcount);
+
+ def_sites = DMNEW(bitvector, ls->ssavarcount);
+ for(a = 0; a < ls->ssavarcount; a++)
+ def_sites[a] = bv_new(ls->basicblockcount);
+
+ ls->phi = DMNEW(int **, ls->basicblockcount);
+ A_phi = DMNEW(bitvector, ls->basicblockcount);
+ for(i = 0; i < ls->basicblockcount; i++) {
+ ls->phi[i] = DMNEW(int *, ls->ssavarcount);
+ for(j = 0; j < ls->ssavarcount; j++)
+ ls->phi[i][j] = NULL;
+ A_phi[i] = bv_new(ls->ssavarcount);
+ }
+
+ /* copy var_def to def_sites */
+ /* var_def is valid for 0.. jd->basicblockcount (bb 0 for param init) */
+
+ for(n = 0; n <= jd->basicblockcount; n++)
+ for(a = 0; a < ls->ssavarcount; a++)
+ if (bv_get_bit(ls->var_def[n], a))
+ bv_set_bit(def_sites[a], n);
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("var Definitions:\n");
+ for(i = 0; i < ls->ssavarcount; i++) {
+ printf("def_sites[%3i]=%p:",i,(void *)def_sites[i]);
+ for(j = 0; j < ls->basicblockcount; j++) {
+ if ((j % 5) == 0) printf(" ");
+ if (bv_get_bit(def_sites[i], j))
+ printf("1");
+ else
+ printf("0");
+ }
+ printf(" (");
+
+ printf("\n");
+ }
+ }
+#endif
+
+ for(a = 0; a < ls->ssavarcount; a++) {
+
+ /* W<-def_sites(a) */
+
+ for(n = 0; n < ls->basicblockcount; n++)
+ if (bv_get_bit(def_sites[a],n)) {
+ wl_add(W, n);
+ }
+
+ while (!wl_is_empty(W)) { /* W not empty */
+ n = wl_get(W);
+
+ for(i = 0; i < dd->num_DF[n]; i++) {
+ Y = dd->DF[n][i];
+
+ /* Node Y is in Dominance Frontier of n -> */
+ /* insert phi function for a at top of Y*/
+
+ _SSA_CHECK_BOUNDS(Y, 0, ls->basicblockcount);
+ if (bv_get_bit( A_phi[Y], a) == 0) {
+
+ /* a is not a Element of A_phi[Y] */
+ /* a <- phi(a,a...,a) to be inserted at top of Block Y */
+ /* phi has as many arguments, as Y has predecessors */
+
+ num_pred = graph_get_num_predecessor(gd, Y);
+ ls->phi[Y][a] = DMNEW(int, num_pred + 1);
+ for (j = 0; j < num_pred + 1; j++)
+ ls->phi[Y][a][j] = a;
+
+ /* increment the number of definitions of a by one */
+ /* for this phi function */
+
+ ls->num_defs[a]++;
+
+ bv_set_bit(A_phi[Y], a);
+ if (bv_get_bit(ls->var_def[Y],a)==0) {
+
+ /* Iterated Dominance Frontier Criterion: */
+ /* if Y had no definition for a, insert it */
+ /* into the Worklist, since now it */
+ /* defines a through the phi function */
+
+ wl_add(W, Y);
+ }
+ }
+ }
+ }
+ }
+}
+
+void ssa_generate_phi_moves(jitdata *jd, graphdata *gd) {
+ int a, i, j, pred;
+ graphiterator iter;
+ lsradata *ls;
+
+ ls = jd->ls;
+
+ /* count moves to be inserted at the end of each block in moves[] */
+
+ ls->num_phi_moves = DMNEW(int, ls->basicblockcount);
+ for(i = 0; i < ls->basicblockcount; i++)
+ ls->num_phi_moves[i] = 0;
+ for(i = 0; i < ls->basicblockcount; i++)
+ for(a = 0; a < ls->ssavarcount; a++)
+ if (ls->phi[i][a] != NULL) {
+#if 0
+ if (ls->lifetime[ls->phi[i][a][0]].use == NULL) {
+ /* Var defined (only <- SSA Form!) in this phi function */
+ /* and not used anywhere -> delete phi function and set */
+ /* var to unused */
+
+ /* TODO: first delete use sites of arguments of phi */
+ /* function */
+ VAR(ls->lifetime[ls->phi[i][a][0]].v_index)->type = UNUSED;
+ ls->lifetime[ls->phi[i][a][0]].def = NULL;
+ ls->phi[i][a] = NULL;
+ }
+ else
+#endif
+ {
+ pred = graph_get_first_predecessor(gd, i, &iter);
+ for(; pred != -1; pred = graph_get_next(&iter)) {
+ ls->num_phi_moves[pred]++;
+ }
+ }
+ }
+
+ /* allocate ls->phi_moves */
+
+ ls->phi_moves = DMNEW( int **, ls->basicblockcount);
+ for(i = 0; i < ls->basicblockcount; i++) {
+ ls->phi_moves[i] = DMNEW( int *, ls->num_phi_moves[i]);
+ for(j = 0; j <ls->num_phi_moves[i]; j++)
+ ls->phi_moves[i][j] = DMNEW(int, 2);
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose)
+ printf("ssa_generate_phi_moves: ls_num_phi_moves[%3i] = %3i\n",
+ i, ls->num_phi_moves[i]);
+#endif
+ }
+
+ /* populate ls->phi_moves */
+
+ for(i = 0; i < ls->basicblockcount; i++)
+ ls->num_phi_moves[i] = 0;
+ for(i = 0; i < ls->basicblockcount; i++)
+ for(a = 0; a < ls->ssavarcount; a++)
+ if (ls->phi[i][a] != NULL) {
+ pred = graph_get_first_predecessor(gd, i, &iter);
+ for(j = 0; pred != -1; j++, pred = graph_get_next(&iter)) {
+ /* target is phi[i][a][0] */
+ /* source is phi[i][a][j+1] */
+ if (ls->phi[i][a][j+1] != ls->varcount_with_indices) {
+ /* valid move */
+ if (ls->phi[i][a][0] != ls->phi[i][a][j+1]) {
+ ls->phi_moves[pred][ls->num_phi_moves[pred]][0] =
+ ls->phi[i][a][0];
+ ls->phi_moves[pred][(ls->num_phi_moves[pred])++][1]=
+ ls->phi[i][a][j+1];
+ }
+ }
+ }
+ }
+}
+
+#ifdef SSA_DEBUG_VERBOSE
+void ssa_print_phi(lsradata *ls, graphdata *gd) {
+ int i,j,k;
+
+ printf("phi Functions (varcount_with_indices: %3i):\n",
+ ls->varcount_with_indices);
+ for(i = 0; i < ls->basicblockcount; i++) {
+ for(j = 0; j < ls->ssavarcount; j++) {
+ if (ls->phi[i][j] != NULL) {
+ printf("BB %3i %3i = phi(", i, ls->phi[i][j][0]);
+ for(k = 1; k <= graph_get_num_predecessor(gd, i); k++)
+ printf("%3i ",ls->phi[i][j][k]);
+ 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:
+ */
--- /dev/null
+/* 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
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You 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$
+
+*/
+
+
+#ifndef _SSA_PHI_H
+#define _SSA_PHI_H
+
+#include "vm/jit/optimizing/graph.h"
+
+#if !defined(NDEBUG)
+# include <assert.h>
+#endif
+
+/* function prototypes */
+void ssa_place_phi_functions(jitdata *jd, graphdata *gd, dominatordata *dd);
+void ssa_generate_phi_moves(jitdata *, graphdata *);
+#ifdef SSA_DEBUG_VERBOSE
+void ssa_print_phi(lsradata *ls, graphdata *gd);
+#endif
+
+#endif /* _SSA_PHI_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/optimizing/ssa.c - static single-assignment form
+
+ Copyright (C) 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., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mm/memory.h"
+
+#include "toolbox/bitvector.h"
+#include "toolbox/worklist.h"
+
+#include "vm/builtin.h"
+
+#include "vm/jit/jit.h" /* icmd_table */
+
+#include "vm/jit/optimizing/dominators.h"
+#include "vm/jit/optimizing/graph.h"
+#include "vm/jit/optimizing/lifetimes.h"
+#include "vm/jit/optimizing/lsra.h"
+#include "vm/jit/optimizing/ssa.h"
+#include "vm/jit/optimizing/ssa_rename.h"
+
+#if defined(SSA_DEBUG_VERBOSE)
+#include "vmcore/options.h" /* compileverbose */
+#endif
+
+/* function prototypes */
+void ssa_rename_(jitdata *jd, graphdata *gd, dominatordata *dd, int n);
+int ssa_rename_def_(lsradata *ls, int a);
+
+/* ssa_rename ******************************************************************
+
+Rename the variables a (0 <= a < ls->ssavarcount) so that each new variable
+has only one definition (SSA form).
+
+ls->def_count[0..ls->ssavarcount[ holds the number of definitions of each var.
+ls->var_0[0..ls->ssavarcount[ will be set to the new index of the first
+ definition of each old var.
+ls->varcount_with_indices will be se to the new maximum varcount of LOCAL
+ and IOVARS.
+
+All other vars (TEMPVAR and PREALLOC) will get a new unique index above
+ls->varcount_with_indices.
+
+jd->var and jd->varcount will be set for this renamed vars.
+
+*******************************************************************************/
+
+void ssa_rename(jitdata *jd, graphdata *gd, dominatordata *dd)
+{
+ int i, mi, l, j, p, t;
+ int type, flags;
+ methoddesc *md = jd->m->parseddesc;
+
+ varinfo *new_vars;
+ lsradata *ls;
+
+ ls = jd->ls;
+
+ ssa_rename_init(jd, gd);
+
+ /* Consider definition of Local Vars initialized with Arguments */
+ /* in Block 0 */
+ /* init is regarded as use too-> ssa_rename_use ->bullshit!!*/
+
+ for (p = 0, l= 0; p < md->paramcount; p++) {
+ t = md->paramtypes[p].type;
+ mi = l * 5 + t;
+ i = jd->local_map[mi];
+ l++;
+ if (IS_2_WORD_TYPE(t))
+ l++;
+ if (i == UNUSED)
+ continue;
+
+ /* !!!!! locals are now numbered as the parameters !!!! */
+ /* !!!!! no additional increment for 2 word types !!!!! */
+ /* this happens later on! here we still need the increment */
+ /* index of var can be in the range from 0 up to not including*/
+ /* jd->varcount */
+
+
+ i = ls->new_varindex[i];
+
+ /* ignore return value, since first definition gives 0 -> */
+ /* no rename necessary */
+
+ j = ssa_rename_def_(ls, i);
+ _SSA_ASSERT(j == 0);
+ jd->local_map[mi] = i;
+ }
+ ssa_rename_(jd, gd, dd, 0);
+
+#if 0
+ /* DO _NOT_ DO THIS! Look at java.util.stringtokenizer.counttokens! */
+ /* if there is no use of the defined Var itself by the phi function */
+ /* for a loop path, in which this var is not used, it will not be life*/
+ /* in this path and overwritten! */
+
+ /* Invalidate all xij from xi0=phi(xi1,xi2,xi3,..,xin) with xij == xi0*/
+ /* this happens if the phi function is the first definition of x or in*/
+ /* a path with a backedge xi has no definition */
+ /* a phi(xij) = ...,xij,... with the only use and definition of xij by*/
+ /* this phi function would otherwise "deadlock" the dead code */
+ /* elemination (invalidate means set it to UNUSED) */
+ /* a phi function phi(xi0)=xi1,xi2,...xin wiht xij == xi0 for all j in*/
+ /* [1,n] can be removed */
+
+ for(i = 0; i < ls->ssavarcount; i++) {
+ for(t = 0; t < ls->basicblockcount; t++) {
+ if (ls->phi[t][i] != 0) {
+ remove_phi = true;
+ for(p = 1; p <= graph_get_num_predecessor(gd, t); p++) {
+ if (ls->phi[t][i][0] == ls->phi[t][i][p])
+ ls->phi[t][i][p] = UNUSED;
+ else
+ remove_phi = false;
+ }
+ }
+ if (remove_phi)
+ ls->phi[t][i] = NULL;
+ }
+ }
+#endif
+
+#if defined(SSA_DEBUG_CHECK) || defined(SSA_DEBUG_VERBOSE)
+# if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose) {
+ printf("%s %s ",jd->m->clazz->name->text, jd->m->name->text);
+ if (code_is_leafmethod(jd->code))
+ printf("**Leafmethod**");
+ printf("\n");
+ }
+# endif
+ if (strcmp(jd->m->clazz->name->text,"fp")==0)
+ if (strcmp(jd->m->name->text,"testfloat")==0)
+# if defined(SSA_DEBUG_VERBOSE)
+ if (compileverbose)
+ printf("12-------------------12\n");
+# else
+ { int dummy=1; dummy++; }
+# endif
+#endif
+
+ /* recreate rd->locals[][] */
+ /* now only one (local_index/type) pair exists anymore */
+ /* all var[t][i] with var_to_index[var[t][i]] >= 0 are locals */
+ /* max local index after SSA indexing is in ls->local_0[ls->max_locals] */
+
+ new_vars = DMNEW(varinfo, ls->vartop);
+ for(i = 0; i < ls->vartop ; i++)
+ new_vars[i].type = UNUSED;
+ for(i = 0; i < jd->varcount; i++) {
+ p = ls->new_varindex[i];
+ if (p != UNUSED) {
+ if (p < ls->ssavarcount)
+ p = ls->var_0[p];
+ new_vars[p].type = VAR(i)->type;
+ new_vars[p].flags = VAR(i)->flags;
+ ls->lifetime[p].v_index = p;
+ ls->lifetime[p].type = VAR(i)->type;
+ }
+ }
+
+ /* take care of newly indexed local & in/out vars */
+
+ for(i = 0; i < ls->ssavarcount; i++) {
+ j = ls->var_0[i];
+ type = new_vars[j].type;
+ flags = new_vars[j].flags;
+ j++;
+ for (; j < ls->var_0[i + 1]; j++) {
+ new_vars[j].type = type;
+ new_vars[j].flags = flags;
+ ls->lifetime[j].v_index = j;
+ ls->lifetime[j].type = type;
+ }
+ }
+
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+
+ printf("ssa_rename: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
+ ls->ssavarcount);
+ for(i = 0; i < jd->varcount; i++) {
+ printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
+ ssa_show_variable(jd, i, VAR(i),0);
+ j = ls->new_varindex[i];
+ if ((j != UNUSED) && (j < ls->ssavarcount))
+ printf(" -> %3i ... %3i", ls->var_0[j], ls->var_0[j + 1] - 1);
+ else
+ printf(" -> %3i", j);
+ printf("\n");
+ }
+ }
+#endif
+
+ jd->var = new_vars;
+ jd->varcount = ls->vartop;
+ jd->vartop = ls->vartop;
+
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("ssa_rename: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
+ ls->ssavarcount);
+ for(i = 0; i < jd->varcount; i++) {
+ printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
+ ssa_show_variable(jd, i, VAR(i),0);
+ printf("\n");
+ }
+ }
+#endif
+}
+
+/* ssa_rename_init *************************************************************
+
+Setup the data structure for ssa_rename
+
+ls->def_count[0..ls->ssavarcount[ holds the number of definitions of each var.
+ls->var_0[0..ls->ssavarcount[ will be set to the new index of the first
+ definition of each old var.
+ls->varcount_with_indices will be se to the new maximum varcount of LOCAL
+ and IOVARS.
+
+All other vars (TEMPVAR and PREALLOC) will get a new unique index above
+ls->varcount_with_indices.
+
+jd->var and jd->varcount will be set for this renamed vars.
+
+*******************************************************************************/
+
+void ssa_rename_init(jitdata *jd, graphdata *gd)
+{
+ int a, i;
+#if 0
+ int p;
+#endif
+ lsradata *ls;
+
+ ls = jd->ls;
+
+ /* set up new locals */
+ /* ls->new_varindex[0..jd->varcount[ holds the new unique index */
+ /* for locals and iovars */
+
+ /* ls->num_defs[index] gives the number of indizes which will be created */
+ /* from SSA */
+
+ /* -> vars will be numbered in this sequence: L0(0)..L0(i) L1(0)..L1(j) ..*/
+ /* ls->var_0[X] will point to each LX(0) */
+ /* ls->var_0[ls->ssavarcount] will hold ls->varcount_with_indices */
+
+ /* as first step cummulate the num_defs array for locals and iovars */
+ /* last element is the maximum var count */
+
+ ls->var_0 = DMNEW(int, max(1, ls->ssavarcount + 1));
+ ls->var_0[0] = 0;
+ ls->varcount_with_indices = 0;
+ for(i = 0; i < ls->ssavarcount; i++) {
+ ls->varcount_with_indices += ls->num_defs[i];
+ ls->var_0[i+1] = ls->var_0[i] + ls->num_defs[i];
+ }
+
+#if 0
+ /* Change the var indices in phi from La to La(0) */
+
+ for(i = 0; i < ls->basicblockcount; i++)
+ for (a = 0; a < ls->ssavarcount; a++)
+ if (ls->phi[i][a] != NULL)
+ for(p = 0; p < graph_get_num_predecessor(gd, i) + 1; p++)
+ ls->phi[i][a][p] = ls->var_0[a];
+#endif
+
+ /* Initialization */
+
+ ls->count = DMNEW(int, max(1, ls->ssavarcount));
+ ls->stack = DMNEW(int *, max(1, ls->ssavarcount));
+ ls->stack_top = DMNEW(int, max(1, ls->ssavarcount));
+ for(a = 0; a < ls->ssavarcount; a++) {
+ ls->count[a] = 0;
+ ls->stack_top[a] = 0;
+
+ /* stack a has to hold number of defs of a Elements + 1 */
+
+ ls->stack[a] = DMNEW(int, ls->num_defs[a] + 1);
+ ls->stack[a][ls->stack_top[a]++] = 0;
+ }
+
+ if (ls->ssavarcount > 0) {
+
+ /* Create the num_var_use Array */
+
+ ls->num_var_use = DMNEW(int *, ls->basicblockcount);
+ for(i = 0; i < ls->basicblockcount; i++) {
+ ls->num_var_use[i] =DMNEW(int, max(1, ls->varcount_with_indices));
+ for(a = 0; a < ls->varcount_with_indices; a++)
+ ls->num_var_use[i][a] = 0;
+ }
+
+ /* Create the use_sites Array of Bitvectors*/
+ /* use max(1,..), to ensure that the array is created! */
+
+ ls->use_sites = DMNEW(bitvector, max(1, ls->varcount_with_indices));
+ for(a = 0; a < ls->varcount_with_indices; a++)
+ ls->use_sites[a] = bv_new(ls->basicblockcount);
+ }
+
+ /* init lifetimes */
+ /* count number of TEMPVARs */
+
+ ls->lifetimecount = 0;
+ for(i = 0; i < jd->varcount; i++)
+ if ((i >= jd->localcount) || (!(jd->var[i].flags & (INOUT | PREALLOC))))
+ ls->lifetimecount++;
+
+ ls->varcount = ls->varcount_with_indices + ls->lifetimecount;
+
+ ls->lifetimecount = ls->varcount;
+ ls->lifetime = DMNEW(struct lifetime, ls->lifetimecount);
+ ls->lt_used = DMNEW(int, ls->lifetimecount);
+ ls->lt_int = DMNEW(int, ls->lifetimecount);
+ ls->lt_int_count = 0;
+ ls->lt_flt = DMNEW(int, ls->lifetimecount);
+ ls->lt_flt_count = 0;
+ ls->lt_mem = DMNEW(int, ls->lifetimecount);
+ ls->lt_mem_count = 0;
+ for (i=0; i < ls->lifetimecount; i++) {
+ ls->lifetime[i].type = UNUSED;
+ ls->lifetime[i].savedvar = 0;
+ ls->lifetime[i].flags = 0;
+ ls->lifetime[i].usagecount = 0;
+ ls->lifetime[i].bb_last_use = -1;
+ ls->lifetime[i].bb_first_def = -1;
+ ls->lifetime[i].use = NULL;
+ ls->lifetime[i].def = NULL;
+ ls->lifetime[i].last_use = NULL;
+ }
+
+ /* for giving TEMP and PREALLOC vars a new unique index */
+
+ ls->vartop = ls->varcount_with_indices;
+
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("ssa_rename_init: Vars: Orig:%3i SSAVar: %3i\n", jd->varcount,
+ ls->ssavarcount);
+ for(i = 0; i < jd->varcount; i++) {
+ if ((i < jd->localcount) || ( VAR(i)->flags & INOUT)) {
+ printf("%3i(%3i,%3x) ",i,VAR(i)->type, VAR(i)->flags);
+ ssa_show_variable(jd, i, VAR(i),0);
+ if ((i < ls->ssavarcount) || (VAR(i)->flags & INOUT)) {
+ printf(" -> %3i", ls->new_varindex[i]);
+ }
+ printf("\n");
+ }
+ }
+ ssa_print_phi(ls, gd);
+ }
+#endif
+}
+
+int ssa_rename_def_(lsradata *ls, int a) {
+ int i;
+
+ _SSA_CHECK_BOUNDS(a,0,ls->ssavarcount);
+ ls->count[a]++;
+ i = ls->count[a] - 1;
+ /* push i on stack[a] */
+ _SSA_CHECK_BOUNDS(ls->stack_top[a], 0, ls->num_defs[a] + 1);
+ ls->stack[a][ls->stack_top[a]++] = i;
+ return i;
+}
+
+int ssa_rename_def(jitdata *jd, int *def_count, int a) {
+ int i, a1, ret;
+ lsradata *ls;
+
+ ls = jd->ls;
+
+ a1 = ls->new_varindex[a];
+ _SSA_CHECK_BOUNDS(a1, UNUSED, ls->varcount);
+ if ((a1 != UNUSED) && (a1 < ls->ssavarcount)) {
+ /* local or inoutvar -> normal ssa renaming */
+ _SSA_ASSERT((a < jd->localcount) || (VAR(a)->flags & INOUT));
+ /* !IS_TEMPVAR && !IS_PREALLOC == (IS_LOCALVAR || IS_INOUT) */
+
+ def_count[a1]++;
+ i = ssa_rename_def_(ls, a1);
+ ret = ls->var_0[a1] + i;
+ }
+ else {
+ /* TEMP or PREALLOC var */
+ if (a1 == UNUSED) {
+ ls->new_varindex[a] = ls->vartop;
+ ret = ls->vartop;
+ ls->vartop++;
+ _SSA_ASSERT( ls->vartop < ls->varcount);
+ }
+ else
+ ret = a1;
+ }
+ return ret;
+}
+
+void ssa_rename_use_(lsradata *ls, int n, int a) {
+ _SSA_CHECK_BOUNDS(a, 0, ls->varcount_with_indices);
+ if (ls->ssavarcount > 0) {
+ bv_set_bit(ls->use_sites[a], n);
+ ls->num_var_use[n][a]++;
+ }
+}
+
+int ssa_rename_use(lsradata *ls, int n, int a) {
+ int a1, i;
+ int ret;
+
+ a1 = ls->new_varindex[a];
+ _SSA_CHECK_BOUNDS(a1, UNUSED, ls->varcount);
+ if ((a1 != UNUSED) && (a1 < ls->ssavarcount)) {
+ /* local or inoutvar -> normal ssa renaming */
+ /* i <- top(stack[a]) */
+
+ _SSA_CHECK_BOUNDS(ls->stack_top[a1]-1, 0, ls->num_defs[a1]+1);
+ i = ls->stack[a1][ls->stack_top[a1] - 1];
+ _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a1]);
+
+ ret = ls->var_0[a1] + i;
+ }
+ else {
+ /* TEMP or PREALLOC var */
+ if (a1 == UNUSED) {
+ ls->new_varindex[a] = ls->vartop;
+ ret = ls->vartop;
+ ls->vartop++;
+ _SSA_ASSERT( ls->vartop < ls->varcount);
+ }
+ else
+ ret = a1;
+ }
+
+ return ret;
+}
+
+#ifdef SSA_DEBUG_VERBOSE
+void ssa_rename_print(instruction *iptr, char *op, int from, int to) {
+ if (compileverbose) {
+ printf("ssa_rename_: ");
+ if (iptr != NULL)
+ printf("%s ", bytecode[iptr->opc].mnemonic);
+ else
+ printf(" ");
+
+ printf("%s: %3i->%3i\n", op, from, to);
+ }
+}
+#endif
+
+/* ssa_rename_ ****************************************************************
+
+Algorithm is based on "modern compiler implementation in C" from andrew
+w. appel, edition 2004
+
+page 443 Algorithm 19.7. Renaming Variables
+
+*******************************************************************************/
+
+void ssa_rename_(jitdata *jd, graphdata *gd, dominatordata *dd, int n) {
+ int a, i, j, k, iindex, Y, v;
+ int in_d, out_d;
+ int *def_count;
+ /* [0..ls->varcount[ Number of Definitions of this var in this */
+ /* Basic Block. Used to remove the entries off the stack at the */
+ /* end of the function */
+ instruction *iptr;
+ s4 *in, *out, *argp;
+ graphiterator iter_succ, iter_pred;
+ struct lifetime *lt;
+
+ methoddesc *md;
+ methodinfo *m;
+ builtintable_entry *bte;
+ lsradata *ls;
+
+ ls = jd->ls;
+ m = jd->m;
+
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose)
+ printf("ssa_rename_: BB %i\n",n);
+#endif
+
+ _SSA_CHECK_BOUNDS(n, 0, ls->basicblockcount);
+
+ def_count = DMNEW(int, max(1, ls->ssavarcount));
+ for(i = 0; i < ls->ssavarcount; i++)
+ def_count[i] = 0;
+
+ /* change Store of possible phi functions from a to ai*/
+
+ for(a = 0; a < ls->ssavarcount; a++)
+ if (ls->phi[n][a] != NULL) {
+ def_count[a]++;
+
+ /* do not mark this store as use - maybe this phi function */
+ /* can be removed for unused Vars*/
+
+ j = ls->var_0[a] + ssa_rename_def_(ls, a);
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( NULL, "phi-st", ls->phi[n][a][0], j);
+#endif
+ ls->phi[n][a][0] = j;
+ }
+
+ in = ls->basicblocks[n]->invars;
+ in_d = ls->basicblocks[n]->indepth - 1;
+
+ /* change use of instack Interface stackslots except top SBR and EXH */
+ /* stackslots */
+
+ if ((ls->basicblocks[n]->type == BBTYPE_EXH) ||
+ (ls->basicblocks[n]->type == BBTYPE_SBR)) {
+ in_d--;
+ }
+/* out = ls->basicblocks[n]->outvars; */
+/* out_d = ls->basicblocks[n]->outdepth - 1; */
+
+/* for(; out_d > in_d; out_d--); */
+
+ for (; in_d >= 0; in_d--) {
+ /* Possible Use of ls->new_varindex[jd->var[in_d]] */
+ _SSA_ASSERT(ls->new_varindex[in[in_d]] != UNUSED);
+
+ a = ls->new_varindex[in[in_d]];
+ _SSA_CHECK_BOUNDS(a, 0, ls->ssavarcount);
+
+ /* i <- top(stack[a]) */
+
+ _SSA_CHECK_BOUNDS(ls->stack_top[a]-1, 0, ls->num_defs[a]+1);
+ i = ls->stack[a][ls->stack_top[a]-1];
+ _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a]);
+
+ /* Replace use of x with xi */
+
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( NULL, "invar", in[in_d], ls->var_0[a]+i);
+#endif
+ in[in_d] = ls->var_0[a] + i;
+ lt = ls->lifetime + in[in_d];
+
+ lt->v_index = in[in_d];
+ lt->bb_last_use = -1;
+ }
+
+ iptr = ls->basicblocks[n]->iinstr;
+
+ for(iindex = 0; iindex < ls->basicblocks[n]->icount; iindex++, iptr++) {
+
+ /* check for use (s1, s2, s3 or special (argp) ) */
+
+ switch (icmd_table[iptr->opc].dataflow) {
+ case DF_3_TO_0:
+ case DF_3_TO_1: /* icmd has s1, s2 and s3 */
+ j = ssa_rename_use(ls, n, iptr->sx.s23.s3.varindex);
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( iptr, "s3 ", iptr->sx.s23.s3.varindex, j);
+#endif
+ iptr->sx.s23.s3.varindex = j;
+
+ /* now "fall through" for handling of s2 and s1 */
+
+ case DF_2_TO_0:
+ case DF_2_TO_1: /* icmd has s1 and s2 */
+ j = ssa_rename_use(ls, n, iptr->sx.s23.s2.varindex);
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( iptr, "s2 ", iptr->sx.s23.s2.varindex, j);
+#endif
+ iptr->sx.s23.s2.varindex = j;
+
+ /* now "fall through" for handling of s1 */
+
+ case DF_1_TO_0:
+ case DF_1_TO_1:
+ case DF_MOVE:
+ case DF_COPY:
+ j = ssa_rename_use(ls, n, iptr->s1.varindex);
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( iptr, "s1 ", iptr->s1.varindex, j);
+#endif
+ iptr->s1.varindex = j;
+ break;
+
+ case DF_INVOKE:
+ case DF_BUILTIN:
+ case DF_N_TO_1:
+ /* do not use md->paramcount, pass-through stackslots have */
+ /* to be renamed, too */
+ i = iptr->s1.argcount;
+ argp = iptr->sx.s23.s2.args;
+ while (--i >= 0) {
+ j = ssa_rename_use(ls, n, *argp);
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( iptr, "arg", *argp, j);
+#endif
+ *argp = j;
+ argp++;
+ }
+ break;
+ }
+
+
+ /* Look for definitions (iptr->dst). INVOKE and BUILTIN have */
+ /* an optional dst - so they to be checked first */
+
+ v = UNUSED;
+ if (icmd_table[iptr->opc].dataflow == DF_INVOKE) {
+ INSTRUCTION_GET_METHODDESC(iptr,md);
+ if (md->returntype.type != TYPE_VOID)
+ v = iptr->dst.varindex;
+ }
+ else if (icmd_table[iptr->opc].dataflow == DF_BUILTIN) {
+ bte = iptr->sx.s23.s3.bte;
+ md = bte->md;
+ if (md->returntype.type != TYPE_VOID)
+ v = iptr->dst.varindex;
+ }
+ else if (icmd_table[iptr->opc].dataflow >= DF_DST_BASE) {
+ v = iptr->dst.varindex;
+ }
+
+ if (v != UNUSED) {
+ j = ssa_rename_def(jd, def_count, iptr->dst.varindex);
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( iptr, "dst", iptr->dst.varindex, j);
+#endif
+ iptr->dst.varindex = j;
+ }
+
+ /* ?????????????????????????????????????????????????????????? */
+ /* Mark Def as use, too. Since param initialisation is in */
+ /* var_def and this would not remove this locals, if not used */
+ /* elsewhere */
+ /* ?????????????????????????????????????????????????????????? */
+
+ }
+
+ /* change outstack Interface stackslots */
+ out = ls->basicblocks[n]->outvars;
+ out_d = ls->basicblocks[n]->outdepth - 1;
+
+ for (;out_d >= 0; out_d--) {
+ /* Possible Use of ls->new_varindex[jd->var[out_d]] */
+ _SSA_ASSERT(ls->new_varindex[out[out_d]] != UNUSED);
+
+ a = ls->new_varindex[out[out_d]];
+ _SSA_CHECK_BOUNDS(a, 0, ls->ssavarcount);
+
+ /* i <- top(stack[a]) */
+
+ _SSA_CHECK_BOUNDS(ls->stack_top[a]-1, 0, ls->num_defs[a]+1);
+ i = ls->stack[a][ls->stack_top[a]-1];
+ _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a]);
+
+ /* Replace use of x with xi */
+
+#ifdef SSA_DEBUG_VERBOSE
+ ssa_rename_print( NULL, "outvar", out[out_d], ls->var_0[a]+i);
+#endif
+ out[out_d] = ls->var_0[a] + i;
+ lt = ls->lifetime + out[out_d];
+
+ lt->v_index = out[out_d];
+ lt->bb_last_use = -1;
+ }
+
+ /* change use in phi Functions of Successors */
+
+ Y = graph_get_first_successor(gd, n, &iter_succ);
+ for(; Y != -1; Y = graph_get_next(&iter_succ)) {
+ _SSA_CHECK_BOUNDS(Y, 0, ls->basicblockcount);
+ k = graph_get_first_predecessor(gd, Y, &iter_pred);
+ for (j = 0; (k != -1) && (k != n); j++)
+ k = graph_get_next(&iter_pred);
+ _SSA_ASSERT(k == n);
+
+ /* n is jth Predecessor of Y */
+
+ for(a = 0; a < ls->ssavarcount; a++)
+ if (ls->phi[Y][a] != NULL) {
+
+ /* i <- top(stack[a]) */
+
+ if (ls->stack_top[a] == 1) {
+ /* no definition till now in controll flow */
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("Succ %3i Arg %3i \n", Y, j);
+ ssa_rename_print( NULL, "phi-use", ls->phi[Y][a][j+1], UNUSED);
+ }
+#endif
+ ls->phi[Y][a][j+1] = UNUSED;
+ }
+ else {
+ _SSA_CHECK_BOUNDS(ls->stack_top[a]-1, 0, ls->num_defs[a]+1);
+ i = ls->stack[a][ls->stack_top[a]-1];
+ _SSA_CHECK_BOUNDS(i, 0, ls->num_defs[a]);
+
+ /* change jth operand from a0 to ai */
+
+ i = ls->var_0[a] + i;
+#ifdef SSA_DEBUG_VERBOSE
+ if (compileverbose) {
+ printf("Succ %3i Arg %3i \n", Y, j);
+ ssa_rename_print( NULL, "phi-use", ls->phi[Y][a][j+1], i);
+ }
+#endif
+ ls->phi[Y][a][j+1] = i;
+ _SSA_CHECK_BOUNDS(ls->phi[Y][a][j+1], 0,
+ ls->varcount_with_indices);
+
+ /* use by phi function has to be remembered, too */
+
+ ssa_rename_use_(ls, n, ls->phi[Y][a][j+1]);
+ }
+
+ /* ????????????????????????????????????????????? */
+ /* why was this only for local vars before ? */
+ /* ????????????????????????????????????????????? */
+
+ }
+ }
+
+ /* Call ssa_rename_ for all Childs of n of the Dominator Tree */
+ for(i = 0; i < ls->basicblockcount; i++)
+ if (dd->idom[i] == n)
+ ssa_rename_(jd, gd, dd, i);
+
+ /* pop Stack[a] for each definition of a var a in the original S */
+ for(a = 0; a < ls->ssavarcount; a++) {
+ ls->stack_top[a] -= def_count[a];
+ _SSA_ASSERT(ls->stack_top[a] >= 0);
+ }
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/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
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You 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$
+
+*/
+
+
+#ifndef _SSA_RENAME_H
+#define _SSA_RENAME_H
+
+#include "vm/jit/optimizing/graph.h"
+
+#if !defined(NDEBUG)
+# include <assert.h>
+#endif
+
+/* function prototypes */
+void ssa_rename_init(jitdata *jd, graphdata *gd);
+void ssa_rename(jitdata *jd, graphdata *gd, dominatordata *dd);
+
+#endif /* _SSA_RENAME_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:
+ */
/* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
- 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/parse.h"
#include "vm/jit/loop/loop.h"
+#include "vm/jit/ir/bytecode.h"
+
#include "vmcore/linker.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
mark the current bytecode instruction as basic-block
starting instruction. */
- /* NOTE: Some compilers put a JAVA_NOP after a blockend
+ /* NOTE: Some compilers put a BC_nop after a blockend
instruction. */
- if (blockend && (opcode != JAVA_NOP)) {
+ if (blockend && (opcode != BC_nop)) {
MARK_BASICBLOCK(&pd, bcindex);
blockend = false;
}
/* compute next instruction start */
- nextbc = bcindex + jcommandsize[opcode];
+ nextbc = bcindex + bytecode[opcode].length;
CHECK_END_OF_BYTECODE(nextbc);
/* add stack elements produced by this instruction */
- s_count += stackreq[opcode];
+ s_count += bytecode[opcode].slots;
/* We check here for the space of 1 instruction in the
instruction array. If an opcode is converted to more than
/* translate this bytecode instruction */
switch (opcode) {
- case JAVA_NOP:
+ case BC_nop:
break;
/* pushing constants onto the stack ***********************************/
- case JAVA_BIPUSH:
+ case BC_bipush:
OP_LOADCONST_I(SUCK_BE_S1(m->jcode + bcindex + 1));
break;
- case JAVA_SIPUSH:
+ case BC_sipush:
OP_LOADCONST_I(SUCK_BE_S2(m->jcode + bcindex + 1));
break;
- case JAVA_LDC1:
+ case BC_ldc1:
i = SUCK_BE_U1(m->jcode + bcindex + 1);
goto pushconstantitem;
- case JAVA_LDC2:
- case JAVA_LDC2W:
+ case BC_ldc2:
+ case BC_ldc2w:
i = SUCK_BE_U2(m->jcode + bcindex + 1);
pushconstantitem:
#if defined(ENABLE_VERIFIER)
- if (i >= m->class->cpcount) {
+ if (i >= m->clazz->cpcount) {
exceptions_throw_verifyerror(m,
"Attempt to access constant outside range");
return false;
}
#endif
- switch (m->class->cptags[i]) {
+ switch (m->clazz->cptags[i]) {
case CONSTANT_Integer:
- OP_LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_I(((constant_integer *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_Long:
- OP_LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_L(((constant_long *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_Float:
- OP_LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_F(((constant_float *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_Double:
- OP_LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
+ OP_LOADCONST_D(((constant_double *) (m->clazz->cpinfos[i]))->value);
break;
case CONSTANT_String:
- OP_LOADCONST_STRING(literalstring_new((utf *) (m->class->cpinfos[i])));
+ OP_LOADCONST_STRING(literalstring_new((utf *) (m->clazz->cpinfos[i])));
break;
case CONSTANT_Class:
- cr = (constant_classref *) (m->class->cpinfos[i]);
+ cr = (constant_classref *) (m->clazz->cpinfos[i]);
if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
return false;
}
break;
- case JAVA_ACONST_NULL:
+ case BC_aconst_null:
OP_LOADCONST_NULL();
break;
- case JAVA_ICONST_M1:
- case JAVA_ICONST_0:
- case JAVA_ICONST_1:
- case JAVA_ICONST_2:
- case JAVA_ICONST_3:
- case JAVA_ICONST_4:
- case JAVA_ICONST_5:
- OP_LOADCONST_I(opcode - JAVA_ICONST_0);
+ case BC_iconst_m1:
+ case BC_iconst_0:
+ case BC_iconst_1:
+ case BC_iconst_2:
+ case BC_iconst_3:
+ case BC_iconst_4:
+ case BC_iconst_5:
+ OP_LOADCONST_I(opcode - BC_iconst_0);
break;
- case JAVA_LCONST_0:
- case JAVA_LCONST_1:
- OP_LOADCONST_L(opcode - JAVA_LCONST_0);
+ case BC_lconst_0:
+ case BC_lconst_1:
+ OP_LOADCONST_L(opcode - BC_lconst_0);
break;
- case JAVA_FCONST_0:
- case JAVA_FCONST_1:
- case JAVA_FCONST_2:
- OP_LOADCONST_F(opcode - JAVA_FCONST_0);
+ case BC_fconst_0:
+ case BC_fconst_1:
+ case BC_fconst_2:
+ OP_LOADCONST_F(opcode - BC_fconst_0);
break;
- case JAVA_DCONST_0:
- case JAVA_DCONST_1:
- OP_LOADCONST_D(opcode - JAVA_DCONST_0);
+ case BC_dconst_0:
+ case BC_dconst_1:
+ OP_LOADCONST_D(opcode - BC_dconst_0);
break;
/* stack operations ***************************************************/
- /* We need space for additional ICMDs so we can translate these */
- /* instructions to sequences of ICMD_COPY and ICMD_MOVE instructions. */
+ /* We need space for additional instruction so we can
+ translate these instructions to sequences of ICMD_COPY and
+ ICMD_MOVE instructions. */
- case JAVA_DUP_X1:
+ case BC_dup_x1:
INSTRUCTIONS_CHECK(4);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_DUP_X2:
+ case BC_dup_x2:
INSTRUCTIONS_CHECK(6);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_DUP2:
+ case BC_dup2:
INSTRUCTIONS_CHECK(2);
OP(opcode);
OP(ICMD_NOP);
break;
- case JAVA_DUP2_X1:
+ case BC_dup2_x1:
INSTRUCTIONS_CHECK(7);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_DUP2_X2:
+ case BC_dup2_x2:
INSTRUCTIONS_CHECK(9);
OP(opcode);
OP(ICMD_NOP);
OP(ICMD_NOP);
break;
- case JAVA_SWAP:
+ case BC_swap:
INSTRUCTIONS_CHECK(3);
OP(opcode);
OP(ICMD_NOP);
/* local variable access instructions *********************************/
- case JAVA_ILOAD:
- case JAVA_FLOAD:
- case JAVA_ALOAD:
+ case BC_iload:
+ case BC_fload:
+ case BC_aload:
if (iswide == false) {
i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
nextbc = bcindex + 3;
iswide = false;
}
- OP_LOAD_ONEWORD(opcode, i, opcode - JAVA_ILOAD);
+ OP_LOAD_ONEWORD(opcode, i, opcode - BC_iload);
break;
- case JAVA_LLOAD:
- case JAVA_DLOAD:
+ case BC_lload:
+ case BC_dload:
if (iswide == false) {
i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
nextbc = bcindex + 3;
iswide = false;
}
- OP_LOAD_TWOWORD(opcode, i, opcode - JAVA_ILOAD);
+ OP_LOAD_TWOWORD(opcode, i, opcode - BC_iload);
break;
- case JAVA_ILOAD_0:
- case JAVA_ILOAD_1:
- case JAVA_ILOAD_2:
- case JAVA_ILOAD_3:
- OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0, TYPE_INT);
+ case BC_iload_0:
+ case BC_iload_1:
+ case BC_iload_2:
+ case BC_iload_3:
+ OP_LOAD_ONEWORD(ICMD_ILOAD, opcode - BC_iload_0, TYPE_INT);
break;
- case JAVA_LLOAD_0:
- case JAVA_LLOAD_1:
- case JAVA_LLOAD_2:
- case JAVA_LLOAD_3:
- OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0, TYPE_LNG);
+ case BC_lload_0:
+ case BC_lload_1:
+ case BC_lload_2:
+ case BC_lload_3:
+ OP_LOAD_TWOWORD(ICMD_LLOAD, opcode - BC_lload_0, TYPE_LNG);
break;
- case JAVA_FLOAD_0:
- case JAVA_FLOAD_1:
- case JAVA_FLOAD_2:
- case JAVA_FLOAD_3:
- OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0, TYPE_FLT);
+ case BC_fload_0:
+ case BC_fload_1:
+ case BC_fload_2:
+ case BC_fload_3:
+ OP_LOAD_ONEWORD(ICMD_FLOAD, opcode - BC_fload_0, TYPE_FLT);
break;
- case JAVA_DLOAD_0:
- case JAVA_DLOAD_1:
- case JAVA_DLOAD_2:
- case JAVA_DLOAD_3:
- OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0, TYPE_DBL);
+ case BC_dload_0:
+ case BC_dload_1:
+ case BC_dload_2:
+ case BC_dload_3:
+ OP_LOAD_TWOWORD(ICMD_DLOAD, opcode - BC_dload_0, TYPE_DBL);
break;
- case JAVA_ALOAD_0:
- case JAVA_ALOAD_1:
- case JAVA_ALOAD_2:
- case JAVA_ALOAD_3:
- OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0, TYPE_ADR);
+ case BC_aload_0:
+ case BC_aload_1:
+ case BC_aload_2:
+ case BC_aload_3:
+ OP_LOAD_ONEWORD(ICMD_ALOAD, opcode - BC_aload_0, TYPE_ADR);
break;
- case JAVA_ISTORE:
- case JAVA_FSTORE:
- case JAVA_ASTORE:
+ case BC_istore:
+ case BC_fstore:
+ case BC_astore:
if (iswide == false) {
i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
nextbc = bcindex + 3;
iswide = false;
}
- OP_STORE_ONEWORD(opcode, i, opcode - JAVA_ISTORE);
+ OP_STORE_ONEWORD(opcode, i, opcode - BC_istore);
break;
- case JAVA_LSTORE:
- case JAVA_DSTORE:
+ case BC_lstore:
+ case BC_dstore:
if (iswide == false) {
i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
nextbc = bcindex + 3;
iswide = false;
}
- OP_STORE_TWOWORD(opcode, i, opcode - JAVA_ISTORE);
+ OP_STORE_TWOWORD(opcode, i, opcode - BC_istore);
break;
- case JAVA_ISTORE_0:
- case JAVA_ISTORE_1:
- case JAVA_ISTORE_2:
- case JAVA_ISTORE_3:
- OP_STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0, TYPE_INT);
+ case BC_istore_0:
+ case BC_istore_1:
+ case BC_istore_2:
+ case BC_istore_3:
+ OP_STORE_ONEWORD(ICMD_ISTORE, opcode - BC_istore_0, TYPE_INT);
break;
- case JAVA_LSTORE_0:
- case JAVA_LSTORE_1:
- case JAVA_LSTORE_2:
- case JAVA_LSTORE_3:
- OP_STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0, TYPE_LNG);
+ case BC_lstore_0:
+ case BC_lstore_1:
+ case BC_lstore_2:
+ case BC_lstore_3:
+ OP_STORE_TWOWORD(ICMD_LSTORE, opcode - BC_lstore_0, TYPE_LNG);
break;
- case JAVA_FSTORE_0:
- case JAVA_FSTORE_1:
- case JAVA_FSTORE_2:
- case JAVA_FSTORE_3:
- OP_STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0, TYPE_FLT);
+ case BC_fstore_0:
+ case BC_fstore_1:
+ case BC_fstore_2:
+ case BC_fstore_3:
+ OP_STORE_ONEWORD(ICMD_FSTORE, opcode - BC_fstore_0, TYPE_FLT);
break;
- case JAVA_DSTORE_0:
- case JAVA_DSTORE_1:
- case JAVA_DSTORE_2:
- case JAVA_DSTORE_3:
- OP_STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0, TYPE_DBL);
+ case BC_dstore_0:
+ case BC_dstore_1:
+ case BC_dstore_2:
+ case BC_dstore_3:
+ OP_STORE_TWOWORD(ICMD_DSTORE, opcode - BC_dstore_0, TYPE_DBL);
break;
- case JAVA_ASTORE_0:
- case JAVA_ASTORE_1:
- case JAVA_ASTORE_2:
- case JAVA_ASTORE_3:
- OP_STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0, TYPE_ADR);
+ case BC_astore_0:
+ case BC_astore_1:
+ case BC_astore_2:
+ case BC_astore_3:
+ OP_STORE_ONEWORD(ICMD_ASTORE, opcode - BC_astore_0, TYPE_ADR);
break;
- case JAVA_IINC:
+ case BC_iinc:
{
int v;
if (iswide == false) {
i = SUCK_BE_U1(m->jcode + bcindex + 1);
v = SUCK_BE_S1(m->jcode + bcindex + 2);
-
}
else {
i = SUCK_BE_U2(m->jcode + bcindex + 1);
/* wider index for loading, storing and incrementing ******************/
- case JAVA_WIDE:
+ case BC_wide:
bcindex++;
iswide = true;
goto fetch_opcode;
/* managing arrays ****************************************************/
- case JAVA_NEWARRAY:
+ case BC_newarray:
switch (SUCK_BE_S1(m->jcode + bcindex + 1)) {
case 4:
bte = builtintable_get_internal(BUILTIN_newarray_boolean);
OP_BUILTIN_CHECK_EXCEPTION(bte);
break;
- case JAVA_ANEWARRAY:
+ case BC_anewarray:
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
+ compr = (constant_classref *) class_getconstant(m->clazz, i, CONSTANT_Class);
if (compr == NULL)
return false;
s_count++;
break;
- case JAVA_MULTIANEWARRAY:
+ case BC_multianewarray:
i = SUCK_BE_U2(m->jcode + bcindex + 1);
j = SUCK_BE_U1(m->jcode + bcindex + 3);
- cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
+ cr = (constant_classref *) class_getconstant(m->clazz, i, CONSTANT_Class);
if (cr == NULL)
return false;
/* control flow instructions ******************************************/
- case JAVA_IFEQ:
- case JAVA_IFLT:
- case JAVA_IFLE:
- case JAVA_IFNE:
- case JAVA_IFGT:
- case JAVA_IFGE:
- case JAVA_IFNULL:
- case JAVA_IFNONNULL:
- case JAVA_IF_ICMPEQ:
- case JAVA_IF_ICMPNE:
- case JAVA_IF_ICMPLT:
- case JAVA_IF_ICMPGT:
- case JAVA_IF_ICMPLE:
- case JAVA_IF_ICMPGE:
- case JAVA_IF_ACMPEQ:
- case JAVA_IF_ACMPNE:
- case JAVA_GOTO:
+ case BC_ifeq:
+ case BC_iflt:
+ case BC_ifle:
+ case BC_ifne:
+ case BC_ifgt:
+ case BC_ifge:
+ case BC_ifnull:
+ case BC_ifnonnull:
+ case BC_if_icmpeq:
+ case BC_if_icmpne:
+ case BC_if_icmplt:
+ case BC_if_icmpgt:
+ case BC_if_icmple:
+ case BC_if_icmpge:
+ case BC_if_acmpeq:
+ case BC_if_acmpne:
+ case BC_goto:
i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
CHECK_BYTECODE_INDEX(i);
MARK_BASICBLOCK(&pd, i);
OP_INSINDEX(opcode, i);
break;
- case JAVA_GOTO_W:
+ case BC_goto_w:
i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
CHECK_BYTECODE_INDEX(i);
MARK_BASICBLOCK(&pd, i);
OP_INSINDEX(ICMD_GOTO, i);
break;
- case JAVA_JSR:
+ case BC_jsr:
i = bcindex + SUCK_BE_S2(m->jcode + bcindex + 1);
jsr_tail:
CHECK_BYTECODE_INDEX(i);
MARK_BASICBLOCK(&pd, i);
blockend = true;
- OP_PREPARE_ZEROFLAGS(JAVA_JSR);
+ OP_PREPARE_ZEROFLAGS(BC_jsr);
iptr->sx.s23.s3.jsrtarget.insindex = i;
PINC;
break;
- case JAVA_JSR_W:
+ case BC_jsr_w:
i = bcindex + SUCK_BE_S4(m->jcode + bcindex + 1);
goto jsr_tail;
- case JAVA_RET:
+ case BC_ret:
if (iswide == false) {
i = SUCK_BE_U1(m->jcode + bcindex + 1);
}
OP_LOAD_ONEWORD(opcode, i, TYPE_ADR);
break;
- case JAVA_IRETURN:
- case JAVA_LRETURN:
- case JAVA_FRETURN:
- case JAVA_DRETURN:
- case JAVA_ARETURN:
- case JAVA_RETURN:
+ case BC_ireturn:
+ case BC_lreturn:
+ case BC_freturn:
+ case BC_dreturn:
+ case BC_areturn:
+ case BC_return:
blockend = true;
/* XXX ARETURN will need a flag in the typechecker */
OP(opcode);
break;
- case JAVA_ATHROW:
+ case BC_athrow:
blockend = true;
/* XXX ATHROW will need a flag in the typechecker */
OP(opcode);
/* table jumps ********************************************************/
- case JAVA_LOOKUPSWITCH:
+ case BC_lookupswitch:
{
s4 num, j;
lookup_target_t *lookup;
break;
}
-
- case JAVA_TABLESWITCH:
+ case BC_tableswitch:
{
s4 num, j;
s4 deftarget;
/* load and store of object fields ************************************/
- case JAVA_AASTORE:
+ case BC_aastore:
OP(opcode);
code_unflag_leafmethod(code);
break;
- case JAVA_GETSTATIC:
- case JAVA_PUTSTATIC:
- case JAVA_GETFIELD:
- case JAVA_PUTFIELD:
+ case BC_getstatic:
+ case BC_putstatic:
+ case BC_getfield:
+ case BC_putfield:
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- fmi = class_getconstant(m->class, i, CONSTANT_Fieldref);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_Fieldref);
if (fmi == NULL)
return false;
return false;
if (result != resolveSucceeded) {
- uf = resolve_create_unresolved_field(m->class, m, iptr);
+ uf = resolve_create_unresolved_field(m->clazz, m, iptr);
if (uf == NULL)
return false;
/* method invocation **************************************************/
- case JAVA_INVOKESTATIC:
+ case BC_invokestatic:
OP_PREPARE_ZEROFLAGS(opcode);
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- fmi = class_getconstant(m->class, i, CONSTANT_Methodref);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
if (fmi == NULL)
return false;
goto invoke_method;
- case JAVA_INVOKESPECIAL:
+ case BC_invokespecial:
OP_PREPARE_FLAGS(opcode, INS_FLAG_CHECK);
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- fmi = class_getconstant(m->class, i, CONSTANT_Methodref);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
goto invoke_nonstatic_method;
- case JAVA_INVOKEINTERFACE:
+ case BC_invokeinterface:
OP_PREPARE_ZEROFLAGS(opcode);
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- fmi = class_getconstant(m->class, i, CONSTANT_InterfaceMethodref);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_InterfaceMethodref);
goto invoke_nonstatic_method;
- case JAVA_INVOKEVIRTUAL:
+ case BC_invokevirtual:
OP_PREPARE_ZEROFLAGS(opcode);
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- fmi = class_getconstant(m->class, i, CONSTANT_Methodref);
+ fmi = class_getconstant(m->clazz, i, CONSTANT_Methodref);
invoke_nonstatic_method:
if (fmi == NULL)
if (!JITDATA_HAS_FLAG_VERIFY(jd)) {
#endif
result = resolve_method_lazy(m, fmi,
- (opcode == JAVA_INVOKESPECIAL));
+ (opcode == BC_invokespecial));
if (result == resolveFailed)
return false;
}
}
else {
- um = resolve_create_unresolved_method(m->class, m, fmi,
- (opcode == JAVA_INVOKESTATIC),
- (opcode == JAVA_INVOKESPECIAL));
+ um = resolve_create_unresolved_method(m->clazz, m, fmi,
+ (opcode == BC_invokestatic),
+ (opcode == BC_invokespecial));
if (um == NULL)
return false;
/* instructions taking class arguments ********************************/
- case JAVA_NEW:
+ case BC_new:
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- cr = class_getconstant(m->class, i, CONSTANT_Class);
+ cr = class_getconstant(m->clazz, i, CONSTANT_Class);
if (cr == NULL)
return false;
s_count++;
break;
- case JAVA_CHECKCAST:
+ case BC_checkcast:
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- cr = class_getconstant(m->class, i, CONSTANT_Class);
+ cr = class_getconstant(m->clazz, i, CONSTANT_Class);
if (cr == NULL)
return false;
OP_S3_CLASSINFO_OR_CLASSREF(opcode, c, cr, flags);
break;
- case JAVA_INSTANCEOF:
+ case BC_instanceof:
i = SUCK_BE_U2(m->jcode + bcindex + 1);
- cr = class_getconstant(m->class, i, CONSTANT_Class);
+ cr = class_getconstant(m->clazz, i, CONSTANT_Class);
if (cr == NULL)
return false;
/* synchronization instructions ***************************************/
- case JAVA_MONITORENTER:
+ case BC_monitorenter:
#if defined(ENABLE_THREADS)
if (checksync) {
bte = builtintable_get_internal(LOCK_monitor_enter);
}
break;
- case JAVA_MONITOREXIT:
+ case BC_monitorexit:
#if defined(ENABLE_THREADS)
if (checksync) {
bte = builtintable_get_internal(LOCK_monitor_exit);
/* arithmetic instructions that may become builtin functions **********/
- case JAVA_IDIV:
+ case BC_idiv:
#if !SUPPORT_DIVISION
bte = builtintable_get_internal(BUILTIN_idiv);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_IREM:
+ case BC_irem:
#if !SUPPORT_DIVISION
bte = builtintable_get_internal(BUILTIN_irem);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_LDIV:
+ case BC_ldiv:
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
bte = builtintable_get_internal(BUILTIN_ldiv);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_LREM:
+ case BC_lrem:
#if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
bte = builtintable_get_internal(BUILTIN_lrem);
OP_BUILTIN_ARITHMETIC(opcode, bte);
#endif
break;
- case JAVA_FREM:
+ case BC_frem:
#if defined(__I386__)
OP(opcode);
#else
#endif
break;
- case JAVA_DREM:
+ case BC_drem:
#if defined(__I386__)
OP(opcode);
#else
#endif
break;
- case JAVA_F2I:
+ case BC_f2i:
#if defined(__ALPHA__)
if (!opt_noieee) {
bte = builtintable_get_internal(BUILTIN_f2i);
}
break;
- case JAVA_F2L:
+ case BC_f2l:
#if defined(__ALPHA__)
if (!opt_noieee) {
bte = builtintable_get_internal(BUILTIN_f2l);
}
break;
- case JAVA_D2I:
+ case BC_d2i:
#if defined(__ALPHA__)
if (!opt_noieee) {
bte = builtintable_get_internal(BUILTIN_d2i);
}
break;
- case JAVA_D2L:
+ case BC_d2l:
#if defined(__ALPHA__)
if (!opt_noieee) {
bte = builtintable_get_internal(BUILTIN_d2l);
}
break;
+
/* invalid opcodes ****************************************************/
/* check for invalid opcodes if the verifier is enabled */
#if defined(ENABLE_VERIFIER)
- case JAVA_BREAKPOINT:
+ case BC_breakpoint:
exceptions_throw_verifyerror(m, "Quick instructions shouldn't appear, yet.");
return false;
- case 186: /* unused opcode */
+
+ /* Unused opcodes ************************************************** */
+
+ case 186:
case 203:
case 204:
case 205:
/* opcodes that don't require translation *****************************/
default:
- /* straight-forward translation to ICMD */
+ /* Straight-forward translation to HIR. */
OP(opcode);
break;
/* resolve instruction indices to basic blocks */
switch (iptr->opc) {
- case JAVA_IFEQ:
- case JAVA_IFLT:
- case JAVA_IFLE:
- case JAVA_IFNE:
- case JAVA_IFGT:
- case JAVA_IFGE:
- case JAVA_IFNULL:
- case JAVA_IFNONNULL:
- case JAVA_IF_ICMPEQ:
- case JAVA_IF_ICMPNE:
- case JAVA_IF_ICMPLT:
- case JAVA_IF_ICMPGT:
- case JAVA_IF_ICMPLE:
- case JAVA_IF_ICMPGE:
- case JAVA_IF_ACMPEQ:
- case JAVA_IF_ACMPNE:
- case JAVA_GOTO:
+ case ICMD_IFEQ:
+ case ICMD_IFLT:
+ case ICMD_IFLE:
+ case ICMD_IFNE:
+ case ICMD_IFGT:
+ case ICMD_IFGE:
+ case ICMD_IFNULL:
+ case ICMD_IFNONNULL:
+ case ICMD_IF_ICMPEQ:
+ case ICMD_IF_ICMPNE:
+ case ICMD_IF_ICMPLT:
+ case ICMD_IF_ICMPGT:
+ case ICMD_IF_ICMPLE:
+ case ICMD_IF_ICMPGE:
+ case ICMD_IF_ACMPEQ:
+ case ICMD_IF_ACMPNE:
+ case ICMD_GOTO:
BYTECODEINDEX_TO_BASICBLOCK(iptr->dst);
break;
{
s4 nlocals = 0;
s4 i;
+ s4 t;
+ s4 varindex;
s4 *mapptr;
+ s4 *reversemap;
mapptr = local_map;
MZERO(jd->var, varinfo, jd->varcount);
/* set types of all locals in jd->var */
+ /* and fill the reverselocalmap */
+
+ reversemap = DMNEW(s4, nlocals);
+
+ for (i = 0; i < m->maxlocals; i++)
+ for (t=0; t<5; t++) {
+ varindex = local_map[5*i + t];
+ if (varindex != UNUSED) {
+ VAR(varindex)->type = t;
+ reversemap[varindex] = i;
+ }
+ }
- for (mapptr = local_map, i = 0; i < (m->maxlocals * 5); i++, mapptr++)
- if (*mapptr != UNUSED)
- VAR(*mapptr)->type = i%5;
+ jd->reverselocalmap = reversemap;
}
/* assign local variables to method variables */
/* allocate stack table */
- jd->stack = DMNEW(stackelement, jd->stackcount);
+ jd->stack = DMNEW(stackelement_t, jd->stackcount);
/* everything's ok */
/* src/vm/jit/patcher-common.c - architecture independent code patching stuff
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/vm.h" /* for vm_abort */
#include "vm/jit/code.h"
+#include "vm/jit/disass.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
/* walk through all patcher references for the given codeinfo */
- pr = list_first_unsynced(code->patchers);
+ pr = list_first(code->patchers);
+
while (pr) {
/*#define TRACE_PATCHER_FIND*/
if (pr->mpc == (ptrint) pc)
return pr;
- pr = list_next_unsynced(code->patchers, pr);
+ pr = list_next(code->patchers, pr);
}
return NULL;
/* allocate patchref on heap (at least freed together with codeinfo) */
pr = NEW(patchref_t);
- list_add_first_unsynced(code->patchers, pr);
+ list_add_first(code->patchers, pr);
#if defined(ENABLE_STATISTICS)
if (opt_stat)
}
+/**
+ * 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
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 *) pr->patcher);
- TRACE_PATCHER_INDENT; printf("\tmcodes before = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
+ 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);
}
if (opt_DebugPatcher) {
assert(patcher_depth > 0);
patcher_depth--;
- TRACE_PATCHER_INDENT; printf("\tmcodes after = "); for (i=0; i<5; i++) printf("0x%08x ", *((u4 *) pr->mpc + i)); printf("\n");
+
+ 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");
}
void patcher_add_patch_ref(jitdata *jd, functionptr patcher, voidptr ref,
s4 disp);
+void patcher_resolve(jitdata* jd);
+
java_handle_t *patcher_handler(u1 *pc);
## src/vm/jit/powerpc/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.
##
codegen.h \
$(DISASS_SOURCES) \
emit.c \
+ patcher.c \
+ \
+ md-trap.h \
md.c \
- patcher.c
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
/* src/vm/jit/powerpc/codegen.c - machine code generator for 32-bit PowerPC
- 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/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
codegendata *cd;
registerdata *rd;
s4 len, s1, s2, s3, d, disp;
- ptrint a;
varinfo *var;
basicblock *bptr;
instruction *iptr;
fieldinfo *fi;
unresolved_field *uf;
s4 fieldtype;
- s4 varindex;
+ s4 varindex;
+ int i;
/* get required compiler data */
/* get or test the lock object */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_ALD(REG_A0, REG_PV, disp);
}
else {
M_TST(REG_A0);
M_BNE(1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
M_AST(REG_A0, REG_SP, s1 * 8);
case ICMD_FCONST: /* ... ==> ..., constant */
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- a = dseg_add_float(cd, iptr->sx.val.f);
- M_FLD(d, REG_PV, a);
+ disp = dseg_add_float(cd, iptr->sx.val.f);
+ M_FLD(d, REG_PV, disp);
emit_store_dst(jd, iptr, d);
break;
case ICMD_DCONST: /* ... ==> ..., constant */
d = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
- a = dseg_add_double(cd, iptr->sx.val.d);
- M_DLD(d, REG_PV, a);
+ disp = dseg_add_double(cd, iptr->sx.val.d);
+ M_DLD(d, REG_PV, disp);
emit_store_dst(jd, iptr, d);
break;
s2 = emit_load_s2(jd, iptr, REG_A2_A3_PACKED);
/* XXX TODO: only do this if arithmetic check is really done! */
- M_OR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
+ M_IOR_TST(GET_HIGH_REG(s2), GET_LOW_REG(s2), REG_ITMP3);
/* XXX could be optimized */
emit_arithmetic_check(cd, iptr, REG_ITMP3);
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_AND_IMM(s2, 0x1f, REG_ITMP3);
+ M_IAND_IMM(s2, 0x1f, REG_ITMP3);
M_SLL(s1, REG_ITMP3, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_AND_IMM(s2, 0x1f, REG_ITMP3);
+ M_IAND_IMM(s2, 0x1f, REG_ITMP3);
M_SRA(s1, REG_ITMP3, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_AND_IMM(s2, 0x1f, REG_ITMP2);
+ M_IAND_IMM(s2, 0x1f, REG_ITMP2);
M_SRL(s1, REG_ITMP2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_AND(s1, s2, d);
+ M_IAND(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
- M_AND_IMM(s1, iptr->sx.val.i, d);
+ M_IAND_IMM(s1, iptr->sx.val.i, d);
/*
else if (iptr->sx.val.i == 0xffffff) {
M_RLWINM(s1, 0, 8, 31, d);
*/
else {
ICONST(REG_ITMP3, iptr->sx.val.i);
- M_AND(s1, REG_ITMP3, d);
+ M_IAND(s1, REG_ITMP3, d);
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
- M_AND(s1, s2, GET_LOW_REG(d));
+ M_IAND(s1, s2, GET_LOW_REG(d));
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/
- M_AND(s1, s2, GET_HIGH_REG(d));
+ M_IAND(s1, s2, GET_HIGH_REG(d));
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
if ((s3 >= 0) && (s3 <= 65535))
- M_AND_IMM(s1, s3, GET_LOW_REG(d));
+ M_IAND_IMM(s1, s3, GET_LOW_REG(d));
else {
ICONST(REG_ITMP3, s3);
- M_AND(s1, REG_ITMP3, GET_LOW_REG(d));
+ M_IAND(s1, REG_ITMP3, GET_LOW_REG(d));
}
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s3 = iptr->sx.val.l >> 32;
if ((s3 >= 0) && (s3 <= 65535))
- M_AND_IMM(s1, s3, GET_HIGH_REG(d));
+ M_IAND_IMM(s1, s3, GET_HIGH_REG(d));
else {
ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */
- M_AND(s1, REG_ITMP3, GET_HIGH_REG(d));
+ M_IAND(s1, REG_ITMP3, GET_HIGH_REG(d));
}
emit_store_dst(jd, iptr, d);
break;
M_BGE(1 + 2*(iptr->sx.val.i >= 32768));
if (iptr->sx.val.i >= 32768) {
M_ADDIS(REG_ZERO, iptr->sx.val.i >> 16, REG_ITMP2);
- M_OR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2);
+ M_IOR_IMM(REG_ITMP2, iptr->sx.val.i, REG_ITMP2);
M_IADD(s1, REG_ITMP2, REG_ITMP2);
}
else {
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
s2 = emit_load_s2(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
- M_OR(s1, s2, d);
+ M_IOR(s1, s2, d);
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP2);
if ((iptr->sx.val.i >= 0) && (iptr->sx.val.i <= 65535))
- M_OR_IMM(s1, iptr->sx.val.i, d);
+ M_IOR_IMM(s1, iptr->sx.val.i, d);
else {
ICONST(REG_ITMP3, iptr->sx.val.i);
- M_OR(s1, REG_ITMP3, d);
+ M_IOR(s1, REG_ITMP3, d);
}
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
- M_OR(s1, s2, GET_LOW_REG(d));
+ M_IOR(s1, s2, GET_LOW_REG(d));
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);/* don't use REG_ITMP2*/
- M_OR(s1, s2, GET_HIGH_REG(d));
+ M_IOR(s1, s2, GET_HIGH_REG(d));
emit_store_dst(jd, iptr, d);
break;
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
if ((s3 >= 0) && (s3 <= 65535))
- M_OR_IMM(s1, s3, GET_LOW_REG(d));
+ M_IOR_IMM(s1, s3, GET_LOW_REG(d));
else {
ICONST(REG_ITMP3, s3);
- M_OR(s1, REG_ITMP3, GET_LOW_REG(d));
+ M_IOR(s1, REG_ITMP3, GET_LOW_REG(d));
}
s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
s3 = iptr->sx.val.l >> 32;
if ((s3 >= 0) && (s3 <= 65535))
- M_OR_IMM(s1, s3, GET_HIGH_REG(d));
+ M_IOR_IMM(s1, s3, GET_HIGH_REG(d));
else {
ICONST(REG_ITMP3, s3); /* don't use REG_ITMP2 */
- M_OR(s1, REG_ITMP3, GET_HIGH_REG(d));
+ M_IOR(s1, REG_ITMP3, GET_HIGH_REG(d));
}
emit_store_dst(jd, iptr, d);
break;
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, disp);
+ fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, disp);
+ fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
if (iptr->sx.val.l == 0) {
- M_OR_TST(s1, s2, REG_ITMP3);
+ M_IOR_TST(s1, s2, REG_ITMP3);
}
else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
M_XOR_IMM(s2, 0, REG_ITMP2);
M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1);
- M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+ M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
}
else {
ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
M_XOR(s1, REG_ITMP3, REG_ITMP1);
ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
M_XOR(s2, REG_ITMP3, REG_ITMP2);
- M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+ M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
}
emit_beq(cd, iptr->dst.block);
break;
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
/* if (iptr->sx.val.l == 0) { */
-/* M_OR(s1, s2, REG_ITMP3); */
+/* M_IOR(s1, s2, REG_ITMP3); */
/* M_CMPI(REG_ITMP3, 0); */
/* } else */
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
if (iptr->sx.val.l == 0) {
- M_OR_TST(s1, s2, REG_ITMP3);
+ M_IOR_TST(s1, s2, REG_ITMP3);
}
else if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 0xffff)) {
M_XOR_IMM(s2, 0, REG_ITMP2);
M_XOR_IMM(s1, iptr->sx.val.l & 0xffff, REG_ITMP1);
- M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+ M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
}
else {
ICONST(REG_ITMP3, iptr->sx.val.l & 0xffffffff);
M_XOR(s1, REG_ITMP3, REG_ITMP1);
ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
M_XOR(s2, REG_ITMP3, REG_ITMP2);
- M_OR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
+ M_IOR_TST(REG_ITMP1, REG_ITMP2, REG_ITMP3);
}
emit_bne(cd, iptr->dst.block);
break;
s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
s2 = emit_load_s1_high(jd, iptr, REG_ITMP2);
/* if (iptr->sx.val.l == 0) { */
-/* M_OR(s1, s2, REG_ITMP3); */
+/* M_IOR(s1, s2, REG_ITMP3); */
/* M_CMPI(REG_ITMP3, 0); */
/* } else */
}
gen_method:
- s3 = md->paramcount;
+ i = md->paramcount;
- MCODECHECK((s3 << 1) + 64);
+ MCODECHECK((i << 1) + 64);
- /* copy arguments to registers or stack location */
+ /* Copy arguments to registers or stack location. */
- for (s3 = s3 - 1; s3 >= 0; s3--) {
- var = VAR(iptr->sx.s23.s2.args[s3]);
- d = md->params[s3].regoff;
+ for (i = i - 1; i >= 0; i--) {
+ var = VAR(iptr->sx.s23.s2.args[i]);
+ d = md->params[i].regoff;
+
+ /* Already pre-allocated? */
- /* Already Preallocated? */
if (var->flags & PREALLOC)
continue;
- if (IS_INT_LNG_TYPE(var->type)) {
- if (!md->params[s3].inmemory) {
- if (IS_2_WORD_TYPE(var->type)) {
- s1 = emit_load(jd, iptr, var, d);
- M_LNGMOVE(s1, d);
- }
- else {
- s1 = emit_load(jd, iptr, var, d);
- M_INTMOVE(s1, d);
- }
- }
- else {
- if (IS_2_WORD_TYPE(var->type)) {
- s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
- M_LST(s1, REG_SP, d);
- }
- else {
- s1 = emit_load(jd, iptr, var, REG_ITMP1);
- M_IST(s1, REG_SP, d);
- }
+ if (!md->params[i].inmemory) {
+ s1 = emit_load(jd, iptr, var, d);
+
+ switch (var->type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ M_INTMOVE(s1, d);
+ break;
+
+ case TYPE_LNG:
+ M_LNGMOVE(s1, d);
+ break;
+
+ case TYPE_FLT:
+ case TYPE_DBL:
+ M_FLTMOVE(s1, d);
+ break;
}
}
else {
- if (!md->params[s3].inmemory) {
- s1 = emit_load(jd, iptr, var, d);
- M_FLTMOVE(s1, d);
- }
- else {
+ switch (var->type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ s1 = emit_load(jd, iptr, var, REG_ITMP1);
+ M_IST(s1, REG_SP, d);
+ break;
+
+ case TYPE_LNG:
+ s1 = emit_load(jd, iptr, var, REG_ITMP12_PACKED);
+ M_LST(s1, REG_SP, d);
+ break;
+
+ case TYPE_FLT:
+ case TYPE_DBL:
s1 = emit_load(jd, iptr, var, REG_FTMP1);
M_DST(s1, REG_SP, d);
+ break;
}
}
}
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
break;
}
- /* store return value */
+ /* Store return value. */
- d = md->returntype.type;
+ switch (md->returntype.type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
+ M_INTMOVE(REG_RESULT, s1);
+ emit_store_dst(jd, iptr, s1);
+ break;
- if (d != TYPE_VOID) {
- if (IS_INT_LNG_TYPE(d)) {
- if (IS_2_WORD_TYPE(d)) {
- s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
- M_LNGMOVE(REG_RESULT_PACKED, s1);
- }
- else {
- s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT);
- M_INTMOVE(REG_RESULT, s1);
- }
- }
- else {
- s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
- M_FLTMOVE(REG_FRESULT, s1);
- }
+ case TYPE_LNG:
+ s1 = codegen_reg_of_dst(jd, iptr, REG_RESULT_PACKED);
+ M_LNGMOVE(REG_RESULT_PACKED, s1);
+ emit_store_dst(jd, iptr, s1);
+ break;
+
+ case TYPE_FLT:
+ case TYPE_DBL:
+ s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
+ M_FLTMOVE(REG_FRESULT, s1);
emit_store_dst(jd, iptr, s1);
+ break;
+
+ case TYPE_VOID:
+ break;
}
break;
disp);
M_ILD(REG_ITMP2, REG_PV, disp);
- M_AND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
+ M_IAND_IMM(REG_ITMP2, ACC_INTERFACE, REG_ITMP2);
emit_label_beq(cd, BRANCH_LABEL_2);
}
iptr->sx.s23.s3.c.ref, disp);
M_ILD(REG_ITMP3, REG_PV, disp);
- M_AND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
+ M_IAND_IMM(REG_ITMP3, ACC_INTERFACE, REG_ITMP3);
emit_label_beq(cd, BRANCH_LABEL_2);
}
s4 s1, s2;
int disp;
- /* get required compiler data */
+ /* Sanity check. */
+
+ assert(f != NULL);
+
+ /* Get required compiler data. */
m = jd->m;
code = jd->code;
for (i = md->paramcount - 1, j = i + skipparams; i >= 0; i--, j--) {
t = md->paramtypes[i].type;
- if (IS_INT_LNG_TYPE(t)) {
- if (!md->params[i].inmemory) {
- s1 = md->params[i].regoff;
- s2 = nmd->params[j].regoff;
+ if (!md->params[i].inmemory) {
+ s1 = md->params[i].regoff;
+ s2 = nmd->params[j].regoff;
- if (!nmd->params[j].inmemory) {
- if (IS_2_WORD_TYPE(t))
- M_LNGMOVE(s1, s2);
- else
- M_INTMOVE(s1, s2);
- }
- else {
- if (IS_2_WORD_TYPE(t))
- M_LST(s1, REG_SP, s2);
- else
- M_IST(s1, REG_SP, s2);
- }
- }
- else {
- s1 = md->params[i].regoff + cd->stackframesize * 8;
- s2 = nmd->params[j].regoff;
+ switch (t) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ if (!nmd->params[j].inmemory)
+ M_INTMOVE(s1, s2);
+ else
+ M_IST(s1, REG_SP, s2);
+ break;
- M_ILD(REG_ITMP1, REG_SP, s1);
- if (IS_2_WORD_TYPE(t))
- M_ILD(REG_ITMP2, REG_SP, s1 + 4);
+ case TYPE_LNG:
+ if (!nmd->params[j].inmemory)
+ M_LNGMOVE(s1, s2);
+ else
+ M_LST(s1, REG_SP, s2);
+ break;
- M_IST(REG_ITMP1, REG_SP, s2);
- if (IS_2_WORD_TYPE(t))
- M_IST(REG_ITMP2, REG_SP, s2 + 4);
+ case TYPE_FLT:
+ case TYPE_DBL:
+ /* We only copy spilled float arguments, as the float
+ argument registers keep unchanged. */
+ break;
}
}
else {
- /* We only copy spilled float arguments, as the float
- argument registers keep unchanged. */
+ s1 = md->params[i].regoff + cd->stackframesize * 8;
+ s2 = nmd->params[j].regoff;
- if (md->params[i].inmemory) {
- s1 = md->params[i].regoff + cd->stackframesize * 8;
- s2 = nmd->params[j].regoff;
+ switch (t) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ M_ILD(REG_ITMP1, REG_SP, s1);
+ M_IST(REG_ITMP1, REG_SP, s2);
+ break;
+ case TYPE_LNG:
+ M_LLD(REG_ITMP12_PACKED, REG_SP, s1);
+ M_LST(REG_ITMP12_PACKED, REG_SP, s2);
+ break;
+
+ case TYPE_FLT:
M_DLD(REG_FTMP1, REG_SP, s1);
+ M_FST(REG_FTMP1, REG_SP, s2);
+ break;
- if (IS_2_WORD_TYPE(t))
- M_DST(REG_FTMP1, REG_SP, s2);
- else
- M_FST(REG_FTMP1, REG_SP, s2);
+ case TYPE_DBL:
+ M_DLD(REG_FTMP1, REG_SP, s1);
+ M_DST(REG_FTMP1, REG_SP, s2);
+ break;
}
}
}
/* src/vm/jit/powerpc/codegen.h - code generation macros and definitions for
32-bit PowerPC
- 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)
-/* instruction macros *********************************************************/
+/* machine instruction macros **************************************************
+
+ Argument order:
+
+ machine instruction macro:
+ Same order as for the mnemonic (d, s1, s2).
+
+ emit macro:
+ Same order as in the instruction encoding.
+
+*******************************************************************************/
+
+#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_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 MI_ori(rA,rS,UIMM) M_OP2_IMM(24, rS, rA, UIMM)
+#define MI_stwcxdot(rS,rA,rB) M_OP3(31, 150, 0, 1, rS, rA, rB)
+#define MI_subf(rD,rA,rB) M_OP3(31, 40, 0, 0, rD, rA, rB)
+#define MI_subfdot(rD,rA,rB) M_OP3(31, 40, 0, 1, rD, rA, rB)
+#define MI_sync M_OP3(31, 598, 0, 0, 0, 0, 0)
+
+
+/* HIR macros ******************************************************************
+
+ Argument order:
+
+ HIR macro:
+ Default usage in CACAO (s1, s2, d).
+
+ machine instruction macro:
+ Same order as for the mnemonic (d, s1, s2).
+
+*******************************************************************************/
+
+/* integer instructions *******************************************************/
+
+#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_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)
+#define M_ISUB(a,b,d) MI_subf(d, b, a)
+#define M_ISUB_TST(a,b,d) MI_subfdot(d, b, a)
+#define M_MOV(a,d) MI_or(d, a, a)
+#define M_NOP MI_ori(0, 0, 0)
+
-#define M_IADD(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)
#define M_ADDC(a,b,c) M_OP3(31, 10, 0, 0, c, a, b)
+#define M_ADDE(a,b,c) M_OP3(31, 138, 0, 0, c, a, b)
#define M_ADDIC(a,b,c) M_OP2_IMM(12, c, a, b)
#define M_ADDICTST(a,b,c) M_OP2_IMM(13, c, a, b)
-#define M_ADDE(a,b,c) M_OP3(31, 138, 0, 0, c, a, b)
-#define M_ADDZE(a,b) M_OP3(31, 202, 0, 0, b, a, 0)
+#define M_ADDIS(a,b,c) M_OP2_IMM(15, c, a, b)
#define M_ADDME(a,b) M_OP3(31, 234, 0, 0, b, a, 0)
-#define M_ISUB(a,b,c) M_OP3(31, 40, 0, 0, c, b, a)
-#define M_ISUBTST(a,b,c) M_OP3(31, 40, 0, 1, c, b, a)
-#define M_SUBC(a,b,c) M_OP3(31, 8, 0, 0, c, b, a)
-#define M_SUBIC(a,b,c) M_OP2_IMM(8, c, b, a)
-#define M_SUBE(a,b,c) M_OP3(31, 136, 0, 0, c, b, a)
-#define M_SUBZE(a,b) M_OP3(31, 200, 0, 0, b, a, 0)
-#define M_SUBME(a,b) M_OP3(31, 232, 0, 0, b, a, 0)
-
-#define M_AND(a,b,c) M_OP3(31, 28, 0, 0, a, c, b)
-#define M_AND_IMM(a,b,c) M_OP2_IMM(28, a, c, b)
+#define M_ADDZE(a,b) M_OP3(31, 202, 0, 0, b, a, 0)
+#define M_ADDZE(a,b) M_OP3(31, 202, 0, 0, b, a, 0)
#define M_ANDIS(a,b,c) M_OP2_IMM(29, a, c, b)
-#define M_OR(a,b,c) M_OP3(31, 444, 0, 0, a, c, b)
-#define M_OR_TST(a,b,c) M_OP3(31, 444, 0, 1, a, c, b)
-#define M_OR_IMM(a,b,c) M_OP2_IMM(24, a, c, b)
-#define M_ORIS(a,b,c) M_OP2_IMM(25, a, c, b)
-#define M_XOR(a,b,c) M_OP3(31, 316, 0, 0, a, c, b)
-#define M_XOR_IMM(a,b,c) M_OP2_IMM(26, a, c, b)
-#define M_XORIS(a,b,c) M_OP2_IMM(27, a, c, b)
-
-#define M_SLL(a,b,c) M_OP3(31, 24, 0, 0, a, c, b)
-#define M_SRL(a,b,c) M_OP3(31, 536, 0, 0, a, c, b)
-#define M_SRA(a,b,c) M_OP3(31, 792, 0, 0, a, c, b)
-#define M_SRA_IMM(a,b,c) M_OP3(31, 824, 0, 0, a, c, b)
-
+#define M_BEQ(a) M_BC(12, 2, a, 0, 0)
+#define M_BGE(a) M_BC(4, 0, a, 0, 0)
+#define M_BGT(a) M_BC(12, 1, a, 0, 0)
+#define M_BL(a) M_B(a, 0, 1)
+#define M_BLDU(a,b,c) M_OP2_IMM(34, a, b, c)
+#define M_BLE(a) M_BC(4, 1, a, 0, 0)
+#define M_BLT(a) M_BC(12, 0, a, 0, 0)
+#define M_BNAN(a) M_BC(12, 3, a, 0, 0)
+#define M_BNE(a) M_BC(4, 2, a, 0, 0)
+#define M_BR(a) M_B(a, 0, 0)
+#define M_BSEXT(a,b) M_OP3(31, 954, 0, 0, a, b, 0)
+#define M_BST(a,b,c) M_OP2_IMM(38, a, b, c)
+#define M_CMP(a,b) M_OP3(31, 0, 0, 0, 0, a, b)
+#define M_CMPI(a,b) M_OP2_IMM(11, 0, a, b)
+#define M_CMPU(a,b) M_OP3(31, 32, 0, 0, 0, a, b)
+#define M_CMPUI(a,b) M_OP2_IMM(10, 0, a, b)
+#define M_CZEXT(a,b) M_RLWINM(a,0,16,31,b)
+#define M_IADD(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)
+#define M_IDIV(a,b,c) M_OP3(31, 491, 0, 0, c, a, b)
#define M_IMUL(a,b,c) M_OP3(31, 235, 0, 0, c, a, b)
#define M_IMUL_IMM(a,b,c) M_OP2_IMM(7, c, a, b)
-#define M_IDIV(a,b,c) M_OP3(31, 491, 0, 0, c, a, b)
-
+#define M_JSR M_OP3(19, 528, 0, 1, 20, 0, 0)
+#define M_LBZX(a,b,c) M_OP3(31, 87, 0, 0, a, b, c)
+#define M_LHAX(a,b,c) M_OP3(31, 343, 0, 0, a, b, c)
+#define M_LHZX(a,b,c) M_OP3(31, 279, 0, 0, a, b, c)
+#define M_LWZX(a,b,c) M_OP3(31, 23, 0, 0, a, b, c)
+#define M_MFCTR(a) M_OP3(31, 339, 0, 0, a, 9, 0)
+#define M_MFLR(a) M_OP3(31, 339, 0, 0, a, 8, 0)
+#define M_MFXER(a) M_OP3(31, 339, 0, 0, a, 1, 0)
+#define M_MTCTR(a) M_OP3(31, 467, 0, 0, a, 9, 0)
+#define M_MTLR(a) M_OP3(31, 467, 0, 0, a, 8, 0)
+#define M_MTXER(a) M_OP3(31, 467, 0, 0, a, 1, 0)
#define M_NEG(a,b) M_OP3(31, 104, 0, 0, b, a, 0)
#define M_NOT(a,b) M_OP3(31, 124, 0, 0, a, b, a)
-
-#define M_SUBFIC(a,b,c) M_OP2_IMM(8, c, a, b)
-#define M_SUBFZE(a,b) M_OP3(31, 200, 0, 0, b, a, 0)
+#define M_ORIS(a,b,c) M_OP2_IMM(25, a, c, b)
+#define M_RET M_OP3(19, 16, 0, 0, 20, 0, 0)
#define M_RLWINM(a,b,c,d,e) M_OP4(21, d, 0, a, e, b, c)
-#define M_ADDZE(a,b) M_OP3(31, 202, 0, 0, b, a, 0)
+#define M_RTS M_OP3(19, 528, 0, 0, 20, 0, 0)
+#define M_SLDU(a,b,c) M_OP2_IMM(40, a, b, c)
+#define M_SLL(a,b,c) M_OP3(31, 24, 0, 0, a, c, b)
#define M_SLL_IMM(a,b,c) M_RLWINM(a,b,0,31-(b),c)
+#define M_SRA(a,b,c) M_OP3(31, 792, 0, 0, a, c, b)
+#define M_SRA_IMM(a,b,c) M_OP3(31, 824, 0, 0, a, c, b)
+#define M_SRL(a,b,c) M_OP3(31, 536, 0, 0, a, c, b)
#define M_SRL_IMM(a,b,c) M_RLWINM(a,32-(b),b,31,c)
-#define M_ADDIS(a,b,c) M_OP2_IMM(15, c, a, b)
-#define M_STFIWX(a,b,c) M_OP3(31, 983, 0, 0, a, b, c)
-#define M_LWZX(a,b,c) M_OP3(31, 23, 0, 0, a, b, c)
-#define M_LHZX(a,b,c) M_OP3(31, 279, 0, 0, a, b, c)
-#define M_LHAX(a,b,c) M_OP3(31, 343, 0, 0, a, b, c)
-#define M_LBZX(a,b,c) M_OP3(31, 87, 0, 0, a, b, c)
-#define M_LFSX(a,b,c) M_OP3(31, 535, 0, 0, a, b, c)
-#define M_LFDX(a,b,c) M_OP3(31, 599, 0, 0, a, b, c)
-#define M_STWX(a,b,c) M_OP3(31, 151, 0, 0, a, b, c)
-#define M_STHX(a,b,c) M_OP3(31, 407, 0, 0, a, b, c)
+#define M_SSEXT(a,b) M_OP3(31, 922, 0, 0, a, b, 0)
+#define M_SST(a,b,c) M_OP2_IMM(44, a, b, c)
#define M_STBX(a,b,c) M_OP3(31, 215, 0, 0, a, b, c)
-#define M_STFSX(a,b,c) M_OP3(31, 663, 0, 0, a, b, c)
-#define M_STFDX(a,b,c) M_OP3(31, 727, 0, 0, a, b, c)
-
-#define M_STWU_INTERN(a,b,disp) M_OP2_IMM(37,a,b,disp)
-
-#define M_STWU(a,b,disp) \
- do { \
- s4 lo = (disp) & 0x0000ffff; \
- s4 hi = ((disp) >> 16); \
- if (((disp) >= -32678) && ((disp) <= 32767)) { \
- M_STWU_INTERN(a,b,lo); \
- } else { \
- M_ADDIS(REG_ZERO,hi,REG_ITMP3); \
- M_OR_IMM(REG_ITMP3,lo,REG_ITMP3); \
- M_STWUX(REG_SP,REG_SP,REG_ITMP3); \
- } \
- } while (0)
-
+#define M_STHX(a,b,c) M_OP3(31, 407, 0, 0, a, b, c)
#define M_STWUX(a,b,c) M_OP3(31,183,0,0,a,b,c)
-
-#define M_LDAH(a,b,c) M_ADDIS(b, c, a)
-
+#define M_STWX(a,b,c) M_OP3(31, 151, 0, 0, a, b, c)
+#define M_SUBC(a,b,c) M_OP3(31, 8, 0, 0, c, b, a)
+#define M_SUBE(a,b,c) M_OP3(31, 136, 0, 0, c, b, a)
+#define M_SUBFIC(a,b,c) M_OP2_IMM(8, c, a, b)
+#define M_SUBFZE(a,b) M_OP3(31, 200, 0, 0, b, a, 0)
+#define M_SUBIC(a,b,c) M_OP2_IMM(8, c, b, a)
+#define M_SUBME(a,b) M_OP3(31, 232, 0, 0, b, a, 0)
+#define M_SUBZE(a,b) M_OP3(31, 200, 0, 0, b, a, 0)
#define M_TRAP M_OP3(31, 4, 0, 0, 31, 0, 0)
#define M_TRAPGEU(a,b) M_OP3(31, 4, 0, 0, 5, a, b)
-
-#define M_NOP M_OR_IMM(0, 0, 0)
-#define M_MOV(a,b) M_OR(a, a, b)
#define M_TST(a) M_OP3(31, 444, 0, 1, a, a, a)
+#define M_XOR(a,b,c) M_OP3(31, 316, 0, 0, a, c, b)
+#define M_XORIS(a,b,c) M_OP2_IMM(27, a, c, b)
+#define M_XOR_IMM(a,b,c) M_OP2_IMM(26, a, c, b)
-#define M_DADD(a,b,c) M_OP3(63, 21, 0, 0, c, a, b)
-#define M_FADD(a,b,c) M_OP3(59, 21, 0, 0, c, a, b)
-#define M_DSUB(a,b,c) M_OP3(63, 20, 0, 0, c, a, b)
-#define M_FSUB(a,b,c) M_OP3(59, 20, 0, 0, c, a, b)
-#define M_DMUL(a,b,c) M_OP4(63, 25, 0, c, a, 0, b)
-#define M_FMUL(a,b,c) M_OP4(59, 25, 0, c, a, 0, b)
-#define M_DDIV(a,b,c) M_OP3(63, 18, 0, 0, c, a, b)
-#define M_FDIV(a,b,c) M_OP3(59, 18, 0, 0, c, a, b)
-
-#define M_FABS(a,b) M_OP3(63, 264, 0, 0, b, 0, a)
-#define M_CVTDL(a,b) M_OP3(63, 14, 0, 0, b, 0, a)
-#define M_CVTDL_C(a,b) M_OP3(63, 15, 0, 0, b, 0, a)
-#define M_CVTDF(a,b) M_OP3(63, 12, 0, 0, b, 0, a)
-#define M_FMOV(a,b) M_OP3(63, 72, 0, 0, b, 0, a)
-#define M_FMOVN(a,b) M_OP3(63, 40, 0, 0, b, 0, a)
-#define M_DSQRT(a,b) M_OP3(63, 22, 0, 0, b, 0, a)
-#define M_FSQRT(a,b) M_OP3(59, 22, 0, 0, b, 0, a)
-#define M_FCMPU(a,b) M_OP3(63, 0, 0, 0, 0, a, b)
-#define M_FCMPO(a,b) M_OP3(63, 32, 0, 0, 0, a, b)
+#define M_LDAH(a,b,c) M_ADDIS(b, c, a)
+#define M_LDATST(a,b,c) M_ADDICTST(b, c, a)
+#define M_CLR(a) M_IADD_IMM(0, 0, a)
-#define M_BLDU(a,b,c) M_OP2_IMM(34, a, b, c)
-#define M_SLDU(a,b,c) M_OP2_IMM(40, a, b, c)
#define M_ILD_INTERN(a,b,disp) M_OP2_IMM(32,a,b,disp)
} \
} while (0)
-#define M_ALD_INTERN(a,b,disp) M_ILD_INTERN(a,b,disp)
-#define M_ALD(a,b,disp) M_ILD(a,b,disp)
-
-#define M_BST(a,b,c) M_OP2_IMM(38, a, b, c)
-#define M_SST(a,b,c) M_OP2_IMM(44, a, b, c)
-
#define M_IST_INTERN(a,b,disp) M_OP2_IMM(36,a,b,disp)
/* Stores with displacement overflow should only happen with PUTFIELD
} \
} while (0)
+#define M_STWU_INTERN(a,b,disp) M_OP2_IMM(37,a,b,disp)
+
+#define M_STWU(a,b,disp) \
+ do { \
+ s4 lo = (disp) & 0x0000ffff; \
+ s4 hi = ((disp) >> 16); \
+ if (((disp) >= -32678) && ((disp) <= 32767)) { \
+ M_STWU_INTERN(a,b,lo); \
+ } else { \
+ M_ADDIS(REG_ZERO,hi,REG_ITMP3); \
+ M_IOR_IMM(REG_ITMP3,lo,REG_ITMP3); \
+ M_STWUX(REG_SP,REG_SP,REG_ITMP3); \
+ } \
+ } while (0)
+
+#define M_LDA_INTERN(a,b,c) M_IADD_IMM(b, c, a)
+
+#define M_LDA(a,b,disp) \
+ do { \
+ s4 lo = (short) (disp); \
+ s4 hi = (short) (((disp) - lo) >> 16); \
+ if (hi == 0) { \
+ M_LDA_INTERN(a,b,lo); \
+ } else { \
+ M_ADDIS(b,hi,a); \
+ M_LDA_INTERN(a,a,lo); \
+ } \
+ } while (0)
+
+
+#define M_AADD(a,b,d) M_IADD(a, b, d)
+#define M_AADD_IMM(a,b,d) M_IADD_IMM(a, b, d)
+#define M_ALD_INTERN(a,b,disp) M_ILD_INTERN(a,b,disp)
+#define M_ALD(a,b,disp) M_ILD(a,b,disp)
#define M_AST_INTERN(a,b,disp) M_IST_INTERN(a,b,disp)
#define M_AST(a,b,disp) M_IST(a,b,disp)
-#define M_BSEXT(a,b) M_OP3(31, 954, 0, 0, a, b, 0)
-#define M_SSEXT(a,b) M_OP3(31, 922, 0, 0, a, b, 0)
-#define M_CZEXT(a,b) M_RLWINM(a,0,16,31,b)
-#define M_BR(a) M_B(a, 0, 0)
-#define M_BL(a) M_B(a, 0, 1)
-#define M_RET M_OP3(19, 16, 0, 0, 20, 0, 0)
-#define M_JSR M_OP3(19, 528, 0, 1, 20, 0, 0)
-#define M_RTS M_OP3(19, 528, 0, 0, 20, 0, 0)
+/* floating point instructions ************************************************/
-#define M_CMP(a,b) M_OP3(31, 0, 0, 0, 0, a, b)
-#define M_CMPU(a,b) M_OP3(31, 32, 0, 0, 0, a, b)
-#define M_CMPI(a,b) M_OP2_IMM(11, 0, a, b)
-#define M_CMPUI(a,b) M_OP2_IMM(10, 0, a, b)
+#define M_CVTDF(a,b) M_OP3(63, 12, 0, 0, b, 0, a)
+#define M_CVTDL(a,b) M_OP3(63, 14, 0, 0, b, 0, a)
+#define M_CVTDL_C(a,b) M_OP3(63, 15, 0, 0, b, 0, a)
+#define M_DADD(a,b,c) M_OP3(63, 21, 0, 0, c, a, b)
+#define M_DDIV(a,b,c) M_OP3(63, 18, 0, 0, c, a, b)
+#define M_DMUL(a,b,c) M_OP4(63, 25, 0, c, a, 0, b)
+#define M_DSQRT(a,b) M_OP3(63, 22, 0, 0, b, 0, a)
+#define M_DSUB(a,b,c) M_OP3(63, 20, 0, 0, c, a, b)
+#define M_FABS(a,b) M_OP3(63, 264, 0, 0, b, 0, a)
+#define M_FADD(a,b,c) M_OP3(59, 21, 0, 0, c, a, b)
+#define M_FCMPO(a,b) M_OP3(63, 32, 0, 0, 0, a, b)
+#define M_FCMPU(a,b) M_OP3(63, 0, 0, 0, 0, a, b)
+#define M_FDIV(a,b,c) M_OP3(59, 18, 0, 0, c, a, b)
+#define M_FMOV(a,b) M_OP3(63, 72, 0, 0, b, 0, a)
+#define M_FMOVN(a,b) M_OP3(63, 40, 0, 0, b, 0, a)
+#define M_FMUL(a,b,c) M_OP4(59, 25, 0, c, a, 0, b)
+#define M_FSQRT(a,b) M_OP3(59, 22, 0, 0, b, 0, a)
+#define M_FSUB(a,b,c) M_OP3(59, 20, 0, 0, c, a, b)
+#define M_LFDX(a,b,c) M_OP3(31, 599, 0, 0, a, b, c)
+#define M_LFSX(a,b,c) M_OP3(31, 535, 0, 0, a, b, c)
+#define M_STFDX(a,b,c) M_OP3(31, 727, 0, 0, a, b, c)
+#define M_STFIWX(a,b,c) M_OP3(31, 983, 0, 0, a, b, c)
+#define M_STFSX(a,b,c) M_OP3(31, 663, 0, 0, a, b, c)
-#define M_BLT(a) M_BC(12, 0, a, 0, 0)
-#define M_BLE(a) M_BC(4, 1, a, 0, 0)
-#define M_BGT(a) M_BC(12, 1, a, 0, 0)
-#define M_BGE(a) M_BC(4, 0, a, 0, 0)
-#define M_BEQ(a) M_BC(12, 2, a, 0, 0)
-#define M_BNE(a) M_BC(4, 2, a, 0, 0)
-#define M_BNAN(a) M_BC(12, 3, a, 0, 0)
#define M_FLD_INTERN(a,b,disp) M_OP2_IMM(48,a,b,disp)
-#define M_DLD_INTERN(a,b,disp) M_OP2_IMM(50,a,b,disp)
#define M_FLD(a,b,disp) \
do { \
} \
} while (0)
+#define M_DLD_INTERN(a,b,disp) M_OP2_IMM(50,a,b,disp)
+
#define M_DLD(a,b,disp) \
do { \
s4 lo = (short) (disp); \
} while (0)
#define M_FST_INTERN(a,b,disp) M_OP2_IMM(52,a,b,disp)
-#define M_DST_INTERN(a,b,disp) M_OP2_IMM(54,a,b,disp)
#define M_FST(a,b,disp) \
do { \
} \
} while (0)
+#define M_DST_INTERN(a,b,disp) M_OP2_IMM(54,a,b,disp)
+
#define M_DST(a,b,disp) \
do { \
s4 lo = (short) (disp); \
} \
} while (0)
-#define M_MFLR(a) M_OP3(31, 339, 0, 0, a, 8, 0)
-#define M_MFXER(a) M_OP3(31, 339, 0, 0, a, 1, 0)
-#define M_MFCTR(a) M_OP3(31, 339, 0, 0, a, 9, 0)
-#define M_MTLR(a) M_OP3(31, 467, 0, 0, a, 8, 0)
-#define M_MTXER(a) M_OP3(31, 467, 0, 0, a, 1, 0)
-#define M_MTCTR(a) M_OP3(31, 467, 0, 0, a, 9, 0)
-
-#define M_LDA_INTERN(a,b,c) M_IADD_IMM(b, c, a)
-
-#define M_LDA(a,b,disp) \
- do { \
- s4 lo = (short) (disp); \
- s4 hi = (short) (((disp) - lo) >> 16); \
- if (hi == 0) { \
- M_LDA_INTERN(a,b,lo); \
- } else { \
- M_ADDIS(b,hi,a); \
- M_LDA_INTERN(a,a,lo); \
- } \
- } while (0)
-
-
-#define M_LDATST(a,b,c) M_ADDICTST(b, c, a)
-#define M_CLR(a) M_IADD_IMM(0, 0, a)
-#define M_AADD_IMM(a,b,c) M_IADD_IMM(a, b, c)
-
#endif /* _CODEGEN_H */
-/* src/vm/jit/powerpc/darwin/md-abi.c - functions for PowerPC Darwin ABI
+/* src/vm/jit/powerpc/darwin/md-abi.c - PowerPC Darwin ABI
- 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/global.h"
#include "vm/jit/abi.h"
+#include "vm/jit/stack.h"
#include "vmcore/descriptor.h"
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t* stackslot)
{
methodinfo *m;
codeinfo *code;
/* src/vm/jit/powerpc/darwin/md-os.c - machine dependent PowerPC Darwin functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/powerpc/codegen.h"
#include "vm/jit/powerpc/darwin/md-abi.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
/* src/vm/jit/powerpc/disass.c - wrapper functions for GNU binutils disassembler
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+ 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
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Andreas Krall
- Reinhard Grafl
-
- Changes: Stefan Ring
- Christian Thalinger
-
-
*/
#include "config.h"
#include <dis-asm.h>
+#include <stdint.h>
#include <stdio.h>
-#include "vm/types.h"
-
#include "vm/global.h"
+
#include "vm/jit/disass.h"
/* src/vm/jit/powerpc/emit.c - PowerPC code emitter functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
#include "vm/jit/trace.h"
+#include "vm/jit/trap.h"
#include "vmcore/options.h"
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TST(reg);
M_BNE(1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_ArithmeticException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TST(REG_RESULT);
M_BNE(1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_ArrayStoreException);
}
}
default:
vm_abort("emit_classcast_check: unknown condition %d", condition);
}
- M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+ M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TST(reg);
M_BNE(1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TST(REG_RESULT);
M_BNE(1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
- M_ALD_INTERN(REG_METHODPTR, REG_ZERO, EXCEPTION_HARDWARE_COMPILER);
+ M_ALD_INTERN(REG_METHODPTR, REG_ZERO, TRAP_COMPILER);
}
/* Get machine code which is patched back in later. The
trap is 1 instruction word long. */
- mcode = *((u4 *) cd->mcodeptr);
+ mcode = *((uint32_t *) cd->mcodeptr);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_PATCHER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
return mcode;
}
/* src/vm/jit/powerpc/linux/md-abi.c - functions for PowerPC Linux ABI
- 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/global.h"
#include "vm/jit/abi.h"
+#include "vm/jit/stack.h"
#include "vmcore/descriptor.h"
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
methodinfo *m;
codeinfo *code;
registerdata *rd;
methoddesc *md;
+ varinfo *v;
/* get required compiler data */
has not to survive method invokations. */
if (!(stackslot->flags & SAVEDVAR)) {
- VAR(stackslot->varnum)->flags = PREALLOC;
+ v = VAR(stackslot->varnum);
+ v->flags = PREALLOC;
- if (IS_INT_LNG_TYPE(md->returntype.type)) {
- if (!IS_2_WORD_TYPE(md->returntype.type)) {
- if (rd->argintreguse < 1)
- rd->argintreguse = 1;
+ switch (md->returntype.type) {
+ case TYPE_INT:
+ case TYPE_ADR:
+ if (rd->argintreguse < 1)
+ rd->argintreguse = 1;
- VAR(stackslot->varnum)->vv.regoff = REG_RESULT;
- }
- else {
- if (rd->argintreguse < 2)
- rd->argintreguse = 2;
+ v->vv.regoff = REG_RESULT;
+ break;
- VAR(stackslot->varnum)->vv.regoff = REG_RESULT_PACKED;
- }
- }
- else { /* float/double */
+ case TYPE_LNG:
+ if (rd->argintreguse < 2)
+ rd->argintreguse = 2;
+
+ v->vv.regoff = REG_RESULT_PACKED;
+ break;
+
+ case TYPE_FLT:
+ case TYPE_DBL:
if (rd->argfltreguse < 1)
rd->argfltreguse = 1;
-
- VAR(stackslot->varnum)->vv.regoff = REG_FRESULT;
+
+ v->vv.regoff = REG_FRESULT;
+ break;
}
}
}
/* src/vm/jit/powerpc/linux/md-os.c - machine dependent PowerPC Linux functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/powerpc/md.h"
#include "vm/jit/powerpc/linux/md-abi.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
#if defined(ENABLE_PROFILING)
# include "vm/jit/optimizing/profile.h"
#endif
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
+
+#include "vmcore/system.h"
/* md_signal_handler_sigsegv ***************************************************
type = disp;
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
/* The XPC is the RA minus 4, because the RA points to the
instruction after the call. */
define is 0. */
addr = _gregs[s1];
- type = EXCEPTION_HARDWARE_NULLPOINTER;
-
- if (addr != 0)
- vm_abort("md_signal_handler_sigsegv: faulting address is not NULL: addr=%p", addr);
+ type = addr;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* Set registers. */
switch (type) {
- case EXCEPTION_HARDWARE_COMPILER:
+ case TRAP_COMPILER:
if (p != NULL) {
_gregs[REG_PV] = (uintptr_t) p;
_gregs[PT_NIP] = (uintptr_t) p;
/* fall-through */
- case EXCEPTION_HARDWARE_PATCHER:
+ case TRAP_PATCHER:
if (p == NULL)
break;
s1 = M_OP3_GET_A(mcode);
- /* for now we only handle ArrayIndexOutOfBoundsException */
+ /* For now we only handle ArrayIndexOutOfBoundsException. */
- type = EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS;
+ type = TRAP_ArrayIndexOutOfBoundsException;
val = _gregs[s1];
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- /* set registers */
+ /* Set registers. */
- _gregs[REG_ITMP1_XPTR] = (intptr_t) p;
- _gregs[REG_ITMP2_XPC] = (intptr_t) xpc;
- _gregs[PT_NIP] = (intptr_t) asm_handle_exception;
+ _gregs[REG_ITMP1_XPTR] = (uintptr_t) p;
+ _gregs[REG_ITMP2_XPC] = (uintptr_t) xpc;
+ _gregs[PT_NIP] = (uintptr_t) asm_handle_exception;
}
#endif
+/* md_executionstate_read ******************************************************
+
+ Read the given context into an executionstate.
+
+*******************************************************************************/
+
+void md_executionstate_read(executionstate_t *es, void *context)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ unsigned long *_gregs;
+ s4 i;
+
+ _uc = (ucontext_t *) context;
+
+#if defined(__UCLIBC__)
+#error Please port md_executionstate_read to __UCLIBC__
+#else
+ _mc = _uc->uc_mcontext.uc_regs;
+ _gregs = _mc->gregs;
+#endif
+
+ /* 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];
+
+ /* read integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ es->intregs[i] = _gregs[i];
+
+ /* read float registers */
+ /* Do not use the assignment operator '=', as the type of
+ * the _mc->fpregs[i] can cause invalid conversions. */
+
+ assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
+ system_memcpy(&es->fltregs, &_mc->fpregs.fpregs, sizeof(_mc->fpregs.fpregs));
+}
+
+
+/* md_executionstate_write *****************************************************
+
+ Write the given executionstate back to the context.
+
+*******************************************************************************/
+
+void md_executionstate_write(executionstate_t *es, void *context)
+{
+ ucontext_t *_uc;
+ mcontext_t *_mc;
+ unsigned long *_gregs;
+ s4 i;
+
+ _uc = (ucontext_t *) context;
+
+#if defined(__UCLIBC__)
+#error Please port md_executionstate_write to __UCLIBC__
+#else
+ _mc = _uc->uc_mcontext.uc_regs;
+ _gregs = _mc->gregs;
+#endif
+
+ /* write integer registers */
+ for (i = 0; i < INT_REG_CNT; i++)
+ _gregs[i] = es->intregs[i];
+
+ /* write float registers */
+ /* Do not use the assignment operator '=', as the type of
+ * the _mc->fpregs[i] can cause invalid conversions. */
+
+ assert(sizeof(_mc->fpregs.fpregs) == sizeof(es->fltregs));
+ system_memcpy(&_mc->fpregs.fpregs, &es->fltregs, sizeof(_mc->fpregs.fpregs));
+
+ /* write special registers */
+ _gregs[PT_NIP] = (ptrint) es->pc;
+ _gregs[REG_SP] = (ptrint) es->sp;
+ _gregs[REG_PV] = (ptrint) es->pv;
+ _gregs[PT_LNK] = (ptrint) es->ra;
+}
+
+
/* md_critical_section_restart *************************************************
Search the critical sections tree for a matching section and set
#ifndef _MACHINE_INSTR_H
#define _MACHINE_INSTR_H
-static inline void
-atomic_add(int *mem, int val)
-{
- int temp;
-
- __asm__ __volatile__ ("\n\
-1: lwarx %0,0,%2 \n\
- add %0,%0,%1 \n\
- stwcx. %0,0,%2 \n\
- bne- 1b \n\
-" : "=&r"(temp)
- : "r"(val), "r"(mem) : "cr0", "memory");
-}
-
static inline long compare_and_swap(long *p, long oldval, long newval)
{
long ret, temp;
}
#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("sync" : : : "memory");
#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("isync" : : : "memory");
#define MEMORY_BARRIER() __asm__ __volatile__ ( "sync" : : : "memory" );
--- /dev/null
+/* src/vm/jit/powerpc/md-trap.h - PowerPC hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (powerpc) the trap numbers are used as load
+ * displacements and thus must not be 4- or 8-byte aligned.
+ *
+ * NOTE: In trap_init() we have a check whether the offset of
+ * java_arrayheader.data[0] is greater than the largest displacement
+ * defined below. Otherwise normal array loads/stores could trigger
+ * an exception.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 1
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+
+ /* Don't use 4 (could be a normal load offset). */
+
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+
+ /* Don't use 8 (could be a normal load offset). */
+
+ TRAP_COMPILER = 9,
+ TRAP_END
+};
+
+#endif /* _MD_TRAP_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:
+ */
-/* src/vm/jit/powerpc/netbsd/md-abi.c - functions for PowerPC NetBSD ABI
+/* src/vm/jit/powerpc/netbsd/md-abi.c - PowerPC NetBSD ABI
- 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 "vm/descriptor.h"
#include "vm/global.h"
+
#include "vm/jit/abi.h"
+#include "vm/jit/stack.h"
#define _ALIGN(a) do { if ((a) & 1) (a)++; } while (0)
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t* stackslot)
{
methodinfo *m;
registerdata *rd;
/* src/vm/jit/powerpc/patcher.c - PowerPC code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
PATCH_BACK_ORIGINAL_MCODE;
/* patch interfacetable index */
disp = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->class->index;
+ sizeof(methodptr*) * m->clazz->index;
/* XXX TWISTI: check displacement */
/* patch method offset */
- disp = sizeof(methodptr) * (m - m->class->methods);
+ disp = sizeof(methodptr) * (m - m->clazz->methods);
/* XXX TWISTI: check displacement */
## src/vm/jit/powerpc64/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.
##
codegen.h \
$(DISASS_SOURCES) \
emit.c \
+ patcher.c \
+ \
+ md-trap.h \
md.c \
- patcher.c
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
#define SPECIALMEMUSE
-/* #define HAS_4BYTE_STACKSLOT */
/* #define SUPPORT_COMBINE_INTEGER_REGISTERS */
/* src/vm/jit/powerpc64/codegen.c - machine code generator for 64-bit PowerPC
- 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/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
/* get or test the lock object */
if (m->flags & ACC_STATIC) {
- p = dseg_add_address(cd, &m->class->object.header);
+ p = dseg_add_address(cd, &m->clazz->object.header);
M_ALD(REG_A0, REG_PV, p);
}
else {
M_TST(REG_A0);
M_BNE(1);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
M_AST(REG_A0, REG_SP, s1 * 8); /* rd->memuse * 8 */
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
}
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
}
}
} else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
code = jd->code;
cd = jd->cd;
+ /* Sanity check. */
+
+ assert(!code_is_leafmethod(code));
+
/* set some variables */
md = m->parseddesc;
/* src/vm/jit/powerpc64/emit.c - PowerPC64 code emitter functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/trace.h"
+#include "vm/jit/trap.h"
#include "vmcore/options.h"
void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
{
if (checkbounds) {
-#define SOFTEX 0
-#if SOFTEX
- M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
- M_CMPU(s2, REG_ITMP3);
- codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
- BRANCH_NOPS;
-#else
M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
M_CMPU(s2, REG_ITMP3);
M_BLT(1);
/* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
- M_LWZ(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
-#endif
+ M_LWZ(s2, REG_ZERO, TRAP_ArrayIndexOutOfBoundsException);
}
}
M_TST(REG_RESULT);
M_BNE(1);
/* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
- M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_LWZ(REG_ZERO, REG_ZERO, TRAP_ArrayStoreException);
}
}
void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
{
if (INSTRUCTION_MUST_CHECK(iptr)) {
- #if SOFTEX
- M_TST(reg);
- codegen_add_arithmeticexception_ref(cd);
- BRANCH_NOPS;
- #else
M_TST(reg);
M_BNE(1);
/* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
- M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
- #endif
+ M_LWZ(REG_ZERO, REG_ZERO, TRAP_ArithmeticException);
}
}
-#if 0
-/* emit_arraystore_check *******************************************************
-
- Emit an ArrayStoreException check.
-
-*******************************************************************************/
-
-void emit_arraystore_check(codegendata *cd, instruction *iptr, s4 reg)
-{
- if (INSTRUCTION_MUST_CHECK(iptr)) {
- M_TST(REG_RESULT);
- codegen_add_arraystoreexception_ref(cd);
- BRANCH_NOPS;
- }
-}
-#endif
/* emit_classcast_check ********************************************************
void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
{
if (INSTRUCTION_MUST_CHECK(iptr)) {
- #if SOFTEX
- codegen_add_classcastexception_ref(cd, condition, s1);
- BRANCH_NOPS;
- M_NOP;
- #else
switch(condition) {
- case BRANCH_LE:
- M_BGT(1);
- break;
- case BRANCH_EQ:
- M_BNE(1);
- break;
- case BRANCH_GT:
- M_BLE(1);
- break;
- default:
- vm_abort("emit_classcast_check: unknown condition %d", condition);
+ case BRANCH_LE:
+ M_BGT(1);
+ break;
+ case BRANCH_EQ:
+ M_BNE(1);
+ break;
+ case BRANCH_GT:
+ M_BLE(1);
+ break;
+ default:
+ vm_abort("emit_classcast_check: unknown condition %d", condition);
}
+
/* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
- M_LWZ(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
- #endif
+ M_LWZ(s1, REG_ZERO, TRAP_ClassCastException);
}
}
M_TST(reg);
M_BNE(1);
/* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
- M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_LWZ(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
}
void emit_exception_check(codegendata *cd, instruction *iptr)
{
if (INSTRUCTION_MUST_CHECK(iptr)) {
- #if SOFTEX
- M_CMPI(REG_RESULT, 0);
- codegen_add_fillinstacktrace_ref(cd);
- BRANCH_NOPS;
- #else
M_TST(REG_RESULT);
M_BNE(1);
/* ALD is 4 byte aligned, ILD 2, onyl LWZ is byte aligned */
- M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
- #endif
+ M_LWZ(REG_ZERO, REG_ZERO, TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
- M_LWZ(REG_METHODPTR, REG_ZERO, EXCEPTION_HARDWARE_COMPILER);
+ M_LWZ(REG_METHODPTR, REG_ZERO, TRAP_COMPILER);
}
mcode = *((uint32_t *) cd->mcodeptr);
/* ALD is 4 byte aligned, ILD 2, only LWZ is byte aligned */
- M_LWZ(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_PATCHER);
+ M_LWZ(REG_ZERO, REG_ZERO, TRAP_PATCHER);
return mcode;
}
/* src/vm/jit/powerpc64/linux/md-abi.c - functions for PowerPC64 Linux ABI
- 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/global.h"
#include "vm/jit/abi.h"
+#include "vm/jit/stack.h"
#include "vmcore/descriptor.h"
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
methodinfo *m;
codeinfo *code;
/* src/vm/jit/powerpc64/linux/md-os.c - machine dependent PowerPC64 Linux functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/powerpc64/md.h"
#include "vm/jit/powerpc64/linux/md-abi.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/builtin.h"
#include "vm/exceptions.h"
#endif
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
/* md_signal_handler_sigsegv ***************************************************
val = _mc->gp_regs[d];
if (s1 == REG_ZERO) {
- /* we use the exception type as load displacement */
+ /* We use the exception type as load displacement. */
type = disp;
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
/* The XPC is the RA minus 1, because the RA points to the
instruction after the call. */
}
}
else {
- /* normal NPE */
+ /* Normal NPE. */
addr = _mc->gp_regs[s1];
type = (int) addr;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* Set registers. */
switch (type) {
- case EXCEPTION_HARDWARE_COMPILER:
+ case TRAP_COMPILER:
if (p != NULL) {
_mc->gp_regs[REG_PV] = (uintptr_t) p;
_mc->gp_regs[PT_NIP] = (uintptr_t) p;
/* fall-through */
- case EXCEPTION_HARDWARE_PATCHER:
+ case TRAP_PATCHER:
if (p == NULL)
break;
}
#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("sync" : : : "memory");
#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("isync" : : : "memory");
#define MEMORY_BARRIER() __asm__ __volatile__ ( "sync" : : : "memory" );
--- /dev/null
+/* src/vm/jit/powerpc64/md-trap.h - PowerPC64 hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (alpha) the trap numbers are used as load
+ * displacements and thus must not be 4- or 8-byte aligned.
+ *
+ * NOTE: In trap_init() we have a check whether the offset of
+ * java_arrayheader.data[0] is greater than the largest displacement
+ * defined below. Otherwise normal array loads/stores could trigger
+ * an exception.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 1
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+
+ /* Don't use 4 (could be a normal load offset). */
+
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+
+ /* Don't use 8 (could be a normal load offset). */
+
+ TRAP_COMPILER = 9,
+ TRAP_END
+};
+
+#endif /* _MD_TRAP_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 "vm/global.h"
#include "vm/jit/jit.h"
+#include "vm/jit/trap.h"
/* md_init *********************************************************************
*(u4*)(savedmcode) = *(u4*)(pc);
/* build the machine code for the patch */
- mcode = (0x80000000 | (EXCEPTION_HARDWARE_PATCHER));
+ mcode = (0x80000000 | TRAP_PATCHER);
/* write the new machine code */
*(u4*)(pc) = (u4) mcode;
/* src/vm/jit/powerpc64/patcher.c - PowerPC64 code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
/* patch back original code */
/* patch interfacetable index */
disp = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->class->index;
+ sizeof(methodptr*) * m->clazz->index;
/* XXX TWISTI: check displacement */
/* patch method offset */
- disp = sizeof(methodptr) * (m - m->class->methods);
+ disp = sizeof(methodptr) * (m - m->clazz->methods);
/* XXX TWISTI: check displacement */
--- /dev/null
+/* src/vm/jit/python.c - Python pass
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+ Note: this code is currently alpha and needs to be documented.
+
+ This code wraps the jitdata structure into a python object and
+ makes it possible to implement a compiler pass as python function.
+
+ The wrapping of cacao types to python objects is meant to be easy and
+ straight-forward.
+
+ Cacao structs a wrapped into a python ``wrapper'' object, the state of
+ which consists of:
+
+ * A void pointer.
+ * A pointer to a class function (see class_func), which implements the
+ object's behaviour.
+
+ Arrays and collection-like data structures are wrapped into a python
+ ``iterator'' object, the state of wich consists of:
+
+ * A void pointer.
+ * Another void pointer that is the cursor.
+ * A pointer to a iterator function (see iterator_func) which implements
+ the iterator's behaviour.
+
+ Because in python field names are identified as strings, to avoid a lot
+ of string comparisons, we translate the field as early as possible into
+ an integer constant. This is achieved using the field_map array.
+
+ We could have used a wrapper generator like swig, but we don't want to
+ wrap the rather low level C api to python 1:1. When wrapping stuff, try
+ to do it rather high level and in a pythonic way. Examples:
+
+ * Bad: instruction.flags and cacao.FLAG_UNRESOLVED == 0
+ * Good: instruction.is_unresolved
+ * Bad: for i in range(0, bb.icount): instr = bb.instructions[i]
+ * Good: for instr in bb.instructions
+
+ Adding instructions or variables is currently problematic, because it
+ requires to resize fixed sized arrays. Reallocating an array means that
+ all elements are possibly moved, their addresses are changed and the
+ associated python object become invalid. Further, usually there is the
+ need to add several instructions, which possibly results in several
+ reallocations of the array. A good solution would be:
+
+ * Copy-on-write the array (ex. bptr->instructions) into a python list,
+ and put that list into the dictionnary of the parent object.
+ * When the python parent object is destroyed, recreate the array from the
+ list.
+ * From python, bptr.instructions will return either the wrapped array, or
+ the list from the dictionnary.
+
+*/
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "vm/global.h"
+#include "vm/jit/python.h"
+#include "vm/jit/show.h"
+#if defined(ENABLE_THREADS)
+# include "threads/lock-common.h"
+#endif
+
+#if defined(ENABLE_THREADS)
+static java_object_t *python_global_lock;
+#endif
+
+/*
+ * Defs
+ */
+
+typedef struct root_state root_state;
+
+struct root_state {
+ jitdata *jd;
+ PyObject *object_cache;
+};
+
+typedef struct class_state class_state;
+
+struct class_state {
+ root_state *root;
+ void *vp;
+};
+
+union class_arg {
+ struct {
+ int is_method;
+ int field;
+ PyObject **result;
+ } get;
+ struct {
+ int field;
+ PyObject *value;
+ } set;
+ struct {
+ PyObject *args;
+ PyObject **result;
+ } call;
+ struct {
+ int method;
+ PyObject *args;
+ PyObject **result;
+ } method_call;
+ struct {
+ PyObject **result;
+ } str;
+ void *key;
+};
+
+typedef union class_arg class_arg;
+
+enum class_op {
+ CLASS_SET_FIELD,
+ CLASS_GET_FIELD,
+ CLASS_CALL,
+ CLASS_STR,
+ CLASS_METHOD_CALL
+};
+
+typedef enum class_op class_op;
+
+typedef int(*class_func)(class_op, class_state *, class_arg *);
+#define CLASS_FUNC(name) int name(class_op op, class_state *state, class_arg *arg)
+#define CLASS_FUNC_CALL(name) name(op, state, arg)
+
+struct iterator_state {
+ root_state *root;
+ void *data;
+ void *pos;
+};
+
+union iterator_arg {
+ struct {
+ PyObject **result;
+ } get;
+ struct {
+ unsigned int index;
+ PyObject **result;
+ } subscript;
+ int length;
+ struct {
+ unsigned int index;
+ PyObject *value;
+ } setitem;
+};
+
+typedef union iterator_arg iterator_arg;
+
+typedef struct iterator_state iterator_state;
+
+enum iterator_op {
+ ITERATOR_INIT,
+ ITERATOR_GET,
+ ITERATOR_FORWARD,
+ ITERATOR_END,
+ ITERATOR_SUBSCRIPT,
+ ITERATOR_LENGTH,
+ ITERATOR_SETITEM
+};
+
+typedef enum iterator_op iterator_op;
+
+typedef int(*iterator_func)(iterator_op op, iterator_state *state, iterator_arg *arg);
+#define ITERATOR_FUNC(name) int name (iterator_op op, iterator_state *state, iterator_arg *arg)
+#define ITERATOR_SUBSCRIPT_CHECK(end) if (arg->subscript.index >= (end)) return -1
+#define ITERATOR_SETITEM_CHECK(end) if (arg->setitem.index >= (end)) return -1
+
+typedef struct method_state method_state;
+
+struct method_state {
+ int method;
+ class_state *cstate;
+};
+
+struct field_map_entry {
+ const char *name;
+ int tag;
+};
+
+typedef struct field_map_entry field_map_entry;
+
+enum field {
+ F_BASIC_BLOCKS,
+ F_CALL_RETURN_TYPE,
+ F_CALL_ARGS,
+ F_CLASSREF,
+ F_CONTROL_FLOW,
+ F_CONTROL_FLOW_EX,
+ F_DATA_FLOW,
+ F_DATA_FLOW_EX,
+ F_DESCRIPTOR,
+ F_DOM_SUCCESSORS,
+ F_DOMINANCE_FRONTIER,
+ F_DST,
+ F_END,
+ F_EXCEPTION_HANDLER,
+ F_EXCEPTION_TABLE,
+ F_FIELD,
+ F_FIELD_TYPE,
+ F_HANDLER,
+ F_HAS_CALL_ARGS,
+ F_HAS_DST,
+ F_IDOM,
+ F_INDEX,
+ F_INSTRUCTIONS,
+ F_INTERFACE_MAP,
+ F_IN_VARS,
+ F_IS_CLASS_CONSTANT,
+ F_IS_IN_MEMORY,
+ F_IS_INOUT,
+ F_IS_LOCAL,
+ F_IS_PREALLOCATED,
+ F_IS_SAVED,
+ F_IS_TEMPORARY,
+ F_IS_UNRESOLVED,
+ F_LOCAL_METHODINFO,
+ F_KLASS,
+ F_LINE,
+ F_LOCAL_MAP,
+ F_METHOD,
+ F_NAME,
+ F_NAME_EX,
+ F_NR,
+ F_OFFSET,
+ F_OPCODE,
+ F_OPCODE_EX,
+ F_OUT_VARS,
+ F_PARAMS,
+ F_PARAM_TYPES,
+ F_PEI,
+ F_PEI_EX,
+ F_PREDECESSORS,
+ F_REACHED,
+ F_REGISTER_OFFSET,
+ F_RETURN_TYPE,
+ F_S,
+ F_SHOW,
+ F_SUCCESSORS,
+ F_START,
+ F_TYPE,
+ F_UNRESOLVED_FIELD,
+ F_UNUSED,
+ F_VARS
+};
+
+/* Keep it soreted alphabetically, so we can support binary search in future. */
+struct field_map_entry field_map[] = {
+ { "basic_blocks", F_BASIC_BLOCKS },
+ { "call_return_type", F_CALL_RETURN_TYPE },
+ { "call_args", F_CALL_ARGS },
+ { "classref", F_CLASSREF },
+ { "control_flow", F_CONTROL_FLOW },
+ { "control_flow_ex", F_CONTROL_FLOW_EX },
+ { "data_flow", F_DATA_FLOW },
+ { "data_flow_ex", F_DATA_FLOW_EX },
+ { "descriptor", F_DESCRIPTOR },
+ { "dom_successors", F_DOM_SUCCESSORS },
+ { "dominance_frontier", F_DOMINANCE_FRONTIER },
+ { "dst", F_DST },
+ { "end", F_END },
+ { "exception_handler", F_EXCEPTION_HANDLER },
+ { "exception_table", F_EXCEPTION_TABLE },
+ { "field", F_FIELD },
+ { "field_type", F_FIELD_TYPE },
+ { "handler", F_HANDLER },
+ { "has_call_args", F_HAS_CALL_ARGS },
+ { "has_dst", F_HAS_DST },
+ { "idom", F_IDOM, },
+ { "index", F_INDEX },
+ { "instructions", F_INSTRUCTIONS },
+ { "interface_map", F_INTERFACE_MAP },
+ { "in_vars", F_IN_VARS },
+ { "is_class_constant", F_IS_CLASS_CONSTANT },
+ { "is_inout", F_IS_INOUT },
+ { "is_in_memory", F_IS_IN_MEMORY },
+ { "is_local", F_IS_LOCAL },
+ { "is_preallocated", F_IS_PREALLOCATED },
+ { "is_saved", F_IS_SAVED },
+ { "is_temporary", F_IS_TEMPORARY },
+ { "is_unresolved", F_IS_UNRESOLVED },
+ { "klass", F_KLASS },
+ { "line", F_LINE },
+ { "local_map", F_LOCAL_MAP },
+ { "local_methodinfo", F_LOCAL_METHODINFO },
+ { "method", F_METHOD },
+ { "name", F_NAME },
+ { "name_ex", F_NAME_EX },
+ { "nr", F_NR },
+ { "offset", F_OFFSET },
+ { "opcode", F_OPCODE },
+ { "opcode_ex", F_OPCODE_EX },
+ { "out_vars", F_OUT_VARS },
+ { "params", F_PARAMS },
+ { "param_types", F_PARAM_TYPES },
+ { "pei", F_PEI },
+ { "pei_ex", F_PEI_EX },
+ { "predecessors", F_PREDECESSORS },
+ { "reached", F_REACHED },
+ { "register_offset", F_REGISTER_OFFSET },
+ { "return_type", F_RETURN_TYPE },
+ { "s", F_S },
+ { "show", F_SHOW },
+ { "start", F_START },
+ { "successors", F_SUCCESSORS },
+ { "type", F_TYPE },
+ { "unresolved_field", F_UNRESOLVED_FIELD },
+ { "unused", F_UNUSED },
+ { "vars", F_VARS },
+ { NULL, 0 }
+};
+
+int field_find(const char *key) {
+ field_map_entry *it;
+
+ for (it = field_map; it->name; ++it) {
+ if (strcmp(it->name, key) == 0) {
+ return it->tag;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * Python
+ */
+
+typedef struct method method;
+
+struct method {
+ PyObject_HEAD;
+ class_func func;
+ method_state state;
+};
+
+PyObject *method_call(method *m, PyObject *args, PyObject *kw) {
+ class_arg arg;
+ PyObject *result = NULL;
+
+ arg.method_call.method = m->state.method;
+ arg.method_call.args = args;
+ arg.method_call.result = &result;
+
+ if (m->func(CLASS_METHOD_CALL, m->state.cstate, &arg) == -1) {
+ return NULL;
+ }
+
+ if (result == NULL) {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+
+ return result;
+}
+
+PyTypeObject method_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "method", /* tp_name */
+ sizeof(method), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ method_call, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+struct wrapper {
+ PyObject_HEAD
+ class_state state;
+ class_func func;
+ PyObject *dict;
+};
+
+typedef struct wrapper wrapper;
+
+PyObject *wrapper_getattr(wrapper *w, PyObject *fld) {
+ class_arg arg;
+ PyObject *result;
+
+ /* First, try generic getattr */
+
+ result = PyObject_GenericGetAttr(w, fld);
+
+ if (result != NULL) {
+ return result;
+ }
+
+ /* Exception is set here */
+
+ arg.get.field = field_find(PyString_AsString(fld));
+ if (arg.get.field == -1) {
+ goto failout;
+ }
+
+ arg.get.is_method = 0;
+ arg.get.result = &result;
+
+ if (w->func(CLASS_GET_FIELD, &w->state, &arg) == -1) {
+ goto failout;
+ }
+
+ if (arg.get.is_method) {
+ result = PyObject_CallObject((PyObject *)&method_type, NULL);
+ method *m = (method *)result;
+ m->func = w->func;
+ m->state.method = arg.get.field;
+ m->state.cstate = &w->state;
+ }
+
+ PyErr_Clear();
+
+ return result;
+
+failout:
+
+ return NULL;
+}
+
+int wrapper_setattr(wrapper *w, PyObject *fld, PyObject *value) {
+ class_arg arg;
+
+ arg.set.field = field_find(PyString_AsString(fld));
+ if (arg.set.field == -1) {
+ goto failout;
+ }
+ arg.set.value = value;
+
+ if (w->func(CLASS_SET_FIELD, &w->state, &arg) == -1) {
+ goto failout;
+ }
+
+ return 0;
+
+failout:
+
+ return PyObject_GenericSetAttr(w, fld, value);
+}
+
+extern PyTypeObject wrapper_type;
+
+inline void *wrapper_key(wrapper *w) {
+ return w->state.vp;
+}
+
+int wrapper_compare(wrapper *a, wrapper *b) {
+ void *keya, *keyb;
+ if (PyObject_TypeCheck(b, &wrapper_type)) {
+ keya = wrapper_key(a);
+ keyb = wrapper_key(b);
+ if (keya < keyb) {
+ return -1;
+ } else if (keya > keyb) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
+ /* If classes differ, compare classes */
+ return PyObject_Compare(a->ob_type, b->ob_type);
+ }
+}
+
+long wrapper_hash(wrapper *a) {
+ return (long)wrapper_key(a);
+}
+
+PyObject *wrapper_call(wrapper *w, PyObject *args, PyObject *kw) {
+ class_arg arg;
+ PyObject *result;
+
+ arg.call.args = args;
+ arg.call.result = &result;
+
+ if (w->func(CLASS_CALL, &w->state, &arg) == -1) {
+ return NULL;
+ }
+
+ return result;
+}
+
+PyObject *wrapper_str(wrapper *w) {
+ class_arg arg;
+ PyObject *result;
+ arg.str.result = &result;
+ if (w->func(CLASS_STR, &w->state, &arg) == -1) {
+ return PyString_FromFormat("Wrapper(0x%p)", w->state.vp);
+ } else {
+ return result;
+ }
+}
+
+PyTypeObject wrapper_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "wrapper", /* tp_name */
+ sizeof(wrapper), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ wrapper_compare, /* tp_compare */
+ wrapper_str, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ wrapper_hash, /* tp_hash */
+ wrapper_call, /* tp_call */
+ wrapper_str, /* tp_str */
+ wrapper_getattr, /* tp_getattro */
+ wrapper_setattr, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ offsetof(wrapper, dict), /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+struct iterator {
+ PyObject_HEAD
+ iterator_func func;
+ iterator_state state;
+};
+
+typedef struct iterator iterator;
+
+PyObject *iterator_iter(struct iterator *it) {
+ Py_INCREF(it);
+ return (PyObject *)it;
+}
+
+PyObject *iterator_iternext(struct iterator *it) {
+ PyObject *ret;
+ iterator_arg arg;
+
+ if (it->func(ITERATOR_END, &it->state, NULL)) {
+ return NULL;
+ } else {
+ arg.get.result = &ret;
+ it->func(ITERATOR_GET, &it->state, &arg);
+ it->func(ITERATOR_FORWARD, &it->state, NULL);
+ return ret;
+ }
+}
+
+PyObject *iterator_getitem(struct iterator *it, PyObject* item) {
+ iterator_arg arg;
+ PyObject *ret;
+
+ if (PyInt_Check(item)) {
+ arg.subscript.index = PyInt_AS_LONG(item);
+ arg.subscript.result = &ret;
+ if (index < 0) {
+ return NULL;
+ } else if (it->func(ITERATOR_SUBSCRIPT, &it->state, &arg) != -1) {
+ return ret;
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+int iterator_setitem(struct iterator *it, PyObject *item, PyObject *value) {
+ iterator_arg arg;
+ if (PyInt_Check(item)) {
+ arg.setitem.index = PyInt_AS_LONG(item);
+ arg.setitem.value = value;
+ if (it->func(ITERATOR_SETITEM, &it->state, &arg) != -1) {
+ return 0;
+ } else {
+ return -1;
+ }
+ } else {
+ return -1;
+ }
+}
+
+int iterator_length(struct iterator *it) {
+ iterator_arg arg;
+ if (it->func(ITERATOR_LENGTH, &it->state, &arg) == -1) {
+ return -1;
+ } else {
+ return arg.length;
+ }
+}
+
+PyMappingMethods iterator_mapping = {
+ iterator_length,
+ iterator_getitem,
+ iterator_setitem
+};
+
+PyTypeObject iterator_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "iterator", /* tp_name */
+ sizeof(iterator), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ &iterator_mapping, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ iterator_iter, /* tp_iter */
+ iterator_iternext, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ PyType_GenericNew, /* tp_new */
+};
+
+/*
+ * Utils
+ */
+
+int set_s4(s4 *p, PyObject *o) {
+ if (PyInt_Check(o)) {
+ *p = PyInt_AsLong(o);
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int set_s4_flag(s4 *p, s4 flag, PyObject *o) {
+ if (o == Py_True) {
+ *p |= flag;
+ return 0;
+ } else if (o == Py_False) {
+ *p &= ~flag;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int get_int(PyObject **o, int p) {
+ *o = PyInt_FromLong(p);
+ return 0;
+}
+
+int get_string(PyObject **o, const char *str) {
+ *o = PyString_FromString(str);
+ return 0;
+}
+
+int get_obj(PyObject **res, class_func f, root_state *root, void *p) {
+ if (p == NULL) {
+ return get_none(res);
+ } else {
+ PyObject *key = PyInt_FromLong((long)p);
+ PyObject *o = PyDict_GetItem(root->object_cache, key);
+ if (o == NULL) {
+ o = PyObject_CallObject((PyObject *)&wrapper_type, NULL);
+ struct wrapper * w = (struct wrapper *)o;
+ w->func = f;
+ w->state.root = root;
+ w->state.vp = p;
+ PyDict_SetItem(root->object_cache, key, o);
+ } else {
+ Py_INCREF(o);
+ }
+ *res = o;
+ return 0;
+ }
+}
+
+int get_true(PyObject **res) {
+ Py_INCREF(Py_True);
+ *res = Py_True;
+ return 0;
+}
+
+int get_false(PyObject **res) {
+ Py_INCREF(Py_False);
+ *res = Py_False;
+ return 0;
+}
+
+int get_none(PyObject **res) {
+ Py_INCREF(Py_None);
+ *res = Py_None;
+ return 0;
+}
+
+int get_bool(PyObject **res, int cond) {
+ return cond ? get_true(res) : get_false(res);
+}
+
+int get_iter(PyObject **res, iterator_func f, root_state *root, void *p) {
+ PyObject *o = PyObject_CallObject((PyObject *)&iterator_type, NULL);
+ struct iterator * it = (struct iterator *)o;
+ it->func = f;
+ it->state.root = root;
+ it->state.data = p;
+ f(ITERATOR_INIT, &it->state, NULL);
+ *res = o;
+ return 0;
+}
+
+int add_const(PyObject *module, const char *name, int value) {
+ PyObject *pyvalue = PyInt_FromLong(value);
+ if (pyvalue != NULL) {
+ PyModule_AddObject(module, name, pyvalue);
+ }
+}
+
+void *get_vp(PyObject *o, class_func func) {
+ if (o->ob_type == &wrapper_type) {
+ if (((wrapper *)o)->func == func) {
+ return ((wrapper *)o)->state.vp;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * Implemnetation
+ */
+
+CLASS_FUNC(basicblock_func);
+CLASS_FUNC(classinfo_func);
+CLASS_FUNC(constant_classref_func);
+CLASS_FUNC(methodinfo_func);
+CLASS_FUNC(varinfo_func);
+
+int get_varinfo(PyObject **res, root_state *root, s4 index) {
+ return get_obj(res, varinfo_func, root, root->jd->var + index);
+}
+
+static inline int instruction_opcode_ex(instruction *iptr) {
+ if (iptr->opc == ICMD_BUILTIN) {
+ return iptr->sx.s23.s3.bte->opcode;
+ } else {
+ return iptr->opc;
+ }
+}
+
+ITERATOR_FUNC(call_args_iter_func) {
+ instruction *iptr = (instruction *)state->data;
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = iptr->sx.s23.s2.args;
+ return 0;
+ case ITERATOR_LENGTH:
+ arg->length = iptr->s1.argcount;
+ return 0;
+ case ITERATOR_GET:
+ /* return get_int(arg->get.result, *(int *)state->pos);*/
+ return get_varinfo(arg->get.result, state->root, *(int *)state->pos);
+ case ITERATOR_END:
+ return state->pos == iptr->sx.s23.s2.args + iptr->s1.argcount;
+ case ITERATOR_FORWARD:
+ state->pos = ((int *)state->pos) + 1;
+ return 0;
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(iptr->s1.argcount);
+ return get_int(arg->subscript.result, iptr->sx.s23.s2.args[arg->subscript.index]);
+ case ITERATOR_SETITEM:
+ ITERATOR_SETITEM_CHECK(iptr->s1.argcount);
+ return set_s4(iptr->sx.s23.s2.args + arg->setitem.index, arg->setitem.value);
+ }
+ return -1;
+}
+
+CLASS_FUNC(fieldinfo_func) {
+ fieldinfo *fi = (fieldinfo *)state->vp;
+
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_TYPE:
+ return get_int(arg->get.result, fi->type);
+ case F_OFFSET:
+ return get_int(arg->get.result, fi->offset);
+ case F_NAME:
+ return get_string(arg->get.result, fi->name->text);
+ case F_KLASS:
+ return get_obj(arg->get.result, classinfo_func, state->root, fi->clazz);
+ }
+ }
+
+ return -1;
+}
+
+CLASS_FUNC(unresolved_field_func) {
+ unresolved_field *uf = (unresolved_field *)state->vp;
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_NAME:
+ return get_string(arg->get.result, uf->fieldref->name->text);
+ case F_CLASSREF:
+ if (IS_FMIREF_RESOLVED(uf->fieldref)) {
+ return get_none(arg->get.result);
+ } else {
+ return get_obj(arg->get.result, constant_classref_func, state->root, uf->fieldref->p.classref);
+ }
+ case F_DESCRIPTOR:
+ return get_string(arg->get.result, uf->fieldref->descriptor->text);
+ case F_FIELD:
+ if (IS_FMIREF_RESOLVED(uf->fieldref)) {
+ return get_obj(arg->get.result, fieldinfo_func, state->root, uf->fieldref->p.field);
+ } else {
+ return get_none(arg->get.result);
+ }
+ case F_IS_UNRESOLVED:
+ return get_bool(arg->get.result, !IS_FMIREF_RESOLVED(uf->fieldref));
+ }
+ }
+ return -1;
+}
+
+static inline int instruction_num_s(instruction *iptr) {
+ switch (icmd_table[iptr->opc].dataflow) {
+ case DF_1_TO_0:
+ case DF_1_TO_1:
+ case DF_COPY:
+ case DF_MOVE:
+ return 1;
+ case DF_2_TO_0:
+ case DF_2_TO_1:
+ return 2;
+ case DF_3_TO_0:
+ case DF_3_TO_1:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+static inline s4 *instruction_get_s(instruction *iptr, int s) {
+ switch (s) {
+ case 0:
+ return &(iptr->s1.varindex);
+ case 1:
+ return &(iptr->sx.s23.s2.varindex);
+ case 2:
+ return &(iptr->sx.s23.s3.varindex);
+ }
+}
+
+ITERATOR_FUNC(s_iter_func) {
+ instruction *iptr = (instruction *)state->data;
+ uintptr_t pos = (uintptr_t)state->pos;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = (void *)0;
+ return 0;
+ case ITERATOR_LENGTH:
+ arg->length = instruction_num_s(iptr);
+ return 0;
+ case ITERATOR_GET:
+ return get_varinfo(arg->get.result, state->root,
+ *instruction_get_s(iptr, pos));
+ case ITERATOR_END:
+ return pos == instruction_num_s(iptr);
+ case ITERATOR_FORWARD:
+ state->pos = (void *)(pos + 1);
+ return 0;
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(3);
+ return get_varinfo(arg->subscript.result, state->root,
+ *instruction_get_s(iptr, arg->subscript.index));
+ case ITERATOR_SETITEM:
+ ITERATOR_SETITEM_CHECK(3);
+ return set_s4(instruction_get_s(iptr, arg->setitem.index),
+ arg->setitem.value);
+ }
+ return -1;
+}
+
+CLASS_FUNC(instruction_func) {
+
+ instruction *iptr = (instruction *)state->vp;
+
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_OPCODE:
+ return get_int(arg->get.result, iptr->opc);
+ case F_OPCODE_EX:
+ return get_int(arg->get.result, instruction_opcode_ex(iptr));
+ case F_NAME:
+ return get_string(arg->get.result, icmd_table[iptr->opc].name);
+ case F_NAME_EX:
+ return get_string(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].name);
+ case F_S:
+ return get_iter(arg->get.result, s_iter_func, state->root, iptr);
+ case F_DST:
+ return get_varinfo(arg->get.result, state->root,
+ iptr->dst.varindex);
+ case F_HAS_DST:
+ if (
+ (icmd_table[iptr->opc].dataflow == DF_INVOKE) ||
+ (icmd_table[iptr->opc].dataflow == DF_BUILTIN)
+ ) {
+ return get_bool(
+ arg->get.result,
+ instruction_call_site(iptr)->returntype.type != TYPE_VOID
+ );
+ }
+ return get_bool(arg->get.result, icmd_table[iptr->opc].dataflow >= DF_DST_BASE);
+ case F_CALL_RETURN_TYPE:
+ return get_int(arg->get.result, instruction_call_site(iptr)->returntype.type);
+ case F_CALL_ARGS:
+ return get_iter(arg->get.result, call_args_iter_func, state->root, iptr);
+ case F_HAS_CALL_ARGS:
+ return get_bool(arg->get.result,
+ icmd_table[iptr->opc].dataflow == DF_INVOKE ||
+ icmd_table[iptr->opc].dataflow == DF_BUILTIN ||
+ icmd_table[iptr->opc].dataflow == DF_N_TO_1
+ );
+ case F_IS_UNRESOLVED:
+ return get_bool(arg->get.result, iptr->flags.bits & INS_FLAG_UNRESOLVED);
+ case F_IS_CLASS_CONSTANT:
+ return get_bool(arg->get.result, iptr->flags.bits & INS_FLAG_CLASS);
+ case F_KLASS:
+ return get_obj(arg->get.result, classinfo_func, state->root, iptr->sx.val.c.cls);
+ case F_CLASSREF:
+ return get_obj(arg->get.result, constant_classref_func, state->root, iptr->sx.val.c.ref);
+ case F_LOCAL_METHODINFO:
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ return get_none(arg->get.result);
+ } else {
+ return get_obj(arg->get.result, methodinfo_func,
+ state->root, iptr->sx.s23.s3.fmiref->p.method);
+ }
+ case F_FIELD_TYPE:
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ return get_int(arg->get.result,
+ iptr->sx.s23.s3.uf->fieldref->parseddesc.fd->type);
+ } else {
+ return get_int(arg->get.result,
+ iptr->sx.s23.s3.fmiref->p.field->type);
+ }
+ case F_FIELD:
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ return get_none(arg->get.result);
+ } else {
+ return get_obj(arg->get.result, fieldinfo_func, state->root, iptr->sx.s23.s3.fmiref->p.field);
+ }
+ break;
+ case F_UNRESOLVED_FIELD:
+ if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
+ return get_obj(arg->get.result, unresolved_field_func, state->root, iptr->sx.s23.s3.uf);
+ } else {
+ return get_none(arg->get.result);
+ }
+ break;
+ case F_LINE:
+ return get_int(arg->get.result, iptr->line);
+ case F_PEI:
+ return get_bool(arg->get.result, icmd_table[iptr->opc].flags & ICMDTABLE_PEI);
+ case F_PEI_EX:
+ return get_bool(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].flags & ICMDTABLE_PEI);
+ case F_DATA_FLOW:
+ return get_int(arg->get.result, icmd_table[iptr->opc].dataflow);
+ case F_DATA_FLOW_EX:
+ return get_int(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].dataflow);
+ case F_CONTROL_FLOW:
+ return get_int(arg->get.result, icmd_table[iptr->opc].controlflow);
+ case F_CONTROL_FLOW_EX:
+ return get_int(arg->get.result, icmd_table[instruction_opcode_ex(iptr)].controlflow);
+ case F_SHOW:
+ arg->get.is_method = 1;
+ return 0;
+ }
+ case CLASS_SET_FIELD:
+ switch (arg->set.field) {
+ case F_DST:
+ return set_s4(&(iptr->dst.varindex), arg->set.value);
+ case F_OPCODE:
+ return set_s4(&(iptr->opc), arg->set.value);
+ }
+ case CLASS_METHOD_CALL:
+ switch (arg->method_call.method) {
+ case F_SHOW:
+ show_icmd(state->root->jd, iptr, 1, SHOW_CFG);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+ITERATOR_FUNC(predecessors_iter_func) {
+ basicblock *bptr = (basicblock *)state->data;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = bptr->predecessors;
+ return 0;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(bptr->predecessorcount);
+ return get_obj(arg->subscript.result, basicblock_func, state->root,
+ bptr->predecessors[arg->subscript.index]);
+ case ITERATOR_END:
+ return
+ (state->pos == (bptr->predecessors + bptr->predecessorcount)) ||
+ (bptr->predecessorcount < 0);
+ case ITERATOR_FORWARD:
+ state->pos = ((basicblock **)state->pos) + 1;
+ return 0;
+ case ITERATOR_LENGTH:
+ arg->length = bptr->predecessorcount;
+ return 0;
+ }
+
+ return -1;
+}
+
+ITERATOR_FUNC(successors_iter_func) {
+ basicblock *bptr = (basicblock *)state->data;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = bptr->successors;
+ return 0;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(bptr->successorcount);
+ return get_obj(arg->subscript.result, basicblock_func, state->root,
+ bptr->successors[arg->subscript.index]);
+ case ITERATOR_END:
+ return
+ (state->pos == (bptr->successors + bptr->successorcount)) ||
+ (bptr->successorcount < 0);
+ case ITERATOR_FORWARD:
+ state->pos = ((basicblock **)state->pos) + 1;
+ return 0;
+ case ITERATOR_LENGTH:
+ arg->length = bptr->successorcount;
+ return 0;
+ }
+
+ return -1;
+}
+
+ITERATOR_FUNC(dom_successors_iter_func) {
+ basicblock *bptr = (basicblock *)state->data;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = bptr->domsuccessors;
+ return 0;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
+ case ITERATOR_END:
+ return (state->pos == (bptr->domsuccessors + bptr->domsuccessorcount));
+ case ITERATOR_FORWARD:
+ state->pos = ((basicblock **)state->pos) + 1;
+ return 0;
+ case ITERATOR_LENGTH:
+ arg->length = bptr->domsuccessorcount;
+ return 0;
+ }
+
+ return -1;
+}
+
+ITERATOR_FUNC(dominance_frontier_iter_func) {
+ basicblock *bptr = (basicblock *)state->data;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = bptr->domfrontier;
+ return 0;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, basicblock_func, state->root, *(basicblock **)state->pos);
+ case ITERATOR_END:
+ return (state->pos == (bptr->domfrontier + bptr->domfrontiercount));
+ case ITERATOR_FORWARD:
+ state->pos = ((basicblock **)state->pos) + 1;
+ return 0;
+ }
+
+ return -1;
+}
+
+ITERATOR_FUNC(instruction_iter_func) {
+ basicblock *bptr = (basicblock *)state->data;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = bptr->iinstr;
+ return 0;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, instruction_func, state->root, state->pos);
+ case ITERATOR_FORWARD:
+ state->pos = ((instruction *)state->pos) + 1;
+ return 0;
+ case ITERATOR_END:
+ return state->pos == (bptr->iinstr + bptr->icount);
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(bptr->icount);
+ return get_obj(arg->subscript.result, instruction_func, state->root, bptr->iinstr + arg->subscript.index);
+ case ITERATOR_LENGTH:
+ arg->length = bptr->icount;
+ return 0;
+ }
+ return -1;
+}
+
+ITERATOR_FUNC(in_vars_iter_func) {
+ basicblock *bptr = (basicblock *)state->data;
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = bptr->invars;
+ return 0;
+ case ITERATOR_GET:
+ return get_varinfo(arg->get.result, state->root, *(s4 *)(state->pos));
+ case ITERATOR_FORWARD:
+ state->pos = ((s4 *)state->pos) + 1;
+ return 0;
+ case ITERATOR_END:
+ return state->pos == (bptr->invars + bptr->indepth);
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(bptr->icount);
+ return get_varinfo(arg->subscript.result, state->root, bptr->invars[arg->subscript.index]);
+ case ITERATOR_LENGTH:
+ arg->length = bptr->indepth;
+ return 0;
+ }
+}
+
+ITERATOR_FUNC(out_vars_iter_func) {
+ basicblock *bptr = (basicblock *)state->data;
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = bptr->outvars;
+ return 0;
+ case ITERATOR_GET:
+ return get_varinfo(arg->get.result, state->root, *(s4 *)(state->pos));
+ case ITERATOR_FORWARD:
+ state->pos = ((s4 *)state->pos) + 1;
+ return 0;
+ case ITERATOR_END:
+ return state->pos == (bptr->outvars + bptr->outdepth);
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(bptr->icount);
+ return get_varinfo(arg->subscript.result, state->root, bptr->outvars[arg->subscript.index]);
+ case ITERATOR_LENGTH:
+ arg->length = bptr->outdepth;
+ return 0;
+ }
+}
+
+CLASS_FUNC(basicblock_func) {
+ basicblock *bptr = (basicblock *)state->vp;
+
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_INSTRUCTIONS:
+ return get_iter(arg->get.result, instruction_iter_func, state->root, bptr);
+ case F_NR:
+ return get_int(arg->get.result, bptr->nr);
+ case F_PREDECESSORS:
+ return get_iter(arg->get.result, predecessors_iter_func, state->root, bptr);
+ case F_SUCCESSORS:
+ return get_iter(arg->get.result, successors_iter_func, state->root, bptr);
+ case F_REACHED:
+ return get_bool(arg->get.result, bptr->flags >= BBREACHED);
+ case F_EXCEPTION_HANDLER:
+ return get_bool(arg->get.result, bptr->type == BBTYPE_EXH);
+ case F_IDOM:
+ return get_obj(arg->get.result, basicblock_func, state->root, bptr->idom);
+ case F_DOM_SUCCESSORS:
+ return get_iter(arg->get.result, dom_successors_iter_func, state->root, bptr);
+ case F_DOMINANCE_FRONTIER:
+ return get_iter(arg->get.result, dominance_frontier_iter_func, state->root, bptr);
+ case F_IN_VARS:
+ return get_iter(arg->get.result, in_vars_iter_func, state->root, bptr);
+ case F_OUT_VARS:
+ return get_iter(arg->get.result, in_vars_iter_func, state->root, bptr);
+ case F_SHOW:
+ arg->get.is_method = 1;
+ return 0;
+ }
+ case CLASS_STR:
+ *arg->str.result = PyString_FromFormat("BB_%d", bptr->nr);
+ return 0;
+ case CLASS_METHOD_CALL:
+ switch (arg->method_call.method) {
+ case F_SHOW:
+ show_basicblock(state->root->jd, bptr, SHOW_CFG);
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+ITERATOR_FUNC(basicblocks_iter_func) {
+ jitdata *jd = (jitdata *)state->data;
+ basicblock *bb;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = jd->basicblocks;
+ return 0;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, basicblock_func, state->root, state->pos);
+ case ITERATOR_FORWARD:
+ state->pos = ((basicblock *)(state->pos))->next;
+ return 0;
+ case ITERATOR_END:
+ return (state->pos == NULL);
+ case ITERATOR_SUBSCRIPT:
+ for (bb = jd->basicblocks; bb != NULL; bb = bb->next) {
+ if (bb->nr == arg->subscript.index) {
+ return get_obj(arg->subscript.result, basicblock_func, state->root, bb);
+ }
+ }
+ return -1;
+ }
+
+ return -1;
+}
+
+CLASS_FUNC(classinfo_func) {
+ classinfo *c = (classinfo *)state->vp;
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_NAME:
+ return get_string(arg->get.result, c->name->text);
+ }
+ }
+ return -1;
+}
+
+CLASS_FUNC(constant_classref_func) {
+ constant_classref *cr = (constant_classref *)state->vp;
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_NAME:
+ return get_string(arg->get.result, cr->name->text);
+ }
+ }
+ return -1;
+}
+
+ITERATOR_FUNC(param_types_iter_func) {
+ methodinfo *m = (methodinfo *)state->data;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = m->parseddesc->paramtypes;
+ return 0;
+ case ITERATOR_END:
+ return state->pos == (m->parseddesc->paramtypes + m->parseddesc->paramcount);
+ case ITERATOR_FORWARD:
+ state->pos = ((typedesc *)state->pos) + 1;
+ return 0;
+ case ITERATOR_GET:
+ return get_int(arg->get.result, ((typedesc *)state->pos)->type);
+ case ITERATOR_LENGTH:
+ arg->length = m->parseddesc->paramcount;
+ return 0;
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(m->parseddesc->paramcount);
+ return get_int(arg->subscript.result, m->parseddesc->paramtypes[arg->subscript.index].type);
+ }
+
+ return -1;
+}
+
+ITERATOR_FUNC(params_iter_func) {
+
+ methodinfo *m = (methodinfo *)state->data;
+ /* param counter */
+ uint16_t p = (uintptr_t)(state->pos) & 0xFFFF;
+ /* local counter */
+ uint16_t l = ((uintptr_t)(state->pos) >> 16) & 0xFFFF;
+
+ int varnum;
+
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = (void *)0;
+ return 0;
+ case ITERATOR_END:
+ return p == m->parseddesc->paramcount;
+ case ITERATOR_FORWARD:
+ l += (IS_2_WORD_TYPE(m->parseddesc->paramtypes[p].type) ? 2 : 1);
+ p += 1;
+ state->pos = (void *)(uintptr_t)((l << 16) | p);
+ return 0;
+ case ITERATOR_GET:
+ varnum = state->root->jd->local_map[(5 * l) + m->parseddesc->paramtypes[p].type];
+ return get_varinfo(arg->get.result, state->root, varnum);
+ }
+
+ return -1;
+}
+
+CLASS_FUNC(methodinfo_func) {
+ methodinfo *m = (methodinfo *)state->vp;
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_NAME:
+ return get_string(arg->get.result, m->name->text);
+ case F_KLASS:
+ return get_obj(arg->get.result, classinfo_func, state->root, m->clazz);
+ case F_PARAM_TYPES:
+ return get_iter(arg->get.result, param_types_iter_func, state->root, m);
+ case F_PARAMS:
+ if (m == state->root->jd->m) {
+ return get_iter(arg->get.result, params_iter_func, state->root, m);
+ } else {
+ return get_none(arg->get.result);
+ }
+ case F_RETURN_TYPE:
+ return get_int(arg->get.result, m->parseddesc->returntype.type);
+ case F_SHOW:
+ if (m == state->root->jd->m) {
+ arg->get.is_method = 1;
+ return 0;
+ }
+ }
+ case CLASS_METHOD_CALL:
+ switch (arg->method_call.method) {
+ case F_SHOW:
+ show_method(state->root->jd, SHOW_CFG);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static inline PyObject *varinfo_str(jitdata *jd, int index, varinfo *v) {
+ char type = '?';
+ char kind = '?';
+
+ 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';
+ }
+ 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 if (v->flags & INOUT)
+ kind = 'I';
+ else
+ kind = 'T';
+ }
+
+ if (index == -1) {
+ return PyString_FromString("UNUSED");
+ } else {
+ return PyString_FromFormat("%c%c%d", kind, type, index);
+ }
+}
+
+
+CLASS_FUNC(varinfo_func) {
+ jitdata *jd = state->root->jd;
+ varinfo *var = (varinfo *)state->vp;
+ int index = var - jd->var;
+
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_TYPE:
+ return get_int(arg->get.result, var->type);
+ case F_IS_LOCAL:
+ return get_bool(arg->get.result, index < jd->localcount);
+ case F_IS_PREALLOCATED:
+ return get_bool(
+ arg->get.result,
+ (index >= jd->localcount) && (var->flags & PREALLOC)
+ );
+ case F_IS_INOUT:
+ return get_bool(
+ arg->get.result,
+ (index >= jd->localcount) && !(var->flags & PREALLOC) && (var->flags & INOUT)
+ );
+ case F_IS_TEMPORARY:
+ return get_bool(
+ arg->get.result,
+ (index >= jd->localcount) && !(var->flags & PREALLOC) && !(var->flags & INOUT)
+ );
+ case F_IS_SAVED:
+ return get_bool(arg->get.result, var->flags & SAVEDVAR);
+ case F_INDEX:
+ return get_int(arg->get.result, index);
+ case F_UNUSED:
+ return get_bool(arg->get.result, index == UNUSED);
+ case F_REGISTER_OFFSET:
+ return get_int(arg->get.result, var->vv.regoff);
+ case F_IS_IN_MEMORY:
+ return get_bool(arg->get.result, var->flags & INMEMORY);
+ }
+ case CLASS_SET_FIELD:
+ switch (arg->set.field) {
+ case F_TYPE:
+ return set_s4(&(var->type), arg->set.value);
+ case F_IS_LOCAL:
+ if (PyBool_Check(arg->set.value)) {
+ if (arg->set.value == Py_True) {
+ if (jd->localcount < (index + 1)) {
+ jd->localcount = (index + 1);
+ }
+ } else {
+ if (jd->localcount > (index)) {
+ jd->localcount = index;
+ }
+ }
+ return 0;
+ }
+ break;
+ case F_IS_SAVED:
+ if (PyBool_Check(arg->set.value)) {
+ if (arg->set.value == Py_True) {
+ var->flags |= SAVEDVAR;
+ } else {
+ var->flags &= ~SAVEDVAR;
+ }
+ return 0;
+ }
+ break;
+ case F_IS_PREALLOCATED:
+ if (arg->set.value == Py_True) {
+ var->flags |= PREALLOC;
+ return 0;
+ }
+ break;
+ case F_IS_INOUT:
+ if (arg->set.value == Py_True) {
+ var->flags &= ~PREALLOC;
+ var->flags |= INOUT;
+ return 0;
+ }
+ break;
+ case F_IS_TEMPORARY:
+ if (arg->set.value == Py_True) {
+ var->flags &= ~PREALLOC;
+ var->flags &= ~INOUT;
+ return 0;
+ }
+ break;
+ case F_REGISTER_OFFSET:
+ return set_s4(&(var->vv.regoff), arg->set.value);
+ case F_IS_IN_MEMORY:
+ return set_s4_flags(&(var->flags), INMEMORY, arg->set.value);
+ }
+ case CLASS_STR:
+ *arg->str.result = varinfo_str(jd, index, var);
+ return 0;
+
+ }
+ return -1;
+}
+
+int vars_grow(jitdata *jd, unsigned size) {
+ int newcount;
+ if (size > 16 * 1024) {
+ return 0;
+ }
+ if (size >= jd->varcount) {
+ newcount = 2 * jd->varcount;
+ if (size > newcount) {
+ newcount = size;
+ }
+ jd->var = DMREALLOC(jd->var, varinfo, jd->varcount, newcount);
+ MZERO(jd->var + jd->varcount, varinfo, (newcount - jd->varcount));
+ jd->varcount = newcount;
+ }
+ return 1;
+}
+
+ITERATOR_FUNC(vars_iter_func) {
+ jitdata *jd = (jitdata *)state->data;
+ void *vp;
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = jd->var;
+ return 0;
+ case ITERATOR_FORWARD:
+ state->pos = ((varinfo *)state->pos) + 1;
+ return 0;
+ case ITERATOR_END:
+ return state->pos == (jd->var + jd->vartop);
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, varinfo_func, state->root, state->pos);
+ case ITERATOR_LENGTH:
+ arg->length = jd->vartop;
+ return 0;
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(jd->vartop);
+ return get_obj(arg->subscript.result, varinfo_func,
+ state->root, jd->var + arg->subscript.index);
+ case ITERATOR_SETITEM:
+ ITERATOR_SETITEM_CHECK(jd->vartop);
+ vp = get_vp(arg->setitem.value, varinfo_func);
+ if (vp) {
+ jd->var[arg->setitem.index] = *(varinfo *)vp;
+ return 0;
+ }
+
+ }
+ return -1;
+}
+
+ITERATOR_FUNC(map_2_iter_func) {
+ int *arr = (int *)state->data;
+ switch (op) {
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(5);
+ return get_int(arg->subscript.result, arr[arg->subscript.index]);
+ case ITERATOR_LENGTH:
+ arg->length = 5;
+ return 0;
+ case ITERATOR_SETITEM:
+ ITERATOR_SETITEM_CHECK(5);
+ return set_s4(arr + arg->subscript.index, arg->setitem.value);
+ }
+ return -1;
+}
+
+ITERATOR_FUNC(local_map_iter_func) {
+ jitdata *jd = (jitdata *)state->data;
+ switch (op) {
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(jd->maxlocals);
+ return get_iter(arg->subscript.result, map_2_iter_func, state->root,
+ jd->local_map + (5 * arg->subscript.index));
+ }
+ return -1;
+}
+
+ITERATOR_FUNC(interface_map_iter_func) {
+ jitdata *jd = (jitdata *)state->data;
+ switch (op) {
+ case ITERATOR_SUBSCRIPT:
+ ITERATOR_SUBSCRIPT_CHECK(jd->maxinterfaces);
+ return get_iter(arg->subscript.result, map_2_iter_func, state->root,
+ jd->interface_map + (5 * arg->subscript.index));
+ }
+ return -1;
+}
+
+ITERATOR_FUNC(exception_entry_basic_blocks_iter_func) {
+ exception_entry *ee = (exception_entry *)state->data;
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = ee->start;
+ return 0;
+ case ITERATOR_FORWARD:
+ state->pos = ((basicblock *)state->pos)->next;
+ return 0;
+ case ITERATOR_END:
+ return state->pos == ee->end;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, basicblock_func, state->root, state->pos);
+ }
+ return -1;
+}
+
+CLASS_FUNC(exception_entry_func) {
+ exception_entry *ee = (exception_entry *)state->vp;
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_START:
+ return get_obj(arg->get.result, basicblock_func, state->root, ee->start);
+ case F_END:
+ return get_obj(arg->get.result, basicblock_func, state->root, ee->end);
+ case F_HANDLER:
+ return get_obj(arg->get.result, basicblock_func, state->root, ee->handler);
+ case F_BASIC_BLOCKS:
+ return get_iter(arg->get.result, exception_entry_basic_blocks_iter_func, state->root, ee);
+ }
+ break;
+ }
+ return -1;
+}
+
+ITERATOR_FUNC(exception_table_iter_func) {
+ jitdata *jd = (jitdata *)state->data;
+ switch (op) {
+ case ITERATOR_INIT:
+ state->pos = jd->exceptiontable;
+ return 0;
+ case ITERATOR_FORWARD:
+ state->pos = ((exception_entry *)state->pos)->down;
+ return 0;
+ case ITERATOR_END:
+ return state->pos == NULL;
+ case ITERATOR_GET:
+ return get_obj(arg->get.result, exception_entry_func, state->root, state->pos);
+ }
+ return -1;
+}
+
+CLASS_FUNC(jd_func) {
+ jitdata *jd = (jitdata *)state->vp;
+
+ switch (op) {
+ case CLASS_GET_FIELD:
+ switch (arg->get.field) {
+ case F_BASIC_BLOCKS:
+ return get_iter(arg->get.result, basicblocks_iter_func, state->root, jd);
+ case F_METHOD:
+ return get_obj(arg->get.result, methodinfo_func, state->root, jd->m);
+ case F_VARS:
+ return get_iter(arg->get.result, vars_iter_func, state->root, jd);
+ case F_LOCAL_MAP:
+ return get_iter(arg->get.result, local_map_iter_func, state->root, jd);
+ case F_INTERFACE_MAP:
+ return get_iter(arg->get.result, interface_map_iter_func, state->root, jd);
+ case F_EXCEPTION_TABLE:
+ return get_iter(arg->get.result, exception_table_iter_func, state->root, jd);
+ }
+ }
+
+ return -1;
+}
+
+void constants(PyObject *m) {
+ char buf[32];
+ char *pos;
+ int i;
+
+ /* icmds */
+
+ for (i = 0; i < sizeof(icmd_table) / sizeof(icmd_table[0]); ++i) {
+ snprintf(buf, sizeof(buf), "ICMD_%s", icmd_table[i].name);
+ pos = strchr(buf, ' ');
+ if (pos != NULL) {
+ *pos = '\0';
+ }
+ add_const(m, buf, i);
+ }
+
+# define c(x) add_const(m, #x, x)
+
+ /* types */
+
+ c(TYPE_INT);
+ c(TYPE_LNG);
+ c(TYPE_ADR);
+ c(TYPE_FLT);
+ c(TYPE_DBL);
+ c(TYPE_VOID);
+ c(UNUSED);
+
+ /* data flow */
+
+ c(DF_0_TO_0);
+ c(DF_1_TO_0);
+ c(DF_2_TO_0);
+ c(DF_3_TO_0);
+ c(DF_DST_BASE);
+ c(DF_0_TO_1);
+ c(DF_1_TO_1);
+ c(DF_2_TO_1);
+ c(DF_3_TO_1);
+ c(DF_N_TO_1);
+ c(DF_INVOKE);
+ c(DF_BUILTIN);
+ c(DF_COPY);
+ c(DF_MOVE);
+ c(DF_DUP);
+ c(DF_DUP_X1);
+ c(DF_DUP_X2);
+ c(DF_DUP2);
+ c(DF_DUP2_X1);
+ c(DF_DUP2_X2);
+ c(DF_SWAP);
+ c(DF_LOAD);
+ c(DF_STORE);
+ c(DF_IINC);
+ c(DF_POP);
+ c(DF_POP2);
+
+ /* control flow */
+
+ c(CF_NORMAL);
+ c(CF_IF);
+ c(CF_END_BASE);
+ c(CF_END);
+ c(CF_GOTO);
+ c(CF_TABLE);
+ c(CF_LOOKUP);
+ c(CF_JSR);
+ c(CF_RET);
+
+# undef c
+}
+
+/*
+ * Pythonpass
+ */
+
+void pythonpass_init() {
+ PyObject *m;
+
+ Py_Initialize();
+ PyEval_InitThreads();
+
+ if (PyType_Ready(&wrapper_type) < 0) return;
+ if (PyType_Ready(&iterator_type) < 0) return;
+ if (PyType_Ready(&method_type) < 0) return;
+
+ m = Py_InitModule3("cacao", NULL, NULL);
+ if (m != NULL) {
+ constants(m);
+ }
+
+#if defined(ENABLE_THREADS)
+ python_global_lock = NEW(java_object_t);
+ LOCK_INIT_OBJECT_LOCK(python_global_lock);
+#endif
+
+}
+
+void pythonpass_cleanup() {
+ Py_Finalize();
+}
+
+int pythonpass_run(jitdata *jd, const char *module, const char *function) {
+ PyObject *pymodname = NULL;
+ PyObject *pymod = NULL;
+ PyObject *pydict = NULL;
+ PyObject *pyfunc = NULL;
+ PyObject *pyargs = NULL;
+ PyObject *pyret = NULL;
+ PyObject *pyarg = NULL;
+ PyObject *objcache = NULL;
+ int success = 0;
+ root_state root;
+
+ LOCK_MONITOR_ENTER(python_global_lock);
+
+ pymodname = PyString_FromString(module);
+ pymod = PyImport_Import(pymodname);
+
+ root.jd = jd;
+ root.object_cache = objcache = PyDict_New();
+
+ if (pymod != NULL) {
+ pydict = PyModule_GetDict(pymod);
+ pyfunc = PyDict_GetItemString(pydict, function);
+ if (pyfunc != NULL && PyCallable_Check(pyfunc)) {
+ pyargs = PyTuple_New(1);
+
+ if (get_obj(&pyarg, jd_func, &root, jd) != -1) {
+ }
+
+ /* */
+
+ PyTuple_SetItem(pyargs, 0, pyarg);
+
+ pyret = PyObject_CallObject(pyfunc, pyargs);
+ if (pyret == NULL) {
+ PyErr_Print();
+ } else {
+ success = 1;
+ }
+ } else {
+ if (PyErr_Occurred())
+ PyErr_Print();
+ }
+ } else {
+ PyErr_Print();
+ }
+
+ Py_XDECREF(pymodname);
+ Py_XDECREF(pymod);
+ Py_XDECREF(pyargs);
+ Py_XDECREF(pyret);
+ Py_XDECREF(objcache);
+
+ LOCK_MONITOR_EXIT(python_global_lock);
+
+ return (success == 1 ? 1 : 0);
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/jit/python.h - Python pass
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+#ifndef _VM_JIT_PYTHON_H
+#define _VM_JIT_PYTHON_H
+#if defined(ENABLE_PYTHON)
+
+#include "vm/jit/jit.h"
+
+void pythonpass_init();
+void pythonpass_cleanup();
+int pythonpass_run(jitdata *jd, const char *module, const char *function);
+
+#endif
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
/* src/vm/jit/reg.h - register allocator header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
basicblock *retaddr;
} vv;
#if defined(ENABLE_VERIFIER)
- typeinfo typeinfo; /* type info for reference types */
+ typeinfo_t typeinfo; /* type info for reference types */
#endif
};
/* src/vm/jit/replace.c - on-stack replacement of methods
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
#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"
obj = calleeframe->instance.a;
vftbl = obj->vftbl;
- assert(vftbl->class->vftbl == vftbl);
+ assert(vftbl->clazz->vftbl == vftbl);
- DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->class); );
+ DOLOG_SHORT( printf("\tclass: "); class_println(vftbl->clazz); );
replace_patch_class(vftbl, calleem, oldentrypoint, entrypoint);
}
while (rp || sfi) {
- DOLOG( replace_executionstate_println(es); );
+ DOLOG( executionstate_println(es); );
/* if we are not at a replacement point, it is a native frame */
replace_push_activation_record(es, rp, prevframe, ss->frames);
- DOLOG( replace_executionstate_println(es); );
+ DOLOG( executionstate_println(es); );
}
rp = ss->frames->torp;
replace_write_executionstate(rp, es, ss, ss->frames->down == NULL);
- DOLOG( replace_executionstate_println(es); );
+ DOLOG( executionstate_println(es); );
if (rp->type == RPLPOINT_TYPE_CALL) {
parent = NULL;
stackframeinfo_t *sfi;
sourcestate_t *ss;
sourceframe_t *frame;
- s4 dumpsize;
codeinfo *origcode;
rplpoint *origrp;
#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
threadobject *thread;
#endif
+ int32_t dumpmarker;
origcode = es->code;
origrp = rp;
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
- /* get the stackframeinfo for the current thread */
+ /* Get the stackframeinfo for the current thread. */
- sfi = STACKFRAMEINFO;
+ sfi = threads_get_current_stackframeinfo();
/* recover source state */
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
}
if ((rp != NULL) && (rp->pc == pc) && (rp->flags & RPLPOINT_FLAG_ACTIVE)) {
+#if !defined(NDEBUG)
+ executionstate_sanity_check(context);
+#endif
+
/* set codeinfo pointer in execution state */
es.code = code;
/* read execution state from current context */
- md_replace_executionstate_read(&es, context);
+ md_executionstate_read(&es, context);
DOLOG( printf("REPLACEMENT READ: ");
- replace_executionstate_println(&es); );
+ executionstate_println(&es); );
/* do the actual replacement */
/* write execution state to current context */
- md_replace_executionstate_write(&es, context);
+ md_executionstate_write(&es, context);
DOLOG( printf("REPLACEMENT WRITE: ");
- replace_executionstate_println(&es); );
+ executionstate_println(&es); );
/* new code is entered after returning */
executionstate_t *es;
sourcestate_t *ss;
- /* get the stackframeinfo of this thread */
+ /* Get the stackframeinfo of this thread. */
+
assert(thread == THREADOBJECT);
- sfi = STACKFRAMEINFO;
+
+ sfi = threads_get_current_stackframeinfo();
/* create the execution state */
es = DNEW(executionstate_t);
#endif
-/* replace_executionstate_println **********************************************
-
- Print execution state
-
- IN:
- es...............the execution state to print
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void replace_executionstate_println(executionstate_t *es)
-{
- int i;
- int slots;
- stackslot_t *sp;
- int extraslots;
-
- if (!es) {
- printf("(executionstate_t *)NULL\n");
- return;
- }
-
- printf("executionstate_t:\n");
- printf("\tpc = %p",(void*)es->pc);
- printf(" sp = %p",(void*)es->sp);
- printf(" pv = %p\n",(void*)es->pv);
-#if defined(ENABLE_DISASSEMBLER)
- for (i=0; i<INT_REG_CNT; ++i) {
- if (i%4 == 0)
- printf("\t");
- else
- printf(" ");
-#if SIZEOF_VOID_P == 8
- printf("%-3s = %016llx",abi_registers_integer_name[i],(unsigned long long)es->intregs[i]);
-#else
- printf("%-3s = %08lx",abi_registers_integer_name[i],(unsigned long)es->intregs[i]);
-#endif
- if (i%4 == 3)
- printf("\n");
- }
- for (i=0; i<FLT_REG_CNT; ++i) {
- if (i%4 == 0)
- printf("\t");
- else
- printf(" ");
- printf("F%02d = %016llx",i,(unsigned long long)es->fltregs[i]);
- if (i%4 == 3)
- printf("\n");
- }
-# if defined(HAS_ADDRESS_REGISTER_FILE)
- for (i=0; i<ADR_REG_CNT; ++i) {
- if (i%4 == 0)
- printf("\t");
- else
- printf(" ");
- printf("A%02d = %016llx",i,(unsigned long long)es->adrregs[i]);
- if (i%4 == 3)
- printf("\n");
- }
-# endif
-#endif
-
- sp = (stackslot_t *) es->sp;
-
- extraslots = 2;
-
- if (es->code) {
- methoddesc *md = es->code->m->parseddesc;
- slots = es->code->stackframesize;
- extraslots = 1 + md->memuse;
- }
- else
- slots = 0;
-
-
- if (slots) {
- printf("\tstack slots(+%d) at sp:", extraslots);
- for (i=0; i<slots+extraslots; ++i) {
- 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");
- }
-
- printf("\tcode: %p", (void*)es->code);
- if (es->code != NULL) {
- printf(" stackframesize=%d ", es->code->stackframesize);
- method_print(es->code->m);
- }
- printf("\n");
-
- printf("\n");
-}
-#endif
-
#if !defined(NDEBUG)
static void java_value_print(s4 type, replace_val_t value)
{
if (type == TYPE_ADR && value.a != NULL) {
obj = value.a;
putchar(' ');
- utf_display_printable_ascii_classname(obj->vftbl->class->name);
+ utf_display_printable_ascii_classname(obj->vftbl->clazz->name);
- if (obj->vftbl->class == class_java_lang_String) {
+ if (obj->vftbl->clazz == class_java_lang_String) {
printf(" \"");
u = javastring_toutf(obj, false);
utf_display_printable_ascii(u);
if (REPLACE_IS_NATIVE_FRAME(frame)) {
printf("NATIVE (pc %p size %d) ",
- (void*)frame->nativepc, frame->nativeframesize);
+ (void*)frame->nativepc, frame->nativeframesize);
replace_stackframeinfo_println(frame->sfi);
continue;
}
}
#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
typedef struct rplalloc rplalloc;
typedef struct rplpoint rplpoint;
-typedef struct executionstate_t executionstate_t;
typedef struct sourcestate_t sourcestate_t;
typedef struct sourceframe_t sourceframe_t;
typedef union replace_val_t replace_val_t;
};
-/* An `executionsstate` represents the state of a thread as it reached */
-/* an replacement point or is about to enter one. */
-
-struct executionstate_t {
- u1 *pc; /* program counter */
- u1 *sp; /* stack pointer within method */
- u1 *pv; /* procedure value. NULL means */
- /* search the AVL tree */
-
- ptrint intregs[INT_REG_CNT]; /* register values */
- double fltregs[FLT_REG_CNT]; /* register values */
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- ptrint adrregs[ADR_REG_CNT]; /* register values */
-#endif
-
- codeinfo *code; /* codeinfo corresponding to the pv */
-};
-
-
+ u1 *ra; /* return address / link register */
struct sourceframe_t {
sourceframe_t *down; /* source frame down the call chain */
#if !defined(NDEBUG)
void replace_show_replacement_points(codeinfo *code);
void replace_replacement_point_println(rplpoint *rp, int depth);
-void replace_executionstate_println(executionstate_t *es);
void replace_sourcestate_println(sourcestate_t *ss);
void replace_sourcestate_println_short(sourcestate_t *ss);
void replace_source_frame_println(sourceframe_t *frame);
void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert);
#endif
-/* machine and OS dependent functions (code in ARCH_DIR/OS_DIR/md-os.c) */
-
-void md_replace_executionstate_read(executionstate_t *es, void *context);
-void md_replace_executionstate_write(executionstate_t *es, void *context);
-
#endif /* defined(ENABLE_REPLACEMENT) */
#endif /* _REPLACE_H */
## src/vm/jit/s390/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.
##
\
md-abi.c \
md-abi.h \
- md.c
+ md-trap.h \
+ md.c \
+ md.h
$(srcdir)/asmpart.S: $(top_builddir)/config.h
/* misc ***********************************************************************/
-/* #define HAS_4BYTE_STACKSLOT */
#define SUPPORT_COMBINE_INTEGER_REGISTERS
#define JIT_COMPILER_VIA_SIGNAL
la mptr, 2*4(s1) /* load method pointer */
l pv, 0(mptr) /* load procedure vector from method pointer */
basr ra, pv /* call method */
- lr sp, s1 /* restore stack pointer */
L_asm_vm_call_method_return:
+ lr sp, s1 /* restore stack pointer */
l s0, 0*4(sp) /* restore used callee saved registers */
l s1, 1*4(sp)
l %r12, 3*4(sp)
# undef FREGS
# undef OUT
-#if 0
-
-/* asm_abstractmethoderror *****************************************************
-
- Creates and throws an AbstractMethodError.
-
-*******************************************************************************/
-
-asm_abstractmethoderror:
- mov sp,a0 /* pass java sp */
- add $1*8,a0
- mov 0*8(sp),a1 /* pass exception address */
- sub $3,a1
- call exceptions_asm_new_abstractmethoderror@PLT
- /* exception pointer is return value */
- pop xpc /* get exception address */
- sub $3,xpc /* exception address is ra - 3 */
- jmp L_asm_handle_exception
-
-#endif
-
/* Offset table for PIC calls, see CALL_PIC */
L_offsets:
.long _GLOBAL_OFFSET_TABLE_ - L_offsets
L_offset_builtin_throw_exception:
.long builtin_throw_exception@PLTOFF
-L_offset_jit_asm_compile:
- .long jit_asm_compile@PLTOFF
-L_offset_exceptions_get_and_clear_exception:
- .long exceptions_get_and_clear_exception@PLTOFF
L_offset_md_handle_exception:
.long md_handle_exception@PLTOFF
/* src/vm/jit/s390/codegen.c - machine code generator 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 <stdint.h>
#include <stdio.h>
+#include "vm/jit/s390/arch.h"
+#include "vm/jit/s390/codegen.h"
+#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 "mm/memory.h"
-#if defined(ENABLE_THREADS)
-# include "threads/lock-common.h"
-# include "threads/native/lock.h"
-#endif
+#include "threads/lock-common.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
#include "vmcore/statistics.h"
+
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/types.h"
+#include "vm/stringlocal.h"
+#include "vm/vm.h"
+
#include "vm/jit/abi.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
-#include "vm/jit/s390/arch.h"
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/emit.h"
-#include "vm/jit/s390/md-abi.h"
#include "vm/jit/stacktrace.h"
-#include "vm/types.h"
-#include "vm/stringlocal.h"
-#include "vm/vm.h"
+#include "vm/jit/trap.h"
+
/* DO__LOG generates a call to do__log. No registers are destroyed,
* so you may use it anywhere. regs is an array containing all general
/* decide which monitor enter function to call */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_ALD_DSEG(REG_A0, disp);
}
else {
M_TEST(REG_A0);
M_BNE(SZ_BRC + SZ_ILL);
- M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ILL(TRAP_NullPointerException);
}
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
PROFILE_CYCLE_STOP;
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, 0);
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
PROFILE_CYCLE_START;
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
PROFILE_CYCLE_STOP;
- patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->class, disp);
+ patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, disp);
PROFILE_CYCLE_START;
}
}
}
if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
- ((patchref_t *)list_first_unsynced(jd->code->patchers))->disp = (cd->mcodeptr - ref);
+ ((patchref_t *)list_first(jd->code->patchers))->disp = (cd->mcodeptr - ref);
}
switch (fieldtype) {
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* Implicit null-pointer check */
/* src/vm/jit/s390/emit.c - s390 code emitter functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <assert.h>
#include <stdint.h>
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/emit.h"
+#include "vm/jit/s390/md-abi.h"
+
#include "mm/memory.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+
+#include "threads/lock-common.h"
+
#include "vm/builtin.h"
#include "vm/exceptions.h"
#include "vm/global.h"
+#include "vm/types.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
#include "vm/jit/trace.h"
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/emit.h"
-#include "vm/jit/s390/md-abi.h"
-#include "vm/types.h"
+#include "vm/jit/trap.h"
+
#include "vmcore/options.h"
+
/* emit_load *******************************************************************
Emits a possible load of an operand.
mcode = *((u2 *) cd->mcodeptr);
- M_ILL(EXCEPTION_HARDWARE_PATCHER);
+ M_ILL(TRAP_PATCHER);
return mcode;
}
}
}
-void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg) {
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(reg);
M_BNE(SZ_BRC + SZ_ILL);
- M_ILL(EXCEPTION_HARDWARE_ARITHMETIC);
+ M_ILL(TRAP_ArithmeticException);
}
}
*/
N_CL(s2, OFFSET(java_array_t, size), RN, s1);
M_BLT(SZ_BRC + SZ_ILL);
- M_ILL2(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_ILL2(s2, TRAP_ArrayIndexOutOfBoundsException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(REG_RESULT);
M_BNE(SZ_BRC + SZ_ILL);
- M_ILL(EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_ILL(TRAP_ArrayStoreException);
}
}
default:
vm_abort("emit_classcast_check: unknown condition %d", condition);
}
- M_ILL2(s1, EXCEPTION_HARDWARE_CLASSCAST);
+ M_ILL2(s1, TRAP_ClassCastException);
}
}
-void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg) {
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(reg);
M_BNE(SZ_BRC + SZ_ILL);
- M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ILL(TRAP_NullPointerException);
}
}
-void emit_exception_check(codegendata *cd, instruction *iptr) {
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(REG_RESULT);
M_BNE(SZ_BRC + SZ_ILL);
- M_ILL(EXCEPTION_HARDWARE_EXCEPTION);
+ M_ILL(TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
- M_ILL2(REG_METHODPTR, EXCEPTION_HARDWARE_COMPILER);
+ M_ILL2(REG_METHODPTR, TRAP_COMPILER);
}
/*
* Copyright (C) 1992, Linus Torvalds
*/
-#define __CS_LOOP(ptr, op_val, op_string) ({ \
- int old_val, new_val; \
- __asm__ __volatile__(" l %0,0(%3)\n" \
- "0: lr %1,%0\n" \
- op_string " %1,%4\n" \
- " cs %0,%1,0(%3)\n" \
- " jl 0b" \
- : "=&d" (old_val), "=&d" (new_val), \
- "=m" (*ptr) \
- : "a" (ptr), "d" (op_val), \
- "m" (*ptr) \
- : "cc", "memory" ); \
- new_val; \
-})
-
-static inline void
-atomic_add (volatile int *mem, int val)
-{
- __CS_LOOP(mem, val, "ar");
-}
-
static inline long
compare_and_swap (volatile long *p, long oldval, long newval)
{
/* TODO not sure if the following two can't be just empty. */
-#define MEMORY_BARRIER_BEFORE_ATOMIC() eieio()
#define MEMORY_BARRIER_AFTER_ATOMIC() eieio()
#endif
-/* src/vm/jit/x86_64/md-abi.c - functions for x86_64 Linux ABI
+/* src/vm/jit/s390/md-abi.c - s390 Linux ABI
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Christian Thalinger
-
- Changes:
-
*/
+
#include "config.h"
#include "vm/global.h"
+#include "vm/types.h"
+
#include "vm/jit/jit.h"
+#include "vm/jit/stack.h"
+
#include "vm/jit/s390/md-abi.h"
-#include "vm/types.h"
#include "vmcore/descriptor.h"
#include <assert.h>
+
/* register descripton array **************************************************/
s4 nregdescint[] = {
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t* stackslot)
{
methodinfo *m;
codeinfo *code;
--- /dev/null
+/* src/vm/jit/s390/md-trap.h - s390 hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (s390) we use illegal instructions as trap
+ * instructions.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 0
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+ TRAP_ClassCastException = 4,
+ TRAP_CHECK_EXCEPTION = 5,
+ TRAP_PATCHER = 6,
+ TRAP_COMPILER = 7
+};
+
+#endif /* _MD_TRAP_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:
+ */
/* src/vm/jit/s390/md.c - machine dependent s390 Linux 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
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/s390/md-abi.h"
-#if defined(ENABLE_THREADS)
-# include "threads/threads-common.h"
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/abi.h"
#include "vm/jit/methodheader.h"
+#include "vm/jit/methodtree.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
#include "vmcore/options.h" /* XXX debug */
#include "vm/jit/codegen-common.h"
#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/md.h"
/* prototypes *****************************************************************/
log_println("Program counter: 0x%08X", pc);
- pv = codegen_get_pv_from_pc_nocheck(pc);
+ pv = methodtree_find_nocheck(pc);
+
if (pv == NULL) {
log_println("No java method found at location.");
} else {
m = (*(codeinfo **)(pv + CodeinfoPointer))->m;
log_println(
"Java method: class %s, method %s, descriptor %s.",
- m->class->name->text, m->name->text, m->descriptor->text
+ m->clazz->name->text, m->name->text, m->descriptor->text
);
}
log_println("\tf%d\t0x%016llX\t(double)%e\t(float)%f", i, freg.l, freg.fr.d, freg.fr.f);
}
-#if defined(ENABLE_THREADS)
log_println("Dumping the current stacktrace:");
- threads_print_stacktrace();
-#endif
-
+ stacktrace_print_current();
}
/* md_signal_handler_sigsegv ***************************************************
pv = (u1 *)_mc->gregs[REG_PV] - N_PV_OFFSET;
sp = (u1 *)_mc->gregs[REG_SP];
ra = xpc;
- type = EXCEPTION_HARDWARE_NULLPOINTER;
+ type = TRAP_NullPointerException;
val = 0;
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
if (p != NULL) {
- _mc->gregs[REG_ITMP3_XPTR] = (intptr_t) p;
- _mc->gregs[REG_ITMP1_XPC] = (intptr_t) xpc;
- _mc->psw.addr = (intptr_t) asm_handle_exception;
+ _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) p;
+ _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) xpc;
+ _mc->psw.addr = (uintptr_t) asm_handle_exception;
}
else {
- _mc->psw.addr = (intptr_t) xpc;
+ _mc->psw.addr = (uintptr_t) xpc;
}
}
sp = (u1 *)_mc->gregs[REG_SP];
val = (ptrint)_mc->gregs[reg];
- if (EXCEPTION_HARDWARE_COMPILER == type) {
+ if (TRAP_COMPILER == type) {
/* The PV from the compiler stub is equal to the XPC. */
pv = xpc;
xpc = ra - 2;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- if (EXCEPTION_HARDWARE_COMPILER == type) {
+ if (TRAP_COMPILER == type) {
if (NULL == p) {
- _mc->gregs[REG_ITMP3_XPTR] = (intptr_t) builtin_retrieve_exception();
- _mc->gregs[REG_ITMP1_XPC] = (intptr_t) ra - 2;
- _mc->gregs[REG_PV] = (intptr_t) md_codegen_get_pv_from_pc(ra);
- _mc->psw.addr = (intptr_t) asm_handle_exception;
+ _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) builtin_retrieve_exception();
+ _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) ra - 2;
+ _mc->gregs[REG_PV] = (uintptr_t) md_codegen_get_pv_from_pc(ra);
+ _mc->psw.addr = (uintptr_t) asm_handle_exception;
} else {
- _mc->gregs[REG_PV] = (intptr_t) p;
- _mc->psw.addr = (intptr_t) p;
+ _mc->gregs[REG_PV] = (uintptr_t) p;
+ _mc->psw.addr = (uintptr_t) p;
}
} else {
if (p != NULL) {
- _mc->gregs[REG_ITMP3_XPTR] = (intptr_t) p;
- _mc->gregs[REG_ITMP1_XPC] = (intptr_t) xpc;
- _mc->psw.addr = (intptr_t) asm_handle_exception;
+ _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) p;
+ _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) xpc;
+ _mc->psw.addr = (uintptr_t) asm_handle_exception;
}
else {
- _mc->psw.addr = (intptr_t) xpc;
+ _mc->psw.addr = (uintptr_t) xpc;
}
}
} else {
sp = (u1 *)_mc->gregs[REG_SP];
ra = xpc;
- type = EXCEPTION_HARDWARE_ARITHMETIC;
+ type = TRAP_ArithmeticException;
val = 0;
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- _mc->gregs[REG_ITMP3_XPTR] = (intptr_t) p;
- _mc->gregs[REG_ITMP1_XPC] = (intptr_t) xpc;
- _mc->psw.addr = (intptr_t) asm_handle_exception;
+ _mc->gregs[REG_ITMP3_XPTR] = (uintptr_t) p;
+ _mc->gregs[REG_ITMP1_XPC] = (uintptr_t) xpc;
+ _mc->psw.addr = (uintptr_t) asm_handle_exception;
return;
}
++loops;
- pv = codegen_get_pv_from_pc(xpc);
+ pv = methodtree_find(xpc);
handler = exceptions_handle_exception((java_object_t *)xptr, xpc, pv, sp);
/* src/vm/jit/s390/md.h - machine dependent s390 Linux 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
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdint.h>
#include "vm/jit/codegen-common.h"
+#include "vm/jit/methodtree.h"
/* md_stacktrace_get_returnaddress *********************************************
/* md_codegen_get_pv_from_pc ***************************************************
- On this architecture just a wrapper function to
- codegen_get_pv_from_pc.
+ On this architecture just a wrapper function to methodtree_find.
*******************************************************************************/
/* Get the start address of the function which contains this
address from the method table. */
- pv = codegen_get_pv_from_pc(ra);
+ pv = methodtree_find(ra);
return pv;
}
/* src/vm/jit/s390/patcher.c - s390 code patching 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
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
PATCH_BACK_ORIGINAL_MCODE;
/* get interfacetable index */
idx = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr) * m->class->index);
+ sizeof(methodptr) * m->clazz->index);
ASSERT_VALID_IMM(idx);
/* get method offset */
off =
- (s4) (sizeof(methodptr) * (m - m->class->methods));
+ (s4) (sizeof(methodptr) * (m - m->clazz->methods));
ASSERT_VALID_DISP(off);
/* src/vm/jit/show.c - showing the intermediate representation
- 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 "vmcore/options.h"
#if defined(ENABLE_DEBUG_FILTER)
-# include <sys/types.h>
-# include <regex.h>
-# if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-# else
-# include "threads/none/threads.h"
-# endif
+# include <sys/types.h>
+# include <regex.h>
+# include "threads/thread.h"
#endif
+
/* global variables ***********************************************************/
#if defined(ENABLE_THREADS) && !defined(NDEBUG)
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: ");
- show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
+ if (bptr->javalocals)
+ show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
+ else
+ printf("null");
printf("\n");
}
int res;
char *method_name;
s4 len;
- s4 dumpsize;
+ int32_t dumpmarker;
/* compose full name of method */
len =
- utf_bytes(m->class->name) +
+ utf_bytes(m->clazz->name) +
1 +
utf_bytes(m->name) +
utf_bytes(m->descriptor) +
1;
- dumpsize = dump_size(); /* allocate memory */
+ DMARKER;
method_name = DMNEW(char, len);
- utf_cat_classname(method_name, m->class->name);
+ utf_cat_classname(method_name, m->clazz->name);
strcat(method_name, ".");
utf_cat(method_name, m->name);
utf_cat(method_name, m->descriptor);
/* release memory */
- dump_release(dumpsize);
-
+ DRELEASE;
}
#define STATE_IS_INITIAL() ((FILTERVERBOSECALLCTR[0] == 0) && (FILTERVERBOSECALLCTR[1] == 0))
## src/vm/jit/sparc64/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.
##
\
md-abi.c \
md-abi.h \
- md.c
+ md-trap.h \
+ md.c \
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
/* src/vm/jit/sparc64/codegen.c - machine code generator for Sparc
- 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.
/* get correct lock object */
if (m->flags & ACC_STATIC) {
- disp = dseg_add_address(cd, &m->class->object.header);
+ disp = dseg_add_address(cd, &m->clazz->object.header);
M_ALD(REG_OUT0, REG_PV, disp);
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
M_ALD(REG_ITMP3, REG_PV, disp);
M_BNEZ(REG_OUT0, 3);
disp = dseg_add_functionptr(cd, LOCK_monitor_enter);
M_ALD(REG_ITMP3, REG_PV, disp); /* branch delay */
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class))
- codegen_add_patch_ref(cd, PATCHER_clinit, fi->class, disp);
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz))
+ codegen_add_patch_ref(cd, PATCHER_clinit, fi->clazz, disp);
}
M_ALD(REG_ITMP1, REG_PV, disp);
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * lm->class->index;
+ sizeof(methodptr*) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(reg, 3);
M_NOP;
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_ARITHMETIC);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_ArithmeticException);
}
}
M_CMP(s2, REG_ITMP3);
M_XBULT(3);
M_NOP;
- M_ALD_INTERN(s2, REG_ZERO, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_ALD_INTERN(s2, REG_ZERO, TRAP_ArrayIndexOutOfBoundsException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(REG_RESULT_CALLER, 3);
M_NOP;
- M_ALD_INTERN(REG_RESULT_CALLER, REG_ZERO, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_ALD_INTERN(REG_RESULT_CALLER, REG_ZERO, TRAP_ArrayStoreException);
}
}
}
M_NOP;
- M_ALD_INTERN(s1, REG_ZERO, EXCEPTION_HARDWARE_CLASSCAST);
+ M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(reg, 3);
M_NOP;
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_NullPointerException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_BNEZ(REG_RESULT_CALLER, 3);
M_NOP;
- M_ALD_INTERN(REG_RESULT_CALLER, REG_ZERO, EXCEPTION_HARDWARE_EXCEPTION);
+ M_ALD_INTERN(REG_RESULT_CALLER, REG_ZERO, TRAP_CHECK_EXCEPTION);
}
}
/* Get machine code which is patched back in later. The
trap is 1 instruction word long. */
- mcode = *((u4 *) cd->mcodeptr);
+ mcode = *((uint32_t *) cd->mcodeptr);
- M_ALD_INTERN(REG_ZERO, REG_ZERO, EXCEPTION_HARDWARE_PATCHER);
+ M_ALD_INTERN(REG_ZERO, REG_ZERO, TRAP_PATCHER);
return mcode;
}
/* src/vm/jit/sparc64/linux/md-os.c - machine dependent SPARC Linux 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.
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
typedef struct sigcontext sigcontext;
/* flush register windows? */
- val = md_get_reg_from_context(ctx, d);
+ val = md_get_reg_from_context(ctx, d);
/* check for special-load */
type = (int) addr;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* set registers */
- ctx->sigc_regs.u_regs[REG_ITMP2_XPTR] = (intptr_t) p;
- ctx->sigc_regs.u_regs[REG_ITMP3_XPC] = (intptr_t) xpc;
- ctx->sigc_regs.tpc = (intptr_t) asm_handle_exception;
- ctx->sigc_regs.tnpc = (intptr_t) asm_handle_exception + 4;
+ ctx->sigc_regs.u_regs[REG_ITMP2_XPTR] = (uintptr_t) p;
+ ctx->sigc_regs.u_regs[REG_ITMP3_XPC] = (uintptr_t) xpc;
+ ctx->sigc_regs.tpc = (uintptr_t) asm_handle_exception;
+ ctx->sigc_regs.tnpc = (uintptr_t) asm_handle_exception + 4;
}
#include "toolbox/logging.h"
-/*
-static inline void
-__attribute__ ((unused))
-atomic_add (volatile int *mem, int val)
-{
- int temp;
-
- __asm__ __volatile__ (
- "1:\t"
- "ldl_l %1,%3\n\t"
- "addl %1,%2,%1\n\t"
- "stl_c %1,%0\n\t"
- "beq %1,1b\n\t"
- : "=m"(*mem), "=&r"(temp)
- : "r"(val), "m"(*mem));
-}
-*/
-
static inline long
__attribute__ ((unused))
compare_and_swap (volatile long *p, long oldval, long newval)
}
#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("wmb" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("mb" : : : "memory");
#define MEMORY_BARRIER() __asm__ __volatile__ ( \
"membar 0x0F" : : : "memory" );
/* src/vm/jit/sparc64/md-abi.c - functions for Sparc ABI
- 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.
#include "vm/global.h"
#include "vm/jit/abi.h"
+#include "vm/jit/stack.h"
#include "vmcore/descriptor.h"
#include "mm/memory.h"
#include <assert.h>
+
/* helper macros for allocation methods ***************************************/
#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t* stackslot)
{
/* XXX */
}
--- /dev/null
+/* src/vm/jit/sparc64/md-trap.h - SPARC64 hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (sparc64) the trap numbers are used as load
+ * displacements and thus must not be 4- or 8-byte aligned.
+ *
+ * NOTE: In trap_init() we have a check whether the offset of
+ * java_arrayheader.data[0] is greater than the largest displacement
+ * defined below. Otherwise normal array loads/stores could trigger
+ * an exception.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 1
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+
+ /* Don't use 4 (could be a normal load offset). */
+
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+
+ /* Don't use 8 (could be a normal load offset). */
+
+ TRAP_COMPILER = 9,
+ TRAP_END
+};
+
+#endif /* _MD_TRAP_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:
+ */
/* src/vm/jit/mips/patcher.c - SPARC code patching 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.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
/* patch the field value's address */
*((s4 *) (ra + 1 * 4)) |=
(s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->class->index) & 0x00001fff);
+ sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
/* patch method offset */
*((s4 *) (ra + 2 * 4)) |=
- (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
+ (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
/* synchronize instruction cache */
md_icacheflush(ra + 1 * 4, 2 * 4);
}
-else {
+ else {
/* patch interfacetable index */
*((s4 *) (sp + 3 * 8 + 4)) |=
(s4) ((OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr*) * m->class->index) & 0x00001fff);
+ sizeof(methodptr*) * m->clazz->index) & 0x00001fff);
/* patch method offset */
*((s4 *) (ra + 2 * 4)) |=
- (s4) ((sizeof(methodptr) * (m - m->class->methods)) & 0x00001fff);
+ (s4) ((sizeof(methodptr) * (m - m->clazz->methods)) & 0x00001fff);
/* synchronize instruction cache */
/* src/vm/jit/sparc64/solaris/md-os.c - machine dependent SPARC Solaris functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/stringlocal.h"
+
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
ptrint md_get_reg_from_context(mcontext_t *_mc, u4 rindex)
/* This is a normal NPE: addr must be NULL and the NPE-type
define is 0. */
- addr = md_get_reg_from_context(_mc, s1);
+ addr = md_get_reg_from_context(_mc, s1);
type = (int) addr;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
- /* set registers */
+ /* Set registers. */
- _mc->gregs[REG_G2] = (intptr_t) p; /* REG_ITMP2_XPTR */
- _mc->gregs[REG_G3] = (intptr_t) xpc; /* REG_ITMP3_XPC */
- _mc->gregs[REG_PC] = (intptr_t) asm_handle_exception;
- _mc->gregs[REG_nPC] = (intptr_t) asm_handle_exception + 4;
+ _mc->gregs[REG_G2] = (uintptr_t) p; /* REG_ITMP2_XPTR */
+ _mc->gregs[REG_G3] = (uintptr_t) xpc; /* REG_ITMP3_XPC */
+ _mc->gregs[REG_PC] = (uintptr_t) asm_handle_exception;
+ _mc->gregs[REG_nPC] = (uintptr_t) asm_handle_exception + 4;
}
/* src/vm/jit/stack.c - stack analysis
- 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.
struct stackdata_t {
basicblock *bptr; /* the current basic block being analysed */
- stackptr new; /* next free stackelement */
+ stackelement_t *new; /* next free stackelement */
s4 vartop; /* next free variable index */
s4 localcount; /* number of locals (at the start of var) */
s4 varcount; /* maximum number of variables expected */
bool repeat; /* if true, iterate the analysis again */
exception_entry **handlers; /* exception handlers for the current block */
exception_entry *extableend; /* points to the last exception entry */
- stackelement exstack; /* instack for exception handlers */
+ stackelement_t exstack; /* instack for exception handlers */
};
/* forward declarations *******************************************************/
static void stack_create_invars(stackdata_t *sd, basicblock *b,
- stackptr curstack, int stackdepth);
+ stackelement_t * curstack, int stackdepth);
static void stack_create_invars_from_outvars(stackdata_t *sd, basicblock *b);
#if defined(STACK_VERBOSE)
static void stack_verbose_block_enter(stackdata_t *sd, bool reanalyse);
static void stack_verbose_block_exit(stackdata_t *sd, bool superblockend);
static void stack_verbose_show_state(stackdata_t *sd, instruction *iptr,
- stackptr curstack);
+ stackelement_t * curstack);
#endif
*******************************************************************************/
static void stack_create_invars(stackdata_t *sd, basicblock *b,
- stackptr curstack, int stackdepth)
+ stackelement_t * curstack, int stackdepth)
{
- stackptr sp;
+ stackelement_t * sp;
int i;
int index;
varinfo *dv;
*******************************************************************************/
static basicblock * stack_check_invars(stackdata_t *sd, basicblock *b,
- stackptr curstack, int stackdepth)
+ stackelement_t * curstack, int stackdepth)
{
int i;
- stackptr sp;
+ stackelement_t * sp;
basicblock *orig;
bool separable;
varinfo *sv;
*******************************************************************************/
-static stackptr stack_create_instack(stackdata_t *sd)
+static stackelement_t * stack_create_instack(stackdata_t *sd)
{
- stackptr sp;
+ stackelement_t * sp;
int depth;
int index;
*******************************************************************************/
-static basicblock *stack_mark_reached(stackdata_t *sd, basicblock *b, stackptr curstack, int stackdepth)
+static basicblock *stack_mark_reached(stackdata_t *sd, basicblock *b, stackelement_t * curstack, int stackdepth)
{
assert(b != NULL);
assert(iptr->opc == ICMD_NOP);
iptr->opc = ICMD_GOTO;
iptr->dst.block = tbptr;
+#if defined(STACK_VERBOSE)
+ if (iptr->line == 0) printf("goto with line 0 in L%03d\n", sd->bptr->nr);
+#endif
if (tbptr->flags < BBFINISHED)
sd->repeat = true; /* XXX check if we really need to repeat */
*******************************************************************************/
-static void stack_change_to_tempvar(stackdata_t *sd, stackptr sp,
+static void stack_change_to_tempvar(stackdata_t *sd, stackelement_t * sp,
instruction *ilimit)
{
s4 newindex;
registerdata *rd;
stackdata_t sd;
int stackdepth;
- stackptr curstack; /* current stack top */
- stackptr copy;
+ stackelement_t *curstack; /* current stack top */
+ stackelement_t *copy;
int opcode; /* opcode of current instruction */
int i, varindex;
int javaindex;
basicblock *original;
exception_entry *ex;
- stackptr *last_store_boundary;
- stackptr coalescing_boundary;
+ stackelement_t **last_store_boundary;
+ stackelement_t *coalescing_boundary;
- stackptr src1, src2, src3, src4, dst1, dst2;
+ stackelement_t *src1, *src2, *src3, *src4, *dst1, *dst2;
branch_target_t *table;
lookup_target_t *lookup;
for (i = 0; i < m->maxstack * 5; i++)
jd->interface_map[i].flags = UNUSED;
- last_store_boundary = DMNEW(stackptr, m->maxlocals);
+ last_store_boundary = DMNEW(stackelement_t *, m->maxlocals);
/* initialize flags and invars (none) of first block */
case ICMD_IINC:
STATISTICS_STACKDEPTH_DISTRIBUTION(count_store_depth);
- last_store_boundary[iptr->s1.varindex] = sd.new;
+ javaindex = iptr->s1.varindex;
+ last_store_boundary[javaindex] = sd.new;
iptr->s1.varindex =
- jd->local_map[iptr->s1.varindex * 5 + TYPE_INT];
+ jd->local_map[javaindex * 5 + TYPE_INT];
copy = curstack;
i = stackdepth - 1;
while (copy) {
if ((copy->varkind == LOCALVAR) &&
- (copy->varnum == iptr->s1.varindex))
+ (jd->reverselocalmap[copy->varnum] == javaindex))
{
assert(IS_LOCALVAR(copy));
SET_TEMPVAR(copy);
i = stackdepth - 2;
while (copy) {
if ((copy->varkind == LOCALVAR) &&
- (copy->varnum == varindex))
+ (jd->reverselocalmap[copy->varnum] == javaindex))
{
- copy->varkind = TEMPVAR;
assert(IS_LOCALVAR(copy));
SET_TEMPVAR(copy);
}
copy = sd.new; /* most recent stackslot created + 1 */
while (--copy > curstack) {
- if (copy->varkind == LOCALVAR && copy->varnum == varindex)
+ if (copy->varkind == LOCALVAR && jd->reverselocalmap[copy->varnum] == javaindex)
goto assume_conflict;
}
/* revert the coalescing, if it has been done earlier */
assume_conflict:
if ((curstack->varkind == LOCALVAR)
- && (curstack->varnum == varindex))
+ && (jd->reverselocalmap[curstack->varnum] == javaindex))
{
assert(IS_LOCALVAR(curstack));
SET_TEMPVAR(curstack);
printf("\n");
}
-static void stack_verbose_show_state(stackdata_t *sd, instruction *iptr, stackptr curstack)
+static void stack_verbose_show_state(stackdata_t *sd, instruction *iptr, stackelement_t *curstack)
{
- stackptr sp;
+ stackelement_t *sp;
s4 i;
s4 depth;
varinfo *v;
- stackptr *stack;
+ stackelement_t **stack;
printf(" javalocals ");
show_javalocals_array(sd->jd, sd->javalocals, sd->maxlocals, SHOW_STACK);
i++;
depth = i;
- stack = MNEW(stackptr, depth);
+ stack = MNEW(stackelement_t *, depth);
for(sp = curstack; sp; sp = sp->prev)
stack[--i] = sp;
-/* vm/jit/stack.h - stack analysis header
+/* src/vm/jit/stack.h - stack analysis 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
- Edwin Steiner
-
*/
#ifndef _STACK_H
#define _STACK_H
+/* forward typedefs ***********************************************************/
+
+typedef struct stackelement_t stackelement_t;
+
+
#include "config.h"
+#include <stdint.h>
+
#include "vm/types.h"
#include "vm/exceptions.h"
#include "vm/global.h"
+
#include "vm/jit/jit.h"
#include "vm/jit/reg.h"
+/* stack element structure ****************************************************/
+
+/* flags */
+
+#define SAVEDVAR 1 /* variable has to survive method invocations */
+#define INMEMORY 2 /* variable stored in memory */
+#define SAVREG 4 /* allocated to a saved register */
+#define ARGREG 8 /* allocated to an arg register */
+#define PASSTHROUGH 32 /* stackslot was passed-through by an ICMD */
+#define PREALLOC 64 /* preallocated var like for ARGVARS. Used */
+ /* with the new var system */
+#define INOUT 128 /* variable is an invar or/and an outvar */
+
+#define IS_SAVEDVAR(x) ((x) & SAVEDVAR)
+#define IS_INMEMORY(x) ((x) & INMEMORY)
+
+
+/* variable kinds */
+
+#define UNDEFVAR 0 /* stack slot will become temp during regalloc*/
+#define TEMPVAR 1 /* stack slot is temp register */
+#define STACKVAR 2 /* stack slot is numbered stack slot */
+#define LOCALVAR 3 /* stack slot is local variable */
+#define ARGVAR 4 /* stack slot is argument variable */
+
+
+struct stackelement_t {
+ stackelement_t *prev; /* pointer to next element towards bottom */
+ instruction *creator; /* instruction that created this element */
+ s4 type; /* slot type of stack element */
+ s4 flags; /* flags (SAVED, INMEMORY) */
+ s4 varkind; /* kind of variable or register */
+ s4 varnum; /* number of variable */
+};
+
+
/* macros used internally by analyse_stack ************************************/
/*--------------------------------------------------*/
/* src/vm/jit/stacktrace.c - machine independent stacktrace system
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, 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/global.h" /* required here for native includes */
#include "native/jni.h"
#include "native/llni.h"
+
+#include "native/include/java_lang_Object.h"
#include "native/include/java_lang_Throwable.h"
#if defined(WITH_CLASSPATH_GNU)
+# include "native/include/gnu_classpath_Pointer.h"
# include "native/include/java_lang_VMThrowable.h"
#endif
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#else
-# include "threads/none/threads.h"
-#endif
+#include "threads/thread.h"
#include "toolbox/logging.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/methodheader.h"
+#include "vm/jit/methodtree.h"
#include "vmcore/class.h"
#include "vmcore/loader.h"
+#include "vmcore/method.h"
#include "vmcore/options.h"
/* global variables ***********************************************************/
-#if !defined(ENABLE_THREADS)
-stackframeinfo_t *_no_threads_stackframeinfo = NULL;
-#endif
CYCLES_STATS_DECLARE(stacktrace_overhead , 100, 1)
CYCLES_STATS_DECLARE(stacktrace_fillInStackTrace, 40, 5000)
void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc)
{
- stackframeinfo_t **psfi;
- codeinfo *code;
-#if !defined(__I386__) && !defined(__X86_64__) && !defined(__S390__) && !defined(__M68K__)
- bool isleafmethod;
-#endif
+ stackframeinfo_t *currentsfi;
+ codeinfo *code;
#if defined(ENABLE_JIT)
s4 framesize;
#endif
- /* get current stackframe info pointer */
+ /* Get current stackframe info. */
- psfi = &STACKFRAMEINFO;
+ currentsfi = threads_get_current_stackframeinfo();
/* sometimes we don't have pv handy (e.g. in asmpart.S:
L_asm_call_jit_compiler_exception or in the interpreter). */
if (pv == NULL) {
#if defined(ENABLE_INTRP)
if (opt_intrp)
- pv = codegen_get_pv_from_pc(ra);
+ pv = methodtree_find(ra);
else
#endif
{
code = code_get_codeinfo_for_pv(pv);
/* XXX */
-/* assert(m != NULL); */
+ /* assert(m != NULL); */
#if defined(ENABLE_JIT)
# if defined(ENABLE_INTRP)
ra = md_stacktrace_get_returnaddress(sp, framesize);
# else
- /* If the method is a non-leaf function, we need to get the return
- address from the stack. For leaf functions the return address
- is set correctly. This makes the assembler and the signal
- handler code simpler. */
-
- isleafmethod = *((s4 *) (pv + IsLeaf));
+ /* If the method is a non-leaf function, we need to get the
+ return address from the stack. For leaf functions the
+ return address is set correctly. This makes the assembler
+ and the signal handler code simpler. The code is NULL is
+ the asm_vm_call_method special case. */
- if (!isleafmethod) {
+ if ((code == NULL) || !code_is_leafmethod(code)) {
framesize = *((u4 *) (pv + FrameSize));
ra = md_stacktrace_get_returnaddress(sp, framesize);
/* Fill new stackframeinfo structure. */
- sfi->prev = *psfi;
+ sfi->prev = currentsfi;
sfi->code = code;
sfi->pv = pv;
sfi->sp = sp;
/* Store new stackframeinfo pointer. */
- *psfi = sfi;
+ threads_set_current_stackframeinfo(sfi);
/* set the native world flag for the current thread */
/* ATTENTION: This flag tells the GC how to treat this thread in case of
void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi)
{
- stackframeinfo_t **psfi;
-
- /* clear the native world flag for the current thread */
- /* ATTENTION: Clear this flag _before_ removing the stackframe info */
+ /* Clear the native world flag for the current thread. */
+ /* ATTENTION: Clear this flag _before_ removing the stackframe info. */
THREAD_NATIVEWORLD_EXIT;
- /* get current stackframe info pointer */
-
- psfi = &STACKFRAMEINFO;
-
#if !defined(NDEBUG)
if (opt_DebugStackFrameInfo) {
log_start();
}
#endif
- /* restore the old pointer */
+ /* Set previous stackframe info. */
- *psfi = sfi->prev;
+ threads_set_current_stackframeinfo(sfi->prev);
}
tmpsfi->prev = sfi->prev;
#if !defined(NDEBUG)
- /* Print current method information. */
-
- if (opt_DebugStackTrace) {
- log_println("[stacktrace start]");
- log_start();
- log_print("[stacktrace: method=%p, pv=%p, sp=%p, ra=%p, xpc=%p, method=",
- tmpsfi->code->m, tmpsfi->pv, tmpsfi->sp, tmpsfi->ra,
- tmpsfi->xpc);
- method_print(tmpsfi->code->m);
- log_print("]");
- log_finish();
- }
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace fill]");
#endif
}
#if defined(ENABLE_INTRP)
if (opt_intrp)
- pv = codegen_get_pv_from_pc(ra);
+ pv = methodtree_find(ra);
else
#endif
{
/* stacktrace_get **************************************************************
- Builds and returns a stacktrace from the current thread for and
- returns the stacktrace structure wrapped in a Java byte-array to
- not confuse the GC.
+ Builds and returns a stacktrace starting from the given stackframe
+ info and returns the stacktrace structure wrapped in a Java
+ byte-array to not confuse the GC.
+
+ IN:
+ sfi ... stackframe info to start stacktrace from
RETURN:
stacktrace as Java byte-array
*******************************************************************************/
-java_handle_bytearray_t *stacktrace_get(void)
+java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi)
{
- stackframeinfo_t *sfi;
stackframeinfo_t tmpsfi;
int depth;
java_handle_bytearray_t *ba;
skip_fillInStackTrace = true;
skip_init = true;
- /* Get the stacktrace depth of the current thread. */
-
- sfi = STACKFRAMEINFO;
-
depth = stacktrace_depth(sfi);
if (depth == 0)
/* For GNU Classpath we also need to skip
VMThrowable.fillInStackTrace(). */
- if ((m->class == class_java_lang_VMThrowable) &&
+ if ((m->clazz == class_java_lang_VMThrowable) &&
(m->name == utf_fillInStackTrace))
continue;
#endif
exception we are going to skipping them in stack trace. */
if (skip_init == true) {
- if (m->name == utf_init) {
-/* throwable->is_a(method->method_holder())) { */
+ if ((m->name == utf_init) &&
+ (class_issubclass(m->clazz, class_java_lang_Throwable))) {
continue;
}
else {
}
+/* stacktrace_get_current ******************************************************
+
+ Builds and returns a stacktrace from the current thread and returns
+ the stacktrace structure wrapped in a Java byte-array to not
+ confuse the GC.
+
+ RETURN:
+ stacktrace as Java byte-array
+
+*******************************************************************************/
+
+java_handle_bytearray_t *stacktrace_get_current(void)
+{
+ stackframeinfo_t *sfi;
+ java_handle_bytearray_t *ba;
+
+ sfi = threads_get_current_stackframeinfo();
+ ba = stacktrace_get(sfi);
+
+ return ba;
+}
+
+
+/* stacktrace_get_caller_class *************************************************
+
+ Get the class on the stack at the given depth. This function skips
+ various special classes or methods.
+
+ ARGUMENTS:
+ depth ... depth to get caller class of
+
+ RETURN:
+ caller class
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+classinfo *stacktrace_get_caller_class(int depth)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ methodinfo *m;
+ classinfo *c;
+ int i;
+
+#if !defined(NDEBUG)
+ if (opt_DebugStackTrace)
+ log_println("[stacktrace_get_caller_class]");
+#endif
+
+ /* Get the stackframeinfo of the current thread. */
+
+ sfi = threads_get_current_stackframeinfo();
+
+ /* Iterate over the whole stack until we reached the requested
+ depth. */
+
+ i = 0;
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+
+ m = tmpsfi.code->m;
+ c = m->clazz;
+
+ /* Skip builtin methods. */
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ continue;
+
+#if defined(WITH_CLASSPATH_SUN)
+ /* NOTE: See hotspot/src/share/vm/runtime/vframe.cpp
+ (vframeStreamCommon::security_get_caller_frame). */
+
+ /* This is java.lang.reflect.Method.invoke(), skip it. */
+
+ if (m == method_java_lang_reflect_Method_invoke)
+ continue;
+
+ /* This is an auxiliary frame, skip it. */
+
+ if (class_issubclass(c, class_sun_reflect_MagicAccessorImpl))
+ continue;
+#endif
+
+ /* We reached the requested depth. */
+
+ if (i >= depth)
+ return c;
+
+ i++;
+ }
+
+ return NULL;
+}
+#endif
+
+
/* stacktrace_first_nonnull_classloader ****************************************
Returns the first non-null (user-defined) classloader on the stack.
*******************************************************************************/
-classloader *stacktrace_first_nonnull_classloader(void)
+classloader_t *stacktrace_first_nonnull_classloader(void)
{
stackframeinfo_t *sfi;
stackframeinfo_t tmpsfi;
methodinfo *m;
- classloader *cl;
+ classloader_t *cl;
#if !defined(NDEBUG)
if (opt_DebugStackTrace)
/* Get the stackframeinfo of the current thread. */
- sfi = STACKFRAMEINFO;
+ sfi = threads_get_current_stackframeinfo();
/* Iterate over the whole stack. */
stacktrace_stackframeinfo_next(&tmpsfi)) {
m = tmpsfi.code->m;
- cl = class_get_classloader(m->class);
+ cl = class_get_classloader(m->clazz);
if (cl != NULL)
return cl;
log_println("[stacktrace_getClassContext]");
#endif
- sfi = STACKFRAMEINFO;
+ sfi = threads_get_current_stackframeinfo();
/* Get the depth of the current stack. */
/* Store the class in the array. */
- data[i] = (java_object_t *) m->class;
+ data[i] = (java_object_t *) m->clazz;
i++;
}
/* Get the stackframeinfo of the current thread. */
- sfi = STACKFRAMEINFO;
+ sfi = threads_get_current_stackframeinfo();
/* If the stackframeinfo is NULL then FindClass is called through
the Invocation Interface and we return NULL */
m = tmpsfi.code->m;
- if (m->class == class_java_security_PrivilegedAction) {
+ if (m->clazz == class_java_security_PrivilegedAction) {
CYCLES_STATS_END(stacktrace_getCurrentClass);
return NULL;
}
- if (m->class != NULL) {
+ if (m->clazz != NULL) {
CYCLES_STATS_END(stacktrace_getCurrentClass);
- return m->class;
+ return m->clazz;
}
}
/* Get the stackframeinfo of the current thread. */
- sfi = STACKFRAMEINFO;
+ sfi = threads_get_current_stackframeinfo();
/* Get the depth of the current stack. */
/* NOTE: We use a LLNI-macro here, because a classinfo is not
a handle. */
- LLNI_array_direct(classes, i) = (java_object_t *) m->class;
+ LLNI_array_direct(classes, i) = (java_object_t *) m->clazz;
/* Store the name in the array. */
#endif
+/* stacktrace_print_entry ****************************************************
+
+ Print line for a stacktrace entry.
+
+ ARGUMENTS:
+ m ............ methodinfo of the entry
+ linenumber ... linenumber of the entry
+
+*******************************************************************************/
+
+static void stacktrace_print_entry(methodinfo *m, int32_t linenumber)
+{
+ /* Sanity check. */
+
+ assert(m != NULL);
+
+ printf("\tat ");
+
+ if (m->flags & ACC_METHOD_BUILTIN)
+ printf("NULL");
+ else
+ utf_display_printable_ascii_classname(m->clazz->name);
+
+ printf(".");
+ utf_display_printable_ascii(m->name);
+ utf_display_printable_ascii(m->descriptor);
+
+ if (m->flags & ACC_NATIVE) {
+ puts("(Native Method)");
+ }
+ else {
+ if (m->flags & ACC_METHOD_BUILTIN) {
+ puts("(builtin)");
+ }
+ else {
+ printf("(");
+ utf_display_printable_ascii(m->clazz->sourcefile);
+ printf(":%d)\n", linenumber);
+ }
+ }
+
+ fflush(stdout);
+}
+
+
/* stacktrace_print ************************************************************
Print the given stacktrace with CACAO intern methods only (no Java
linenumber = linenumbertable_linenumber_for_pc(&m, ste->code, ste->pc);
- printf("\tat ");
- utf_display_printable_ascii_classname(m->class->name);
- printf(".");
- utf_display_printable_ascii(m->name);
- utf_display_printable_ascii(m->descriptor);
+ stacktrace_print_entry(m, linenumber);
+ }
+}
- if (m->flags & ACC_NATIVE) {
- puts("(Native Method)");
- }
- else {
- printf("(");
- utf_display_printable_ascii(m->class->sourcefile);
- printf(":%d)\n", linenumber);
- }
+
+/* stacktrace_print_current ****************************************************
+
+ Print the current stacktrace of the current thread.
+
+ NOTE: This function prints all frames of the stacktrace and does
+ not skip frames like stacktrace_get.
+
+*******************************************************************************/
+
+void stacktrace_print_current(void)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ codeinfo *code;
+ methodinfo *m;
+ int32_t linenumber;
+
+ sfi = threads_get_current_stackframeinfo();
+
+ if (sfi == NULL) {
+ puts("\t<<No stacktrace available>>");
+ fflush(stdout);
+ return;
}
- /* just to be sure */
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get the methodinfo. */
+
+ code = tmpsfi.code;
+ m = code->m;
- fflush(stdout);
+ /* Get the line number. */
+
+ linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+
+ stacktrace_print_entry(m, linenumber);
+ }
}
+/* stacktrace_print_of_thread **************************************************
+
+ Print the current stacktrace of the given thread.
+
+ ARGUMENTS:
+ t ... thread
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void stacktrace_print_of_thread(threadobject *t)
+{
+ stackframeinfo_t *sfi;
+ stackframeinfo_t tmpsfi;
+ codeinfo *code;
+ methodinfo *m;
+ int32_t linenumber;
+
+ /* Build a stacktrace for the passed thread. */
+
+ sfi = t->_stackframeinfo;
+
+ if (sfi == NULL) {
+ puts("\t<<No stacktrace available>>");
+ fflush(stdout);
+ return;
+ }
+
+ for (stacktrace_stackframeinfo_fill(&tmpsfi, sfi);
+ stacktrace_stackframeinfo_end_check(&tmpsfi) == false;
+ stacktrace_stackframeinfo_next(&tmpsfi)) {
+ /* Get the methodinfo. */
+
+ code = tmpsfi.code;
+ m = code->m;
+
+ /* Get the line number. */
+
+ linenumber = linenumbertable_linenumber_for_pc(&m, code, tmpsfi.xpc);
+
+ stacktrace_print_entry(m, linenumber);
+ }
+}
+#endif
+
+
/* stacktrace_print_exception **************************************************
Print the stacktrace of a given exception (more or less a wrapper
void stacktrace_print_exception(java_handle_t *h)
{
java_lang_Throwable *o;
+
#if defined(WITH_CLASSPATH_GNU)
java_lang_VMThrowable *vmt;
#endif
+
+ java_lang_Object *backtrace;
java_handle_bytearray_t *ba;
stacktrace_t *st;
#if defined(WITH_CLASSPATH_GNU)
LLNI_field_get_ref(o, vmState, vmt);
- LLNI_field_get_ref(vmt, vmData, ba);
+ LLNI_field_get_ref(vmt, vmdata, backtrace);
#elif defined(WITH_CLASSPATH_SUN) || defined(WITH_CLASSPATH_CLDC1_1)
- LLNI_field_get_ref(o, backtrace, ba);
+ LLNI_field_get_ref(o, backtrace, backtrace);
#else
# error unknown classpath configuration
#endif
+ ba = (java_handle_bytearray_t *) backtrace;
+
/* Sanity check. */
assert(ba != NULL);
/* src/vm/jit/stacktrace.h - header file for stacktrace generation
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "md-abi.h"
+#include "threads/thread.h"
+
#include "vm/global.h"
#include "vm/jit/code.h"
void stacktrace_stackframeinfo_add(stackframeinfo_t *sfi, u1 *pv, u1 *sp, u1 *ra, u1 *xpc);
void stacktrace_stackframeinfo_remove(stackframeinfo_t *sfi);
-java_handle_bytearray_t *stacktrace_get(void);
+java_handle_bytearray_t *stacktrace_get(stackframeinfo_t *sfi);
+java_handle_bytearray_t *stacktrace_get_current(void);
#if defined(ENABLE_JAVASE)
-classloader *stacktrace_first_nonnull_classloader(void);
+classinfo *stacktrace_get_caller_class(int depth);
+classloader_t *stacktrace_first_nonnull_classloader(void);
java_handle_objectarray_t *stacktrace_getClassContext(void);
classinfo *stacktrace_get_current_class(void);
java_handle_objectarray_t *stacktrace_get_stack(void);
#endif
void stacktrace_print(stacktrace_t *st);
+void stacktrace_print_current(void);
+
+#if defined(ENABLE_THREADS)
+void stacktrace_print_of_thread(threadobject *t);
+#endif
+
void stacktrace_print_exception(java_handle_t *h);
/* machine dependent functions (code in ARCH_DIR/md.c) */
/* src/vm/jit/trace.c - Functions for tracing from java code.
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "native/include/java_lang_String.h"
#include "native/include/java_lang_Throwable.h"
-#include "threads/threads-common.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
*******************************************************************************/
-static char *trace_java_call_print_argument(char *logtext, s4 *logtextlen,
- typedesc *paramtype, imm_union imu)
+static char *trace_java_call_print_argument(methodinfo *m, char *logtext, s4 *logtextlen, typedesc *paramtype, imm_union imu)
{
java_object_t *o;
classinfo *c;
sprintf(logtext + strlen(logtext), "0x%016lx", (ptrint) imu.l);
#endif
- /* cast to java.lang.Object */
+ /* Workaround for sun.misc.Unsafe methods. In the future
+ (exact GC) we should check if the address is on the GC
+ heap. */
+
+ if ((m->clazz != NULL) &&
+ (m->clazz->name == utf_new_char("sun/misc/Unsafe")))
+ break;
+
+ /* Cast to java.lang.Object. */
o = (java_object_t *) (ptrint) imu.l;
- /* check return argument for java.lang.Class or java.lang.String */
+ /* Check return argument for java.lang.Class or
+ java.lang.String. */
if (o != NULL) {
- if (o->vftbl->class == class_java_lang_String) {
+ if (o->vftbl->clazz == class_java_lang_String) {
/* get java.lang.String object and the length of the
string */
strcat(logtext, "\")");
}
else {
- if (o->vftbl->class == class_java_lang_Class) {
+ if (o->vftbl->clazz == class_java_lang_Class) {
/* if the object returned is a java.lang.Class
cast it to classinfo structure and get the name
of the class */
/* if the object returned is not a java.lang.String or
a java.lang.Class just print the name of the class */
- u = o->vftbl->class->name;
+ u = o->vftbl->clazz->name;
}
len = strlen(" (Class = \"") + utf_bytes(u) + strlen("\")");
imm_union arg;
char *logtext;
s4 logtextlen;
- s4 dumpsize;
s4 i;
s4 pos;
+ int32_t dumpmarker;
+
+ /* We don't trace builtin functions here because the argument
+ passing happens via the native ABI and does not fit these
+ functions. */
+
+ if (method_is_builtin(m))
+ return;
#if defined(ENABLE_DEBUG_FILTER)
if (!show_filters_test_verbosecall_enter(m))
strlen("-2147483647-") + /* INT_MAX should be sufficient */
TRACEJAVACALLINDENT +
strlen("called: ") +
- ((m->class == NULL) ? strlen("NULL") : utf_bytes(m->class->name)) +
+ ((m->clazz == NULL) ? strlen("NULL") : utf_bytes(m->clazz->name)) +
strlen(".") +
utf_bytes(m->name) +
utf_bytes(m->descriptor);
/* allocate memory */
- dumpsize = dump_size();
+ DMARKER;
logtext = DMNEW(char, logtextlen);
strcpy(logtext + pos, "called: ");
- if (m->class != NULL)
- utf_cat_classname(logtext, m->class->name);
+ if (m->clazz != NULL)
+ utf_cat_classname(logtext, m->clazz->name);
else
strcat(logtext, "NULL");
strcat(logtext, ".");
if (m->flags & ACC_NATIVE) strcat(logtext, " NATIVE");
if (m->flags & ACC_INTERFACE) strcat(logtext, " INTERFACE");
if (m->flags & ACC_ABSTRACT) strcat(logtext, " ABSTRACT");
- if (m->flags & ACC_METHOD_BUILTIN) strcat(logtext, " METHOD_BUILTIN");
strcat(logtext, "(");
for (i = 0; i < md->paramcount; ++i) {
arg = argument_jitarray_load(md, i, arg_regs, stack);
- logtext = trace_java_call_print_argument(
- logtext, &logtextlen, &md->paramtypes[i], arg
- );
+ logtext = trace_java_call_print_argument(m, logtext, &logtextlen,
+ &md->paramtypes[i], arg);
if (i != (md->paramcount - 1)) {
strcat(logtext, ", ");
}
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
TRACEJAVACALLINDENT++;
methoddesc *md;
char *logtext;
s4 logtextlen;
- s4 dumpsize;
s4 i;
s4 pos;
imm_union val;
+ int32_t dumpmarker;
+
+ /* We don't trace builtin functions here because the argument
+ passing happens via the native ABI and does not fit these
+ functions. */
+
+ if (method_is_builtin(m))
+ return;
#if defined(ENABLE_DEBUG_FILTER)
if (!show_filters_test_verbosecall_exit(m))
strlen("-2147483647-") + /* INT_MAX should be sufficient */
TRACEJAVACALLINDENT +
strlen("finished: ") +
- ((m->class == NULL) ? strlen("NULL") : utf_bytes(m->class->name)) +
+ ((m->clazz == NULL) ? strlen("NULL") : utf_bytes(m->clazz->name)) +
strlen(".") +
utf_bytes(m->name) +
utf_bytes(m->descriptor) +
/* allocate memory */
- dumpsize = dump_size();
+ DMARKER;
logtext = DMNEW(char, logtextlen);
logtext[pos++] = '\t';
strcpy(logtext + pos, "finished: ");
- if (m->class != NULL)
- utf_cat_classname(logtext, m->class->name);
+ if (m->clazz != NULL)
+ utf_cat_classname(logtext, m->clazz->name);
else
strcat(logtext, "NULL");
strcat(logtext, ".");
val = argument_jitreturn_load(md, return_regs);
logtext =
- trace_java_call_print_argument(logtext, &logtextlen, &md->returntype, val);
+ trace_java_call_print_argument(m, logtext, &logtextlen,
+ &md->returntype, val);
}
log_text(logtext);
/* release memory */
- dump_release(dumpsize);
-
+ DRELEASE;
}
{
char *logtext;
s4 logtextlen;
- s4 dumpsize;
codeinfo *code;
+ int32_t dumpmarker;
/* calculate message length */
if (xptr) {
logtextlen =
- strlen("Exception ") + utf_bytes(xptr->vftbl->class->name);
+ strlen("Exception ") + utf_bytes(xptr->vftbl->clazz->name);
}
else {
logtextlen = strlen("Some Throwable");
if (m) {
logtextlen +=
- utf_bytes(m->class->name) +
+ utf_bytes(m->clazz->name) +
strlen(".") +
utf_bytes(m->name) +
utf_bytes(m->descriptor) +
logtextlen += strlen(")(0x12345678) at position 0x12345678 (");
#endif
- if (m->class->sourcefile == NULL)
+ if (m->clazz->sourcefile == NULL)
logtextlen += strlen("<NO CLASSFILE INFORMATION>");
else
- logtextlen += utf_bytes(m->class->sourcefile);
+ logtextlen += utf_bytes(m->clazz->sourcefile);
logtextlen += strlen(":65536)");
/* allocate memory */
- dumpsize = dump_size();
+ DMARKER;
logtext = DMNEW(char, logtextlen);
if (xptr) {
strcpy(logtext, "Exception ");
- utf_cat_classname(logtext, xptr->vftbl->class->name);
+ utf_cat_classname(logtext, xptr->vftbl->clazz->name);
} else {
strcpy(logtext, "Some Throwable");
strcat(logtext, " thrown in ");
if (m) {
- utf_cat_classname(logtext, m->class->name);
+ utf_cat_classname(logtext, m->clazz->name);
strcat(logtext, ".");
utf_cat(logtext, m->name);
utf_cat(logtext, m->descriptor);
(ptrint) code->entrypoint, (ptrint) pos);
#endif
- if (m->class->sourcefile == NULL)
+ if (m->clazz->sourcefile == NULL)
strcat(logtext, "<NO CLASSFILE INFORMATION>");
else
- utf_cat(logtext, m->class->sourcefile);
+ utf_cat(logtext, m->clazz->sourcefile);
sprintf(logtext + strlen(logtext), ":%d)", 0);
}
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
}
java_lang_String *s;
char *logtext;
s4 logtextlen;
- s4 dumpsize;
+ int32_t dumpmarker;
t = (java_lang_Throwable *) xptr;
if (t) {
logtextlen +=
- utf_bytes(xptr->vftbl->class->name);
+ utf_bytes(xptr->vftbl->clazz->name);
if (s) {
logtextlen += strlen(": ") +
u2_utflength(LLNI_field_direct(s, value)->data
/* allocate memory */
- dumpsize = dump_size();
+ DMARKER;
logtext = DMNEW(char, logtextlen);
strcpy(logtext, "Builtin exception thrown: ");
if (t) {
- utf_cat_classname(logtext, xptr->vftbl->class->name);
+ utf_cat_classname(logtext, xptr->vftbl->clazz->name);
if (s) {
char *buf;
/* release memory */
- dump_release(dumpsize);
+ DRELEASE;
}
--- /dev/null
+/* src/vm/jit/trap.c - hardware traps
+
+ 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 machine dependent trap stuff. */
+
+#include "md-trap.h"
+
+#include "native/llni.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/exceptions.h"
+#include "vm/vm.h"
+
+#include "vm/jit/code.h"
+#include "vm/jit/disass.h"
+#include "vm/jit/jit.h"
+#include "vm/jit/methodtree.h"
+#include "vm/jit/patcher-common.h"
+#include "vm/jit/replace.h"
+#include "vm/jit/stacktrace.h"
+
+#include "vmcore/options.h"
+#include "vmcore/system.h"
+
+
+/**
+ * Mmap the first memory page to support hardware exceptions and check
+ * the maximum hardware trap displacement on the architectures where
+ * it is required (TRAP_INSTRUCTION_IS_LOAD defined to 1).
+ */
+void trap_init(void)
+{
+#if !(defined(__ARM__) && defined(__LINUX__))
+ /* On arm-linux the first memory page can't be mmap'ed, as it
+ contains the exception vectors. */
+
+ int pagesize;
+
+ /* mmap a memory page at address 0x0, so our hardware-exceptions
+ work. */
+
+ pagesize = system_getpagesize();
+
+ (void) system_mmap_anonymous(NULL, pagesize, PROT_NONE, MAP_PRIVATE | MAP_FIXED);
+#endif
+
+ TRACESUBSYSTEMINITIALIZATION("trap_init");
+
+#if !defined(TRAP_INSTRUCTION_IS_LOAD)
+# error TRAP_INSTRUCTION_IS_LOAD is not defined in your md-trap.h
+#endif
+
+#if TRAP_INSTRUCTION_IS_LOAD == 1
+ /* Check if we get into trouble with our hardware-exceptions. */
+
+ if (TRAP_END > OFFSET(java_bytearray_t, data))
+ vm_abort("trap_init: maximum hardware trap displacement is greater than the array-data offset: %d > %d", TRAP_END, OFFSET(java_bytearray_t, data));
+#endif
+}
+
+
+/**
+ * Handles the signal which is generated by trap instructions, caught
+ * by a signal handler and calls the correct function.
+ *
+ * @param type trap number
+ * @param
+ */
+void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context)
+{
+ stackframeinfo_t sfi;
+ int32_t index;
+ java_handle_t *o;
+ methodinfo *m;
+ java_handle_t *p;
+
+#if !defined(NDEBUG)
+ if (opt_TraceTraps)
+ log_println("[signal_handle: trap %d]", type);
+#endif
+
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_signl_type(type);
+#endif
+
+ /* Prevent compiler warnings. */
+
+ o = NULL;
+ m = NULL;
+
+ /* wrap the value into a handle if it is a reference */
+ /* BEFORE: creating stackframeinfo */
+
+ switch (type) {
+ case TRAP_ClassCastException:
+ o = LLNI_WRAP((java_object_t *) val);
+ break;
+
+ case TRAP_COMPILER:
+ /* In this case the passed PV points to the compiler stub. We
+ get the methodinfo pointer here and set PV to NULL so
+ stacktrace_stackframeinfo_add determines the PV for the
+ parent Java method. */
+
+ m = code_get_methodinfo_for_pv(pv);
+ pv = NULL;
+ break;
+
+ default:
+ /* do nothing */
+ break;
+ }
+
+ /* Fill and add a stackframeinfo. */
+
+ stacktrace_stackframeinfo_add(&sfi, pv, sp, ra, xpc);
+
+ switch (type) {
+ case TRAP_NullPointerException:
+ p = exceptions_new_nullpointerexception();
+ break;
+
+ case TRAP_ArithmeticException:
+ p = exceptions_new_arithmeticexception();
+ break;
+
+ case TRAP_ArrayIndexOutOfBoundsException:
+ index = (s4) val;
+ p = exceptions_new_arrayindexoutofboundsexception(index);
+ break;
+
+ case TRAP_ArrayStoreException:
+ p = exceptions_new_arraystoreexception();
+ break;
+
+ case TRAP_ClassCastException:
+ p = exceptions_new_classcastexception(o);
+ break;
+
+ case TRAP_CHECK_EXCEPTION:
+ p = exceptions_fillinstacktrace();
+ break;
+
+ case TRAP_PATCHER:
+#if defined(ENABLE_REPLACEMENT)
+ if (replace_me_wrapper(xpc, context)) {
+ p = NULL;
+ break;
+ }
+#endif
+ p = patcher_handler(xpc);
+ break;
+
+ case TRAP_COMPILER:
+ p = jit_compile_handle(m, sfi.pv, ra, (void *) val);
+ break;
+
+ default:
+ /* Let's try to get a backtrace. */
+
+ (void) methodtree_find(xpc);
+
+ /* If that does not work, print more debug info. */
+
+ log_println("signal_handle: unknown hardware exception type %d", type);
+
+#if SIZEOF_VOID_P == 8
+ log_println("PC=0x%016lx", xpc);
+#else
+ log_println("PC=0x%08x", xpc);
+#endif
+
+#if defined(ENABLE_DISASSEMBLER)
+ log_println("machine instruction at PC:");
+ disassinstr(xpc);
+#endif
+
+ vm_abort("Exiting...");
+
+ /* keep compiler happy */
+
+ p = NULL;
+ }
+
+ /* Remove stackframeinfo. */
+
+ stacktrace_stackframeinfo_remove(&sfi);
+
+ /* unwrap and return the exception object */
+ /* AFTER: removing stackframeinfo */
+
+ if (type == TRAP_COMPILER)
+ return p;
+ else
+ return LLNI_UNWRAP(p);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of 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/trap.h - hardware traps
+
+ 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 _TRAP_H
+#define _TRAP_H
+
+#include "config.h"
+
+#include <stdint.h>
+
+/* Include machine dependent trap stuff. */
+
+#include "md-trap.h"
+
+
+/* function prototypes ********************************************************/
+
+void trap_init(void);
+void* trap_handle(int type, intptr_t val, void *pv, void *sp, void *ra, void *xpc, void *context);
+
+#endif /* _TRAP_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:
+ */
METHOD,
/* XXX make this more efficient, use class_java_lang_Throwable
* directly */
- class_get_classref(METHOD->class,utf_java_lang_Throwable),
+ class_get_classref(METHOD->clazz,utf_java_lang_Throwable),
&OP1->typeinfo);
IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
}
return_tail:
TYPECHECK_COUNT(stat_ins_primitive_return);
- if (STATE->initmethod && METHOD->class != class_java_lang_Object) {
+ if (STATE->initmethod && METHOD->clazz != class_java_lang_Object) {
/* Check if the 'this' instance has been initialized. */
LOG("Checking <init> marker");
#if defined(TYPECHECK_VARIABLESBASED)
/* src/vm/jit/verify/typecheck-builtins.inc - type checking for ICMD_BUILTIN
- 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.
s4 i;
#endif
#if defined(TYPECHECK_STACKBASED)
- typedescriptor *av;
+ typedescriptor_t *av;
#endif
/* verify a generic builtin call */
/* src/vm/jit/verify/typecheck-common.c - shared verifier code
- 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: Edwin Steiner
-
- Changes:
-
*/
if (state->initmethod && newthis)
TYPEINFO_INIT_NEWOBJECT(v->typeinfo, NULL);
else
- typeinfo_init_classinfo(&(v->typeinfo), state->m->class);
+ typeinfo_init_classinfo(&(v->typeinfo), state->m->clazz);
}
skip = 1;
/* src/vm/jit/verify/typecheck-common.h - internal header for the type checker
- 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: Edwin Steiner
-
- Changes:
-
*/
bool active; /* true if this sub is currently active */
char *blockflags; /* saved block flags when JSR was traversed */
char *usedlocals; /* != 0 for each local used in this sub */
- typedescriptor *retlocals; /* locals on the RET edge */
- typedescriptor *retstack; /* stack on the RET edge */
+ typedescriptor_t *retlocals; /* locals on the RET edge */
+ typedescriptor_t *retstack; /* stack on the RET edge */
s4 retdepth; /* stack depth on the RET edge */
};
s4 numlocals; /* number of local variables */
s4 validlocals; /* number of Java-accessible locals */
- s4 *reverselocalmap;
- typedescriptor returntype; /* return type of the current method */
+ typedescriptor_t returntype; /* return type of the current method */
s4 *savedindices;
s4 *savedinvars; /* saved invar pointer */
/* the following fields are used by the stackbased verifier only: */
- typedescriptor *locals; /* current local variables */
- typedescriptor *startlocals; /* locals at the start of each block */
- typedescriptor *startstack; /* stack at the start of each block */
- s4 *indepth; /* stack depth at --''-- */
- typedescriptor *stackceiling; /* upper edge of verifier stack */
+ typedescriptor_t *locals; /* current local variables */
+ typedescriptor_t *startlocals;/* locals at the start of each block */
+ typedescriptor_t *startstack; /* stack at the start of each block */
+ s4 *indepth; /* stack depth at --''-- */
+ typedescriptor_t *stackceiling; /* upper edge of verifier stack */
typecheck_jsr_t *topjsr; /* most recently called subroutine */
typecheck_jsr_t **jsrinfos; /* subroutine info for each block */
/* src/vm/jit/verify/typecheck-fields.inc - type checking for field ICMDs
- 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: Edwin Steiner
-
- Changes:
-
*/
{
unresolved_field *uf;
constant_FMIref *fieldref;
- typeinfo *instanceti;
- typeinfo *valueti;
+ typeinfo_t *instanceti;
+ typeinfo_t *valueti;
#if !defined(TYPECHECK_TYPEINFERER)
resolve_result_t result;
#endif
fi = fieldref->p.field;
result = resolve_field_verifier_checks(
- state->m, fieldref, fi->class, fi,
+ state->m, fieldref, fi->clazz, fi,
instanceti, valueti,
(instance == NULL),
(value != NULL));
if (result != resolveSucceeded) {
if (!uf) {
- uf = resolve_create_unresolved_field(state->m->class,
+ uf = resolve_create_unresolved_field(state->m->clazz,
state->m, state->iptr);
if (!uf)
EXCEPTION;
/* record the subtype constraints for this field access */
if (!resolve_constrain_unresolved_field(
- uf, state->m->class, state->m,
+ uf, state->m->clazz, state->m,
instanceti, valueti))
EXCEPTION; /* XXX maybe wrap exception? */
TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) &&
- !state->iptr->sx.s23.s3.fmiref->p.field->class->initialized,
+ !state->iptr->sx.s23.s3.fmiref->p.field->clazz->initialized,
stat_ins_field_uninitialized);
}
#endif /* !defined(TYPECHECK_TYPEINFERER) */
if (value == NULL) {
#if defined(TYPECHECK_STACKBASED)
- typedescriptor *dv;
+ typedescriptor_t *dv;
if (IS_2_WORD_TYPE(fieldref->parseddesc.fd->type)) {
CHECK_STACK_SPACE(2);
/* src/vm/jit/verify/typecheck-invoke.inc - type checking for invocations
- 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: Edwin Steiner
-
-
*/
s4 argindex; /* argument variable index */
varinfo *av; /* argument variable */
#else
- typedescriptor *av; /* argument stack slot */
+ typedescriptor_t *av; /* argument stack slot */
#endif
int i; /* counter */
resolve_result_t result;
if (IS_FMIREF_RESOLVED(mref)) {
mi = mref->p.method;
- mclassname = mi->class->name;
+ mclassname = mi->clazz->name;
}
else {
mi = NULL;
if (ins)
initclass = ins[-1].sx.val.c;
else
- initclass.cls = state->m->class;
+ initclass.cls = state->m->clazz;
LOGSTR("\t\tclass: "); LOGNAME(initclass); LOGNL;
}
}
/* the current class is linked, so must be its superclass. thus we can be */
/* sure that resolving will be trivial. */
if (mi) {
- cls = mi->class;
+ cls = mi->clazz;
}
else {
if (!resolve_classref(state->m,mref->p.classref,resolveLazy,false,true,&cls))
/* if lazy resolving did not succeed, it's not one of the allowed classes */
/* otherwise we check it directly */
- if (cls == NULL || (cls != state->m->class && cls != state->m->class->super)) {
+ if (cls == NULL || (cls != state->m->clazz && cls != state->m->clazz->super)) {
TYPECHECK_VERIFYERROR_bool("<init> calling <init> of the wrong class");
}
/* impose loading constraints */
if (result == resolveSucceeded) {
- /* XXX state->m->class may have to be wrong when inlining */
- if (!resolve_method_loading_constraints(state->m->class, mi))
+ /* XXX state->m->clazz may have to be wrong when inlining */
+ if (!resolve_method_loading_constraints(state->m->clazz, mi))
return false;
}
/* resolution must be deferred */
if (!um) {
- um = resolve_create_unresolved_method(state->m->class, state->m,
+ um = resolve_create_unresolved_method(state->m->clazz, state->m,
mref,
invokestatic,
invokespecial);
GENERATED /* may use stack[1] ... stack[1] */
GENERATED
GENERATED
-# line 349 "src/vm/jit/verify/icmds.c"
+# line 347 "src/vm/jit/verify/icmds.c"
GENERATED if (IPTR->flags.bits & INS_FLAG_CLASS) {
GENERATED /* a java.lang.Class reference */
GENERATED TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
GENERATED /* may use stack[1] ... stack[1] */
GENERATED
GENERATED
-# line 93 "src/vm/jit/verify/icmds.c"
+# line 91 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_aload);
GENERATED
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 260 "src/vm/jit/verify/icmds.c"
+# line 258 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 270 "src/vm/jit/verify/icmds.c"
+# line 268 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 255 "src/vm/jit/verify/icmds.c"
+# line 253 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 250 "src/vm/jit/verify/icmds.c"
+# line 248 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 115 "src/vm/jit/verify/icmds.c"
+# line 113 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 239 "src/vm/jit/verify/icmds.c"
+# line 237 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
GENERATED && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 245 "src/vm/jit/verify/icmds.c"
+# line 243 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 265 "src/vm/jit/verify/icmds.c"
+# line 263 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 108 "src/vm/jit/verify/icmds.c"
+# line 106 "src/vm/jit/verify/icmds.c"
GENERATED TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
GENERATED
# line 479 "src/vm/jit/verify/typecheck-stackbased-gen.inc"
GENERATED /* may use stack[-2] ... stack[0] */
GENERATED
GENERATED
-# line 296 "src/vm/jit/verify/icmds.c"
+# line 294 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-3] ... stack[0] */
GENERATED
GENERATED
-# line 306 "src/vm/jit/verify/icmds.c"
+# line 304 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-2] ... stack[0] */
GENERATED
GENERATED
-# line 291 "src/vm/jit/verify/icmds.c"
+# line 289 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-3] ... stack[0] */
GENERATED
GENERATED
-# line 286 "src/vm/jit/verify/icmds.c"
+# line 284 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-2] ... stack[0] */
GENERATED
GENERATED
-# line 311 "src/vm/jit/verify/icmds.c"
+# line 309 "src/vm/jit/verify/icmds.c"
GENERATED /* we just check the basic input types and that the */
GENERATED /* destination is an array of references. Assignability to */
GENERATED /* the actual array must be checked at runtime, each time the */
GENERATED /* may use stack[-2] ... stack[0] */
GENERATED
GENERATED
-# line 275 "src/vm/jit/verify/icmds.c"
+# line 273 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
GENERATED && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED /* may use stack[-2] ... stack[0] */
GENERATED
GENERATED
-# line 281 "src/vm/jit/verify/icmds.c"
+# line 279 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[-2] ... stack[0] */
GENERATED
GENERATED
-# line 301 "src/vm/jit/verify/icmds.c"
+# line 299 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 704 "src/vm/jit/verify/icmds.c"
+# line 676 "src/vm/jit/verify/icmds.c"
GENERATED /* we pop 1 */
GENERATED CHECK_CAT1(stack[0]);
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 709 "src/vm/jit/verify/icmds.c"
+# line 681 "src/vm/jit/verify/icmds.c"
GENERATED /* we pop either 11 or 2 */
GENERATED if (IS_CAT1(stack[0]))
GENERATED CHECK_CAT1(stack[-1]);
GENERATED /* may use stack[0] ... stack[1] */
GENERATED
GENERATED
-# line 724 "src/vm/jit/verify/icmds.c"
+# line 696 "src/vm/jit/verify/icmds.c"
GENERATED /* we dup 1 */
GENERATED CHECK_CAT1(stack[0]);
GENERATED
GENERATED /* may use stack[-1] ... stack[1] */
GENERATED
GENERATED
-# line 731 "src/vm/jit/verify/icmds.c"
+# line 703 "src/vm/jit/verify/icmds.c"
GENERATED /* we dup 1 */
GENERATED CHECK_CAT1(stack[0]);
GENERATED /* we skip 1 */
GENERATED /* may use stack[-2] ... stack[1] */
GENERATED
GENERATED
-# line 742 "src/vm/jit/verify/icmds.c"
+# line 714 "src/vm/jit/verify/icmds.c"
GENERATED /* we dup 1 */
GENERATED CHECK_CAT1(stack[0]);
GENERATED /* we skip either 11 or 2 */
GENERATED /* may use stack[-1] ... stack[2] */
GENERATED
GENERATED
-# line 755 "src/vm/jit/verify/icmds.c"
+# line 727 "src/vm/jit/verify/icmds.c"
GENERATED /* we dup either 11 or 2 */
GENERATED if (IS_CAT1(stack[0]))
GENERATED CHECK_CAT1(stack[-1]);
GENERATED /* may use stack[-2] ... stack[2] */
GENERATED
GENERATED
-# line 764 "src/vm/jit/verify/icmds.c"
+# line 736 "src/vm/jit/verify/icmds.c"
GENERATED /* we dup either 11 or 2 */
GENERATED if (IS_CAT1(stack[0]))
GENERATED CHECK_CAT1(stack[-1]);
GENERATED /* may use stack[-3] ... stack[2] */
GENERATED
GENERATED
-# line 778 "src/vm/jit/verify/icmds.c"
+# line 750 "src/vm/jit/verify/icmds.c"
GENERATED /* we dup either 11 or 2 */
GENERATED if (IS_CAT1(stack[0]))
GENERATED CHECK_CAT1(stack[-1]);
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 715 "src/vm/jit/verify/icmds.c"
+# line 687 "src/vm/jit/verify/icmds.c"
GENERATED CHECK_CAT1(stack[0]);
GENERATED CHECK_CAT1(stack[-1]);
GENERATED
GENERATED /* may use stack[1] ... stack[1] */
GENERATED
GENERATED
-# line 393 "src/vm/jit/verify/icmds.c"
+# line 391 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
GENERATED /* may use stack[1] ... stack[2] */
GENERATED
GENERATED
-# line 399 "src/vm/jit/verify/icmds.c"
+# line 397 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
GENERATED /* may use stack[1] ... stack[2] */
GENERATED
GENERATED
-# line 405 "src/vm/jit/verify/icmds.c"
+# line 403 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 390 "src/vm/jit/verify/icmds.c"
+# line 388 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 586 "src/vm/jit/verify/icmds.c"
+# line 558 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED tbptr = IPTR->sx.s23.s3.jsrtarget.block;
GENERATED
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 607 "src/vm/jit/verify/icmds.c"
+# line 579 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED CHECK_LOCAL_TYPE(IPTR->s1.varindex, TYPE_RET);
GENERATED if (!TYPEINFO_IS_PRIMITIVE(STATE->locals[IPTR->s1.varindex].typeinfo))
GENERATED /* may use stack[1] ... stack[1] */
GENERATED
GENERATED
-# line 457 "src/vm/jit/verify/icmds.c"
+# line 429 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_switch);
GENERATED
GENERATED /* may use stack[1] ... stack[1] */
GENERATED
GENERATED
-# line 473 "src/vm/jit/verify/icmds.c"
+# line 445 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_switch);
GENERATED
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 539 "src/vm/jit/verify/icmds.c"
+# line 511 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_INT)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 544 "src/vm/jit/verify/icmds.c"
+# line 516 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_LNG)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 549 "src/vm/jit/verify/icmds.c"
+# line 521 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_FLT)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
GENERATED /* may use stack[-1] ... stack[0] */
GENERATED
GENERATED
-# line 554 "src/vm/jit/verify/icmds.c"
+# line 526 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_DBL)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 514 "src/vm/jit/verify/icmds.c"
+# line 486 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_areturn);
GENERATED if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
GENERATED VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 559 "src/vm/jit/verify/icmds.c"
+# line 531 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_VOID)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
GENERATED return_tail:
GENERATED TYPECHECK_COUNT(stat_ins_primitive_return);
GENERATED
- GENERATED if (STATE->initmethod && METHOD->class != class_java_lang_Object) {
+ GENERATED if (STATE->initmethod && METHOD->clazz != class_java_lang_Object) {
GENERATED /* Check if the 'this' instance has been initialized. */
GENERATED LOG("Checking <init> marker");
GENERATED
GENERATED /* variable number of outslots! */
GENERATED
GENERATED
-# line 158 "src/vm/jit/verify/icmds.c"
+# line 156 "src/vm/jit/verify/icmds.c"
GENERATED stack = typecheck_stackbased_verify_fieldaccess(STATE, NULL, NULL, stack);
GENERATED if (stack == NULL)
GENERATED EXCEPTION;
GENERATED /* variable number of inslots! */
GENERATED
GENERATED
-# line 140 "src/vm/jit/verify/icmds.c"
+# line 138 "src/vm/jit/verify/icmds.c"
GENERATED CHECK_STACK_DEPTH(1);
GENERATED if (!IS_CAT1(stack[0])) {
GENERATED /* (stack depth >= 2 is guaranteed) */
GENERATED /* variable number of outslots! */
GENERATED
GENERATED
-# line 151 "src/vm/jit/verify/icmds.c"
+# line 149 "src/vm/jit/verify/icmds.c"
GENERATED CHECK_STACK_TYPE(stack[0], TYPE_ADR);
GENERATED stack = typecheck_stackbased_verify_fieldaccess(STATE, stack, NULL, stack-1);
GENERATED if (stack == NULL)
GENERATED /* variable number of inslots! */
GENERATED
GENERATED
-# line 128 "src/vm/jit/verify/icmds.c"
+# line 126 "src/vm/jit/verify/icmds.c"
GENERATED CHECK_STACK_DEPTH(2);
GENERATED if (!IS_CAT1(stack[0])) {
GENERATED CHECK_STACK_DEPTH(3);
GENERATED /* variable number of outslots! */
GENERATED
GENERATED
-# line 630 "src/vm/jit/verify/icmds.c"
+# line 602 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_invoke);
GENERATED
GENERATED INSTRUCTION_GET_METHODDESC(IPTR, md);
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 233 "src/vm/jit/verify/icmds.c"
+# line 231 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_ARRAY(OP1->typeinfo)
GENERATED && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
GENERATED VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 493 "src/vm/jit/verify/icmds.c"
+# line 465 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_athrow);
GENERATED r = typeinfo_is_assignable_to_class(&OP1->typeinfo,
GENERATED CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
GENERATED METHOD,
GENERATED /* XXX make this more efficient, use class_java_lang_Throwable
GENERATED * directly */
- GENERATED class_get_classref(METHOD->class,utf_java_lang_Throwable),
+ GENERATED class_get_classref(METHOD->clazz,utf_java_lang_Throwable),
GENERATED &OP1->typeinfo);
GENERATED IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
GENERATED }
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 367 "src/vm/jit/verify/icmds.c"
+# line 365 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED /* returnAddress is not allowed */
GENERATED /* may use stack[0] ... stack[0] */
GENERATED
GENERATED
-# line 379 "src/vm/jit/verify/icmds.c"
+# line 377 "src/vm/jit/verify/icmds.c"
GENERATED /* returnAddress is not allowed */
GENERATED if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
GENERATED VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
GENERATED /* variable number of inslots! */
GENERATED
GENERATED
-# line 668 "src/vm/jit/verify/icmds.c"
+# line 640 "src/vm/jit/verify/icmds.c"
GENERATED if (!typecheck_stackbased_multianewarray(STATE, stack, stackfloor))
GENERATED EXCEPTION;
GENERATED stack -= (IPTR->s1.argcount - 1);
GENERATED /* may use stack[1] ... stack[1] */
GENERATED
GENERATED
-# line 391 "src/vm/jit/verify/icmds.c"
+# line 389 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
GENERATED /* variable number of outslots! */
GENERATED
GENERATED
-# line 684 "src/vm/jit/verify/icmds.c"
+# line 656 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_builtin);
GENERATED if (!typecheck_stackbased_verify_builtin(STATE, stack, stackfloor))
GENERATED EXCEPTION;
/* src/vm/jit/verify/typecheck-stackbased.c - stack-based verifier
- 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.
/* this #if runs over the whole file: */
#if defined(ENABLE_VERIFIER)
-typedef typedescriptor verifier_slot_t;
+typedef typedescriptor_t verifier_slot_t;
#if defined(TYPECHECK_VERBOSE)
static void typecheck_stackbased_show_state(verifier_state *state,
/* XXX should reuse typevector code */
static typecheck_result typecheck_stackbased_merge_locals(methodinfo *m,
- typedescriptor *dst,
- typedescriptor *y,
+ typedescriptor_t *dst,
+ typedescriptor_t *y,
int size)
{
bool changed = false;
typecheck_result r;
- typedescriptor *a = dst;
- typedescriptor *b = y;
+ typedescriptor_t *a = dst;
+ typedescriptor_t *b = y;
while (size--) {
if (a->type != TYPE_VOID && a->type != b->type) {
a->type = TYPE_VOID;
static typecheck_result typecheck_stackbased_merge(verifier_state *state,
basicblock *destblock,
- typedescriptor *stack,
+ typedescriptor_t *stack,
s4 stackdepth)
{
s4 i;
s4 destidx;
- typedescriptor *stackfloor;
- typedescriptor *sp;
- typedescriptor *dp;
+ typedescriptor_t *stackfloor;
+ typedescriptor_t *sp;
+ typedescriptor_t *dp;
typecheck_result r;
bool changed = false;
static bool typecheck_stackbased_reach(verifier_state *state,
basicblock *destblock,
- typedescriptor *stack,
+ typedescriptor_t *stack,
s4 stackdepth)
{
bool changed = false;
MCOPY(state->startstack + (destblock->nr * state->m->maxstack),
stack - (stackdepth - 1),
- typedescriptor,
+ typedescriptor_t,
stackdepth);
MCOPY(state->startlocals + (destblock->nr * state->numlocals),
state->locals,
- typedescriptor,
+ typedescriptor_t,
state->numlocals);
changed = true;
*******************************************************************************/
-static typedescriptor *typecheck_stackbased_verify_fieldaccess(
+static typedescriptor_t *typecheck_stackbased_verify_fieldaccess(
verifier_state *state,
- typedescriptor *instance,
- typedescriptor *value,
- typedescriptor *stack)
+ typedescriptor_t *instance,
+ typedescriptor_t *value,
+ typedescriptor_t *stack)
{
jitdata *jd;
}
static bool typecheck_stackbased_verify_invocation(verifier_state *state,
- typedescriptor *stack,
- typedescriptor *stackfloor)
+ typedescriptor_t *stack,
+ typedescriptor_t *stackfloor)
{
s4 paramslots;
methoddesc *md;
- typedescriptor *dv;
+ typedescriptor_t *dv;
/* check stack depth */
}
static bool typecheck_stackbased_verify_builtin(verifier_state *state,
- typedescriptor *stack,
- typedescriptor *stackfloor)
+ typedescriptor_t *stack,
+ typedescriptor_t *stackfloor)
{
s4 paramslots;
- typedescriptor *dv;
+ typedescriptor_t *dv;
/* check stack depth */
}
static bool typecheck_stackbased_multianewarray(verifier_state *state,
- typedescriptor *stack,
- typedescriptor *stackfloor)
+ typedescriptor_t *stack,
+ typedescriptor_t *stackfloor)
{
/* XXX recombine with verify_multianewarray */
classinfo *arrayclass;
arraydescriptor *desc;
s4 i;
- typedescriptor *sp;
- typedescriptor *dst;
+ typedescriptor_t *sp;
+ typedescriptor_t *dst;
/* destination slot */
jsr->callers = jc;
}
-static typedescriptor *typecheck_stackbased_jsr(verifier_state *state,
- typedescriptor *stack,
- typedescriptor *stackfloor)
+static typedescriptor_t *typecheck_stackbased_jsr(verifier_state *state,
+ typedescriptor_t *stack,
+ typedescriptor_t *stackfloor)
{
typecheck_jsr_t *jsr;
basicblock *tbptr;
/* copy the stack of the RET edge */
- MCOPY(stackfloor, jsr->retstack, typedescriptor, jsr->retdepth);
+ MCOPY(stackfloor, jsr->retstack, typedescriptor_t, jsr->retdepth);
stack = stackfloor + (jsr->retdepth - 1);
/* copy variables that were used in the subroutine from the RET edge */
jsr->start = tbptr;
jsr->usedlocals = DMNEW(char, state->numlocals);
MZERO(jsr->usedlocals, char, state->numlocals);
- jsr->retlocals = DMNEW(typedescriptor, state->numlocals);
- jsr->retstack = DMNEW(typedescriptor, state->m->maxstack);
+ jsr->retlocals = DMNEW(typedescriptor_t, state->numlocals);
+ jsr->retstack = DMNEW(typedescriptor_t, state->m->maxstack);
jsr->retdepth = 0;
}
else {
}
static bool typecheck_stackbased_ret(verifier_state *state,
- typedescriptor *stack,
- typedescriptor *stackfloor)
+ typedescriptor_t *stack,
+ typedescriptor_t *stackfloor)
{
basicblock *tbptr;
typecheck_jsr_caller_t *jsrcaller;
jsr->retblock = state->bptr;
jsr->retdepth = (stack - stackfloor) + 1;
- MCOPY(jsr->retstack, stackfloor, typedescriptor, jsr->retdepth);
- MCOPY(jsr->retlocals, state->locals, typedescriptor, state->numlocals);
+ MCOPY(jsr->retstack, stackfloor, typedescriptor_t, jsr->retdepth);
+ MCOPY(jsr->retlocals, state->locals, typedescriptor_t, state->numlocals);
/* invalidate the returnAddress used by this RET */
/* XXX should we also invalidate the returnAddresses of JSRs that are skipped by this RET? */
for (i=0; i<state->numlocals; ++i) {
- typedescriptor *lc = &(jsr->retlocals[i]);
+ typedescriptor_t *lc = &(jsr->retlocals[i]);
if (TYPE_IS_RETURNADDRESS(lc->type, lc->typeinfo))
if (TYPEINFO_RETURNADDRESS(lc->typeinfo) == tbptr) {
LOG1("invalidating returnAddress in local %d", i);
verifier_state state;
basicblock *tbptr;
exception_entry *ex;
- typedescriptor exstack;
+ typedescriptor_t exstack;
s4 skip = 0;
DOLOG( show_method(jd, SHOW_PARSE); );
if (state.initmethod)
TYPEINFO_INIT_NEWOBJECT(dst->typeinfo, NULL);
else
- typeinfo_init_classinfo(&(dst->typeinfo), state.m->class);
+ typeinfo_init_classinfo(&(dst->typeinfo), state.m->clazz);
skip = 1;
}
#if defined(TYPECHECK_VERBOSE)
static void typecheck_stackbased_show_state(verifier_state *state,
- typedescriptor *stack,
- typedescriptor *stackfloor,
+ typedescriptor_t *stack,
+ typedescriptor_t *stackfloor,
bool showins)
{
- typedescriptor *sp;
+ typedescriptor_t *sp;
s4 i;
LOGSTR1("stackdepth %d stack [", (stack - stackfloor) + 1);
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 355 "src/vm/jit/verify/icmds.c"
+# line 347 "src/vm/jit/verify/icmds.c"
GENERATED if (IPTR->flags.bits & INS_FLAG_CLASS) {
GENERATED /* a java.lang.Class reference */
GENERATED TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 90 "src/vm/jit/verify/icmds.c"
+# line 82 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_stack);
GENERATED COPYTYPE(IPTR->s1, IPTR->dst);
GENERATED DST->type = OP1->type;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 89 "src/vm/jit/verify/icmds.c"
+# line 81 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_stack);
GENERATED COPYTYPE(IPTR->s1, IPTR->dst);
GENERATED DST->type = OP1->type;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 99 "src/vm/jit/verify/icmds.c"
+# line 91 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_aload);
GENERATED
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 121 "src/vm/jit/verify/icmds.c"
+# line 113 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 114 "src/vm/jit/verify/icmds.c"
+# line 106 "src/vm/jit/verify/icmds.c"
GENERATED TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
GENERATED
# line 356 "src/vm/jit/verify/typecheck-typeinferer-gen.inc"
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 414 "src/vm/jit/verify/icmds.c"
+# line 406 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 396 "src/vm/jit/verify/icmds.c"
+# line 388 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 587 "src/vm/jit/verify/icmds.c"
+# line 553 "src/vm/jit/verify/icmds.c"
GENERATED TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
GENERATED REACH(IPTR->sx.s23.s3.jsrtarget);
GENERATED
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 604 "src/vm/jit/verify/icmds.c"
+# line 570 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED /* check returnAddress variable */
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 463 "src/vm/jit/verify/icmds.c"
+# line 429 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_switch);
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 479 "src/vm/jit/verify/icmds.c"
+# line 445 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_switch);
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 230 "src/vm/jit/verify/icmds.c"
+# line 222 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_fieldaccess(state, NULL, NULL))
GENERATED return false;
GENERATED maythrow = true;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 224 "src/vm/jit/verify/icmds.c"
+# line 216 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
GENERATED return false;
GENERATED maythrow = true;
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 626 "src/vm/jit/verify/icmds.c"
+# line 592 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_invoke);
GENERATED if (!handle_invocation(state))
GENERATED EXCEPTION;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 373 "src/vm/jit/verify/icmds.c"
+# line 365 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED /* returnAddress is not allowed */
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 669 "src/vm/jit/verify/icmds.c"
+# line 635 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_multianewarray(STATE))
GENERATED EXCEPTION;
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 684 "src/vm/jit/verify/icmds.c"
+# line 650 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_builtin);
GENERATED if (!handle_builtin(state))
GENERATED EXCEPTION;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 355 "src/vm/jit/verify/icmds.c"
+# line 347 "src/vm/jit/verify/icmds.c"
GENERATED if (IPTR->flags.bits & INS_FLAG_CLASS) {
GENERATED /* a java.lang.Class reference */
GENERATED TYPEINFO_INIT_JAVA_LANG_CLASS(DST->typeinfo,IPTR->sx.val.c);
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 90 "src/vm/jit/verify/icmds.c"
+# line 82 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_stack);
GENERATED COPYTYPE(IPTR->s1, IPTR->dst);
GENERATED DST->type = OP1->type;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 89 "src/vm/jit/verify/icmds.c"
+# line 81 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_stack);
GENERATED COPYTYPE(IPTR->s1, IPTR->dst);
GENERATED DST->type = OP1->type;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 99 "src/vm/jit/verify/icmds.c"
+# line 91 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_aload);
GENERATED
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 266 "src/vm/jit/verify/icmds.c"
+# line 258 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 276 "src/vm/jit/verify/icmds.c"
+# line 268 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 261 "src/vm/jit/verify/icmds.c"
+# line 253 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 256 "src/vm/jit/verify/icmds.c"
+# line 248 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 121 "src/vm/jit/verify/icmds.c"
+# line 113 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED if (!TYPEINFO_MAYBE_ARRAY_OF_REFS(OP1->typeinfo))
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 245 "src/vm/jit/verify/icmds.c"
+# line 237 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
GENERATED && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
GENERATED VERIFY_ERROR("Array type mismatch");
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 251 "src/vm/jit/verify/icmds.c"
+# line 243 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 271 "src/vm/jit/verify/icmds.c"
+# line 263 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 114 "src/vm/jit/verify/icmds.c"
+# line 106 "src/vm/jit/verify/icmds.c"
GENERATED TYPEINFO_COPY(OP1->typeinfo, DST->typeinfo);
GENERATED
# line 493 "src/vm/jit/verify/typecheck-variablesbased-gen.inc"
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 414 "src/vm/jit/verify/icmds.c"
+# line 406 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 302 "src/vm/jit/verify/icmds.c"
+# line 294 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_INT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 312 "src/vm/jit/verify/icmds.c"
+# line 304 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_LONG))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 297 "src/vm/jit/verify/icmds.c"
+# line 289 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_FLOAT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 292 "src/vm/jit/verify/icmds.c"
+# line 284 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_DOUBLE))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 317 "src/vm/jit/verify/icmds.c"
+# line 309 "src/vm/jit/verify/icmds.c"
GENERATED /* we just check the basic input types and that the */
GENERATED /* destination is an array of references. Assignability to */
GENERATED /* the actual array must be checked at runtime, each time the */
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 281 "src/vm/jit/verify/icmds.c"
+# line 273 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BOOLEAN)
GENERATED && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_BYTE))
GENERATED VERIFY_ERROR("Array type mismatch");
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 287 "src/vm/jit/verify/icmds.c"
+# line 279 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_CHAR))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 307 "src/vm/jit/verify/icmds.c"
+# line 299 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo,ARRAYTYPE_SHORT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 396 "src/vm/jit/verify/icmds.c"
+# line 388 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_branch);
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 587 "src/vm/jit/verify/icmds.c"
+# line 553 "src/vm/jit/verify/icmds.c"
GENERATED TYPEINFO_INIT_RETURNADDRESS(DST->typeinfo, BPTR->next);
GENERATED REACH(IPTR->sx.s23.s3.jsrtarget);
GENERATED
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 604 "src/vm/jit/verify/icmds.c"
+# line 570 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED /* check returnAddress variable */
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 463 "src/vm/jit/verify/icmds.c"
+# line 429 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_switch);
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 479 "src/vm/jit/verify/icmds.c"
+# line 445 "src/vm/jit/verify/icmds.c"
GENERATED /* {RESULTNOW} */
GENERATED TYPECHECK_COUNT(stat_ins_switch);
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 545 "src/vm/jit/verify/icmds.c"
+# line 511 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_INT)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 550 "src/vm/jit/verify/icmds.c"
+# line 516 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_LNG)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 555 "src/vm/jit/verify/icmds.c"
+# line 521 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_FLT)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 560 "src/vm/jit/verify/icmds.c"
+# line 526 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_DBL)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 520 "src/vm/jit/verify/icmds.c"
+# line 486 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_areturn);
GENERATED if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
GENERATED VERIFY_ERROR("illegal instruction: ARETURN on non-reference");
GENERATED superblockend = true;
GENERATED
GENERATED
-# line 565 "src/vm/jit/verify/icmds.c"
+# line 531 "src/vm/jit/verify/icmds.c"
GENERATED if (STATE->returntype.type != TYPE_VOID)
GENERATED VERIFY_ERROR("Return type mismatch");
GENERATED
GENERATED return_tail:
GENERATED TYPECHECK_COUNT(stat_ins_primitive_return);
GENERATED
- GENERATED if (STATE->initmethod && METHOD->class != class_java_lang_Object) {
+ GENERATED if (STATE->initmethod && METHOD->clazz != class_java_lang_Object) {
GENERATED /* Check if the 'this' instance has been initialized. */
GENERATED LOG("Checking <init> marker");
GENERATED
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 230 "src/vm/jit/verify/icmds.c"
+# line 222 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_fieldaccess(state, NULL, NULL))
GENERATED return false;
GENERATED maythrow = true;
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 176 "src/vm/jit/verify/icmds.c"
+# line 168 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_fieldaccess(state, NULL, VAROP(iptr->s1)))
GENERATED return false;
GENERATED maythrow = true;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 224 "src/vm/jit/verify/icmds.c"
+# line 216 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_fieldaccess(state, VAROP(iptr->s1), NULL))
GENERATED return false;
GENERATED maythrow = true;
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 170 "src/vm/jit/verify/icmds.c"
+# line 162 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_fieldaccess(state, VAROP(iptr->s1), VAROP(iptr->sx.s23.s2)))
GENERATED return false;
GENERATED maythrow = true;
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 626 "src/vm/jit/verify/icmds.c"
+# line 592 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_invoke);
GENERATED if (!handle_invocation(state))
GENERATED EXCEPTION;
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 239 "src/vm/jit/verify/icmds.c"
+# line 231 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_ARRAY(OP1->typeinfo)
GENERATED && OP1->typeinfo.typeclass.cls != pseudo_class_Arraystub)
GENERATED VERIFY_ERROR("illegal instruction: ARRAYLENGTH on non-array");
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 499 "src/vm/jit/verify/icmds.c"
+# line 465 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_athrow);
GENERATED r = typeinfo_is_assignable_to_class(&OP1->typeinfo,
GENERATED CLASSREF_OR_CLASSINFO(class_java_lang_Throwable));
GENERATED METHOD,
GENERATED /* XXX make this more efficient, use class_java_lang_Throwable
GENERATED * directly */
- GENERATED class_get_classref(METHOD->class,utf_java_lang_Throwable),
+ GENERATED class_get_classref(METHOD->clazz,utf_java_lang_Throwable),
GENERATED &OP1->typeinfo);
GENERATED IPTR->flags.bits |= INS_FLAG_UNRESOLVED;
GENERATED }
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 373 "src/vm/jit/verify/icmds.c"
+# line 365 "src/vm/jit/verify/icmds.c"
GENERATED
# if !defined(TYPECHECK_TYPEINFERER)
GENERATED /* returnAddress is not allowed */
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 385 "src/vm/jit/verify/icmds.c"
+# line 377 "src/vm/jit/verify/icmds.c"
GENERATED /* returnAddress is not allowed */
GENERATED if (!TYPEINFO_IS_REFERENCE(OP1->typeinfo))
GENERATED VERIFY_ERROR("Illegal instruction: INSTANCEOF on non-reference");
# define DST VAROP(iptr->dst)
GENERATED
GENERATED
-# line 669 "src/vm/jit/verify/icmds.c"
+# line 635 "src/vm/jit/verify/icmds.c"
GENERATED if (!handle_multianewarray(STATE))
GENERATED EXCEPTION;
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 326 "src/vm/jit/verify/icmds.c"
+# line 318 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_INT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 331 "src/vm/jit/verify/icmds.c"
+# line 323 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_LONG))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 336 "src/vm/jit/verify/icmds.c"
+# line 328 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BOOLEAN)
GENERATED && !TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_BYTE))
GENERATED VERIFY_ERROR("Array type mismatch");
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 342 "src/vm/jit/verify/icmds.c"
+# line 334 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_CHAR))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 347 "src/vm/jit/verify/icmds.c"
+# line 339 "src/vm/jit/verify/icmds.c"
GENERATED if (!TYPEINFO_MAYBE_PRIMITIVE_ARRAY(OP1->typeinfo, ARRAYTYPE_SHORT))
GENERATED VERIFY_ERROR("Array type mismatch");
GENERATED
GENERATED maythrow = true;
GENERATED
GENERATED
-# line 203 "src/vm/jit/verify/icmds.c"
+# line 195 "src/vm/jit/verify/icmds.c"
GENERATED /* XXX this mess will go away with const operands */
GENERATED INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
GENERATED constvalue.type = fieldref->parseddesc.fd->type;
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 182 "src/vm/jit/verify/icmds.c"
+# line 174 "src/vm/jit/verify/icmds.c"
GENERATED /* XXX this mess will go away with const operands */
GENERATED INSTRUCTION_GET_FIELDREF(state->iptr, fieldref);
GENERATED constvalue.type = fieldref->parseddesc.fd->type;
# define OP1 VAROP(iptr->s1)
GENERATED
GENERATED
-# line 684 "src/vm/jit/verify/icmds.c"
+# line 650 "src/vm/jit/verify/icmds.c"
GENERATED TYPECHECK_COUNT(stat_ins_builtin);
GENERATED if (!handle_builtin(state))
GENERATED EXCEPTION;
/* src/vm/jit/verify/typecheck.c - typechecking (part of bytecode verification)
- 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.
s4 *localmap = jd->local_map;
varinfo *vars = jd->var;
- javaindex = state->reverselocalmap[index];
+ javaindex = jd->reverselocalmap[index];
/* invalidate locals of two-word type at index javaindex-1 */
codegendata *cd;
varinfo *savedlocals;
verifier_state state; /* current state of the verifier */
- s4 i;
- s4 t;
/* collect statistics */
if (state.initmethod)
state.numlocals++; /* VERIFIER_EXTRA_LOCALS */
- state.reverselocalmap = DMNEW(s4, state.validlocals);
- for (i=0; i<jd->maxlocals; ++i)
- for (t=0; t<5; ++t) {
- s4 varindex = jd->local_map[5*i + t];
- if (varindex >= 0)
- state.reverselocalmap[varindex] = i;
- }
-
DOLOG(
+ s4 i;
+ s4 t;
LOG("reverselocalmap:");
for (i=0; i<state.validlocals; ++i) {
- LOG2(" %i => javaindex %i", i, state.reverselocalmap[i]);
+ LOG2(" %i => javaindex %i", i, jd->reverselocalmap[i]);
});
/* allocate the buffer of active exception handlers */
/* src/vm/jit/verify/typeinfo.c - type system used by the type checker
- 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.
*******************************************************************************/
void
-typevector_store(varinfo *vec,int index,int type,typeinfo *info)
+typevector_store(varinfo *vec,int index,int type,typeinfo_t *info)
{
TYPEINFO_ASSERT(vec);
*******************************************************************************/
void
-typevector_store_retaddr(varinfo *vec,int index,typeinfo *info)
+typevector_store_retaddr(varinfo *vec,int index,typeinfo_t *info)
{
TYPEINFO_ASSERT(vec);
TYPEINFO_ASSERT(TYPEINFO_IS_PRIMITIVE(*info));
*******************************************************************************/
bool
-typeinfo_is_array(typeinfo *info)
+typeinfo_is_array(typeinfo_t *info)
{
TYPEINFO_ASSERT(info);
return TYPEINFO_IS_ARRAY(*info);
*******************************************************************************/
bool
-typeinfo_is_primitive_array(typeinfo *info,int arraytype)
+typeinfo_is_primitive_array(typeinfo_t *info,int arraytype)
{
TYPEINFO_ASSERT(info);
return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
*******************************************************************************/
bool
-typeinfo_is_array_of_refs(typeinfo *info)
+typeinfo_is_array_of_refs(typeinfo_t *info)
{
TYPEINFO_ASSERT(info);
return TYPEINFO_IS_ARRAY_OF_REFS(*info);
*******************************************************************************/
static typecheck_result
-mergedlist_implements_interface(typeinfo_mergedlist *merged,
+mergedlist_implements_interface(typeinfo_mergedlist_t *merged,
classinfo *interf)
{
int i;
*******************************************************************************/
static typecheck_result
-merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
+merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist_t *merged,
classinfo *interf)
{
typecheck_result r;
*******************************************************************************/
static typecheck_result
-merged_is_subclass(classinfo *typeclass,typeinfo_mergedlist *merged,
+merged_is_subclass(classinfo *typeclass,typeinfo_mergedlist_t *merged,
classinfo *cls)
{
int i;
*******************************************************************************/
typecheck_result
-typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
+typeinfo_is_assignable_to_class(typeinfo_t *value,classref_or_classinfo dest)
{
classref_or_classinfo c;
classinfo *cls;
arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
int dimension = arraydesc->dimension;
classinfo *elementclass = (arraydesc->elementvftbl)
- ? arraydesc->elementvftbl->class : NULL;
+ ? arraydesc->elementvftbl->clazz : NULL;
/* We are assigning to an array type. */
if (!TYPEINFO_IS_ARRAY(*value))
*******************************************************************************/
typecheck_result
-typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
+typeinfo_is_assignable(typeinfo_t *value,typeinfo_t *dest)
{
TYPEINFO_ASSERT(value);
TYPEINFO_ASSERT(dest);
*******************************************************************************/
void
-typeinfo_init_classinfo(typeinfo *info, classinfo *c)
+typeinfo_init_classinfo(typeinfo_t *info, classinfo *c)
{
if ((info->typeclass.cls = c)->vftbl->arraydesc) {
if (c->vftbl->arraydesc->elementvftbl)
- info->elementclass.cls = c->vftbl->arraydesc->elementvftbl->class;
+ info->elementclass.cls = c->vftbl->arraydesc->elementvftbl->clazz;
else
info->elementclass.any = NULL;
info->dimension = c->vftbl->arraydesc->dimension;
*******************************************************************************/
bool
-typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
+typeinfo_init_class(typeinfo_t *info,classref_or_classinfo c)
{
char *utf_ptr;
int len;
*******************************************************************************/
bool
-typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
+typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo_t *info)
{
TYPEINFO_ASSERT(desc);
*******************************************************************************/
bool
-typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
+typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo_t *infobuf,
int buflen,bool twoword,
- u1 *returntype,typeinfo *returntypeinfo)
+ u1 *returntype,typeinfo_t *returntypeinfo)
{
int i;
int args = 0;
*******************************************************************************/
bool
-typedescriptor_init_from_typedesc(typedescriptor *td,
+typedescriptor_init_from_typedesc(typedescriptor_t *td,
typedesc *desc)
{
TYPEINFO_ASSERT(td);
methoddesc *desc,
int buflen, int startindex,
s4 *map,
- typedescriptor *returntype)
+ typedescriptor_t *returntype)
{
s4 i;
s4 varindex;
*******************************************************************************/
int
-typedescriptors_init_from_methoddesc(typedescriptor *td,
+typedescriptors_init_from_methoddesc(typedescriptor_t *td,
methoddesc *desc,
int buflen,bool twoword,int startindex,
- typedescriptor *returntype)
+ typedescriptor_t *returntype)
{
int i;
int args = 0;
*******************************************************************************/
bool
-typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
+typeinfo_init_component(typeinfo_t *srcarray,typeinfo_t *dst)
{
- typeinfo_mergedlist *merged;
+ typeinfo_mergedlist_t *merged;
TYPEINFO_ASSERT(srcarray);
TYPEINFO_ASSERT(dst);
comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl;
if (comp)
- typeinfo_init_classinfo(dst,comp->class);
+ typeinfo_init_classinfo(dst,comp->clazz);
else
TYPEINFO_INIT_PRIMITIVE(*dst);
}
*******************************************************************************/
void
-typeinfo_clone(typeinfo *src,typeinfo *dest)
+typeinfo_clone(typeinfo_t *src,typeinfo_t *dest)
{
int count;
classref_or_classinfo *srclist,*destlist;
*******************************************************************************/
void
-typeinfo_free(typeinfo *info)
+typeinfo_free(typeinfo_t *info)
{
TYPEINFO_FREEMERGED_IF_ANY(info->merged);
info->merged = NULL;
static
void
-typeinfo_merge_error(methodinfo *m,char *str,typeinfo *x,typeinfo *y) {
+typeinfo_merge_error(methodinfo *m,char *str,typeinfo_t *x,typeinfo_t *y) {
#ifdef TYPEINFO_VERBOSE
fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
fprintf(stderr,"Typeinfo x:\n");
/* Returns: true if dest was changed (currently always true). */
static
bool
-typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
+typeinfo_merge_two(typeinfo_t *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
{
TYPEINFO_ASSERT(dest);
TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
/* Returns: true if dest was changed. */
static
bool
-typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classref_or_classinfo cls)
+typeinfo_merge_add(typeinfo_t *dest,typeinfo_mergedlist_t *m,classref_or_classinfo cls)
{
int count;
- typeinfo_mergedlist *newmerged;
+ typeinfo_mergedlist_t *newmerged;
classref_or_classinfo *mlist,*newlist;
count = m->count;
/* Returns: true if dest was changed. */
static
bool
-typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
- typeinfo_mergedlist *y)
+typeinfo_merge_mergedlists(typeinfo_t *dest,typeinfo_mergedlist_t *x,
+ typeinfo_mergedlist_t *y)
{
int count = 0;
int countx,county;
- typeinfo_mergedlist *temp,*result;
+ typeinfo_mergedlist_t *temp,*result;
classref_or_classinfo *clsx,*clsy,*newlist;
/* count the elements that will be in the resulting list */
*******************************************************************************/
static typecheck_result
-typeinfo_merge_nonarrays(typeinfo *dest,
+typeinfo_merge_nonarrays(typeinfo_t *dest,
classref_or_classinfo *result,
classref_or_classinfo x,classref_or_classinfo y,
- typeinfo_mergedlist *mergedx,
- typeinfo_mergedlist *mergedy)
+ typeinfo_mergedlist_t *mergedx,
+ typeinfo_mergedlist_t *mergedy)
{
classref_or_classinfo t;
classinfo *tcls,*common;
- typeinfo_mergedlist *tmerged;
+ typeinfo_mergedlist_t *tmerged;
bool changed;
typecheck_result r;
utf *xname;
#ifdef TYPEINFO_VERBOSE
{
- typeinfo dbgx,dbgy;
+ typeinfo_t dbgx,dbgy;
fprintf(stderr,"merge_nonarrays:\n");
fprintf(stderr," ");if(IS_CLASSREF(x))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,xname);fprintf(stderr,"\n");
fprintf(stderr," ");if(IS_CLASSREF(y))fprintf(stderr,"<ref>");utf_fprint_printable_ascii(stderr,yname);fprintf(stderr,"\n");
*******************************************************************************/
typecheck_result
-typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y)
+typeinfo_merge(methodinfo *m,typeinfo_t *dest,typeinfo_t* y)
{
- typeinfo *x;
- typeinfo *tmp;
+ typeinfo_t *x;
+ typeinfo_t *tmp;
classref_or_classinfo common;
classref_or_classinfo elementclass;
int dimension;
}
static void
-typeinfo_test_parse(typeinfo *info,char *str)
+typeinfo_test_parse(typeinfo_t *info,char *str)
{
int num;
int i;
- typeinfo *infobuf;
+ typeinfo_t *infobuf;
u1 *typebuf;
int returntype;
utf *desc = utf_new_char(str);
num = typeinfo_count_method_args(desc,false);
if (num) {
typebuf = DMNEW(u1,num);
- infobuf = DMNEW(typeinfo,num);
+ infobuf = DMNEW(typeinfo_t,num);
typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
&returntype,info);
#define TYPEINFO_TEST_BUFLEN 4000
static bool
-typeinfo_equal(typeinfo *x,typeinfo *y)
+typeinfo_equal(typeinfo_t *x,typeinfo_t *y)
{
int i;
}
static void
-typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
+typeinfo_testmerge(typeinfo_t *a,typeinfo_t *b,typeinfo_t *result,int *failed)
{
- typeinfo dest;
+ typeinfo_t dest;
bool changed,changed_should_be;
typecheck_result r;
#if 0
static void
-typeinfo_inc_dimension(typeinfo *info)
+typeinfo_inc_dimension(typeinfo_t *info)
{
if (info->dimension++ == 0) {
info->elementtype = ARRAYTYPE_OBJECT;
char bufa[TYPEINFO_TEST_BUFLEN];
char bufb[TYPEINFO_TEST_BUFLEN];
char bufc[TYPEINFO_TEST_BUFLEN];
- typeinfo a,b,c;
+ typeinfo_t a,b,c;
int maxdim;
int failed = 0;
FILE *file = fopen(filename,"rt");
#if 0
void
-typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
+typeinfo_init_from_fielddescriptor(typeinfo_t *info,char *desc)
{
typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
}
}
void
-typeinfo_print(FILE *file,typeinfo *info,int indent)
+typeinfo_print(FILE *file,typeinfo_t *info,int indent)
{
int i;
char ind[TYPEINFO_MAXINDENT + 1];
}
void
-typeinfo_print_short(FILE *file,typeinfo *info)
+typeinfo_print_short(FILE *file,typeinfo_t *info)
{
int i;
instruction *ins;
}
void
-typeinfo_print_type(FILE *file,int type,typeinfo *info)
+typeinfo_print_type(FILE *file,int type,typeinfo_t *info)
{
switch (type) {
case TYPE_VOID: fprintf(file,"V"); break;
}
void
-typedescriptor_print(FILE *file,typedescriptor *td)
+typedescriptor_print(FILE *file,typedescriptor_t *td)
{
typeinfo_print_type(file,td->type,&(td->typeinfo));
}
/* src/vm/jit/verify/typeinfo.h - type system used by the type checker
- 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.
/* resolve typedef cycles *****************************************************/
-typedef struct typeinfo typeinfo;
-typedef struct typeinfo_mergedlist typeinfo_mergedlist;
-typedef struct typedescriptor typedescriptor;
+typedef struct typeinfo typeinfo_t;
+typedef struct typeinfo_mergedlist typeinfo_mergedlist_t;
+typedef struct typedescriptor typedescriptor_t;
#include "config.h"
#include "vm/types.h"
struct typeinfo {
classref_or_classinfo typeclass;
classref_or_classinfo elementclass; /* valid if dimension>0 */ /* various uses! */
- typeinfo_mergedlist *merged;
+ typeinfo_mergedlist_t *merged;
u1 dimension;
u1 elementtype; /* valid if dimension>0 */
};
/* storing types in the signature of a method */
struct typedescriptor {
- typeinfo typeinfo; /* valid if type == TYPE_ADR */
+ typeinfo_t typeinfo; /* valid if type == TYPE_ADR */
u1 type; /* basic type (TYPE_INT, ...) */
};
((size) * sizeof(varinfo))
#define DNEW_TYPEVECTOR(size) \
- ((varinfo*)dump_alloc(TYPEVECTOR_SIZE(size)))
+ ((varinfo *) DMNEW(uint8_t, TYPEVECTOR_SIZE(size)))
#define DMNEW_TYPEVECTOR(num,size) \
- ((void*)dump_alloc((num) * TYPEVECTOR_SIZE(size)))
+ ((void *) DMNEW(uint8_t, (num) * TYPEVECTOR_SIZE(size)))
#define MGET_TYPEVECTOR(array,index,size) \
((varinfo*) (((u1*)(array)) + TYPEVECTOR_SIZE(size) * (index)))
/* internally used macros ***************************************************/
/* internal, don't use this explicitly! */
-#define TYPEINFO_ALLOCMERGED(mergedlist,count) \
- do {(mergedlist) = (typeinfo_mergedlist*)dump_alloc( \
- sizeof(typeinfo_mergedlist) \
+#define TYPEINFO_ALLOCMERGED(mergedlist,count) \
+ do {(mergedlist) = (typeinfo_mergedlist_t *) DMNEW(uint8_t, \
+ sizeof(typeinfo_mergedlist_t) \
+ ((count)-1)*sizeof(classinfo*));} while(0)
/* internal, don't use this explicitly! */
bool typevector_checkretaddr(varinfo *set,int index);
/* element write access */
-void typevector_store(varinfo *set,int index,int type,typeinfo *info);
-void typevector_store_retaddr(varinfo *set,int index,typeinfo *info);
+void typevector_store(varinfo *set,int index,int type,typeinfo_t *info);
+void typevector_store_retaddr(varinfo *set,int index,typeinfo_t *info);
bool typevector_init_object(varinfo *set,void *ins,classref_or_classinfo initclass,int size);
/* vector functions */
/* inquiry functions (read-only) ********************************************/
-bool typeinfo_is_array(typeinfo *info);
-bool typeinfo_is_primitive_array(typeinfo *info,int arraytype);
-bool typeinfo_is_array_of_refs(typeinfo *info);
+bool typeinfo_is_array(typeinfo_t *info);
+bool typeinfo_is_primitive_array(typeinfo_t *info,int arraytype);
+bool typeinfo_is_array_of_refs(typeinfo_t *info);
-typecheck_result typeinfo_is_assignable(typeinfo *value,typeinfo *dest);
-typecheck_result typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest);
+typecheck_result typeinfo_is_assignable(typeinfo_t *value,typeinfo_t *dest);
+typecheck_result typeinfo_is_assignable_to_class(typeinfo_t *value,classref_or_classinfo dest);
/* initialization functions *************************************************/
* >= 0.............ok,
* -1...............an exception has been thrown.
*/
-void typeinfo_init_classinfo(typeinfo *info,classinfo *c);
-bool typeinfo_init_class(typeinfo *info,classref_or_classinfo c);
-bool typeinfo_init_component(typeinfo *srcarray,typeinfo *dst);
+void typeinfo_init_classinfo(typeinfo_t *info,classinfo *c);
+bool typeinfo_init_class(typeinfo_t *info,classref_or_classinfo c);
+bool typeinfo_init_component(typeinfo_t *srcarray,typeinfo_t *dst);
-bool typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info);
+bool typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo_t *info);
bool typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,
- typeinfo *infobuf,
+ typeinfo_t *infobuf,
int buflen,bool twoword,
- u1 *returntype,typeinfo *returntypeinfo);
-bool typedescriptor_init_from_typedesc(typedescriptor *td,
+ u1 *returntype,typeinfo_t *returntypeinfo);
+bool typedescriptor_init_from_typedesc(typedescriptor_t *td,
typedesc *desc);
bool typeinfo_init_varinfo_from_typedesc(varinfo *var,
typedesc *desc);
-int typedescriptors_init_from_methoddesc(typedescriptor *td,
+int typedescriptors_init_from_methoddesc(typedescriptor_t *td,
methoddesc *desc,
int buflen,bool twoword,int startindex,
- typedescriptor *returntype);
+ typedescriptor_t *returntype);
bool typeinfo_init_varinfos_from_methoddesc(varinfo *vars,
methoddesc *desc,
int buflen, int startindex,
s4 *map,
- typedescriptor *returntype);
+ typedescriptor_t *returntype);
-void typeinfo_clone(typeinfo *src,typeinfo *dest);
+void typeinfo_clone(typeinfo_t *src,typeinfo_t *dest);
/* freeing memory ***********************************************************/
-void typeinfo_free(typeinfo *info);
+void typeinfo_free(typeinfo_t *info);
/* functions for merging types **********************************************/
-typecheck_result typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y);
+typecheck_result typeinfo_merge(methodinfo *m,typeinfo_t *dest,typeinfo_t* y);
/* debugging helpers ********************************************************/
void typeinfo_test();
void typeinfo_print_class(FILE *file,classref_or_classinfo c);
-void typeinfo_print(FILE *file,typeinfo *info,int indent);
-void typeinfo_print_short(FILE *file,typeinfo *info);
-void typeinfo_print_type(FILE *file,int type,typeinfo *info);
-void typedescriptor_print(FILE *file,typedescriptor *td);
+void typeinfo_print(FILE *file,typeinfo_t *info,int indent);
+void typeinfo_print_short(FILE *file,typeinfo_t *info);
+void typeinfo_print_type(FILE *file,int type,typeinfo_t *info);
+void typedescriptor_print(FILE *file,typedescriptor_t *td);
void typevector_print(FILE *file,varinfo *vec,int size);
#endif /* TYPEINFO_DEBUG */
## src/vm/jit/x86_64/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.
##
\
md-abi.c \
md-abi.h \
- md.c
+ md-trap.h \
+ md.c \
+ md.h
libarch_la_LIBADD = \
$(OS_DIR)/libmd.la
/* src/vm/jit/x86_64/asmpart.S - Java-C interface functions for x86_64
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
+ Copyright (C) 1996-2005, 2006, 2007, 2008 R. Grafl, A. Krall, C. Kruegel,
C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
J. Wenninger, Institut f. Computersprachen - TU Wien
mov (0*8+256)(mptr),itmp3 /* load PV */
call *itmp3
+L_asm_vm_call_method_return:
mov s0,sp /* restore SP */
-L_asm_vm_call_method_return:
mov 0*8(sp),%rbx /* restore callee saved registers */
mov 1*8(sp),s0
mov 2*8(sp),s1
mov t0,4*8(sp) /* save maybe-leaf flag */
mov xpc,a0 /* exception pc */
- call codegen_get_pv_from_pc@PLT
+ call methodtree_find@PLT
mov v0,2*8(sp) /* save data segment pointer */
mov 0*8(sp),a0 /* pass exception pointer */
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.h"
+#include "vm/jit/trap.h"
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
/* decide which monitor enter function to call */
if (m->flags & ACC_STATIC) {
- M_MOV_IMM(&m->class->object.header, REG_A0);
+ M_MOV_IMM(&m->clazz->object.header, REG_A0);
}
else {
M_TEST(REG_A0);
M_BNE(8);
- M_ALD_MEM(REG_A0, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_MEM(REG_A0, TRAP_NullPointerException);
}
M_AST(REG_A0, REG_SP, s1 * 8);
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
PROFILE_CYCLE_STOP;
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, 0);
+ fi->clazz, 0);
PROFILE_CYCLE_START;
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
PROFILE_CYCLE_STOP;
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, 0);
+ fi->clazz, 0);
PROFILE_CYCLE_START;
}
fieldtype = fi->type;
disp = dseg_add_address(cd, fi->value);
- if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->class)) {
+ if (!CLASS_IS_OR_ALMOST_INITIALIZED(fi->clazz)) {
PROFILE_CYCLE_STOP;
patcher_add_patch_ref(jd, PATCHER_initialize_class,
- fi->class, 0);
+ fi->clazz, 0);
PROFILE_CYCLE_START;
}
}
else {
s1 = OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr) * lm->class->index;
+ sizeof(methodptr) * lm->clazz->index;
- s2 = sizeof(methodptr) * (lm - lm->class->methods);
+ s2 = sizeof(methodptr) * (lm - lm->clazz->methods);
}
/* implicit null-pointer check */
#include "threads/lock-common.h"
-#include "vm/exceptions.h"
-
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/replace.h"
#include "vm/jit/trace.h"
+#include "vm/jit/trap.h"
#include "vmcore/options.h"
{
codegendata *cd;
s4 disp;
-#if 0
- s4 s;
- u2 opcode;
-#endif
/* get required compiler data */
cd = jd->cd;
-#if 0
- /* do we have to generate a conditional move? */
-
- if ((iptr != NULL) && (iptr->opc & ICMD_CONDITION_MASK)) {
- /* the passed register d is actually the source register */
-
- s = d;
-
- /* Only pass the opcode to codegen_reg_of_var to get the real
- destination register. */
-
- opcode = iptr->opc & ICMD_OPCODE_MASK;
-
- /* get the real destination register */
-
- d = codegen_reg_of_var(rd, opcode, dst, REG_ITMP1);
-
- /* and emit the conditional move */
-
- emit_cmovxx(cd, iptr, s, d);
- }
-#endif
-
if (IS_INMEMORY(dst->flags)) {
COUNT_SPILLS;
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(reg);
M_BNE(8);
- M_ALD_MEM(reg, EXCEPTION_HARDWARE_ARITHMETIC);
+ M_ALD_MEM(reg, TRAP_ArithmeticException);
}
}
M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
M_ICMP(REG_ITMP3, s2);
M_BULT(8);
- M_ALD_MEM(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+ M_ALD_MEM(s2, TRAP_ArrayIndexOutOfBoundsException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(REG_RESULT);
M_BNE(8);
- M_ALD_MEM(REG_RESULT, EXCEPTION_HARDWARE_ARRAYSTORE);
+ M_ALD_MEM(REG_RESULT, TRAP_ArrayStoreException);
}
}
default:
vm_abort("emit_classcast_check: unknown condition %d", condition);
}
- M_ALD_MEM(s1, EXCEPTION_HARDWARE_CLASSCAST);
+ M_ALD_MEM(s1, TRAP_ClassCastException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(reg);
M_BNE(8);
- M_ALD_MEM(reg, EXCEPTION_HARDWARE_NULLPOINTER);
+ M_ALD_MEM(reg, TRAP_NullPointerException);
}
}
if (INSTRUCTION_MUST_CHECK(iptr)) {
M_TEST(REG_RESULT);
M_BNE(8);
- M_ALD_MEM(REG_RESULT, EXCEPTION_HARDWARE_EXCEPTION);
+ M_ALD_MEM(REG_RESULT, TRAP_CHECK_EXCEPTION);
}
}
void emit_trap_compiler(codegendata *cd)
{
- M_ALD_MEM(REG_METHODPTR, EXCEPTION_HARDWARE_COMPILER);
+ M_ALD_MEM(REG_METHODPTR, TRAP_COMPILER);
}
void emit_alu_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
if (IS_IMM8(imm)) {
- emit_rex(1,(basereg),0,0);
+ emit_rex(1,0,0,(basereg));
*(cd->mcodeptr++) = 0x83;
emit_membase(cd, (basereg),(disp),(opc));
emit_imm8((imm));
} else {
- emit_rex(1,(basereg),0,0);
+ emit_rex(1,0,0,(basereg));
*(cd->mcodeptr++) = 0x81;
emit_membase(cd, (basereg),(disp),(opc));
emit_imm32((imm));
void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
if (IS_IMM8(imm)) {
- emit_rex(0,(basereg),0,0);
+ emit_rex(0,0,0,(basereg));
*(cd->mcodeptr++) = 0x83;
emit_membase(cd, (basereg),(disp),(opc));
emit_imm8((imm));
} else {
- emit_rex(0,(basereg),0,0);
+ emit_rex(0,0,0,(basereg));
*(cd->mcodeptr++) = 0x81;
emit_membase(cd, (basereg),(disp),(opc));
emit_imm32((imm));
/* src/vm/jit/x86_64/freebsd/md-os.c - machine dependent x86_64 FreeBSD functions
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <stdlib.h>
#include <ucontext.h>
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/signallocal.h"
/* src/vm/jit/x86_64/linux/md-os.c - machine dependent x86_64 Linux functions
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/x86_64/codegen.h"
#include "vm/jit/x86_64/md.h"
-#if defined(ENABLE_THREADS)
-# include "threads/native/threads.h"
-#endif
+#include "threads/thread.h"
#include "vm/builtin.h"
-#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/executionstate.h"
+#include "vm/jit/trap.h"
#include "vm/jit/stacktrace.h"
val = _mc->gregs[d];
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
/* The PV from the compiler stub is equal to the XPC. */
pv = xpc;
else {
/* this was a normal NPE */
- type = EXCEPTION_HARDWARE_NULLPOINTER;
+ type = TRAP_NullPointerException;
val = 0;
}
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* Set registers. */
- if (type == EXCEPTION_HARDWARE_COMPILER) {
+ if (type == TRAP_COMPILER) {
if (p == NULL) {
o = builtin_retrieve_exception();
xpc = (u1 *) _mc->gregs[REG_RIP];
ra = xpc; /* return address is equal to xpc */
- /* this is an ArithmeticException */
+ /* This is an ArithmeticException. */
- type = EXCEPTION_HARDWARE_ARITHMETIC;
+ type = TRAP_ArithmeticException;
val = 0;
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* set registers */
/* This is a patcher. */
- type = EXCEPTION_HARDWARE_PATCHER;
+ type = TRAP_PATCHER;
val = 0;
- /* Handle the type. */
+ /* Handle the trap. */
- p = signal_handle(type, val, pv, sp, ra, xpc, _p);
+ p = trap_handle(type, val, pv, sp, ra, xpc, _p);
/* set registers */
#endif
-/* md_replace_executionstate_read **********************************************
+/* md_executionstate_read ******************************************************
- Read the given context into an executionstate for Replacement.
+ Read the given context into an executionstate.
*******************************************************************************/
-#if defined(ENABLE_REPLACEMENT)
-void md_replace_executionstate_read(executionstate_t *es, void *context)
+void md_executionstate_read(executionstate_t *es, void *context)
{
ucontext_t *_uc;
mcontext_t *_mc;
_mc = &_uc->uc_mcontext;
/* read special registers */
- es->pc = (u1 *) _mc->gregs[REG_RSP];
+ es->pc = (u1 *) _mc->gregs[REG_RIP];
es->sp = (u1 *) _mc->gregs[REG_RSP];
es->pv = NULL;
for (i = 0; i < FLT_REG_CNT; i++)
es->fltregs[i] = 0xdeadbeefdeadbeefL;
}
-#endif
-/* md_replace_executionstate_write *********************************************
+/* md_executionstate_write *****************************************************
- Write the given executionstate back to the context for Replacement.
+ Write the given executionstate back to the context.
*******************************************************************************/
-#if defined(ENABLE_REPLACEMENT)
-void md_replace_executionstate_write(executionstate_t *es, void *context)
+void md_executionstate_write(executionstate_t *es, void *context)
{
ucontext_t *_uc;
mcontext_t *_mc;
_mc->gregs[REG_RIP] = (ptrint) es->pc;
_mc->gregs[REG_RSP] = (ptrint) es->sp;
}
-#endif
/* md_critical_section_restart *************************************************
#ifndef _MACHINE_INSTR_H
#define _MACHINE_INSTR_H
-static inline void
-__attribute__ ((unused))
-atomic_add (volatile int *mem, int val)
-{
- __asm__ __volatile__ ("lock; addl %1,%0"
- : "=m" (*mem)
- : "ir" (val), "m" (*mem));
-}
-
static inline long
__attribute__ ((unused))
compare_and_swap (volatile long *p, long oldval, long newval)
}
#define STORE_ORDER_BARRIER() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_BEFORE_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
-#define MEMORY_BARRIER_AFTER_ATOMIC() __asm__ __volatile__ ("" : : : "memory");
+#define MEMORY_BARRIER_AFTER_ATOMIC() /* nothing */
#define MEMORY_BARRIER() __asm__ __volatile__ ( \
"mfence" : : : "memory" );
/* src/vm/jit/x86_64/md-abi.c - functions for x86_64 Linux ABI
- 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/abi.h"
#include "vm/jit/jit.h" /* for REG_* (maybe can be removed) */
+#include "vm/jit/stack.h"
#include "vmcore/descriptor.h"
*******************************************************************************/
-void md_return_alloc(jitdata *jd, stackptr stackslot)
+void md_return_alloc(jitdata *jd, stackelement_t *stackslot)
{
methodinfo *m;
codeinfo *code;
--- /dev/null
+/* src/vm/jit/x86_64/md-trap.h - x86_64 hardware traps
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _MD_TRAP_H
+#define _MD_TRAP_H
+
+#include "config.h"
+
+
+/**
+ * Trap number defines.
+ *
+ * On this architecture (x86_64) the trap numbers are used as load
+ * displacements and thus must not be 4- or 8-byte aligned.
+ *
+ * NOTE: In trap_init() we have a check whether the offset of
+ * java_arrayheader.data[0] is greater than the largest displacement
+ * defined below. Otherwise normal array loads/stores could trigger
+ * an exception.
+ */
+
+#define TRAP_INSTRUCTION_IS_LOAD 1
+
+enum {
+ TRAP_NullPointerException = 0,
+ TRAP_ArithmeticException = 1,
+ TRAP_ArrayIndexOutOfBoundsException = 2,
+ TRAP_ArrayStoreException = 3,
+
+ /* Don't use 4 (could be a normal load offset). */
+
+ TRAP_ClassCastException = 5,
+ TRAP_CHECK_EXCEPTION = 6,
+ TRAP_PATCHER = 7,
+
+ /* Don't use 8 (could be a normal load offset). */
+
+ TRAP_COMPILER = 9,
+ TRAP_END
+};
+
+#endif /* _MD_TRAP_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:
+ */
-/* src/vm/jit/x86_64/md.c - machine dependent x86_64 functions
+/* src/vm/jit/x86_64/md.h - machine dependent x86_64 functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
This file is part of CACAO.
#include <stdint.h>
#include "vm/jit/codegen-common.h"
+#include "vm/jit/methodtree.h"
/* inline functions ***********************************************************/
/* md_codegen_get_pv_from_pc ***************************************************
- On this architecture just a wrapper function to
- codegen_get_pv_from_pc.
+ On this architecture this is just a wrapper to methodtree_find.
*******************************************************************************/
void *pv;
/* Get the start address of the function which contains this
- address from the method table. */
+ address from the method tree. */
- pv = codegen_get_pv_from_pc(ra);
+ pv = methodtree_find(ra);
return pv;
}
/* src/vm/jit/x86_64/patcher.c - x86_64 code patching functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* check if the field's class is initialized */
- if (!(fi->class->state & CLASS_INITIALIZED))
- if (!initialize_class(fi->class))
+ if (!(fi->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(fi->clazz))
return false;
PATCH_BACK_ORIGINAL_MCODE;
*((int32_t *) (ra + 3 + 3)) =
(int32_t) (OFFSET(vftbl_t, interfacetable[0]) -
- sizeof(methodptr) * m->class->index);
+ sizeof(methodptr) * m->clazz->index);
/* patch method offset */
*((int32_t *) (ra + 3 + 7 + 3)) =
- (int32_t) (sizeof(methodptr) * (m - m->class->methods));
+ (int32_t) (sizeof(methodptr) * (m - m->clazz->methods));
return true;
}
/* src/vm/jit_interface.h - prototypes of jit functions used in vm/ code
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
void code_free_code_of_method(methodinfo *m);
-methodinfo *code_get_methodinfo_for_pv(u1 *pv);
-
u1 *codegen_generate_stub_compiler(methodinfo *m);
codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f);
/* src/vm/package.c - Java boot-package functions
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
void package_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("package_init");
+
/* create the properties list */
list_package = list_create(OFFSET(list_package_entry_t, linkage));
/* src/vm/primitive.c - primitive types
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
int type;
imm_union value;
+ if (o == NULL) {
+ value.a = NULL;
+ return value;
+ }
+
LLNI_class_get(o, c);
type = primitive_type_get_by_wrapperclass(c);
/* src/vm/properties.c - handling commandline properties
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <unistd.h>
#include <sys/utsname.h>
-#if defined(WITH_JRE_LAYOUT)
-# include <libgen.h>
-#endif
-
#include "vm/types.h"
#include "mm/memory.h"
#include "vmcore/class.h"
#include "vmcore/method.h"
#include "vmcore/options.h"
+#include "vmcore/system.h"
/* internal property structure ************************************************/
void properties_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("properties_init");
+
list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
}
# endif
#endif
-#if defined(WITH_JRE_LAYOUT)
+#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));
- /* Get the path of the current executable. */
+ /* We have a path like:
- p = dirname(p);
+ /path/to/executable/bin/java
-# if defined(WITH_CLASSPATH_GNU)
+ or
+
+ /path/to/executeable/jre/bin/java
- /* Set java.home. */
+ Now let's strip two levels. */
- len = strlen(p) + strlen("/..") + strlen("0");
+ p = system_dirname(p);
+ p = system_dirname(p);
- java_home = MNEW(char, len);
+# if defined(WITH_CLASSPATH_GNU)
- strcpy(java_home, p);
- strcat(java_home, "/..");
+ /* Set java.home. */
+
+ java_home = strdup(p);
/* Set the path to Java core native libraries. */
len =
strlen(p) +
- strlen("/../jre/lib/"JAVA_ARCH"/server/libjvm.so") +
+ 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");
+ strcat(java_home, "/jre/lib/"JAVA_ARCH"/server/libjvm.so");
/* Check if that libjvm.so exists. */
- if (access(java_home, F_OK) == 0) {
+ if (system_access(java_home, F_OK) == 0) {
/* Yes, we add /jre to java.home. */
strcpy(java_home, p);
- strcat(java_home, "/../jre");
+ strcat(java_home, "/jre");
}
else {
/* No, java.home is parent directory. */
strcpy(java_home, p);
- strcat(java_home, "/..");
}
/* Set the path to Java core native libraries. */
strcpy(boot_class_path, p);
}
else {
-#if defined(WITH_JRE_LAYOUT)
+#if defined(ENABLE_JRE_LAYOUT)
# if defined(WITH_CLASSPATH_GNU)
len =
/* search for the entry */
- for (pe = list_first_unsynced(list_properties); pe != NULL;
- pe = list_next_unsynced(list_properties, pe)) {
+ 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 */
pe->key = key;
pe->value = value;
- list_add_last_unsynced(list_properties, pe);
+ list_add_last(list_properties, pe);
}
{
list_properties_entry_t *pe;
- for (pe = list_first_unsynced(list_properties); pe != NULL;
- pe = list_next_unsynced(list_properties, pe)) {
+ for (pe = list_first(list_properties); pe != NULL;
+ pe = list_next(list_properties, pe)) {
if (strcmp(pe->key, key) == 0)
return pe->value;
}
list_t *l;
list_properties_entry_t *pe;
+ /* For convenience. */
+
l = list_properties;
- for (pe = list_first_unsynced(l); pe != NULL;
- pe = list_next_unsynced(l, pe)) {
+ for (pe = list_first(l); pe != NULL; pe = list_next(l, pe)) {
log_println("[properties_dump: key=%s, value=%s]", pe->key, pe->value);
}
}
/* src/vm/resolve.c - resolving classes/interfaces/fields/methods
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/*#define RESOLVE_VERBOSE*/
+/* resolve_handle_pending_exception ********************************************
+
+ Convert a pending ClassNotFoundException into a
+ NoClassDefFoundError if requested.
+
+ See: hotspot/src/share/vm/classfile/systemDictionary.cpp
+ (handle_resolution_exception)
+
+ ARGUMENTS:
+ classname .... name of the class currently resolved
+ throwError ... if true throw a NoClassDefFoundError instead of
+ a ClassNotFoundException
+
+*******************************************************************************/
+
+void resolve_handle_pending_exception(bool throwError)
+{
+ java_handle_t *e;
+
+ /* Get the current exception. */
+
+ e = exceptions_get_exception();
+
+ if (e != NULL) {
+ if (throwError == true) {
+ /* Convert ClassNotFoundException to
+ NoClassDefFoundError. */
+
+ if (builtin_instanceof(e, class_java_lang_ClassNotFoundException)) {
+ /* Clear exception, because we are calling Java code
+ again. */
+
+ exceptions_clear_exception();
+
+ /* create new error */
+
+ exceptions_throw_noclassdeffounderror_cause(e);
+ }
+ else {
+ return;
+ }
+ }
+ else {
+ /* An exception conversion was not requested. Simply
+ return. */
+
+ return;
+ }
+ }
+}
+
+
/******************************************************************************/
/* CLASS RESOLUTION */
/******************************************************************************/
if (cls == NULL) {
cls = load_class_from_classloader(classname, referer->classloader);
- if (cls == NULL) {
- /* If the exception is a ClassNotFoundException,
- convert it to a NoClassDefFoundError. */
-
- exceptions_classnotfoundexception_to_noclassdeffounderror();
-
+ if (cls == NULL)
return false;
- }
}
}
Resolve a symbolic class reference if necessary
- NOTE: If given, refmethod->class is used as the referring class.
+ NOTE: If given, refmethod->clazz is used as the referring class.
Otherwise, cls.ref->referer is used.
IN:
/* being the same, so the referer usually is cls.ref->referer. */
/* There is one important case where it is not: When we do a */
/* deferred assignability check to a formal argument of a method, */
- /* we must use refmethod->class (the caller's class) to resolve */
+ /* we must use refmethod->clazz (the caller's class) to resolve */
/* the type of the formal argument. */
- referer = (refmethod) ? refmethod->class : cls.ref->referer;
+ referer = (refmethod) ? refmethod->clazz : cls.ref->referer;
if (!resolve_class_from_name(referer, refmethod, cls.ref->name,
mode, checkaccess, link, &c))
resolve_err_t error)
{
classinfo *subclass;
- typeinfo subti;
+ typeinfo_t subti;
typecheck_result r;
char *msg;
s4 msglen;
#if defined(ENABLE_VERIFIER)
static resolve_result_t resolve_lazy_subtype_checks(methodinfo *refmethod,
- typeinfo *subtinfo,
+ typeinfo_t *subtinfo,
classref_or_classinfo supertype,
resolve_err_t error)
{
if (supertype.cls == class_java_lang_Object
|| (CLASSREF_OR_CLASSINFO_NAME(supertype) == utf_java_lang_Object
- && refmethod->class->classloader == NULL))
+ && refmethod->clazz->classloader == NULL))
{
return resolveSucceeded;
}
constant_FMIref *fieldref,
classinfo *container,
fieldinfo *fi,
- typeinfo *instanceti,
- typeinfo *valueti,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti,
bool isstatic,
bool isput)
{
/* get the classinfos and the field type */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- declarer = fi->class;
+ declarer = fi->clazz;
assert(declarer);
assert(referer->state & CLASS_LINKED);
/* instance type */
if (instanceti) {
- typeinfo *insttip;
- typeinfo tinfo;
+ typeinfo_t *insttip;
+ typeinfo_t tinfo;
/* The instanceslot must contain a reference to a non-array type */
return resolveFailed;
}
- /* XXX check that class of field == refmethod->class */
+ /* XXX check that class of field == refmethod->clazz */
initclass = referer; /* XXX classrefs */
assert(initclass->state & CLASS_LINKED);
/* the class containing the reference */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
/* check if the field itself is already resolved */
/* the class containing the reference */
- referer = ref->referermethod->class;
+ referer = ref->referermethod->clazz;
assert(referer);
/* check if the field itself is already resolved */
if (IS_FMIREF_RESOLVED(ref->fieldref)) {
fi = ref->fieldref->p.field;
- container = fi->class;
+ container = fi->clazz;
goto resolved_the_field;
}
if (checkresult != resolveSucceeded)
return (bool) checkresult;
- declarer = fi->class;
+ declarer = fi->clazz;
assert(declarer);
assert(declarer->state & CLASS_LOADED);
assert(declarer->state & CLASS_LINKED);
/* get referer and declarer classes */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- declarer = mi->class;
+ declarer = mi->clazz;
assert(declarer);
assert(referer->state & CLASS_LINKED);
/* get the classinfos and the method descriptor */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
- declarer = mi->class;
+ declarer = mi->clazz;
assert(declarer);
/* check static */
#if defined(ENABLE_VERIFIER)
resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
methodinfo *mi,
- typeinfo *instanceti,
+ typeinfo_t *instanceti,
bool invokespecial)
{
- typeinfo tinfo;
- typeinfo *tip;
+ typeinfo_t tinfo;
+ typeinfo_t *tip;
resolve_result_t result;
if (invokespecial && TYPEINFO_IS_NEWOBJECT(*instanceti))
{ /* XXX clean up */
instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->class);
+ : CLASSREF_OR_CLASSINFO(refmethod->clazz);
tip = &tinfo;
if (!typeinfo_init_class(tip, initclass))
return false;
result = resolve_lazy_subtype_checks(refmethod,
tip,
- CLASSREF_OR_CLASSINFO(mi->class),
+ CLASSREF_OR_CLASSINFO(mi->clazz),
resolveLinkageError);
if (result != resolveSucceeded)
return result;
/* check protected access */
- /* XXX use other `declarer` than mi->class? */
+ /* XXX use other `declarer` than mi->clazz? */
if (((mi->flags & ACC_PROTECTED) != 0)
- && !SAME_PACKAGE(mi->class, refmethod->class))
+ && !SAME_PACKAGE(mi->clazz, refmethod->clazz))
{
result = resolve_lazy_subtype_checks(refmethod,
tip,
- CLASSREF_OR_CLASSINFO(refmethod->class),
+ CLASSREF_OR_CLASSINFO(refmethod->clazz),
resolveIllegalAccessError);
if (result != resolveSucceeded)
return result;
methodinfo *refmethod,
methodinfo *mi,
bool invokestatic,
- typedescriptor *stack)
+ typedescriptor_t *stack)
{
- typedescriptor *param;
+ typedescriptor_t *param;
resolve_result_t result;
methoddesc *md;
typedesc *paramtypes;
/* the method definition. Since container is the same as, */
/* or a subclass of declarer, we also constrain declarer */
/* by transitivity of loading constraints. */
- name = mi->class->name;
+ name = mi->clazz->name;
}
else {
name = paramtypes[i].classref->name;
/* The caller (referer) and the callee (container) must agree */
/* on the types of the parameters. */
if (!classcache_add_constraint(referer->classloader,
- mi->class->classloader, name))
+ mi->clazz->classloader, name))
return false; /* exception */
}
}
/* The caller (referer) and the callee (container) must agree */
/* on the return type. */
if (!classcache_add_constraint(referer->classloader,
- mi->class->classloader,
+ mi->clazz->classloader,
md->returntype.classref->name))
return false; /* exception */
}
/* the class containing the reference */
- referer = refmethod->class;
+ referer = refmethod->clazz;
assert(referer);
/* check if the method itself is already resolved */
/* the class containing the reference */
- referer = ref->referermethod->class;
+ referer = ref->referermethod->clazz;
assert(referer);
/* check if the method itself is already resolved */
if (IS_FMIREF_RESOLVED(ref->methodref)) {
mi = ref->methodref->p.method;
- container = mi->class;
+ container = mi->clazz;
goto resolved_the_method;
}
if (!resolve_method_loading_constraints(referer, mi))
return false;
- declarer = mi->class;
+ declarer = mi->clazz;
assert(declarer);
assert(referer->state & CLASS_LINKED);
static bool unresolved_subtype_set_from_typeinfo(classinfo *referer,
methodinfo *refmethod,
unresolved_subtype_set *stset,
- typeinfo *tinfo,
+ typeinfo_t *tinfo,
utf *declaredclassname)
{
int count;
#ifdef ENABLE_VERIFIER
unresolved_class * create_unresolved_class(methodinfo *refmethod,
constant_classref *classref,
- typeinfo *valuetype)
+ typeinfo_t *valuetype)
{
unresolved_class *ref;
bool resolve_constrain_unresolved_field(unresolved_field *ref,
classinfo *referer,
methodinfo *refmethod,
- typeinfo *instanceti,
- typeinfo *valueti)
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti)
{
constant_FMIref *fieldref;
int type;
- typeinfo tinfo;
+ typeinfo_t tinfo;
typedesc *fd;
assert(ref);
/* record subtype constraints for the instance type, if any */
if (instanceti) {
- typeinfo *insttip;
+ typeinfo_t *insttip;
/* The instanceslot must contain a reference to a non-array type */
if (!TYPEINFO_IS_REFERENCE(*instanceti)) {
"accessing field of uninitialized object");
return false;
}
- /* XXX check that class of field == refmethod->class */
- initclass = refmethod->class; /* XXX classrefs */
+ /* XXX check that class of field == refmethod->clazz */
+ initclass = refmethod->clazz; /* XXX classrefs */
assert(initclass->state & CLASS_LOADED);
assert(initclass->state & CLASS_LINKED);
#if defined(ENABLE_VERIFIER)
bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
methodinfo *refmethod,
- typeinfo *instanceti,
+ typeinfo_t *instanceti,
bool invokespecial)
{
constant_FMIref *methodref;
constant_classref *instanceref;
- typeinfo tinfo;
- typeinfo *tip;
+ typeinfo_t tinfo;
+ typeinfo_t *tip;
assert(ref);
methodref = ref->methodref;
/* XXX clean this up */
instanceref = IS_FMIREF_RESOLVED(methodref)
- ? class_get_self_classref(methodref->p.method->class)
+ ? class_get_self_classref(methodref->p.method->clazz)
: methodref->p.classref;
#ifdef RESOLVE_VERBOSE
{ /* XXX clean up */
instruction *ins = (instruction *) TYPEINFO_NEWOBJECT_INSTRUCTION(*instanceti);
classref_or_classinfo initclass = (ins) ? ins[-1].sx.val.c
- : CLASSREF_OR_CLASSINFO(refmethod->class);
+ : CLASSREF_OR_CLASSINFO(refmethod->clazz);
tip = &tinfo;
if (!typeinfo_init_class(tip, initclass))
return false;
tip = instanceti;
}
- if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
&(ref->instancetypes),tip,instanceref->name))
return false;
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
}
assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
ref->paramconstraints + i,&(param->typeinfo),
md->paramtypes[i+instancecount].classref->name))
return false;
bool resolve_constrain_unresolved_method_params_stackbased(
unresolved_method *ref,
methodinfo *refmethod,
- typedescriptor *stack)
+ typedescriptor_t *stack)
{
constant_FMIref *methodref;
- typedescriptor *param;
+ typedescriptor_t *param;
methoddesc *md;
int i,j;
int type;
UNRESOLVED_SUBTYPE_SET_EMTPY(ref->paramconstraints[j]);
}
assert(ref->paramconstraints);
- if (!unresolved_subtype_set_from_typeinfo(refmethod->class, refmethod,
+ if (!unresolved_subtype_set_from_typeinfo(refmethod->clazz, refmethod,
ref->paramconstraints + i - instancecount,&(param->typeinfo),
md->paramtypes[i].classref->name))
return false;
fprintf(file,"unresolved_field(%p):\n",(void *)ref);
if (ref) {
fprintf(file," referer : ");
- utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
+ utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
fprintf(file," refmethod : ");
utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
fprintf(file," refmethodd: ");
fprintf(file,"unresolved_method(%p):\n",(void *)ref);
if (ref) {
fprintf(file," referer : ");
- utf_fprint_printable_ascii(file,ref->referermethod->class->name); fputc('\n',file);
+ utf_fprint_printable_ascii(file,ref->referermethod->clazz->name); fputc('\n',file);
fprintf(file," refmethod : ");
utf_fprint_printable_ascii(file,ref->referermethod->name); fputc('\n',file);
fprintf(file," refmethodd: ");
/* src/vm/resolve.h - resolving classes/interfaces/fields/methods
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#define UNRESOLVED_SUBTYPE_SET_EMTPY(stset) \
do { (stset).subtyperefs = NULL; } while(0)
+
/* function prototypes ********************************************************/
+void resolve_handle_pending_exception(bool throwError);
+
bool resolve_class_from_name(classinfo* referer,methodinfo *refmethod,
utf *classname,
resolve_mode_t mode,
#ifdef ENABLE_VERIFIER
unresolved_class * create_unresolved_class(methodinfo *refmethod,
constant_classref *classref,
- typeinfo *valuetype);
+ typeinfo_t *valuetype);
#endif
unresolved_field *resolve_create_unresolved_field(classinfo *referer,
constant_FMIref *fieldref,
classinfo *container,
fieldinfo *fi,
- typeinfo *instanceti,
- typeinfo *valueti,
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti,
bool isstatic,
bool isput);
bool resolve_constrain_unresolved_field(unresolved_field *ref,
classinfo *referer,
methodinfo *refmethod,
- typeinfo *instanceti,
- typeinfo *valueti);
+ typeinfo_t *instanceti,
+ typeinfo_t *valueti);
resolve_result_t resolve_method_verifier_checks(methodinfo *refmethod,
constant_FMIref *methodref,
resolve_result_t resolve_method_instance_type_checks(methodinfo *refmethod,
methodinfo *mi,
- typeinfo *instanceti,
+ typeinfo_t *instanceti,
bool invokespecial);
resolve_result_t resolve_method_param_type_checks(jitdata *jd,
methodinfo *refmethod,
methodinfo *mi,
bool invokestatic,
- typedescriptor *stack);
+ typedescriptor_t *stack);
bool resolve_method_loading_constraints(classinfo *referer,
methodinfo *mi);
bool resolve_constrain_unresolved_method_instance(unresolved_method *ref,
methodinfo *refmethod,
- typeinfo *instanceti,
+ typeinfo_t *instanceti,
bool invokespecial);
bool resolve_constrain_unresolved_method_params(jitdata *jd,
bool resolve_constrain_unresolved_method_params_stackbased(
unresolved_method *ref,
methodinfo *refmethod,
- typedescriptor *stack);
+ typedescriptor_t *stack);
#endif /* defined(ENABLE_VERIFIER) */
/* src/vm/signal.c - machine independent signal functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include <assert.h>
-#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
/* If we compile with -ansi on darwin, <sys/types.h> is not
included. So let's do it here. */
# include <sys/types.h>
+# include <sys/utsname.h>
#endif
#include "arch.h"
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#if defined(ENABLE_THREADS)
-# include "threads/threads-common.h"
-#else
-# include "threads/none/threads.h"
-#endif
-
-#include "toolbox/logging.h"
+#include "threads/thread.h"
#include "vm/exceptions.h"
#include "vm/signallocal.h"
#include "vm/vm.h"
-#include "vm/jit/codegen-common.h"
-#include "vm/jit/disass.h"
-#include "vm/jit/patcher-common.h"
-
#include "vmcore/options.h"
#if defined(ENABLE_STATISTICS)
#if !defined(__CYGWIN__)
sigset_t mask;
+ TRACESUBSYSTEMINITIALIZATION("signal_init");
+
#if defined(__LINUX__) && defined(ENABLE_THREADS)
/* XXX Remove for exact-GC. */
if (threads_pthreads_implementation_nptl) {
this thread. */
if (sigemptyset(&mask) != 0)
- vm_abort("signal_init: sigemptyset failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigemptyset failed");
#if !defined(WITH_CLASSPATH_SUN)
/* Let OpenJDK handle SIGINT itself. */
if (sigaddset(&mask, SIGINT) != 0)
- vm_abort("signal_init: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigaddset failed");
#endif
#if !defined(__FREEBSD__)
if (sigaddset(&mask, SIGQUIT) != 0)
- vm_abort("signal_init: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigaddset failed");
#endif
if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
- vm_abort("signal_init: sigprocmask failed: %s", strerror(errno));
+ vm_abort_errno("signal_init: sigprocmask failed");
#if defined(__LINUX__) && defined(ENABLE_THREADS)
/* XXX Remove for exact-GC. */
# if defined(ENABLE_INTRP)
}
# endif
-#endif /* !defined(ENABLE_INTRP) */
+
+#if defined(__DARWIN__)
+ do {
+ struct utsname name;
+ kern_return_t kr;
+
+ /* Check if we're on 10.4 (Tiger/8.x) or earlier */
+ if (uname(&name) != 0)
+ break;
+
+ /* Make sure the string is large enough */
+ /* Check the major number (ascii comparison) */
+ /* Verify that we're not looking at '10.' by checking for a trailing period. */
+ if (name.release[0] == '\0' || name.release[0] > '8' || name.release[1] != '.')
+ break;
+
+ /* Reset CrashReporter's task signal handler */
+ kr = task_set_exception_ports(mach_task_self(),
+ EXC_MASK_BAD_ACCESS
+# if defined(__I386__)
+ | EXC_MASK_BAD_INSTRUCTION
+#endif
+ , MACH_PORT_NULL,
+ EXCEPTION_STATE_IDENTITY,
+ MACHINE_THREAD_STATE);
+
+ assert(kr == KERN_SUCCESS);
+ } while (false);
+#endif
+#endif /* !defined(ENABLE_JIT) */
#if defined(ENABLE_THREADS)
/* SIGHUP handler for threads_thread_interrupt */
function = (void (*)(int, siginfo_t *, void *)) handler;
if (sigemptyset(&act.sa_mask) != 0)
- vm_abort("signal_register_signal: sigemptyset failed: %s",
- strerror(errno));
+ vm_abort_errno("signal_register_signal: sigemptyset failed");
act.sa_sigaction = function;
act.sa_flags = flags;
if (sigaction(signum, &act, NULL) != 0)
- vm_abort("signal_register_signal: sigaction failed: %s",
- strerror(errno));
-}
-
-
-/* signal_handle ***************************************************************
-
- Handles the signal caught by a signal handler and calls the correct
- function.
-
-*******************************************************************************/
-
-void *signal_handle(int type, intptr_t val,
- void *pv, void *sp, void *ra, void *xpc, void *context)
-{
- stackframeinfo_t sfi;
- int32_t index;
- java_handle_t *o;
- methodinfo *m;
- java_handle_t *p;
-
- /* Prevent compiler warnings. */
-
- o = NULL;
- m = NULL;
-
- /* wrap the value into a handle if it is a reference */
- /* BEFORE: creating stackframeinfo */
-
- switch (type) {
- case EXCEPTION_HARDWARE_CLASSCAST:
- o = LLNI_WRAP((java_object_t *) val);
- break;
-
- case EXCEPTION_HARDWARE_COMPILER:
- /* In this case the passed PV points to the compiler stub. We
- get the methodinfo pointer here and set PV to NULL so
- stacktrace_stackframeinfo_add determines the PV for the
- parent Java method. */
-
- m = code_get_methodinfo_for_pv(pv);
- pv = NULL;
- break;
-
- default:
- /* do nothing */
- break;
- }
-
- /* Fill and add a stackframeinfo. */
-
- stacktrace_stackframeinfo_add(&sfi, pv, sp, ra, xpc);
-
- switch (type) {
- case EXCEPTION_HARDWARE_NULLPOINTER:
- p = exceptions_new_nullpointerexception();
- break;
-
- case EXCEPTION_HARDWARE_ARITHMETIC:
- p = exceptions_new_arithmeticexception();
- break;
-
- case EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS:
- index = (s4) val;
- p = exceptions_new_arrayindexoutofboundsexception(index);
- break;
-
- case EXCEPTION_HARDWARE_ARRAYSTORE:
- p = exceptions_new_arraystoreexception();
- break;
-
- case EXCEPTION_HARDWARE_CLASSCAST:
- p = exceptions_new_classcastexception(o);
- break;
-
- case EXCEPTION_HARDWARE_EXCEPTION:
- p = exceptions_fillinstacktrace();
- break;
-
- case EXCEPTION_HARDWARE_PATCHER:
-#if defined(ENABLE_REPLACEMENT)
- if (replace_me_wrapper(xpc, context)) {
- p = NULL;
- break;
- }
-#endif
- p = patcher_handler(xpc);
- break;
-
- case EXCEPTION_HARDWARE_COMPILER:
- p = jit_compile_handle(m, sfi.pv, ra, (void *) val);
- break;
-
- default:
- /* Let's try to get a backtrace. */
-
- codegen_get_pv_from_pc(xpc);
-
- /* If that does not work, print more debug info. */
-
- log_println("signal_handle: unknown hardware exception type %d", type);
-
-#if SIZEOF_VOID_P == 8
- log_println("PC=0x%016lx", xpc);
-#else
- log_println("PC=0x%08x", xpc);
-#endif
-
-#if defined(ENABLE_DISASSEMBLER)
- log_println("machine instruction at PC:");
- disassinstr(xpc);
-#endif
-
- vm_abort("Exiting...");
-
- /* keep compiler happy */
-
- p = NULL;
- }
-
- /* Remove stackframeinfo. */
-
- stacktrace_stackframeinfo_remove(&sfi);
-
- /* unwrap and return the exception object */
- /* AFTER: removing stackframeinfo */
-
- if (type == EXCEPTION_HARDWARE_COMPILER)
- return p;
- else
- return LLNI_UNWRAP(p);
+ vm_abort_errno("signal_register_signal: sigaction failed");
}
t = THREADOBJECT;
if (sigemptyset(&mask) != 0)
- vm_abort("signal_thread: sigemptyset failed: %s", strerror(errno));
+ vm_abort_errno("signal_thread: sigemptyset failed");
#if !defined(WITH_CLASSPATH_SUN)
/* Let OpenJDK handle SIGINT itself. */
if (sigaddset(&mask, SIGINT) != 0)
- vm_abort("signal_thread: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_thread: sigaddset failed");
#endif
#if !defined(__FREEBSD__)
if (sigaddset(&mask, SIGQUIT) != 0)
- vm_abort("signal_thread: sigaddset failed: %s", strerror(errno));
+ vm_abort_errno("signal_thread: sigaddset failed");
#endif
for (;;) {
/* just wait for a signal */
#if defined(ENABLE_THREADS)
- threads_thread_state_waiting(t);
+ thread_set_state_waiting(t);
#endif
/* XXX We don't check for an error here, although the man-page
revisit this code with our new exact-GC. */
/* if (sigwait(&mask, &sig) != 0) */
-/* vm_abort("signal_thread: sigwait failed: %s", strerror(errno)); */
+/* vm_abort_errno("signal_thread: sigwait failed"); */
(void) sigwait(&mask, &sig);
#if defined(ENABLE_THREADS)
- threads_thread_state_runnable(t);
+ thread_set_state_runnable(t);
#endif
/* Handle the signal. */
bool signal_init(void);
void signal_register_signal(int signum, functionptr handler, int flags);
-void *signal_handle(int type, intptr_t val,
- void *pv, void *sp, void *ra, void *xpc, void *context);
-
void signal_thread_handler(int sig);
bool signal_start_thread(void);
/* src/vm/string.c - java.lang.String related functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include <assert.h>
+#include "vmcore/system.h"
+
#include "vm/types.h"
#include "vm/global.h"
bool string_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("string_init");
+
/* create string (javastring) hashtable */
hashtable_create(&hashtable_string, HASHTABLE_STRING_SIZE);
s4 nbytes;
s4 len;
- assert(text);
+ if (text == NULL)
+ return NULL;
/* Get number of bytes. We need this to completely emulate the messy */
/* behaviour of the RI. :( */
*******************************************************************************/
+#if 0
+/* TWISTI This one is currently not used. */
+
static void literalstring_free(java_object_t* string)
{
heapstring_t *s;
/* dispose memory of java-characterarray */
FREE(a, sizeof(java_chararray_t) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
}
+#endif
/* javastring_intern ***********************************************************
}
-/* javastring_print ************************************************************
+/* javastring_fprint ***********************************************************
- Print the given Java string.
+ Print the given Java string to the given stream.
*******************************************************************************/
-void javastring_print(java_handle_t *s)
+void javastring_fprint(java_handle_t *s, FILE *stream)
{
java_lang_String *so;
java_handle_chararray_t *value;
for (i = offset; i < offset + count; i++) {
c = LLNI_array_direct(value, i);
- putchar(c);
+ fputc(c, stream);
}
}
/* src/vm/stringlocal.h - string header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
+
+#include "vmcore/system.h"
+
#include "vm/types.h"
#include "toolbox/hashtable.h"
java_object_t *literalstring_new(utf *u);
java_handle_t *javastring_intern(java_handle_t *s);
-void javastring_print(java_handle_t *s);
+void javastring_fprint(java_handle_t *s, FILE *stream);
#endif /* _STRINGLOCAL_H */
/* src/vm/vm.c - VM startup and shutdown functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/abi-asm.h"
+#include "mm/codememory.h"
#include "mm/gc-common.h"
#include "mm/memory.h"
#include "native/vm/nativevm.h"
-#include "threads/threads-common.h"
+#include "threads/lock-common.h"
+#include "threads/mutex.h"
+#include "threads/threadlist.h"
+#include "threads/thread.h"
#include "toolbox/logging.h"
#include "vm/jit/argument.h"
#include "vm/jit/asmpart.h"
+#include "vm/jit/code.h"
#if defined(ENABLE_DISASSEMBLER)
# include "vm/jit/disass.h"
#endif
#include "vm/jit/jit.h"
+#include "vm/jit/methodtree.h"
#if defined(ENABLE_PROFILING)
# include "vm/jit/optimizing/profile.h"
#include "vm/jit/optimizing/recompile.h"
+#if defined(ENABLE_PYTHON)
+# include "vm/jit/python.h"
+#endif
+
+#include "vm/jit/trap.h"
+
#include "vmcore/classcache.h"
#include "vmcore/options.h"
#include "vmcore/statistics.h"
#include "vmcore/suck.h"
+#include "vmcore/system.h"
#if defined(ENABLE_JVMTI)
# include "native/jvmti/cacaodbg.h"
s4 vms = 0; /* number of VMs created */
bool vm_initializing = false;
-bool vm_exiting = false;
+bool vm_created = false;
+bool vm_exiting = false;
char *mainstring = NULL;
classinfo *mainclass = NULL;
OPT_EA,
OPT_DA,
+ OPT_EA_NOARG,
+ OPT_DA_NOARG,
+
OPT_ESA,
OPT_DSA,
OPT_LSRA,
#endif
-#if defined(ENABLE_INLINING)
- OPT_INLINING,
-#if !defined(NDEBUG)
- OPT_INLINE_LOG,
-#endif
-#if defined(ENABLE_INLINING_DEBUG)
- OPT_INLINE_DEBUG_ALL,
- OPT_INLINE_DEBUG_END,
- OPT_INLINE_DEBUG_MIN,
- OPT_INLINE_DEBUG_MAX,
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#endif /* defined(ENABLE_INLINING) */
-
#if defined(ENABLE_INTRP)
/* interpreter options */
{ "ea:", true, OPT_EA },
{ "da:", true, OPT_DA },
- { "ea", false, OPT_EA },
- { "da", false, OPT_DA },
+ { "ea", false, OPT_EA_NOARG },
+ { "da", false, OPT_DA_NOARG },
+
+ { "enableassertions:", true, OPT_EA },
+ { "disableassertions:", true, OPT_DA },
+ { "enableassertions", false, OPT_EA_NOARG },
+ { "disableassertions", false, OPT_DA_NOARG },
{ "esa", false, OPT_ESA },
{ "enablesystemassertions", false, OPT_ESA },
#if defined(ENABLE_IFCONV)
{ "ifconv", false, OPT_IFCONV },
#endif
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+#if defined(ENABLE_LSRA)
{ "lsra", false, OPT_LSRA },
#endif
+#if defined(ENABLE_SSA)
+ { "lsra", true, OPT_LSRA },
+#endif
#if defined(ENABLE_INTRP)
/* interpreter options */
{ "Xprof", false, OPT_PROF },
#endif
- /* inlining options */
-
-#if defined(ENABLE_INLINING)
-#if defined(ENABLE_INLINING_DEBUG)
- { "ia", false, OPT_INLINE_DEBUG_ALL },
- { "ii", true, OPT_INLINE_DEBUG_MIN },
- { "im", true, OPT_INLINE_DEBUG_MAX },
- { "ie", true, OPT_INLINE_DEBUG_END },
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#if !defined(NDEBUG)
- { "il", false, OPT_INLINE_LOG },
-#endif
- { "i", false, OPT_INLINING },
-#endif /* defined(ENABLE_INLINING) */
-
/* keep these at the end of the list */
#if !defined(NDEBUG)
#endif
puts(" (d)atasegment data segment listing");
-#if defined(ENABLE_INLINING)
- puts(" -i activate inlining");
-#if !defined(NDEBUG)
- puts(" -il log inlining");
-#endif
-#if defined(ENABLE_INLINING_DEBUG)
- puts(" -ia use inlining for all methods");
- puts(" -ii <size> set minimum size for inlined result");
- puts(" -im <size> set maximum size for inlined result");
- puts(" -ie <number> stop inlining after the given number of roots");
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#endif /* defined(ENABLE_INLINING) */
-
#if defined(ENABLE_IFCONV)
puts(" -ifconv use if-conversion");
#endif
puts(" -lsra use linear scan register allocation");
#endif
#if defined(ENABLE_SSA)
- puts(" -lsra use linear scan register allocation (with SSA)");
+ puts(" -lsra:... use linear scan register allocation (with SSA)");
+ puts(" (d)ead code elimination");
+ puts(" (c)opy propagation");
#endif
#if defined(ENABLE_DEBUG_FILTER)
puts(" -XXfi <regex> begin of dynamic scope for verbosecall filter");
static void version(bool opt_exit)
{
puts("java version \""JAVA_VERSION"\"");
- puts("CACAO version "VERSION"");
-
- puts("Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,");
- puts("C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,");
- puts("E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,");
- puts("J. Wenninger, Institut f. Computersprachen - TU Wien\n");
+ puts("CACAO version "VERSION"\n");
- puts("This program is free software; you can redistribute it and/or");
- puts("modify it under the terms of the GNU General Public License as");
- puts("published by the Free Software Foundation; either version 2, or (at");
- puts("your option) any later version.\n");
-
- puts("This program is distributed in the hope that it will be useful, but");
- puts("WITHOUT ANY WARRANTY; without even the implied warranty of");
- puts("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU");
- puts("General Public License for more details.");
+ puts("Copyright (C) 1996-2005, 2006, 2007, 2008");
+ puts("CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
+ puts("This is free software; see the source for copying conditions. There is NO");
+ puts("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
/* exit normally, if requested */
printf(" initial heap size : %d\n", HEAP_STARTSIZE);
printf(" stack size : %d\n", STACK_SIZE);
-#if defined(WITH_JRE_LAYOUT)
+#if defined(ENABLE_JRE_LAYOUT)
/* When we're building with JRE-layout, the default paths are the
same as the runtime paths. */
#else
jdwp = agentbypath = false;
#endif
-#if defined(ENABLE_VMLOG)
- vmlog_cacao_init(vm_args);
-#endif
-
#if defined(ENABLE_JNI)
/* Check the JNI version requested. */
/* First of all, parse the -XX options. */
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_init_options();
+#endif
+
options_xx(vm_args);
+#if defined(ENABLE_VMLOG)
+ vmlog_cacao_init();
+#endif
+
/* We need to check if the actual size of a java.lang.Class object
is smaller or equal than the assumption made in
src/vmcore/class.h. */
break;
#endif
-#if defined(ENABLE_INLINING)
-#if defined(ENABLE_INLINING_DEBUG)
- case OPT_INLINE_DEBUG_ALL:
- opt_inline_debug_all = true;
- break;
- case OPT_INLINE_DEBUG_END:
- opt_inline_debug_end_counter = atoi(opt_arg);
- break;
- case OPT_INLINE_DEBUG_MIN:
- opt_inline_debug_min_size = atoi(opt_arg);
- break;
- case OPT_INLINE_DEBUG_MAX:
- opt_inline_debug_max_size = atoi(opt_arg);
- break;
-#endif /* defined(ENABLE_INLINING_DEBUG) */
-#if !defined(NDEBUG)
- case OPT_INLINE_LOG:
- opt_inline_debug_log = true;
- break;
-#endif /* !defined(NDEBUG) */
-
- case OPT_INLINING:
- opt_inlining = true;
- break;
-#endif /* defined(ENABLE_INLINING) */
-
#if defined(ENABLE_IFCONV)
case OPT_IFCONV:
opt_ifconv = true;
break;
#endif
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+#if defined(ENABLE_LSRA)
+ case OPT_LSRA:
+ opt_lsra = true;
+ break;
+#endif
+#if defined(ENABLE_SSA)
case OPT_LSRA:
opt_lsra = true;
+ for (i = 0; i < strlen(opt_arg); i++) {
+ switch (opt_arg[i]) {
+ case 'c':
+ opt_ssa_cp = true;
+ break;
+
+ case 'd':
+ opt_ssa_dce = true;
+ break;
+
+ case ':':
+ break;
+
+ default:
+ usage();
+ }
+ }
break;
#endif
#endif
break;
+ case OPT_EA_NOARG:
+#if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = true;
+#endif
+ break;
+
+ case OPT_DA_NOARG:
+#if defined(ENABLE_ASSERTION)
+ assertion_user_enabled = false;
+#endif
+ break;
+
case OPT_ESA:
#if defined(ENABLE_ASSERTION)
assertion_system_enabled = true;
gc_init(opt_heapmaxsize, opt_heapstartsize);
#if defined(ENABLE_THREADS)
+ /* BEFORE: threads_preinit */
+
+ threadlist_init();
+
/* AFTER: gc_init (directly after, as this initializes the
stopworldlock lock */
threads_preinit();
+ lock_init();
+ critical_init();
#endif
/* install architecture dependent signal handlers */
/* AFTER: threads_preinit */
- if (!utf8_init())
- vm_abort("vm_create: utf8_init failed");
+ utf8_init();
/* AFTER: thread_preinit */
if (!classcache_init())
vm_abort("vm_create: classcache_init failed");
- /* initialize the memory subsystem (must be done _after_
- threads_preinit) */
+ /* Initialize the code memory management. */
+ /* AFTER: threads_preinit */
- if (!memory_init())
- vm_abort("vm_create: memory_init failed");
+ codememory_init();
/* initialize the finalizer stuff (must be done _after_
threads_preinit) */
if (!finalizer_init())
vm_abort("vm_create: finalizer_init failed");
- /* initializes jit compiler */
+ /* Initialize the JIT compiler. */
jit_init();
+ code_init();
+ methodtree_init();
+
+#if defined(ENABLE_PYTHON)
+ pythonpass_init();
+#endif
/* BEFORE: loader_preinit */
/* AFTER: loader_init, linker_init */
primitive_postinit();
+ method_init();
- exceptions_init();
+#if defined(ENABLE_JIT)
+ trap_init();
+#endif
if (!builtin_init())
vm_abort("vm_create: builtin_init failed");
/* Register the native methods implemented in the VM. */
/* BEFORE: threads_init */
- if (!nativevm_preinit())
- vm_abort("vm_create: nativevm_preinit failed");
+ nativevm_preinit();
#if defined(ENABLE_JNI)
/* Initialize the JNI subsystem (must be done _before_
vm_abort("vm_create: localref_table_init failed");
#endif
+ /* Iinitialize some important system classes. */
+ /* BEFORE: threads_init */
+
+ initialize_init();
+
#if defined(ENABLE_THREADS)
- if (!threads_init())
- vm_abort("vm_create: threads_init failed");
+ threads_init();
#endif
/* Initialize the native VM subsystem. */
/* AFTER: threads_init (at least for SUN's classes) */
- if (!nativevm_init())
- vm_abort("vm_create: nativevm_init failed");
+ nativevm_init();
#if defined(ENABLE_PROFILING)
/* initialize profiling */
}
#endif
- /* increment the number of VMs */
+ /* Increment the number of VMs. */
vms++;
- /* initialization is done */
+ /* Initialization is done, VM is created.. */
+ vm_created = true;
vm_initializing = false;
-#if !defined(NDEBUG)
/* Print the VM configuration after all stuff is set and the VM is
initialized. */
if (opt_PrintConfig)
vm_printconfig();
-#endif
/* everything's ok */
s4 oalength;
utf *u;
java_handle_t *s;
- s4 status;
- s4 i;
+ int status;
+ int i;
+
+#if defined(ENABLE_THREADS)
+ threadobject *t;
+#endif
#if !defined(NDEBUG)
if (compileall) {
status = 1;
}
- /* unload the JavaVM */
+#if defined(ENABLE_THREADS)
+ /* Detach the main thread so that it appears to have ended when
+ the application's main method exits. */
+
+ t = thread_get_current();
+
+ if (!threads_detach_thread(t))
+ vm_abort("vm_run: Could not detach main thread.");
+#endif
+
+ /* Destroy the JavaVM. */
(void) vm_destroy(vm);
- /* and exit */
+ /* And exit. */
vm_exit(status);
}
*******************************************************************************/
-s4 vm_destroy(JavaVM *vm)
+int vm_destroy(JavaVM *vm)
{
#if defined(ENABLE_THREADS)
+ /* Create a a trivial new Java waiter thread called
+ "DestroyJavaVM". */
+
+ JavaVMAttachArgs args;
+
+ args.name = "DestroyJavaVM";
+ args.group = NULL;
+
+ if (!threads_attach_current_thread(&args, false))
+ return 1;
+
+ /* Wait until we are the last non-daemon thread. */
+
threads_join_all_threads();
#endif
- /* everything's ok */
+ /* VM is gone. */
+
+ vm_created = false;
+
+ /* Everything is ok. */
return 0;
}
#if defined(ENABLE_JVMTI)
/* terminate cacaodbgserver */
if (dbgcom!=NULL) {
- pthread_mutex_lock(&dbgcomlock);
+ mutex_lock(&dbgcomlock);
dbgcom->running=1;
- pthread_mutex_unlock(&dbgcomlock);
+ mutex_unlock(&dbgcomlock);
jvmti_cacaodbgserver_quit();
}
#endif
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 */
+ /* Print the log message. */
log_start();
log_finish();
- /* now abort the VM */
+ /* Now abort the VM. */
- abort();
+ system_abort();
+}
+
+
+/* vm_abort_errnum *************************************************************
+
+ Prints an error message, appends ":" plus the strerror-message of
+ errnum and aborts the VM.
+
+ IN:
+ errnum ... error number
+ text ..... error message to print
+
+*******************************************************************************/
+
+void vm_abort_errnum(int errnum, const char *text, ...)
+{
+ va_list ap;
+
+ /* Print the log message. */
+
+ log_start();
+
+ va_start(ap, text);
+ log_vprint(text, ap);
+ va_end(ap);
+
+ /* Print the strerror-message of errnum. */
+
+ log_print(": %s", system_strerror(errnum));
+
+ log_finish();
+
+ /* Now abort the VM. */
+
+ system_abort();
+}
+
+
+/* vm_abort_errno **************************************************************
+
+ Equal to vm_abort_errnum, but uses errno to get the error number.
+
+ IN:
+ text ... error message to print
+
+*******************************************************************************/
+
+void vm_abort_errno(const char *text, ...)
+{
+ va_list ap;
+
+ va_start(ap, text);
+ vm_abort_errnum(errno, text, ap);
+ va_end(ap);
}
o = vm_call_method(m, o, s);
if (o == NULL) {
- exceptions_print_stacktrace();
+ fprintf(stderr, "Failed to load Main-Class manifest attribute from\n");
+ fprintf(stderr, "%s\n", mainstring);
return NULL;
}
type vm_call_method##name##_valist(methodinfo *m, java_handle_t *o, \
va_list ap) \
{ \
- int32_t dumpsize; \
uint64_t *array; \
type value; \
+ int32_t dumpmarker; \
\
if (m->code == NULL) \
if (!jit_compile(m)) \
return 0; \
\
THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
\
- dumpsize = dump_size(); \
array = argument_vmarray_from_valist(m, o, ap); \
value = vm_call##name##_array(m, array); \
- dump_release(dumpsize); \
\
+ DRELEASE; \
THREAD_NATIVEWORLD_ENTER; \
\
return value; \
type vm_call_method##name##_jvalue(methodinfo *m, java_handle_t *o, \
const jvalue *args) \
{ \
- int32_t dumpsize; \
uint64_t *array; \
type value; \
+ int32_t dumpmarker; \
\
if (m->code == NULL) \
if (!jit_compile(m)) \
return 0; \
\
THREAD_NATIVEWORLD_EXIT; \
+ DMARKER; \
\
- dumpsize = dump_size(); \
array = argument_vmarray_from_jvalue(m, o, args); \
value = vm_call##name##_array(m, array); \
- dump_release(dumpsize); \
\
+ DRELEASE; \
THREAD_NATIVEWORLD_ENTER; \
\
return value; \
java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
java_handle_objectarray_t *params)
{
- int32_t dumpsize;
uint64_t *array;
java_handle_t *xptr;
java_handle_t *ro;
imm_union value;
+ int32_t dumpmarker;
+
+ /* Prevent compiler warnings. */
+
+ ro = NULL;
/* compile methods which are not yet compiled */
/* mark start of dump memory area */
- dumpsize = dump_size();
+ DMARKER;
/* Fill the argument array from a object-array. */
if (array == NULL) {
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
/* enter the nativeworld again */
/* release dump area */
- dump_release(dumpsize);
+ DRELEASE;
/* enter the nativeworld again */
/* src/vm/vm.h - basic JVM functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include <stdarg.h>
+#include <stdint.h>
#include "vm/types.h"
extern _Jv_JNIEnv *_Jv_env;
extern bool vm_initializing;
+extern bool vm_created;
extern bool vm_exiting;
extern char *mainstring;
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 */
/* src/vmcore/annotation.c - class annotations
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
assert(m != NULL);
LLNI_classinfo_field_get(
- m->class, method_annotationdefaults, annotationdefaults);
+ m->clazz, method_annotationdefaults, annotationdefaults);
if (!annotation_load_attribute_body(
cb, &annotationdefault,
}
if (annotationdefault != NULL) {
- slot = m - m->class->methods;
+ slot = m - m->clazz->methods;
annotationdefaults = annotation_bytearrays_insert(
annotationdefaults, slot, annotationdefault);
}
LLNI_classinfo_field_set(
- m->class, method_annotationdefaults, annotationdefaults);
+ m->clazz, method_annotationdefaults, annotationdefaults);
}
return true;
assert(m != NULL);
LLNI_classinfo_field_get(
- m->class, method_parameterannotations, parameterannotations);
+ m->clazz, method_parameterannotations, parameterannotations);
if (!annotation_load_attribute_body(
cb, &annotations,
}
if (annotations != NULL) {
- slot = m - m->class->methods;
+ slot = m - m->clazz->methods;
parameterannotations = annotation_bytearrays_insert(
parameterannotations, slot, annotations);
}
LLNI_classinfo_field_set(
- m->class, method_parameterannotations, parameterannotations);
+ m->clazz, method_parameterannotations, parameterannotations);
}
return true;
return false;
}
- LLNI_classinfo_field_set(
- cb->class, annotations, (java_handle_t*)annotations);
+ LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations);
return true;
}
assert(m != NULL);
LLNI_classinfo_field_get(
- m->class, method_annotations, method_annotations);
+ m->clazz, method_annotations, method_annotations);
if (!annotation_load_attribute_body(
cb, &annotations,
}
if (annotations != NULL) {
- slot = m - m->class->methods;
+ slot = m - m->clazz->methods;
method_annotations = annotation_bytearrays_insert(
method_annotations, slot, annotations);
}
LLNI_classinfo_field_set(
- m->class, method_annotations, method_annotations);
+ m->clazz, method_annotations, method_annotations);
}
return true;
assert(f != NULL);
LLNI_classinfo_field_get(
- f->class, field_annotations, field_annotations);
+ f->clazz, field_annotations, field_annotations);
if (!annotation_load_attribute_body(
cb, &annotations,
}
if (annotations != NULL) {
- slot = f - f->class->fields;
+ slot = f - f->clazz->fields;
field_annotations = annotation_bytearrays_insert(
field_annotations, slot, annotations);
}
LLNI_classinfo_field_set(
- f->class, field_annotations, field_annotations);
+ f->clazz, field_annotations, field_annotations);
}
return true;
/* src/vmcore/class.c - class related functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vmcore/utf8.h"
+#if defined(ENABLE_JAVASE)
+/* We need to define some reflection functions here since we cannot
+ include native/vm/reflect.h as it includes generated header
+ files. */
+
+java_object_t *reflect_constructor_new(methodinfo *m);
+java_object_t *reflect_field_new(fieldinfo *f);
+java_object_t *reflect_method_new(methodinfo *m);
+#endif
+
+
/* global variables ***********************************************************/
/* frequently used classes ****************************************************/
-/* important system classes */
+/* Important system classes. */
classinfo *class_java_lang_Object;
classinfo *class_java_lang_Class;
classinfo *class_java_lang_VMThrowable;
#endif
+/* Important system exceptions. */
+
+classinfo *class_java_lang_Exception;
+classinfo *class_java_lang_ClassNotFoundException;
+classinfo *class_java_lang_RuntimeException;
+
#if defined(WITH_CLASSPATH_SUN)
classinfo *class_sun_reflect_MagicAccessorImpl;
#endif
classinfo *class_java_util_Vector;
classinfo *class_java_util_HashMap;
+# if defined(WITH_CLASSPATH_GNU)
+classinfo *class_java_lang_reflect_VMConstructor;
+classinfo *class_java_lang_reflect_VMField;
+classinfo *class_java_lang_reflect_VMMethod;
+# endif
+
classinfo *arrayclass_java_lang_Object;
# if defined(ENABLE_ANNOTATIONS)
*******************************************************************************/
-classinfo *class_define(utf *name, classloader *cl, int32_t length, const uint8_t *data, java_handle_t *pd)
+classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
{
classinfo *c;
classinfo *r;
cb = NEW(classbuffer);
- cb->class = c;
+ cb->clazz = c;
cb->size = length;
cb->data = data;
cb->pos = cb->data;
/* get classinfo */
- c = cb->class;
+ c = cb->clazz;
/* check buffer size */
/* get classinfo */
- c = cb->class;
+ c = cb->clazz;
/* check buffer size */
uint16_t flags;
int i, j;
- c = cb->class;
+ c = cb->clazz;
/* get attributes count */
*******************************************************************************/
-static classinfo *get_array_class(utf *name,classloader *initloader,
- classloader *defloader,bool link)
+static classinfo *get_array_class(utf *name,classloader_t *initloader,
+ classloader_t *defloader,bool link)
{
classinfo *c;
classinfo *class_array_of(classinfo *component, bool link)
{
- classloader *cl;
+ classloader_t *cl;
s4 namelen;
char *namebuf;
utf *u;
classinfo *c;
- s4 dumpsize;
+ int32_t dumpmarker;
cl = component->classloader;
- dumpsize = dump_size();
+ DMARKER;
/* Assemble the array class name */
namelen = component->name->blength;
c = get_array_class(u, cl, cl, link);
- dump_release(dumpsize);
+ DRELEASE;
return c;
}
{
s4 namelen;
char *namebuf;
- s4 dumpsize;
classinfo *c;
+ int32_t dumpmarker;
- dumpsize = dump_size();
+ DMARKER;
if (dim < 1) {
log_text("Invalid array dimension requested");
element->classloader,
link);
- dump_release(dumpsize);
+ DRELEASE;
return c;
}
{
s4 namelen;
char *namebuf;
- s4 dumpsize;
constant_classref *cr;
+ int32_t dumpmarker;
assert(ref);
assert(dim >= 1 && dim <= 255);
- dumpsize = dump_size();
+ DMARKER;
/* Assemble the array class name */
namelen = ref->name->blength;
cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
- dump_release(dumpsize);
+ DRELEASE;
return cr;
}
}
+/* class_is_assignable_from ****************************************************
+
+ Return whether an instance of the "from" class parameter would be
+ an instance of this class "to" as well.
+
+ ARGUMENTS:
+ to ..... class
+ from ... class
+
+ RETURN:
+ true .... is assignable
+ false ... is not assignable
+
+*******************************************************************************/
+
+bool class_is_assignable_from(classinfo *to, classinfo *from)
+{
+ if (!(to->state & CLASS_LINKED))
+ if (!link_class(to))
+ return false;
+
+ if (!(from->state & CLASS_LINKED))
+ if (!link_class(from))
+ return false;
+
+ return class_isanysubclass(from, to);
+}
+
+
+/* class_is_instance ***********************************************************
+
+ Return if the given Java object is an instance of the given class.
+
+ ARGUMENTS:
+ c ... class
+ h ... Java object
+
+ RETURN:
+ true .... is instance
+ false ... is not instance
+
+*******************************************************************************/
+
+bool class_is_instance(classinfo *c, java_handle_t *h)
+{
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+ return builtin_instanceof(h, c);
+}
+
+
/* class_get_componenttype *****************************************************
Return the component class of the given class. If the given class
return NULL;
if (ad->arraytype == ARRAYTYPE_OBJECT)
- component = ad->componentvftbl->class;
+ component = ad->componentvftbl->clazz;
else
component = primitive_class_get_by_type(ad->arraytype);
}
+/**
+ * Return an array of declared constructors of the given class.
+ *
+ * @param c class to get the constructors of
+ * @param publicOnly show only public fields
+ *
+ * @return array of java.lang.reflect.Constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
+{
+ methodinfo* m;
+ java_handle_objectarray_t* oa;
+ java_handle_t* rc;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of constructors. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init))
+ count++;
+ }
+
+ /* Create array of constructors. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the constructors and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init)) {
+ /* Create Constructor object. This is actualy a
+ java_lang_reflect_Constructor pointer, but we use a
+ java_handle_t here, because we don't have the header
+ available when building vmcore. */
+
+ rc = reflect_constructor_new(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, rc);
+ index++;
+ }
+ }
+
+ return oa;
+}
+#endif
+
+
+/* class_get_declaredfields ****************************************************
+
+ Return an array of declared fields of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the fields of
+ publicOnly ... show only public fields
+
+ RETURN:
+ array of java.lang.reflect.Field
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
+{
+ java_handle_objectarray_t *oa;
+ fieldinfo *f;
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of fields. */
+
+ count = 0;
+
+ for (i = 0; i < c->fieldscount; i++)
+ if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
+ count++;
+
+ /* Create array of fields. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Field);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the fields and store them in the array. */
+
+ for (i = 0, index = 0; i < c->fieldscount; i++) {
+ f = &(c->fields[i]);
+
+ if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+ /* Create Field object. This is actualy a
+ java_lang_reflect_Field pointer, but we use a
+ java_handle_t here, because we don't have the header
+ available when building vmcore. */
+
+ h = reflect_field_new(f);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+}
+#endif
+
+
+/* class_get_declaredmethods ***************************************************
+
+ Return an array of declared methods of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the methods of
+ publicOnly ... show only public methods
+
+ RETURN:
+ array of java.lang.reflect.Method
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
+{
+ java_handle_objectarray_t *oa; /* result: array of Method-objects */
+ methodinfo *m; /* the current method to be represented */
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* JOWENN: array classes do not declare methods according to mauve
+ test. It should be considered, if we should return to my old
+ clone method overriding instead of declaring it as a member
+ function. */
+
+ if (class_is_array(c))
+ return builtin_anewarray(0, class_java_lang_reflect_Method);
+
+ /* Determine number of methods. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA))
+ count++;
+ }
+
+ /* Create array of methods. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Method);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the methods and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA)) {
+ /* Create method object. This is actualy a
+ java_lang_reflect_Method pointer, but we use a
+ java_handle_t here, because we don't have the header
+ available when building vmcore. */
+
+ h = reflect_method_new(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+}
+#endif
+
+
/* class_get_declaringclass ****************************************************
If the class or interface given is a member of another class,
}
+/**
+ * Return the enclosing constructor as java.lang.reflect.Constructor
+ * object for the given class.
+ *
+ * @param c class to return the enclosing constructor for
+ *
+ * @return java.lang.reflect.Constructor object of the enclosing
+ * constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingconstructor(classinfo *c)
+{
+ methodinfo* m;
+ java_handle_t* rc;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* Check for <init>. */
+
+ if (m->name != utf_init)
+ return NULL;
+
+ /* Create Constructor object. */
+
+ rc = reflect_constructor_new(m);
+
+ return rc;
+}
+#endif
+
+
+/* class_get_enclosingmethod ***************************************************
+
+ Return the enclosing method for the given class.
+
+ IN:
+ c ... class to return the enclosing method for
+
+ RETURN:
+ methodinfo of the enclosing method
+
+*******************************************************************************/
+
+methodinfo *class_get_enclosingmethod_raw(classinfo *c)
+{
+ constant_nameandtype *cn;
+ classinfo *ec;
+ methodinfo *m;
+
+ /* get enclosing class and method */
+
+ ec = class_get_enclosingclass(c);
+ cn = c->enclosingmethod;
+
+ /* check for enclosing class and method */
+
+ if (ec == NULL)
+ return NULL;
+
+ if (cn == NULL)
+ return NULL;
+
+ /* find method in enclosing class */
+
+ m = class_findmethod(ec, cn->name, cn->descriptor);
+
+ if (m == NULL) {
+ exceptions_throw_internalerror("Enclosing method doesn't exist");
+ return NULL;
+ }
+
+ return m;
+}
+
+
+/**
+ * Return the enclosing method as java.lang.reflect.Method object for
+ * the given class.
+ *
+ * @param c class to return the enclosing method for
+ *
+ * @return java.lang.reflect.Method object of the enclosing method
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingmethod(classinfo *c)
+{
+ methodinfo* m;
+ java_handle_t* rm;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* check for <init> */
+
+ if (m->name == utf_init)
+ return NULL;
+
+ /* create java.lang.reflect.Method object */
+
+ rm = reflect_method_new(m);
+
+ return rm;
+}
+#endif
+
+
/* class_get_interfaces ********************************************************
Return an array of interfaces of the given class.
/* src/vmcore/class.h - class related functions header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "toolbox/list.h"
#include "vm/global.h"
+#include "vm/stringlocal.h"
#if defined(ENABLE_JAVASE)
# include "vmcore/annotation.h"
#endif
#endif
- classloader *classloader; /* NULL for bootstrap classloader */
+ classloader_t *classloader; /* NULL for bootstrap classloader */
#if defined(ENABLE_JAVASE)
# if defined(WITH_CLASSPATH_SUN)
/* frequently used classes ****************************************************/
-/* important system classes */
+/* Important system classes. */
extern classinfo *class_java_lang_Object;
extern classinfo *class_java_lang_Class;
extern classinfo *class_java_lang_Throwable;
extern classinfo *class_java_io_Serializable;
+/* Important system exceptions. */
+
+extern classinfo *class_java_lang_Exception;
+extern classinfo *class_java_lang_ClassNotFoundException;
+extern classinfo *class_java_lang_RuntimeException;
+
#if defined(WITH_CLASSPATH_GNU)
extern classinfo *class_java_lang_VMSystem;
extern classinfo *class_java_lang_VMThread;
extern classinfo *class_java_util_Vector;
extern classinfo *class_java_util_HashMap;
+# if defined(WITH_CLASSPATH_GNU)
+extern classinfo *class_java_lang_reflect_VMConstructor;
+extern classinfo *class_java_lang_reflect_VMField;
+extern classinfo *class_java_lang_reflect_VMMethod;
+# endif
+
extern classinfo *arrayclass_java_lang_Object;
# if defined(ENABLE_ANNOTATIONS)
/* inline functions ***********************************************************/
+/**
+ * Returns the classname of the class, where slashes ('/') are
+ * replaced by dots ('.').
+ *
+ * @param c class to get name of
+ * @return classname
+ */
+inline static java_handle_t* class_get_classname(classinfo* c)
+{
+ java_handle_t *s;
+
+ /* Create a java string. */
+
+ s = javastring_new_slash_to_dot(c->name);
+
+ return s;
+}
+
+
/* class_is_primitive **********************************************************
Checks if the given class is a primitive class.
*******************************************************************************/
-static inline classloader *class_get_classloader(classinfo *c)
+static inline classloader_t *class_get_classloader(classinfo *c)
{
- classloader *cl;
+ classloader_t *cl;
cl = c->classloader;
classinfo *class_create_classinfo(utf *u);
void class_postset_header_vftbl(void);
-classinfo *class_define(utf *name, classloader *cl, int32_t length, const uint8_t *data, java_handle_t *pd);
+classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd);
void class_set_packagename(classinfo *c);
bool class_load_attributes(classbuffer *cb);
methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
-bool class_issubclass(classinfo *sub, classinfo *super);
-bool class_isanysubclass(classinfo *sub, classinfo *super);
-
-bool class_is_primitive(classinfo *c);
-bool class_is_anonymousclass(classinfo *c);
-bool class_is_array(classinfo *c);
-bool class_is_interface(classinfo *c);
-bool class_is_localclass(classinfo *c);
-bool class_is_memberclass(classinfo *c);
+bool class_issubclass(classinfo *sub, classinfo *super);
+bool class_isanysubclass(classinfo *sub, classinfo *super);
+bool class_is_assignable_from(classinfo *to, classinfo *from);
+bool class_is_instance(classinfo *c, java_handle_t *h);
-classloader *class_get_classloader(classinfo *c);
+classloader_t *class_get_classloader(classinfo *c);
classinfo *class_get_superclass(classinfo *c);
classinfo *class_get_componenttype(classinfo *c);
java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly);
+java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly);
+java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly);
+java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly);
classinfo *class_get_declaringclass(classinfo *c);
classinfo *class_get_enclosingclass(classinfo *c);
+java_handle_t* class_get_enclosingconstructor(classinfo *c);
+methodinfo* class_get_enclosingmethod_raw(classinfo *c);
+java_handle_t* class_get_enclosingmethod(classinfo *c);
java_handle_objectarray_t *class_get_interfaces(classinfo *c);
java_handle_bytearray_t *class_get_annotations(classinfo *c);
int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib);
+java_handle_t *class_get_name(classinfo *c);
#if defined(ENABLE_JAVASE)
utf *class_get_signature(classinfo *c);
/* src/vmcore/classcache.c - loaded class cache and loading constraints
- 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/exceptions.h"
#include "vmcore/classcache.h"
+#include "vmcore/options.h"
#include "vmcore/utf8.h"
bool classcache_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("classcache_init");
+
/* create the hashtable */
hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
*******************************************************************************/
static classcache_loader_entry * classcache_new_loader_entry(
- classloader * loader,
+ classloader_t * loader,
classcache_loader_entry * next)
{
classcache_loader_entry *lden;
*******************************************************************************/
-classinfo *classcache_lookup(classloader *initloader, utf *classname)
+classinfo *classcache_lookup(classloader_t *initloader, utf *classname)
{
classcache_name_entry *en;
classcache_class_entry *clsen;
*******************************************************************************/
-classinfo *classcache_lookup_defined(classloader *defloader, utf *classname)
+classinfo *classcache_lookup_defined(classloader_t *defloader, utf *classname)
{
classcache_name_entry *en;
classcache_class_entry *clsen;
*******************************************************************************/
-classinfo *classcache_lookup_defined_or_initiated(classloader *loader,
+classinfo *classcache_lookup_defined_or_initiated(classloader_t *loader,
utf *classname)
{
classcache_name_entry *en;
*******************************************************************************/
-classinfo *classcache_store(classloader *initloader, classinfo *cls,
+classinfo *classcache_store(classloader_t *initloader, classinfo *cls,
bool mayfree)
{
classcache_name_entry *en;
static classcache_class_entry * classcache_find_loader(
classcache_name_entry * entry,
- classloader * loader)
+ classloader_t * loader)
{
classcache_class_entry *clsen;
classcache_loader_entry *lden;
*******************************************************************************/
#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraint(classloader * a,
- classloader * b,
+bool classcache_add_constraint(classloader_t * a,
+ classloader_t * b,
utf * classname)
{
classcache_name_entry *en;
*******************************************************************************/
#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraints_for_params(classloader * a,
- classloader * b,
+bool classcache_add_constraints_for_params(classloader_t * a,
+ classloader_t * b,
methodinfo *m)
{
methoddesc *md;
/* src/vmcore/classcache.h - loaded class cache and loading constraints
- 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.
struct classcache_loader_entry
{
- classloader *loader; /* class loader object */
+ classloader_t *loader; /* class loader object */
classcache_loader_entry *next; /* next loader entry in the list */
};
bool classcache_init(void);
void classcache_free(void);
-classinfo * classcache_lookup(classloader *initloader,utf *classname);
-classinfo * classcache_lookup_defined(classloader *defloader,utf *classname);
-classinfo * classcache_lookup_defined_or_initiated(classloader *loader,utf *classname);
+classinfo * classcache_lookup(classloader_t *initloader,utf *classname);
+classinfo * classcache_lookup_defined(classloader_t *defloader,utf *classname);
+classinfo * classcache_lookup_defined_or_initiated(classloader_t *loader,utf *classname);
bool classcache_store_unique(classinfo *cls);
-classinfo * classcache_store(classloader *initloader,classinfo *cls,bool mayfree);
+classinfo * classcache_store(classloader_t *initloader,classinfo *cls,bool mayfree);
classinfo * classcache_store_defined(classinfo *cls);
#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraint(classloader *a,classloader *b,utf *classname);
-bool classcache_add_constraints_for_params(classloader *a,classloader *b,
+bool classcache_add_constraint(classloader_t *a,classloader_t *b,utf *classname);
+bool classcache_add_constraints_for_params(classloader_t *a,classloader_t *b,
methodinfo *m);
#endif
/* src/vmcore/descriptor.c - checking and parsing of field / method descriptors
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
struct descriptor_hash_entry {
descriptor_hash_entry *hashlink;
utf *desc;
- parseddesc parseddesc;
+ parseddesc_t parseddesc;
s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
};
/* src/vmcore/field.c - field functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* Get class. */
- c = cb->class;
+ c = cb->clazz;
- f->class = c;
+ f->clazz = c;
/* Get access flags. */
/* load the class of the field-type with the field's
classloader */
- c = load_class_from_classloader(u, f->class->classloader);
+ c = load_class_from_classloader(u, f->clazz->classloader);
}
else {
c = primitive_class_get_by_type(td->decltype);
java_handle_t *field_annotations; /* array of unparsed */
/* annotations of all fields of the declaring class */
- c = f->class;
+ c = f->clazz;
slot = f - c->fields;
annotations = NULL;
return;
}
- utf_display_printable_ascii_classname(f->class->name);
+ 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
/* src/vmcore/field.h - field functions header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* value as CLASSREF_PSEUDO_VFTBL! This is used to check whether */
/* a constant_FMIref has been resolved. */
- classinfo *class; /* needed by typechecker. Could be optimized */
+ classinfo *clazz; /* needed by typechecker. Could be optimized */
/* away by using constant_FMIref instead of */
/* fieldinfo throughout the compiler. */
/* src/vmcore/linker.c - class linker functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#endif
#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code) do { if (opt_inline_debug_log) { code } } while (0)
+#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
#else
#define INLINELOG(code)
#endif
void linker_preinit(void)
{
+ TRACESUBSYSTEMINITIALIZATION("linker_preinit");
+
/* Check for if alignment for long and double matches what we
assume for the current architecture. */
void linker_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("linker_init");
+
/* Link java.lang.Class as first class of the system, because we
need it's vftbl for all other classes so we can use a class as
object. */
vm_abort("linker_init: linking failed");
#endif
+ /* Important system exceptions. */
+
+ if (!link_class(class_java_lang_Exception))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_ClassNotFoundException))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_RuntimeException))
+ vm_abort("linker_init: linking failed");
/* some classes which may be used more often */
if (!link_class(class_java_lang_reflect_Method))
vm_abort("linker_init: linking failed");
+# if defined(WITH_CLASSPATH_GNU)
+ if (!link_class(class_java_lang_reflect_VMConstructor))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_VMField))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_VMMethod))
+ vm_abort("linker_init: linking failed");
+# endif
+
if (!link_class(class_java_security_PrivilegedAction))
vm_abort("linker_init: linking failed");
classinfo *cg;
classinfo *cs;
- cg = mg->class;
- cs = ms->class;
+ cg = mg->clazz;
+ cs = ms->clazz;
/* overriding a final method is illegal */
MCOPY(am, im, methodinfo, 1);
am->vftblindex = (vftbllength++);
- am->class = c;
+ am->clazz = c;
am->flags |= ACC_MIRANDA;
noabstractmethod2:
(interfacetablelength - 1) * (interfacetablelength > 1));
c->vftbl = v;
- v->class = c;
+ v->clazz = c;
v->vftbllength = vftbllength;
v->interfacetablelength = interfacetablelength;
v->arraydesc = arraydesc;
struct _vftbl {
methodptr *interfacetable[1]; /* interface table (access via macro) */
- classinfo *class; /* class, the vtbl belongs to */
+ 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 */
/* src/vmcore/loader.c - class loader functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
{
#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;
void loader_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("loader_init");
+
/* Load primitive-type wrapping classes. */
assert(vm_initializing == true);
load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
#endif
- /* Some classes which may be used often. */
+ /* Important system exceptions. */
-#if defined(ENABLE_JAVASE)
- class_java_lang_StackTraceElement =
- load_class_bootstrap(utf_java_lang_StackTraceElement);
+ class_java_lang_Exception = load_class_bootstrap(utf_java_lang_Exception);
- class_java_lang_reflect_Constructor =
- load_class_bootstrap(utf_java_lang_reflect_Constructor);
+ class_java_lang_ClassNotFoundException =
+ load_class_bootstrap(utf_java_lang_ClassNotFoundException);
- class_java_lang_reflect_Field =
- load_class_bootstrap(utf_java_lang_reflect_Field);
+ class_java_lang_RuntimeException =
+ load_class_bootstrap(utf_java_lang_RuntimeException);
- class_java_lang_reflect_Method =
- load_class_bootstrap(utf_java_lang_reflect_Method);
+ /* Some classes which may be used often. */
- class_java_security_PrivilegedAction =
- load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
+#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_CLASSPATH_GNU)
+ 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_util_HashMap =
- load_class_bootstrap(utf_new_char("java/util/HashMap"));
+ class_java_security_PrivilegedAction = load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
- class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
+ 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_CLASSPATH_SUN)
class_sun_reflect_MagicAccessorImpl =
*******************************************************************************/
-classloader *loader_hashtable_classloader_add(java_handle_t *cl)
+classloader_t *loader_hashtable_classloader_add(java_handle_t *cl)
{
hashtable_classloader_entry *cle;
u4 key;
*******************************************************************************/
-classloader *loader_hashtable_classloader_find(java_handle_t *cl)
+classloader_t *loader_hashtable_classloader_find(java_handle_t *cl)
{
hashtable_classloader_entry *cle;
u4 key;
u1 *cptags;
voidptr *cpinfos;
- c = cb->class;
+ c = cb->clazz;
/* number of entries in the constant_pool table plus one */
if (!suck_check_classbuffer_size(cb, 2))
/* get classinfo */
- c = cb->class;
+ c = cb->clazz;
/* check remaining bytecode */
{
methodinfo *m;
java_handle_t *clo;
- classloader *cl;
+ classloader_t *cl;
classinfo *c;
assert(class_java_lang_Object);
*******************************************************************************/
-classinfo *load_class_from_classloader(utf *name, classloader *cl)
+classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
{
java_handle_t *o;
classinfo *c;
/* Get the classbuffer's class. */
- c = cb->class;
+ c = cb->clazz;
if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
return false;
/* XXX This should be done better. */
tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
- if (tc == NULL)
+ if (tc == NULL) {
+ resolve_handle_pending_exception(true);
return false;
+ }
/* Interfaces are not allowed as super classes. */
/* XXX This should be done better. */
tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
- if (tc == NULL)
+ if (tc == NULL) {
+ resolve_handle_pending_exception(true);
return false;
+ }
/* Detect circularity. */
methodinfo *m = &c->methods[i];
m->parseddesc =
descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
- m->flags, class_get_self_classref(m->class));
+ m->flags, class_get_self_classref(m->clazz));
if (!m->parseddesc)
return false;
classinfo *load_class_from_classbuffer(classbuffer *cb)
{
classinfo *c;
- int32_t dumpsize;
bool result;
+ int32_t dumpmarker;
/* Get the classbuffer's class. */
- c = cb->class;
+ c = cb->clazz;
/* Check if the class is already loaded. */
/* Mark start of dump memory area. */
- dumpsize = dump_size();
+ DMARKER;
/* Class is currently loading. */
/* Release dump area. */
- dump_release(dumpsize);
+ DRELEASE;
/* An error occurred. */
*******************************************************************************/
-classinfo *load_newly_created_array(classinfo *c, classloader *loader)
+classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
{
classinfo *comp = NULL;
methodinfo *clone;
clone->name = utf_clone;
clone->descriptor = utf_void__java_lang_Object;
clone->parseddesc = clonedesc;
- clone->class = c;
+ clone->clazz = c;
/* parse the descriptor to get the register allocation */
/* src/vmcore/loader.h - class loader header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* classbuffer ****************************************************************/
struct classbuffer {
- classinfo *class; /* pointer to classinfo structure */
- u1 *data; /* pointer to byte code */
- s4 size; /* size of the byte code */
- u1 *pos; /* current read position */
+ 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) */
};
*******************************************************************************/
#if defined(ENABLE_HANDLES)
-typedef hashtable_classloader_entry classloader;
+typedef hashtable_classloader_entry classloader_t;
#else
-typedef java_object_t classloader;
+typedef java_object_t classloader_t;
#endif
void loader_init(void);
/* classloader management functions */
-classloader *loader_hashtable_classloader_add(java_handle_t *cl);
-classloader *loader_hashtable_classloader_find(java_handle_t *cl);
+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);
/* class loading functions */
classinfo *load_class_from_sysloader(utf *name);
-classinfo *load_class_from_classloader(utf *name, classloader *cl);
+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 *loader);
+classinfo *load_newly_created_array(classinfo *c, classloader_t *loader);
#endif /* _LOADER_H */
/* src/vmcore/method.c - method functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/exceptions.h"
#include "vm/global.h"
#include "vm/resolve.h"
+#include "vm/vm.h"
+#include "vm/jit/code.h"
#include "vm/jit/methodheader.h"
#include "vm/jit_interface.h"
#include "vmcore/method.h"
#include "vmcore/options.h"
#include "vmcore/suck.h"
+#include "vmcore/utf8.h"
#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code) do { if (opt_inline_debug_log) { code } } while (0)
+#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
#else
#define INLINELOG(code)
#endif
+/* global variables ***********************************************************/
+
+methodinfo *method_java_lang_reflect_Method_invoke;
+
+
+/* method_init *****************************************************************
+
+ Initialize method subsystem.
+
+*******************************************************************************/
+
+void method_init(void)
+{
+#if defined(ENABLE_JAVASE)
+ /* Sanity check. */
+
+ if (class_java_lang_reflect_Method == NULL)
+ vm_abort("method_init: class_java_lang_reflect_Method is NULL");
+
+ /* Cache java.lang.reflect.Method.invoke() */
+
+ method_java_lang_reflect_Method_invoke =
+ class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
+
+ if (method_java_lang_reflect_Method_invoke == NULL)
+ vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
+#endif
+}
+
+
/* method_load *****************************************************************
Loads a method from the class file and fills an existing methodinfo
/* get classinfo */
- c = cb->class;
+ c = cb->clazz;
LOCK_INIT_OBJECT_LOCK(&(m->header));
/* all fields of m have been zeroed in load_class_from_classbuffer */
- m->class = c;
+ m->clazz = c;
if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
return false;
/* Get the method from the virtual function table. Is this an
interface method? */
- if (m->class->flags & ACC_INTERFACE) {
- pmptr = vftbl->interfacetable[-(m->class->index)];
- mptr = pmptr[(m - m->class->methods)];
+ if (m->clazz->flags & ACC_INTERFACE) {
+ pmptr = vftbl->interfacetable[-(m->clazz->index)];
+ mptr = pmptr[(m - m->clazz->methods)];
}
else {
mptr = vftbl->table[m->vftblindex];
java_handle_t *method_annotations; /* all methods' unparsed annotations */
/* of the declaring class */
- c = m->class;
+ c = m->clazz;
slot = m - c->methods;
annotations = NULL;
/* parameter annotations of */
/* the declaring class */
- c = m->class;
+ c = m->clazz;
slot = m - c->methods;
parameterAnnotations = NULL;
/* annotation default values of */
/* the declaring class */
- c = m->class;
+ c = m->clazz;
slot = m - c->methods;
annotationDefault = NULL;
return;
}
- if (m->class != NULL)
- utf_display_printable_ascii_classname(m->class->name);
+ if (m->clazz != NULL)
+ utf_display_printable_ascii_classname(m->clazz->name);
else
printf("NULL");
printf(".");
/* src/vmcore/method.h - method functions header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
methoddesc *parseddesc; /* parsed descriptor */
- classinfo *class; /* class, the method belongs to */
+ classinfo *clazz; /* class, the method belongs to */
s4 vftblindex; /* index of method in virtual function */
/* table (if it is a virtual method) */
s4 maxstack; /* maximum stack depth of method */
};
+/* global variables ***********************************************************/
+
+extern methodinfo *method_java_lang_reflect_Method_invoke;
+
+
+/* inline functions ***********************************************************/
+
+inline static bool method_is_builtin(methodinfo* m)
+{
+ return m->flags & ACC_METHOD_BUILTIN;
+}
+
+
/* function prototypes ********************************************************/
+void method_init(void);
+
bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool);
void method_free(methodinfo *m);
bool method_canoverwrite(methodinfo *m, methodinfo *old);
/* src/vmcore/options.c - contains global options
- 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 <errno.h>
+#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#if defined(HAVE_STRING_H)
-# include <string.h>
-#endif
-
-#include <limits.h>
-
#include "mm/memory.h"
#include "native/jni.h"
#include "vm/vm.h"
#include "vmcore/options.h"
+#include "vmcore/system.h"
/* command line option ********************************************************/
#endif
-/* inlining options ***********************************************************/
-
-#if defined(ENABLE_INLINING)
-bool opt_inlining = false;
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
-s4 opt_inline_debug_min_size = 0;
-s4 opt_inline_debug_max_size = INT_MAX;
-s4 opt_inline_debug_end_counter = INT_MAX;
-bool opt_inline_debug_all = false;
-#endif /* defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG) */
-#if !defined(NDEBUG)
-bool opt_inline_debug_log = false;
-#endif /* !defined(NDEBUG) */
-#endif /* defined(ENABLE_INLINING) */
-
-
/* optimization options *******************************************************/
#if defined(ENABLE_IFCONV)
#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
bool opt_lsra = false;
#endif
+#if defined(ENABLE_SSA)
+bool opt_ssa_dce = false; /* enable dead code elemination */
+bool opt_ssa_cp = false; /* enable copy propagation */
+#endif
/* interpreter options ********************************************************/
/* NOTE: For better readability keep these alpha-sorted. */
-int opt_DebugExceptions = 0;
-int opt_DebugFinalizer = 0;
-int opt_DebugLocalReferences = 0;
-int opt_DebugLocks = 0;
-int opt_DebugPackage = 0;
-int opt_DebugPatcher = 0;
-int opt_DebugProperties = 0;
-int32_t opt_DebugStackFrameInfo = 0;
-int opt_DebugStackTrace = 0;
-int opt_DebugThreads = 0;
+/* Options which must always be available (production options in
+ HotSpot). */
+
+int64_t opt_MaxDirectMemorySize = -1;
+int opt_MaxPermSize = 0;
+int opt_PermSize = 0;
+int opt_ThreadStackSize = 0;
+
+/* Debugging options which can be turned off. */
+
+int opt_DebugExceptions = 0;
+int opt_DebugFinalizer = 0;
+int opt_DebugLocalReferences = 0;
+int opt_DebugLocks = 0;
+int opt_DebugPackage = 0;
+int opt_DebugPatcher = 0;
+int opt_DebugProperties = 0;
+int opt_DebugStackFrameInfo = 0;
+int opt_DebugStackTrace = 0;
+int opt_DebugThreads = 0;
#if defined(ENABLE_DISASSEMBLER)
-int opt_DisassembleStubs = 0;
+int opt_DisassembleStubs = 0;
#endif
#if defined(ENABLE_GC_CACAO)
-int32_t opt_GCDebugRootSet = 0;
-int32_t opt_GCStress = 0;
-#endif
-int32_t opt_MaxPermSize = 0;
-int32_t opt_PermSize = 0;
-int opt_PrintConfig = 0;
-int32_t opt_ProfileGCMemoryUsage = 0;
-int32_t opt_ProfileMemoryUsage = 0;
-FILE *opt_ProfileMemoryUsageGNUPlot = NULL;
+int opt_GCDebugRootSet = 0;
+int opt_GCStress = 0;
+#endif
+#if defined(ENABLE_INLINING)
+int opt_Inline = 0;
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+int opt_InlineAll = 0;
+int opt_InlineCount = INT_MAX;
+int opt_InlineMaxSize = INT_MAX;
+int opt_InlineMinSize = 0;
+#endif
+#endif
+int opt_PrintConfig = 0;
+int opt_ProfileGCMemoryUsage = 0;
+int opt_ProfileMemoryUsage = 0;
+FILE *opt_ProfileMemoryUsageGNUPlot = NULL;
#if defined(ENABLE_REPLACEMENT)
-int opt_TestReplacement = 0;
-#endif
-int32_t opt_ThreadStackSize = 0;
-int opt_TraceCompilerCalls = 0;
-int32_t opt_TraceExceptions = 0;
-int32_t opt_TraceJavaCalls = 0;
-int32_t opt_TraceJNICalls = 0;
-int32_t opt_TraceJVMCalls = 0;
-int32_t opt_TraceLinkClass = 0;
+int opt_TestReplacement = 0;
+#endif
+int opt_TraceCompilerCalls = 0;
+int opt_TraceExceptions = 0;
+int opt_TraceHPI = 0;
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+int opt_TraceInlining = 0;
+#endif
+int opt_TraceJavaCalls = 0;
+int opt_TraceJNICalls = 0;
+int opt_TraceJVMCalls = 0;
+int opt_TraceJVMCallsVerbose = 0;
+int opt_TraceLinkClass = 0;
#if defined(ENABLE_REPLACEMENT)
-int32_t opt_TraceReplacement = 0;
+int opt_TraceReplacement = 0;
#endif
+int opt_TraceSubsystemInitialization = 0;
+int opt_TraceTraps = 0;
enum {
};
enum {
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ OPT_MaxDirectMemorySize,
+ OPT_MaxPermSize,
+ OPT_PermSize,
+ OPT_ThreadStackSize,
+
+ /* Debugging options which can be turned off. */
+
OPT_DebugExceptions,
OPT_DebugFinalizer,
OPT_DebugLocalReferences,
OPT_DisassembleStubs,
OPT_GCDebugRootSet,
OPT_GCStress,
- OPT_MaxPermSize,
- OPT_PermSize,
+ OPT_Inline,
+ OPT_InlineAll,
+ OPT_InlineCount,
+ OPT_InlineMaxSize,
+ OPT_InlineMinSize,
OPT_PrintConfig,
OPT_ProfileGCMemoryUsage,
OPT_ProfileMemoryUsage,
OPT_ProfileMemoryUsageGNUPlot,
OPT_TestReplacement,
- OPT_ThreadStackSize,
OPT_TraceCompilerCalls,
OPT_TraceExceptions,
+ OPT_TraceHPI,
+ OPT_TraceInlining,
OPT_TraceJavaCalls,
OPT_TraceJNICalls,
OPT_TraceJVMCalls,
+ OPT_TraceJVMCallsVerbose,
OPT_TraceLinkClass,
- OPT_TraceReplacement
+ OPT_TraceReplacement,
+ OPT_TraceSubsystemInitialization,
+ OPT_TraceTraps,
+ OPT_Vmlog,
+ OPT_VmlogStrings,
+ OPT_VmlogIgnore
};
option_t options_XX[] = {
- { "DebugExceptions", OPT_DebugExceptions, OPT_TYPE_BOOLEAN, "debug exceptions" },
- { "DebugFinalizer", OPT_DebugFinalizer, OPT_TYPE_BOOLEAN, "debug finalizer thread" },
- { "DebugLocalReferences", OPT_DebugLocalReferences, OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
- { "DebugLocks", OPT_DebugLocks, OPT_TYPE_BOOLEAN, "print debug information for locks" },
- { "DebugPackage", OPT_DebugPackage, OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
- { "DebugPatcher", OPT_DebugPatcher, OPT_TYPE_BOOLEAN, "debug JIT code patching" },
- { "DebugProperties", OPT_DebugProperties, OPT_TYPE_BOOLEAN, "print debug information for properties" },
- { "DebugStackFrameInfo", OPT_DebugStackFrameInfo, OPT_TYPE_BOOLEAN, "TODO" },
- { "DebugStackTrace", OPT_DebugStackTrace, OPT_TYPE_BOOLEAN, "debug stacktrace creation" },
- { "DebugThreads", OPT_DebugThreads, OPT_TYPE_BOOLEAN, "print debug information for threads" },
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ { "MaxDirectMemorySize", OPT_MaxDirectMemorySize, OPT_TYPE_VALUE, "Maximum total size of NIO direct-buffer allocations" },
+ { "MaxPermSize", OPT_MaxPermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "PermSize", OPT_PermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "ThreadStackSize", OPT_ThreadStackSize, OPT_TYPE_VALUE, "TODO" },
+
+ /* Debugging options which can be turned off. */
+
+ { "DebugExceptions", OPT_DebugExceptions, OPT_TYPE_BOOLEAN, "debug exceptions" },
+ { "DebugFinalizer", OPT_DebugFinalizer, OPT_TYPE_BOOLEAN, "debug finalizer thread" },
+ { "DebugLocalReferences", OPT_DebugLocalReferences, OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
+ { "DebugLocks", OPT_DebugLocks, OPT_TYPE_BOOLEAN, "print debug information for locks" },
+ { "DebugPackage", OPT_DebugPackage, OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
+ { "DebugPatcher", OPT_DebugPatcher, OPT_TYPE_BOOLEAN, "debug JIT code patching" },
+ { "DebugProperties", OPT_DebugProperties, OPT_TYPE_BOOLEAN, "print debug information for properties" },
+ { "DebugStackFrameInfo", OPT_DebugStackFrameInfo, OPT_TYPE_BOOLEAN, "TODO" },
+ { "DebugStackTrace", OPT_DebugStackTrace, OPT_TYPE_BOOLEAN, "debug stacktrace creation" },
+ { "DebugThreads", OPT_DebugThreads, OPT_TYPE_BOOLEAN, "print debug information for threads" },
#if defined(ENABLE_DISASSEMBLER)
- { "DisassembleStubs", OPT_DisassembleStubs, OPT_TYPE_BOOLEAN, "disassemble builtin and native stubs when generated" },
+ { "DisassembleStubs", OPT_DisassembleStubs, OPT_TYPE_BOOLEAN, "disassemble builtin and native stubs when generated" },
#endif
#if defined(ENABLE_GC_CACAO)
- { "GCDebugRootSet", OPT_GCDebugRootSet, OPT_TYPE_BOOLEAN, "GC: print root-set at collection" },
- { "GCStress", OPT_GCStress, OPT_TYPE_BOOLEAN, "GC: forced collection at every allocation" },
-#endif
- { "MaxPermSize", OPT_MaxPermSize, OPT_TYPE_VALUE, "not implemented" },
- { "PermSize", OPT_PermSize, OPT_TYPE_VALUE, "not implemented" },
- { "PrintConfig", OPT_PrintConfig, OPT_TYPE_BOOLEAN, "print VM configuration" },
- { "ProfileGCMemoryUsage", OPT_ProfileGCMemoryUsage, OPT_TYPE_VALUE, "profiles GC memory usage in the given interval, <value> is in seconds (default: 5)" },
- { "ProfileMemoryUsage", OPT_ProfileMemoryUsage, OPT_TYPE_VALUE, "TODO" },
- { "ProfileMemoryUsageGNUPlot", OPT_ProfileMemoryUsageGNUPlot, OPT_TYPE_VALUE, "TODO" },
+ { "GCDebugRootSet", OPT_GCDebugRootSet, OPT_TYPE_BOOLEAN, "GC: print root-set at collection" },
+ { "GCStress", OPT_GCStress, OPT_TYPE_BOOLEAN, "GC: forced collection at every allocation" },
+#endif
+#if defined(ENABLE_INLINING)
+ { "Inline", OPT_Inline, OPT_TYPE_BOOLEAN, "enable method inlining" },
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ { "InlineAll", OPT_InlineAll, OPT_TYPE_BOOLEAN, "use inlining in all compilations" },
+ { "InlineCount", OPT_InlineCount, OPT_TYPE_VALUE, "stop inlining after the given number of roots" },
+ { "InlineMaxSize", OPT_InlineMaxSize, OPT_TYPE_VALUE, "maximum size for inlined result" },
+ { "InlineMinSize", OPT_InlineMinSize, OPT_TYPE_VALUE, "minimum size for inlined result" },
+#endif
+#endif
+ { "PrintConfig", OPT_PrintConfig, OPT_TYPE_BOOLEAN, "print VM configuration" },
+ { "ProfileGCMemoryUsage", OPT_ProfileGCMemoryUsage, OPT_TYPE_VALUE, "profiles GC memory usage in the given interval, <value> is in seconds (default: 5)" },
+ { "ProfileMemoryUsage", OPT_ProfileMemoryUsage, OPT_TYPE_VALUE, "TODO" },
+ { "ProfileMemoryUsageGNUPlot", OPT_ProfileMemoryUsageGNUPlot, OPT_TYPE_VALUE, "TODO" },
#if defined(ENABLE_REPLACEMENT)
- { "TestReplacement" , OPT_TestReplacement, OPT_TYPE_BOOLEAN, "activate all replacement points during code generation" },
-#endif
- { "ThreadStackSize", OPT_ThreadStackSize, OPT_TYPE_VALUE, "TODO" },
- { "TraceCompilerCalls", OPT_TraceCompilerCalls, OPT_TYPE_BOOLEAN, "trace JIT compiler calls" },
- { "TraceExceptions", OPT_TraceExceptions, OPT_TYPE_BOOLEAN, "trace Exception throwing" },
- { "TraceJavaCalls", OPT_TraceJavaCalls, OPT_TYPE_BOOLEAN, "trace Java method calls" },
- { "TraceJNICalls", OPT_TraceJNICalls, OPT_TYPE_BOOLEAN, "trace JNI method calls" },
- { "TraceJVMCalls", OPT_TraceJVMCalls, OPT_TYPE_BOOLEAN, "TODO" },
- { "TraceLinkClass", OPT_TraceLinkClass, OPT_TYPE_BOOLEAN, "trace class linking" },
+ { "TestReplacement", OPT_TestReplacement, OPT_TYPE_BOOLEAN, "activate all replacement points during code generation" },
+#endif
+ { "TraceCompilerCalls", OPT_TraceCompilerCalls, OPT_TYPE_BOOLEAN, "trace JIT compiler calls" },
+ { "TraceExceptions", OPT_TraceExceptions, OPT_TYPE_BOOLEAN, "trace Exception throwing" },
+ { "TraceHPI", OPT_TraceHPI, OPT_TYPE_BOOLEAN, "Trace Host Porting Interface (HPI)" },
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ { "TraceInlining", OPT_TraceInlining, OPT_TYPE_VALUE, "trace method inlining with the given verbosity level (default: 1)" },
+#endif
+#if !defined(ENABLE_VMLOG)
+ { "TraceJavaCalls", OPT_TraceJavaCalls, OPT_TYPE_BOOLEAN, "trace Java method calls" },
+#endif
+ { "TraceJNICalls", OPT_TraceJNICalls, OPT_TYPE_BOOLEAN, "trace JNI method calls" },
+ { "TraceJVMCalls", OPT_TraceJVMCalls, OPT_TYPE_BOOLEAN, "trace JVM method calls but omit very frequent ones" },
+ { "TraceJVMCallsVerbose", OPT_TraceJVMCallsVerbose, OPT_TYPE_BOOLEAN, "trace all JVM method calls" },
+ { "TraceLinkClass", OPT_TraceLinkClass, OPT_TYPE_BOOLEAN, "trace class linking" },
#if defined(ENABLE_REPLACEMENT)
- { "TraceReplacement", OPT_TraceReplacement, OPT_TYPE_VALUE, "trace on-stack replacement with the given verbosity level (default: 1)" },
+ { "TraceReplacement", OPT_TraceReplacement, OPT_TYPE_VALUE, "trace on-stack replacement with the given verbosity level (default: 1)" },
+#endif
+ { "TraceSubsystemInitialization", OPT_TraceSubsystemInitialization, OPT_TYPE_BOOLEAN, "trace initialization of subsystems" },
+ { "TraceTraps", OPT_TraceTraps, OPT_TYPE_BOOLEAN, "trace traps generated by JIT code" },
+#if defined(ENABLE_VMLOG)
+ { "Vmlog", OPT_Vmlog, OPT_TYPE_VALUE, "prefix for vmlog trace files (enables vmlog)" },
+ { "VmlogStrings", OPT_VmlogStrings, OPT_TYPE_VALUE, "prefix of vmlog string file to load" },
+ { "VmlogIgnore", OPT_VmlogIgnore, OPT_TYPE_VALUE, "prefix of vmlog ignore file to load" },
#endif
/* end marker */
- { NULL, -1, -1, NULL }
+ { NULL, -1, -1, NULL }
};
*******************************************************************************/
-s4 options_get(opt_struct *opts, JavaVMInitArgs *vm_args)
+int options_get(opt_struct *opts, JavaVMInitArgs *vm_args)
{
char *option;
- s4 i;
+ int i;
if (opt_index >= vm_args->nOptions)
return OPT_DONE;
opt_index++;
if (opt_index < vm_args->nOptions) {
-
-#if defined(HAVE_STRDUP)
- opt_arg = strdup(vm_args->options[opt_index].optionString);
-#else
-# error !HAVE_STRDUP
-#endif
-
+ opt_arg = system_strdup(vm_args->options[opt_index].optionString);
opt_index++;
return opts[i].value;
}
* parameter with no argument starting with same letter as param with argument
* but named after that one, ouch! */
- size_t l = strlen(opts[i].name);
+ size_t l = system_strlen(opts[i].name);
- if (strlen(option + 1) > l) {
+ if (system_strlen(option + 1) > l) {
if (memcmp(option + 1, opts[i].name, l) == 0) {
opt_index++;
-
-#if defined(HAVE_STRDUP)
- opt_arg = strdup(option + 1 + l);
-#else
-# error !HAVE_STRDUP
-#endif
-
+ opt_arg = system_strdup(option + 1 + l);
return opts[i].value;
}
}
int i;
char *c;
+ /* Prevent compiler warning. */
+
+ length = 0;
+
for (opt = options_XX; opt->name != NULL; opt++) {
printf(" -XX:");
switch (opt->type) {
case OPT_TYPE_BOOLEAN:
printf("+%s", opt->name);
- length = strlen(" -XX:+") + strlen(opt->name);
+ length = system_strlen(" -XX:+") + system_strlen(opt->name);
break;
+
case OPT_TYPE_VALUE:
printf("%s=<value>", opt->name);
- length = strlen(" -XX:") + strlen(opt->name) + strlen("=<value>");
+ length = system_strlen(" -XX:") + system_strlen(opt->name) +
+ system_strlen("=<value>");
break;
+
+ default:
+ vm_abort("options_xxusage: unkown option type %d", opt->type);
}
/* Check if the help fits into one 80-column line.
/* Check documentation length. */
- length = strlen(opt->doc);
+ length = system_strlen(opt->doc);
if (length < (80 - 29)) {
printf("%s", opt->doc);
end = strchr(start, '=');
if (end == NULL) {
- length = strlen(start);
+ length = system_strlen(start);
value = NULL;
}
else {
/* Process the option. */
switch (opt->value) {
+
+ /* Options which must always be available (production options
+ in HotSpot). */
+
+ case OPT_MaxDirectMemorySize:
+ opt_MaxDirectMemorySize = system_atoi(value);
+ break;
+
+ case OPT_MaxPermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_PermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_ThreadStackSize:
+ /* currently ignored */
+ break;
+
+ /* Debugging options which can be turned off. */
+
case OPT_DebugExceptions:
opt_DebugExceptions = enable;
break;
break;
#endif
- case OPT_MaxPermSize:
- /* currently ignored */
+#if defined(ENABLE_INLINING)
+ case OPT_Inline:
+ opt_Inline = enable;
+ break;
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ case OPT_InlineAll:
+ opt_InlineAll = enable;
break;
- case OPT_PermSize:
- /* currently ignored */
+ case OPT_InlineCount:
+ if (value != NULL)
+ opt_InlineCount = system_atoi(value);
break;
+ case OPT_InlineMaxSize:
+ if (value != NULL)
+ opt_InlineMaxSize = system_atoi(value);
+ break;
+
+ case OPT_InlineMinSize:
+ if (value != NULL)
+ opt_InlineMinSize = system_atoi(value);
+ break;
+#endif
+#endif
+
case OPT_PrintConfig:
opt_PrintConfig = enable;
break;
if (value == NULL)
opt_ProfileGCMemoryUsage = 5;
else
- opt_ProfileGCMemoryUsage = atoi(value);
+ opt_ProfileGCMemoryUsage = system_atoi(value);
break;
case OPT_ProfileMemoryUsage:
if (value == NULL)
opt_ProfileMemoryUsage = 5;
else
- opt_ProfileMemoryUsage = atoi(value);
+ opt_ProfileMemoryUsage = system_atoi(value);
# if defined(ENABLE_STATISTICS)
/* we also need statistics */
file = fopen(filename, "w");
if (file == NULL)
- vm_abort("options_xx: fopen failed: %s", strerror(errno));
+ vm_abort_errno("options_xx: fopen failed");
opt_ProfileMemoryUsageGNUPlot = file;
break;
break;
#endif
- case OPT_ThreadStackSize:
- /* currently ignored */
- break;
-
case OPT_TraceCompilerCalls:
opt_TraceCompilerCalls = enable;
break;
opt_TraceExceptions = enable;
break;
+ case OPT_TraceHPI:
+ opt_TraceHPI = enable;
+ break;
+
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ case OPT_TraceInlining:
+ if (value == NULL)
+ opt_TraceInlining = 1;
+ else
+ opt_TraceInlining = system_atoi(value);
+ break;
+#endif
+
case OPT_TraceJavaCalls:
opt_verbosecall = enable;
opt_TraceJavaCalls = enable;
opt_TraceJVMCalls = enable;
break;
+ case OPT_TraceJVMCallsVerbose:
+ opt_TraceJVMCallsVerbose = enable;
+ break;
+
case OPT_TraceLinkClass:
opt_TraceLinkClass = enable;
break;
if (value == NULL)
opt_TraceReplacement = 1;
else
- opt_TraceReplacement = atoi(value);
+ opt_TraceReplacement = system_atoi(value);
+ break;
+#endif
+
+ case OPT_TraceSubsystemInitialization:
+ opt_TraceSubsystemInitialization = enable;
+ break;
+
+ case OPT_TraceTraps:
+ opt_TraceTraps = enable;
+ break;
+
+#if defined(ENABLE_VMLOG)
+ case OPT_Vmlog:
+ if (value == NULL)
+ vmlog_cacao_set_prefix("vmlog");
+ else
+ vmlog_cacao_set_prefix(value);
+ opt_verbosecall = 1;
+ opt_TraceJavaCalls = 1;
+ break;
+
+ case OPT_VmlogStrings:
+ if (value != NULL)
+ vmlog_cacao_set_stringprefix(value);
+ break;
+
+ case OPT_VmlogIgnore:
+ if (value != NULL)
+ vmlog_cacao_set_ignoreprefix(value);
break;
#endif
/* src/vmcore/options.h - define global options extern
- 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.
extern bool opt_prof_bb;
#endif
-/* inlining options ***********************************************************/
-
-#if defined(ENABLE_INLINING)
-extern bool opt_inlining;
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
-extern s4 opt_inline_debug_min_size;
-extern s4 opt_inline_debug_max_size;
-extern s4 opt_inline_debug_end_counter;
-extern bool opt_inline_debug_all;
-#endif /* defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG) */
-#if !defined(NDEBUG)
-extern bool opt_inline_debug_log;
-#endif /* !defined(NDEBUG) */
-#endif /* defined(ENABLE_INLINING) */
-
-
/* optimization options *******************************************************/
#if defined(ENABLE_IFCONV)
#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
extern bool opt_lsra;
#endif
-
+#if defined(ENABLE_SSA)
+extern bool opt_ssa_dce; /* enable dead code elemination */
+extern bool opt_ssa_cp; /* enable copy propagation */
+#endif
/* interpreter options ********************************************************/
/* NOTE: For better readability keep these alpha-sorted. */
+/* Options which must always be available (production options in
+ HotSpot). */
+
+extern int64_t opt_MaxDirectMemorySize;
+extern int opt_MaxPermSize;
+extern int opt_PermSize;
+extern int opt_ThreadStackSize;
+
+/* Debugging options which can be turned off. */
+
extern int opt_DebugExceptions;
extern int opt_DebugFinalizer;
extern int opt_DebugLocalReferences;
extern int opt_DebugPatcher;
extern int opt_DebugPackage;
extern int opt_DebugProperties;
-extern int32_t opt_DebugStackFrameInfo;
+extern int opt_DebugStackFrameInfo;
extern int opt_DebugStackTrace;
extern int opt_DebugThreads;
#if defined(ENABLE_DISASSEMBLER)
extern int opt_DisassembleStubs;
#endif
#if defined(ENABLE_GC_CACAO)
-extern int32_t opt_GCDebugRootSet;
-extern int32_t opt_GCStress;
+extern int opt_GCDebugRootSet;
+extern int opt_GCStress;
+#endif
+#if defined(ENABLE_INLINING)
+extern int opt_Inline;
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+extern int opt_InlineAll;
+extern int opt_InlineCount;
+extern int opt_InlineMaxSize;
+extern int opt_InlineMinSize;
+#endif
#endif
-extern int32_t opt_MaxPermSize;
-extern int32_t opt_PermSize;
extern int opt_PrintConfig;
-extern int32_t opt_ProfileGCMemoryUsage;
-extern int32_t opt_ProfileMemoryUsage;
+extern int opt_ProfileGCMemoryUsage;
+extern int opt_ProfileMemoryUsage;
extern FILE *opt_ProfileMemoryUsageGNUPlot;
#if defined(ENABLE_REPLACEMENT)
extern int opt_TestReplacement;
#endif
-extern int32_t opt_ThreadStackSize;
extern int opt_TraceCompilerCalls;
-extern int32_t opt_TraceExceptions;
-extern int32_t opt_TraceJavaCalls;
-extern int32_t opt_TraceJNICalls;
-extern int32_t opt_TraceJVMCalls;
-extern int32_t opt_TraceLinkClass;
+extern int opt_TraceExceptions;
+extern int opt_TraceHPI;
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+extern int opt_TraceInlining;
+#endif
+extern int opt_TraceJavaCalls;
+extern int opt_TraceJNICalls;
+extern int opt_TraceJVMCalls;
+extern int opt_TraceJVMCallsVerbose;
+extern int opt_TraceLinkClass;
#if defined(ENABLE_REPLACEMENT)
-extern int32_t opt_TraceReplacement;
+extern int opt_TraceReplacement;
#endif
+extern int opt_TraceSubsystemInitialization;
+extern int opt_TraceTraps;
/* function prototypes ********************************************************/
-s4 options_get(opt_struct *opts, JavaVMInitArgs *vm_args);
+int options_get(opt_struct *opts, JavaVMInitArgs *vm_args);
void options_xx(JavaVMInitArgs *vm_args);
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define TRACESUBSYSTEMINITIALIZATION(text) \
+ do { \
+ if (opt_TraceSubsystemInitialization) { \
+ log_println("[Initializing subsystem: %s]", text); \
+ } \
+ } while (0)
+#else
+# define TRACESUBSYSTEMINITIALIZATION(text)
+#endif
+
#endif /* _OPTIONS_H */
/* src/vmcore/primitivecore.c - core functions for primitive types
- Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/vm.h"
#include "vmcore/class.h"
+#include "vmcore/options.h"
#include "vmcore/utf8.h"
classinfo *ac;
int i;
+ TRACESUBSYSTEMINITIALIZATION("primitive_init");
+
/* Load and link primitive-type classes and array-classes. */
for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
classinfo *c;
int i;
+ TRACESUBSYSTEMINITIALIZATION("primitive_postinit");
+
assert(class_java_lang_Class);
assert(class_java_lang_Class->vftbl);
/* src/vmcore/references.h - references to classes/fields/methods
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
} classref_or_classinfo;
-/* parseddesc *****************************************************************/
+/* parseddesc_t ***************************************************************/
typedef union parseddesc {
struct typedesc *fd; /* parsed field descriptor */
struct methoddesc *md; /* parsed method descriptor */
void *any; /* used for simple test against NULL */
-} parseddesc;
+} parseddesc_t;
#include "config.h"
/* constant_FMIref ************************************************************/
-struct constant_FMIref{ /* Fieldref, Methodref and InterfaceMethodref */
+struct constant_FMIref{ /* Fieldref, Methodref and InterfaceMethodref */
union {
s4 index; /* used only within the loader */
constant_classref *classref; /* class having this field/meth./intfm. */
fieldinfo *field; /* resolved field */
methodinfo *method; /* resolved method */
} p;
- utf *name; /* field/method/interfacemethod name */
- utf *descriptor; /* field/method/intfmeth. type descriptor string */
- parseddesc parseddesc; /* parsed descriptor */
+ utf *name; /* field/method/interfacemethod name */
+ utf *descriptor; /* field/method/intfmeth. type descriptor string */
+ parseddesc_t parseddesc; /* parsed descriptor */
};
/* macro for accessing the class name of a method reference */
#define METHODREF_CLASSNAME(fmiref) \
- (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.method->class->name \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.method->clazz->name \
: (fmiref)->p.classref->name)
/* macro for accessing the class name of a method reference */
#define FIELDREF_CLASSNAME(fmiref) \
- (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.field->class->name \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.field->clazz->name \
: (fmiref)->p.classref->name)
/* initialize a constant_classref with referer `ref` and name `classname` */
/* src/vmcore/stackmap.c - class attribute StackMapTable
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* get classinfo */
- c = cb->class;
+ c = cb->clazz;
/* allocate stack map structure */
/* src/vmcore/suck.c - functions to read LE ordered types from a buffer
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ 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 <assert.h>
-#include <dirent.h>
-#include <sys/stat.h>
#include <stdlib.h>
#include "vm/types.h"
#include "vmcore/loader.h"
#include "vmcore/options.h"
#include "vmcore/suck.h"
+#include "vmcore/system.h"
#include "vmcore/zip.h"
bool suck_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("suck_init");
+
list_classpath_entries = list_create(OFFSET(list_classpath_entry, linkage));
/* everything's ok */
/* scan the directory found for zip/jar files */
- n = scandir(path, &namelist, scandir_filter, alphasort);
+ n = system_scandir(path, &namelist, scandir_filter, alphasort);
/* On error, just continue, this should be ok. */
{
#ifdef ENABLE_VERIFIER
if (len < 0 || ((cb->data + cb->size) - cb->pos) < len) {
- exceptions_throw_classformaterror((cb)->class, "Truncated class file");
+ exceptions_throw_classformaterror(cb->clazz, "Truncated class file");
return false;
}
#endif /* ENABLE_VERIFIER */
strcpy(path, lce->path);
strcat(path, filename);
- classfile = fopen(path, "r");
+ classfile = system_fopen(path, "r");
if (classfile) { /* file exists */
- if (!stat(path, &buffer)) { /* read classfile data */
+ if (!system_stat(path, &buffer)) { /* read classfile data */
cb = NEW(classbuffer);
- cb->class = c;
+ cb->clazz = c;
cb->size = buffer.st_size;
cb->data = MNEW(u1, cb->size);
cb->pos = cb->data;
/* read class data */
- len = fread(cb->data, 1, cb->size, classfile);
+ len = system_fread((void *) cb->data, 1, cb->size,
+ classfile);
if (len != buffer.st_size) {
suck_stop(cb);
/* close the class file */
- fclose(classfile);
+ system_fclose(classfile);
}
}
/* src/vmcore/system.c - system (OS) functions
Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* src/vmcore/system.h - system (OS) functions
- Copyright (C) 2007
- CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* NOTE: In this file we check for all system headers, because we wrap
all system calls into inline functions for better portability. */
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#endif
+
+#if defined(HAVE_FCNTL_H)
+# include <fcntl.h>
+#endif
+
+#if defined(ENABLE_JRE_LAYOUT)
+# if defined(HAVE_LIBGEN_H)
+# include <libgen.h>
+# endif
+#endif
+
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#endif
+#if defined(HAVE_STDIO_H)
+# include <stdio.h>
+#endif
+
#if defined(HAVE_STDLIB_H)
# include <stdlib.h>
#endif
# include <unistd.h>
#endif
+#if defined(HAVE_SYS_MMAN_H)
+# include <sys/mman.h>
+#endif
+
+#if defined(HAVE_SYS_SOCKET_H)
+# include <sys/socket.h>
+#endif
+
+#if defined(HAVE_SYS_STAT_H)
+# include <sys/stat.h>
+#endif
+
+#if defined(HAVE_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+
/* inline functions ***********************************************************/
+inline static void system_abort(void)
+{
+#if defined(HAVE_ABORT)
+ abort();
+#else
+# error abort not available
+#endif
+}
+
+inline static int system_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
+{
+#if defined(HAVE_ACCEPT)
+ return accept(sockfd, addr, addrlen);
+#else
+# error accept not available
+#endif
+}
+
+inline static int system_access(const char *pathname, int mode)
+{
+#if defined(HAVE_ACCESS)
+ return access(pathname, mode);
+#else
+# error access not available
+#endif
+}
+
+inline static int system_atoi(const char *nptr)
+{
+#if defined(HAVE_ATOI)
+ return atoi(nptr);
+#else
+# error atoi not available
+#endif
+}
+
inline static void *system_calloc(size_t nmemb, size_t size)
{
#if defined(HAVE_CALLOC)
#endif
}
+inline static int system_close(int fd)
+{
+#if defined(HAVE_CLOSE)
+ return close(fd);
+#else
+# error close not available
+#endif
+}
+
+inline static int system_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen)
+{
+#if defined(HAVE_CONNECT)
+ return connect(sockfd, serv_addr, addrlen);
+#else
+# error connect not available
+#endif
+}
+
+#if defined(ENABLE_JRE_LAYOUT)
+inline static char *system_dirname(char *path)
+{
+#if defined(HAVE_DIRNAME)
+ return dirname(path);
+#else
+# error dirname not available
+#endif
+}
+#endif
+
+inline static FILE *system_fopen(const char *path, const char *mode)
+{
+#if defined(HAVE_FOPEN)
+ return fopen(path, mode);
+#else
+# error fopen not available
+#endif
+}
+
+inline static int system_fclose(FILE *fp)
+{
+#if defined(HAVE_FCLOSE)
+ return fclose(fp);
+#else
+# error fclose not available
+#endif
+}
+
+inline static size_t system_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
+{
+#if defined(HAVE_FREAD)
+ return fread(ptr, size, nmemb, stream);
+#else
+# error fread not available
+#endif
+}
+
inline static void system_free(void *ptr)
{
#if defined(HAVE_FREE)
#endif
}
+inline static int system_fsync(int fd)
+{
+#if defined(HAVE_FSYNC)
+ return fsync(fd);
+#else
+# error fsync not available
+#endif
+}
+
+inline static int system_ftruncate(int fd, off_t length)
+{
+#if defined(HAVE_FTRUNCATE)
+ return ftruncate(fd, length);
+#else
+# error ftruncate not available
+#endif
+}
+
+inline static int system_gethostname(char *name, size_t len)
+{
+#if defined(HAVE_GETHOSTNAME)
+ return gethostname(name, len);
+#else
+# error gethostname not available
+#endif
+}
+
inline static int system_getpagesize(void)
{
#if defined(HAVE_GETPAGESIZE)
#endif
}
+inline static int system_getsockname(int s, struct sockaddr *name, socklen_t *namelen)
+{
+#if defined(HAVE_GETSOCKNAME)
+ return getsockname(s, name, namelen);
+#else
+# error getsockname not available
+#endif
+}
+
+inline static int system_getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen)
+{
+#if defined(HAVE_GETSOCKOPT)
+ return getsockopt(s, level, optname, optval, optlen);
+#else
+# error getsockopt not available
+#endif
+}
+
+inline static int system_listen(int sockfd, int backlog)
+{
+#if defined(HAVE_LISTEN)
+ return listen(sockfd, backlog);
+#else
+# error listen not available
+#endif
+}
+
+inline static off_t system_lseek(int fildes, off_t offset, int whence)
+{
+#if defined(HAVE_LSEEK)
+ return lseek(fildes, offset, whence);
+#else
+# error lseek not available
+#endif
+}
+
inline static void *system_malloc(size_t size)
{
#if defined(HAVE_MALLOC)
#endif
}
+inline static int system_mprotect(void *addr, size_t len, int prot)
+{
+#if defined(HAVE_MPROTECT)
+ return mprotect(addr, len, prot);
+#else
+# error mprotect not available
+#endif
+}
+
+inline static int system_open(const char *pathname, int flags, mode_t mode)
+{
+#if defined(HAVE_OPEN)
+ return open(pathname, flags, mode);
+#else
+# error open not available
+#endif
+}
+
+inline static ssize_t system_read(int fd, void *buf, size_t count)
+{
+#if defined(HAVE_READ)
+ return read(fd, buf, count);
+#else
+# error read not available
+#endif
+}
+
inline static void *system_realloc(void *ptr, size_t size)
{
#if defined(HAVE_REALLOC)
#endif
}
+#if defined(__LINUX__)
+inline static int system_scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
+#else
+inline static int system_scandir(const char *dir, struct dirent ***namelist, int(*filter)(struct dirent *), int(*compar)(const void *, const void *))
+#endif
+{
+#if defined(HAVE_SCANDIR)
+ return scandir(dir, namelist, filter, compar);
+#else
+# error scandir not available
+#endif
+}
+
+inline static int system_setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen)
+{
+#if defined(HAVE_SETSOCKOPT)
+ return setsockopt(s, level, optname, optval, optlen);
+#else
+# error setsockopt not available
+#endif
+}
+
+inline static int system_shutdown(int s, int how)
+{
+#if defined(HAVE_SHUTDOWN)
+ return shutdown(s, how);
+#else
+# error shutdown not available
+#endif
+}
+
+inline static int system_socket(int domain, int type, int protocol)
+{
+#if defined(HAVE_SOCKET)
+ return socket(domain, type, protocol);
+#else
+# error socket not available
+#endif
+}
+
+inline static int system_stat(const char *path, struct stat *buf)
+{
+#if defined(HAVE_STAT)
+ return stat(path, buf);
+#else
+# error stat not available
+#endif
+}
+
+inline static char *system_strcat(char *dest, const char *src)
+{
+#if defined(HAVE_STRCAT)
+ return strcat(dest, src);
+#else
+# error strcat not available
+#endif
+}
+
+inline static char *system_strcpy(char *dest, const char *src)
+{
+#if defined(HAVE_STRCPY)
+ return strcpy(dest, src);
+#else
+# error strcpy not available
+#endif
+}
+
+inline static char *system_strdup(const char *s)
+{
+#if defined(HAVE_STRDUP)
+ return strdup(s);
+#else
+# error strdup not available
+#endif
+}
+
+inline static char *system_strerror(int errnum)
+{
+#if defined(HAVE_STRERROR)
+ return strerror(errnum);
+#else
+# error strerror not available
+#endif
+}
+
+inline static size_t system_strlen(const char *s)
+{
+#if defined(HAVE_STRLEN)
+ return strlen(s);
+#else
+# error strlen not available
+#endif
+}
+
+inline static ssize_t system_write(int fd, const void *buf, size_t count)
+{
+#if defined(HAVE_WRITE)
+ return write(fd, buf, count);
+#else
+# error write not available
+#endif
+}
+
/* function prototypes ********************************************************/
/* src/vmcore/utf8.c - utf8 string functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
utf *utf_java_lang_InterruptedException;
utf *utf_java_lang_NegativeArraySizeException;
utf *utf_java_lang_NullPointerException;
+utf *utf_java_lang_RuntimeException;
utf *utf_java_lang_StringIndexOutOfBoundsException;
utf *utf_java_lang_reflect_InvocationTargetException;
utf *utf_java_lang_reflect_Constructor;
utf *utf_java_lang_reflect_Field;
utf *utf_java_lang_reflect_Method;
+
+# if defined(WITH_CLASSPATH_GNU)
+utf *utf_java_lang_reflect_VMConstructor;
+utf *utf_java_lang_reflect_VMField;
+utf *utf_java_lang_reflect_VMMethod;
+# endif
+
utf *utf_java_util_Vector;
#endif
utf *utf_clinit; /* <clinit> */
utf *utf_clone; /* clone */
utf *utf_finalize; /* finalize */
+utf *utf_invoke;
+utf *utf_main;
utf *utf_run; /* run */
utf *utf_add;
utf *utf_java_lang_String__java_lang_Class;
utf *utf_java_lang_Thread__V; /* (Ljava/lang/Thread;)V */
utf *utf_java_lang_Thread_java_lang_Throwable__V;
+utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
utf *utf_java_lang_Throwable__void; /* (Ljava/lang/Throwable;)V */
utf *utf_java_lang_Throwable__java_lang_Throwable;
*******************************************************************************/
-bool utf8_init(void)
+void utf8_init(void)
{
+ TRACESUBSYSTEMINITIALIZATION("utf8_init");
+
/* create utf8 hashtable */
hashtable_utf = NEW(hashtable);
utf_java_lang_NullPointerException =
utf_new_char("java/lang/NullPointerException");
+ utf_java_lang_RuntimeException =
+ utf_new_char("java/lang/RuntimeException");
+
utf_java_lang_StringIndexOutOfBoundsException =
utf_new_char("java/lang/StringIndexOutOfBoundsException");
utf_java_lang_reflect_Field = utf_new_char("java/lang/reflect/Field");
utf_java_lang_reflect_Method = utf_new_char("java/lang/reflect/Method");
+
+# if defined(WITH_CLASSPATH_GNU)
+ utf_java_lang_reflect_VMConstructor = utf_new_char("java/lang/reflect/VMConstructor");
+ utf_java_lang_reflect_VMField = utf_new_char("java/lang/reflect/VMField");
+ utf_java_lang_reflect_VMMethod = utf_new_char("java/lang/reflect/VMMethod");
+# endif
+
utf_java_util_Vector = utf_new_char("java/util/Vector");
#endif
utf_Signature = utf_new_char("Signature");
utf_StackMapTable = utf_new_char("StackMapTable");
-#if defined(ENABLE_ANNOTATIONS)
+# if defined(ENABLE_ANNOTATIONS)
utf_RuntimeVisibleAnnotations = utf_new_char("RuntimeVisibleAnnotations");
utf_RuntimeInvisibleAnnotations = utf_new_char("RuntimeInvisibleAnnotations");
utf_RuntimeVisibleParameterAnnotations = utf_new_char("RuntimeVisibleParameterAnnotations");
utf_RuntimeInvisibleParameterAnnotations = utf_new_char("RuntimeInvisibleParameterAnnotations");
utf_AnnotationDefault = utf_new_char("AnnotationDefault");
-#endif
+# endif
#endif
utf_init = utf_new_char("<init>");
utf_clinit = utf_new_char("<clinit>");
utf_clone = utf_new_char("clone");
utf_finalize = utf_new_char("finalize");
+ utf_invoke = utf_new_char("invoke");
+ utf_main = utf_new_char("main");
utf_run = utf_new_char("run");
utf_add = utf_new_char("add");
utf_java_lang_Thread_java_lang_Throwable__V =
utf_new_char("(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
+ utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V =
+ utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
+
utf_java_lang_Throwable__void = utf_new_char("(Ljava/lang/Throwable;)V");
utf_java_lang_Throwable__java_lang_Throwable =
utf_null = utf_new_char("null");
utf_not_named_yet = utf_new_char("\t<not_named_yet>");
array_packagename = utf_new_char("\t<the array package>");
-
- /* everything's ok */
-
- return true;
}
/* src/vmcore/utf8.h - utf8 string functions
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
extern utf *utf_java_lang_InterruptedException;
extern utf *utf_java_lang_NegativeArraySizeException;
extern utf *utf_java_lang_NullPointerException;
+extern utf *utf_java_lang_RuntimeException;
extern utf *utf_java_lang_StringIndexOutOfBoundsException;
extern utf *utf_java_lang_reflect_InvocationTargetException;
extern utf *utf_java_lang_reflect_Constructor;
extern utf *utf_java_lang_reflect_Field;
extern utf *utf_java_lang_reflect_Method;
+
+# if defined(WITH_CLASSPATH_GNU)
+extern utf *utf_java_lang_reflect_VMConstructor;
+extern utf *utf_java_lang_reflect_VMField;
+extern utf *utf_java_lang_reflect_VMMethod;
+# endif
+
extern utf *utf_java_util_Vector;
#endif
extern utf *utf_clinit;
extern utf *utf_clone;
extern utf *utf_finalize;
+extern utf *utf_invoke;
+extern utf *utf_main;
extern utf *utf_run;
extern utf *utf_add;
extern utf *utf_java_lang_String__java_lang_Class;
extern utf *utf_java_lang_Thread__V;
extern utf *utf_java_lang_Thread_java_lang_Throwable__V;
+extern utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
extern utf *utf_java_lang_Throwable__void;
extern utf *utf_java_lang_Throwable__java_lang_Throwable;
/* function prototypes ********************************************************/
/* initialize the utf8 subsystem */
-bool utf8_init(void);
+void utf8_init(void);
u4 utf_hashkey(const char *text, u4 length);
u4 utf_full_hashkey(const char *text, u4 length);
/* src/vmcore/zip.c - ZIP file handling for bootstrap classloader
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
cb = NEW(classbuffer);
- cb->class = c;
+ cb->clazz = c;
cb->size = htzfe->uncompressedsize;
cb->data = outdata;
cb->pos = outdata;
+++ /dev/null
-public class A2 {
-static A a2 = new A();
-static int myZero;
-
-}
-
-
+++ /dev/null
-public class AA
-{
-static int xx;
-
-public void f9() {
- int x = 1;
-}
-public static void main(String[] s) {
-AA2 a;
-DD d = new DD();
-EE e = new EE();
-int x = 1;
-
-for (int i=1;i<5;i++) {
-xx = 5;
-if (x==1)
- a=d;
-else
- a=e;
-a.f();
-
-
-}
-}
-}
+++ /dev/null
-public class AA1 extends AA
-{
-public void f() {
- int x = 3;
-}
-}
+++ /dev/null
-public class AA2 extends AA1
-{
-public void f3() {
- int x = 3;
-}
-}
+++ /dev/null
-public class BB extends AA
-{
-public void f() {
- int x = 2;
- GG g = new GG();
-}
-}
+++ /dev/null
-class C extends A {
-static int cx = 1;
-
-void m1( ) {ax = 100; cx=1;
-}
-
-public static void main(String[] s) {
- A a;
- B b = new B();
- a=b;
- b.m1();
- b.m2();
- cx++;
-// System.out.println("Hello World"));
-// System.out.println("C: "+ ax +"; B: "+b.ax +"; A: "+a.ax);
- }
-}
-
+++ /dev/null
-class C2 extends A {
-int cx;
-void m1( ) {ax = 100; cx=1;
-//D d = new D();
-}
-public static void main(String[] s) {
- A a;
- B b;
- int i=1;
-if (i==1)
- a = new A();
-else
- a = new D();
-
- a.m1();
- a.m2();
- }
-}
-
+++ /dev/null
-class C3 extends A {
-int cx;
-void m1( ) {ax = 100; cx=1;
-}
-public static void main(String[] s) {
- A a = A2.a2;
- B b = new B();
- int x = A2.myZero;
- a=b;
- b.m1();
- b.m2();
-
-// System.out.println("Hello World"));
-// System.out.println("C: "+ ax +"; B: "+b.ax +"; A: "+a.ax);
- }
-}
-
-
+++ /dev/null
-public class CC extends AA2
-{
-public void f() {
- int x = 3;
-}
-}
+++ /dev/null
-class D extends A {
-int ax = 133;
-
-void m1( ) {ax = ax + 10;
- // System.out.println("In D.m1: "+ax);
- }
-
-B m3( ) {
-B b = new B();
-b.bx++;
-return b;
-}
-}
+++ /dev/null
-public class DD extends CC
-{
-public void f2() {
- int x = 4;
-}
-}
+++ /dev/null
-public class EE extends CC
-{
-public void f2() {
- int x = 6;
-}
-}
+++ /dev/null
-public class GG extends BB
-{
-public void f() {
- int x = 5;
-}
-}
+++ /dev/null
-public class HI2 {
- public static int max1(int i, int j) {
-
- if (i > j)
- return i;
- else
- return j;
- }
-
- public static void main(String[] args) {
- int i;
- int j;
- int k;
- for (i=0; i<10; i++) {
- j = (i*2)-5;
- k = max1(i, j);
- }
- }
-}
+++ /dev/null
-interface II{
-public void foo();
-public void foo2();
-}
+++ /dev/null
-class IIAA implements II {
-int xx;
-int yy;
-int zz;
-
-public void foo( ) {
- int j = xx;
-}
-
-public void foo2( ) {
- int j = zz;
-}
-
-public void bar ( ) {
-yy=0;
-zz=1;
-}
-}
+++ /dev/null
-class IIBB extends IIAA {
-public void foo() {
- yy=0;
- zz=0;
- int j= zz;
-}
-
-public void bar ( ) {
- yy=1;
-}
-}
+++ /dev/null
-class IICC extends IIAA {
-public void foo( ) {
- this.bar();
-}
-}
+++ /dev/null
-class IIexample {
-public static void main (String[] args) {
-ff();
-gg();
-}
-
-static void ff() {
-II i1 = new IIBB();
-i1.foo();
-}
-
-static void gg() {
-//II i2 = new IICC();
-II i2 = new IIBB(); // so unique
-i2.foo();
-}
-
-}
## tests/Makefile.am
##
-## 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.
##
## 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
-##
-## Changes:
-## Process this file with automake to produce Makefile.in
-SUBDIRS = regression
+JAVA = LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(top_builddir)/src/cacao/cacao
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -bootclasspath $(BOOTCLASSPATH)
-EXTRA_DIST = \
- hello.java \
- prop.java \
- x.java \
- x.output \
- TestBase.java \
- TestArrayClasses.java \
- TestArrayClasses.output \
- BasicToStrings.java \
- BasicToStrings.output \
- GCBench.java \
- JavaPerformance.java \
- param_test.java \
- exception_restore_registers.java
-
-JAVA = $(top_builddir)/src/cacao/cacao
+SUBDIRS = \
+ regression
-checkall: x.tst TestArrayClasses.tst BasicToStrings.tst param_test.tst exception_restore_registers.tst
+EXTRA_DIST = \
+ $(srcdir)/*.java
-%.tst:
- $(JAVAC) $*.java
- sh Test.sh $(JAVA) $*
-# $(JAVA) $* > $*.thisoutput
-# diff --brief $*.output $*.thisoutput
- $(RM) $*.thisoutput
- $(RM) $*.this2output
+CLEANFILES = \
+ *.class
-%.tstrun:
- $(JAVAC) $*.java
- $(JAVA) $*
+build:
+ $(JAVACCMD) -d . $(srcdir)/*.java
## Local variables:
+++ /dev/null
-
-public class n implements a {
- public void do_a () { };
- public void do_a2 () { };
- public void do_b () { };
- }
-
\ No newline at end of file
+++ /dev/null
-public class HelloWorld {
- public static void main(String[] argv) {
- System.out.println("OK");
- }
-}
## tests/regression/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.
##
SUBDIRS = \
- codepatching \
+ assertion \
+ bugzilla \
jasmin \
+ junit \
native \
resolving
-JAVA = $(top_builddir)/src/cacao/cacao
-
-if WITH_CLASSPATH_GNU
-JAVAFLAGS = -Xbootclasspath:$(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
-else
-JAVAFLAGS = -Xbootclasspath:$(CLASSPATH_CLASSES)
-endif
+JAVA = $(top_builddir)/src/cacao/cacao
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -source 1.5 -target 1.5 -nowarn -bootclasspath $(BOOTCLASSPATH)
SOURCE_FILES = \
- $(srcdir)/HelloWorld.java \
$(srcdir)/jctest.java \
$(srcdir)/fptest.java \
$(srcdir)/fp.java \
$(srcdir)/extest.java \
- $(srcdir)/clinitexception.java \
$(srcdir)/LoadDisplacementOverflow.java \
$(srcdir)/FieldDisplacementOverflow.java \
$(srcdir)/StackDisplacementOverflow.java \
fptest.output \
fp.output\
extest.2output \
- clinitexception.2output \
LoadDisplacementOverflow.output \
FieldDisplacementOverflow.output \
StackDisplacementOverflow.output \
*.class \
*.thisoutput
-SIMPLE_JAVA_TESTS = \
- HelloWorld
-
OUTPUT_JAVA_TESTS = \
jctest \
fptest \
fp \
extest \
\
- clinitexception \
LoadDisplacementOverflow \
FieldDisplacementOverflow \
StackDisplacementOverflow \
MinimalClassReflection \
TestAnnotations
-check: build $(SIMPLE_JAVA_TESTS) $(OUTPUT_JAVA_TESTS)
+check: build run
build:
- @$(JAVAC) -d . $(SOURCE_FILES)
-
-$(SIMPLE_JAVA_TESTS):
- @echo "$@: "
- @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(JAVA) $(JAVAFLAGS) $@
+ $(JAVACCMD) -d . $(SOURCE_FILES)
+run: $(OUTPUT_JAVA_TESTS)
$(OUTPUT_JAVA_TESTS):
- @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVA) $(JAVAFLAGS)" $@ $(srcdir)
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD)" $@ $(srcdir)
## Local variables:
/* tests/regression/TestAnnotations.java - checks correct functionality of the
annotation API
- 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) 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: Mathias Panzenböck
-
*/
import java.lang.annotation.Annotation;
--- /dev/null
+## tests/regression/assertion/Makefile.am
+##
+## Copyright (C) 1996-2005, 2006, 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+
+JAVA = $(top_builddir)/src/cacao/cacao
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -bootclasspath $(BOOTCLASSPATH) -source 1.5 -target 1.5
+
+SOURCE_FILES = \
+ $(srcdir)/testassertions.java \
+ $(srcdir)/packagetest/testassertions.java
+
+EXTRA_DIST = \
+ $(SOURCE_FILES) \
+ Test.sh \
+ \
+ enabled.output \
+ disabled.output
+
+CLEANFILES = \
+ *.class \
+ *.thisoutput \
+ packagetest/*.class
+
+ASSERTION_TESTS = \
+ EA_TEST1 \
+ EA_TEST2 \
+ EA_PACKAGE_TEST1 \
+ EA_PACKAGE_TEST2 \
+ EA_PACKAGE_TEST3 \
+ EA_PACKAGE_TEST4 \
+ EA_PACKAGE_TEST5 \
+ DA_PACKAGE_TEST1 \
+ DA_PACKAGE_TEST2 \
+ DA_PACKAGE_TEST3 \
+ DA_PACKAGE_TEST4 \
+ DA_PACKAGE_TEST5 \
+ EA_CLASS_TEST1 \
+ EA_CLASS_TEST2 \
+ EA_CLASS_TEST3 \
+ EA_CLASS_TEST4 \
+ EA_CLASS_TEST5 \
+ DA_CLASS_TEST1 \
+ DA_CLASS_TEST2 \
+ DA_CLASS_TEST3 \
+ DA_CLASS_TEST4 \
+ DA_CLASS_TEST5 \
+ ESA_TEST1 \
+ ESA_TEST2
+
+check: build run
+
+build:
+ $(JAVACCMD) -d . $(SOURCE_FILES)
+
+run: $(ASSERTION_TESTS)
+
+EA_TEST1:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -ea" testassertions eatest1 enabled $(srcdir)
+
+EA_TEST2:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -enableassertions" testassertions eatest2 enabled $(srcdir)
+
+EA_PACKAGE_TEST1:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -da -ea:packagetest..." packagetest.testassertions eapackagetest1 enabled $(srcdir)
+
+EA_PACKAGE_TEST2:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -disableassertions -ea:packagetest..." packagetest.testassertions eapackagetest2 enabled $(srcdir)
+
+EA_PACKAGE_TEST3:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -disableassertions -enableassertions:packagetest..." packagetest.testassertions eapackagetest3 enabled $(srcdir)
+
+EA_PACKAGE_TEST4:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -enableassertions:packagetest... -disableassertions " packagetest.testassertions eapackagetest4 enabled $(srcdir)
+
+EA_PACKAGE_TEST5:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -da -enableassertions:packagetest..." packagetest.testassertions eapackagetest5 enabled $(srcdir)
+
+EA_CLASS_TEST1:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -da -ea:testassertions" testassertions eaclasstest1 enabled $(srcdir)
+
+EA_CLASS_TEST2:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -disableassertions -ea:testassertions" testassertions eaclasstest2 enabled $(srcdir)
+
+EA_CLASS_TEST3:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -disableassertions -enableassertions:testassertions" testassertions eaclasstest3 enabled $(srcdir)
+
+EA_CLASS_TEST4:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -enableassertions:testassertions -disableassertions " testassertions eaclasstest4 enabled $(srcdir)
+
+EA_CLASS_TEST5:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -da -enableassertions:testassertions" testassertions eaclasstest5 enabled $(srcdir)
+
+DA_PACKAGE_TEST1:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -da:packagetest... -ea" packagetest.testassertions dapackagetest1 disabled $(srcdir)
+
+DA_PACKAGE_TEST2:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -disableassertions:packagetest... -ea" packagetest.testassertions dapackagetest2 disabled $(srcdir)
+
+DA_PACKAGE_TEST3:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -disableassertions:packagetest... -enableassertions" packagetest.testassertions dapackagetest3 disabled $(srcdir)
+
+DA_PACKAGE_TEST4:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -enableassertions -disableassertions:packagetest... " packagetest.testassertions dapackagetest4 disabled $(srcdir)
+
+DA_PACKAGE_TEST5:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -da:packagetest... -enableassertions" packagetest.testassertions dapackagetest5 disabled $(srcdir)
+
+DA_CLASS_TEST1:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -ea -da:testassertions" testassertions daclasstest1 disabled $(srcdir)
+
+DA_CLASS_TEST2:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -enableassertions -da:testassertions" testassertions daclasstest2 disabled $(srcdir)
+
+DA_CLASS_TEST3:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -enableassertions -disableassertions:testassertions" testassertions daclasstest3 disabled $(srcdir)
+
+DA_CLASS_TEST4:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -disableassertions:testassertions -enableassertions " testassertions daclasstest4 disabled $(srcdir)
+
+DA_CLASS_TEST5:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -ea -disableassertions:testassertions" testassertions daclasstest5 disabled $(srcdir)
+
+ESA_TEST1:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -esa" testassertions esatest1 disabled $(srcdir)
+
+ESA_TEST2:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(SHELL) $(srcdir)/Test.sh "$(JAVACMD) -enablesystemassertions" testassertions esatest2 disabled $(srcdir)
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+#!/bin/sh
+
+JAVA=$1
+CLASS=$2
+TESTNAME=$3
+TEST=$4
+SRCDIR=$5
+
+echo -n "$TESTNAME: "
+
+$JAVA $CLASS > $TEST.thisoutput 2>&1
+
+if [ $? -eq "0" ]; then
+ # no Error returned
+ if [ -f $SRCDIR/$TEST.2output ]; then
+ # Error should have been returned
+ echo "OK, but wrong return value: $?"
+ head $TEST.thisoutput
+ exit
+ fi
+
+ cmp -s $SRCDIR/$TEST.output $TEST.thisoutput
+
+ if [ $? -eq "0" ]; then
+ echo "OK"
+ else
+ echo "FAILED"
+ diff -u $SRCDIR/$TEST.output $TEST.thisoutput
+ fi
+
+else
+ # Error returned
+ if [ ! -f $SRCDIR/$TEST.2output ]; then
+ # No Error should have been returned
+ echo "FAILED, but wrong return value: $?"
+ head $TEST.this2output
+ exit
+ fi
+
+ cmp -s $SRCDIR/$TEST.2output $TEST.thisoutput
+
+ if [ $? -eq "0" ]; then
+ echo "OK"
+ else
+ echo "FAILED"
+ diff -u $SRCDIR/$TEST.2output $TEST.thisoutput
+ fi
+fi
+
+rm -f $TEST.thisoutput
--- /dev/null
+Assertions disabled!
--- /dev/null
+Assertions enabled!
--- /dev/null
+/* tests/regression/native/testassertions.java - assertion testing\r
+\r
+ Copyright (C) 2007\r
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO\r
+\r
+ This file is part of CACAO.\r
+\r
+ This program is free software; you can redistribute it and/or\r
+ modify it under the terms of the GNU General Public License as\r
+ published by the Free Software Foundation; either version 2, or (at\r
+ your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
+ 02110-1301, USA.\r
+\r
+*/\r
+\r
+package packagetest;\r
+\r
+public class testassertions {\r
+ public static void main(String[] args) {\r
+ try {\r
+ assert 1 == 2;\r
+ System.out.println("Assertions disabled!");\r
+ } catch (AssertionError ae) {\r
+ System.out.println("Assertions enabled!");\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/* tests/regression/native/testassertions.java - assertion testing\r
+\r
+ Copyright (C) 2007\r
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO\r
+\r
+ This file is part of CACAO.\r
+\r
+ This program is free software; you can redistribute it and/or\r
+ modify it under the terms of the GNU General Public License as\r
+ published by the Free Software Foundation; either version 2, or (at\r
+ your option) any later version.\r
+\r
+ This program is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\r
+ 02110-1301, USA.\r
+\r
+*/\r
+\r
+public class testassertions {\r
+ public static void main(String[] args) {\r
+ try {\r
+ assert 1 == 2;\r
+ System.out.println("Assertions disabled!");\r
+ } catch (AssertionError ae) {\r
+ System.out.println("Assertions enabled!");\r
+ }\r
+ }\r
+}
\ No newline at end of file
--- /dev/null
+/* tests/regression/bugzilla/All.java - runs all CACAO regression unit tests
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+public class All extends TestCase {
+ /**
+ * Runs all CACAO regression unit tests using
+ * junit.textui.TestRunner
+ */
+ public static void main(String[] args) {
+ Test s = suite();
+ TestRunner.run(s);
+ }
+
+ /**
+ * Collects all CACAO regression unit tests as one suite
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("CACAO Regression Unit Tests");
+
+ // Add your test here.
+
+ suite.addTest(new TestSuite(PR52.class));
+ suite.addTest(new TestSuite(PR57.class));
+ suite.addTest(new TestSuite(PR58.class));
+ suite.addTest(new TestSuite(PR65.class));
+
+ return suite;
+ }
+}
--- /dev/null
+## tests/regression/bugzilla/Makefile.am
+##
+## Copyright (C) 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+
+JAVA = LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(top_builddir)/src/cacao/cacao
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -bootclasspath $(BOOTCLASSPATH)
+
+EXTRA_DIST = \
+ $(srcdir)/*.java
+
+CLEANFILES = \
+ *.class
+
+check: build run
+
+build:
+ $(JAVACCMD) -classpath /usr/share/java/junit4.jar -d . $(srcdir)/*.java
+
+run:
+ $(JAVACMD) -classpath /usr/share/java/junit4.jar:. org.junit.runner.JUnitCore All
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+/* tests/regression/bugzilla/PR52.java
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+import java.security.*;
+
+public class PR52 extends TestCase {
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(PR52.class);
+ }
+
+ public void test() {
+ // This one only triggers with GNU Classpath.
+ AccessController.getContext();
+ }
+}
--- /dev/null
+/* tests/regression/bugzilla/PR57.java
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+public class PR57 extends TestCase {
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(PR57.class);
+ }
+
+ public void test() {
+ try {
+ Class.forName("x");
+ fail("Should throw ClassNotFoundException");
+ }
+ catch (ClassNotFoundException success) {
+ }
+ }
+}
--- /dev/null
+/* tests/regression/bugzilla/PR58.java
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+import java.io.*;
+
+public class PR58 extends TestCase {
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(PR58.class);
+ }
+
+ class x extends y {}
+ class y {}
+
+ public void testSuperClass() {
+ // Delete the class file which is extended.
+ new File("PR58$y.class").delete();
+
+ try {
+ Class.forName("PR58$x");
+ fail("Should throw NoClassDefFoundError");
+ }
+ catch (ClassNotFoundException error) {
+ fail("Unexpected exception: " + error);
+ }
+ catch (NoClassDefFoundError success) {
+ // Check if the cause is correct.
+ assertTrue(success.getCause() instanceof ClassNotFoundException);
+ }
+ }
+
+ interface i {}
+ class j implements i {}
+
+ public void testSuperInterface() {
+ // Delete the interface file which is implemented.
+ new File("PR58$i.class").delete();
+
+ try {
+ Class.forName("PR58$j");
+ fail("Should throw NoClassDefFoundError");
+ }
+ catch (ClassNotFoundException error) {
+ fail("Unexpected exception: " + error);
+ }
+ catch (NoClassDefFoundError success) {
+ // Check if the cause is correct.
+ assertTrue(success.getCause() instanceof ClassNotFoundException);
+ }
+ }
+}
--- /dev/null
+/* tests/regression/bugzilla/PR65.java
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+public class PR65 extends TestCase {
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(PR65.class);
+ }
+
+ public void test() {
+ try {
+ Object o = new int[2][1];
+ Number[][] na = (Number[][]) o;
+ fail("Should throw ClassCastException");
+ } catch (ClassCastException success) {
+ }
+ }
+}
+++ /dev/null
-Exception in thread "main" java.lang.ExceptionInInitializerError
- <<No stacktrace available>>
-Caused by: java.lang.RuntimeException
- at clinitexception.<clinit>(clinitexception.java:4)
+++ /dev/null
-public class clinitexception {
- static {
- if (true)
- throw new RuntimeException();
- }
-
- public static void main(String[] argv) {
- }
-}
+++ /dev/null
-## tests/regression/codepatching/Makefile.am
-##
-## Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
-##
-## This file is part of CACAO.
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License as
-## published by the Free Software Foundation; either version 2, or (at
-## your option) any later version.
-##
-## This program is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-## 02110-1301, USA.
-##
-## Contact: cacao@cacaojvm.org
-##
-## Authors: Christian Thalinger
-
-
-JAVA = $(top_builddir)/src/cacao/cacao
-
-if WITH_CLASSPATH_GNU
-JAVAFLAGS = -Xbootclasspath:$(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
-else
-JAVAFLAGS = -Xbootclasspath:$(CLASSPATH_CLASSES)
-endif
-
-SOURCE_FILES = \
- $(srcdir)/aastoreconstClass.java \
- $(srcdir)/checkcastC.java \
- $(srcdir)/checkcastI.java \
- $(srcdir)/getfieldD.java \
- $(srcdir)/getfieldF.java \
- $(srcdir)/getfieldI.java \
- $(srcdir)/getfieldJ.java \
- $(srcdir)/getfieldL.java \
- $(srcdir)/getstaticD.java \
- $(srcdir)/getstaticF.java \
- $(srcdir)/getstaticI.java \
- $(srcdir)/getstaticJ.java \
- $(srcdir)/getstaticL.java \
- $(srcdir)/instanceofC.java \
- $(srcdir)/instanceofI.java \
- $(srcdir)/invokespecial.java \
- $(srcdir)/invokestatic.java \
- $(srcdir)/multianewarray.java \
- $(srcdir)/newarray.java \
- $(srcdir)/putfieldD.java \
- $(srcdir)/putfieldF.java \
- $(srcdir)/putfieldI.java \
- $(srcdir)/putfieldJ.java \
- $(srcdir)/putfieldL.java \
- $(srcdir)/putfieldconstC.java \
- $(srcdir)/putfieldconstD.java \
- $(srcdir)/putfieldconstF.java \
- $(srcdir)/putfieldconstI.java \
- $(srcdir)/putfieldconstJ.java \
- $(srcdir)/putfieldconstL.java \
- $(srcdir)/putstaticD.java \
- $(srcdir)/putstaticF.java \
- $(srcdir)/putstaticI.java \
- $(srcdir)/putstaticJ.java \
- $(srcdir)/putstaticL.java \
- $(srcdir)/putstaticconstC.java \
- $(srcdir)/putstaticconstD.java \
- $(srcdir)/putstaticconstF.java \
- $(srcdir)/putstaticconstI.java \
- $(srcdir)/putstaticconstJ.java \
- $(srcdir)/putstaticconstL.java \
- $(srcdir)/test.java
-
-EXTRA_DIST = \
- $(SOURCE_FILES)
-
-MAINCLASS = \
- test.class
-
-CLASSES = \
- aastoreconstClass.class \
- checkcastC.class \
- checkcastI.class \
- getfieldD.class \
- getfieldF.class \
- getfieldI.class \
- getfieldJ.class \
- getfieldL.class \
- getstaticD.class \
- getstaticF.class \
- getstaticI.class \
- getstaticJ.class \
- getstaticL.class \
- instanceofC.class \
- instanceofI.class \
- invokespecial.class \
- invokestatic.class \
- multianewarray.class \
- newarray.class \
- putfieldD.class \
- putfieldF.class \
- putfieldI.class \
- putfieldJ.class \
- putfieldL.class \
- putfieldconstC.class \
- putfieldconstD.class \
- putfieldconstF.class \
- putfieldconstI.class \
- putfieldconstJ.class \
- putfieldconstL.class \
- putstaticD.class \
- putstaticF.class \
- putstaticI.class \
- putstaticJ.class \
- putstaticL.class \
- putstaticconstC.class \
- putstaticconstD.class \
- putstaticconstF.class \
- putstaticconstI.class \
- putstaticconstJ.class \
- putstaticconstL.class
-
-CLEANFILES = \
- *.class
-
-check: build
- @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(JAVA) $(JAVAFLAGS) test
-
-build:
- @$(JAVAC) -nowarn -d . $(SOURCE_FILES)
-
-remove:
- $(RM) $(CLASSES)
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
+++ /dev/null
-public class aastoreconstClass {
-}
-
+++ /dev/null
-public class checkcastC {
-}
+++ /dev/null
-public interface checkcastI {
-}
+++ /dev/null
-public class getfieldD {
- public double d = 789.012;
-}
+++ /dev/null
-public class getfieldF {
- public float f = 123.456F;
-}
+++ /dev/null
-public class getfieldI {
- public int i = 123;
-}
+++ /dev/null
-public class getfieldJ {
- public long l = 1234567890123L;
-}
+++ /dev/null
-public class getfieldL {
- public Object o = null;
-}
+++ /dev/null
-public class getstaticD {
- public static double d = 789.012;
-}
+++ /dev/null
-public class getstaticF {
- public static float f = 123.456F;
-}
+++ /dev/null
-public class getstaticI {
- public static int i = 123;
-}
+++ /dev/null
-public class getstaticJ {
- public static long l = 1234567890123L;
-}
+++ /dev/null
-public class getstaticL {
- public static Object o = null;
-}
+++ /dev/null
-public class instanceofC {
-}
+++ /dev/null
-public interface instanceofI {
-}
+++ /dev/null
-public class invokespecial {
- public invokespecial() {
- System.out.println("OK");
- }
-}
+++ /dev/null
-public class invokestatic {
- public static void sub() {
- System.out.println("OK");
- }
-}
+++ /dev/null
-public class multianewarray {
-}
+++ /dev/null
-public class newarray {
-}
+++ /dev/null
-public class putfieldD {
- public double d;
-}
+++ /dev/null
-public class putfieldF {
- public float f;
-}
+++ /dev/null
-public class putfieldI {
- public int i;
-}
+++ /dev/null
-public class putfieldJ {
- public long l;
-}
+++ /dev/null
-public class putfieldL {
- public Object o;
-}
+++ /dev/null
-public class putfieldconstC {
- public Class c;
-}
+++ /dev/null
-public class putfieldconstD {
- public double d;
-}
+++ /dev/null
-public class putfieldconstF {
- public float f;
-}
+++ /dev/null
-public class putfieldconstI {
- public int i;
-}
+++ /dev/null
-public class putfieldconstJ {
- public long l;
-}
+++ /dev/null
-public class putfieldconstL {
- public Object o;
-}
+++ /dev/null
-public class putstaticD {
- public static double d;
-}
+++ /dev/null
-public class putstaticF {
- public static float f;
-}
+++ /dev/null
-public class putstaticI {
- public static int i;
-}
+++ /dev/null
-public class putstaticJ {
- public static long l;
-}
+++ /dev/null
-public class putstaticL {
- public static Object o;
-}
+++ /dev/null
-public class putstaticconstC {
- public static Class c;
-}
+++ /dev/null
-public class putstaticconstD {
- public static double d;
-}
+++ /dev/null
-public class putstaticconstF {
- public static float f;
-}
+++ /dev/null
-public class putstaticconstI {
- public static int i;
-}
+++ /dev/null
-public class putstaticconstJ {
- public static long l;
-}
+++ /dev/null
-public class putstaticconstL {
- public static Object o;
-}
+++ /dev/null
-public class test extends Thread {
- static boolean doit = true;
-
- public static void main(String[] argv) {
- int threadcount = 1;
-
- if (argv.length > 0) {
- for (int i = 0; i < argv.length; i++) {
- if (argv[i].equals("--help")) {
- usage();
-
- } else if (argv[i].equals("skip")) {
- doit = false;
-
- } else {
- threadcount = Integer.valueOf(argv[i]).intValue();
- }
- }
- }
-
- System.out.println("Running with " + threadcount + " threads.");
-
- for (int i = 0; i < threadcount; i++) {
- new test().start();
- }
- }
-
- static void usage() {
- System.out.println("test [number of threads] [skip]");
- System.exit(1);
- }
-
- public test() {
- }
-
- public void start() {
- run();
- }
-
- public void run() {
- invokestatic();
-
- getstatic();
- putstatic();
- putstaticconst();
-
- getfield();
- putfield();
- putfieldconst();
-
- newarray();
- multianewarray();
-
- invokespecial();
-
- checkcast();
- _instanceof();
-
- aastoreconst();
- }
-
-
- final private static void invokestatic() {
- try {
- p("invokestatic: ");
- if (doit)
- invokestatic.sub();
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
-
- private void getstatic() {
- try {
- p("getstatic (I): ");
- if (doit)
- check(getstaticI.i, 123);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getstatic (J): ");
- if (doit)
- check(getstaticJ.l, 1234567890123L);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getstatic (F): ");
- if (doit)
- check(getstaticF.f, 123.456F);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getstatic (D): ");
- if (doit)
- check(getstaticD.d, 789.012);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getstatic (L): ");
- if (doit)
- check(getstaticL.o, null);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void putstatic() {
- try {
- p("putstatic (I): ");
- if (doit) {
- int i = 123;
- putstaticI.i = i;
- check(putstaticI.i, i);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstatic (J): ");
- if (doit) {
- long l = 1234567890123L;
- putstaticJ.l = l;
- check(putstaticJ.l, l);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstatic (F): ");
- if (doit) {
- float f = 123.456F;
- putstaticF.f = f;
- check(putstaticF.f, f);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstatic (D): ");
- if (doit) {
- double d = 789.012;
- putstaticD.d = d;
- check(putstaticD.d, d);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
-
- try {
- p("putstatic (L): ");
- if (doit) {
- Object o = null;
- putstaticL.o = o;
- check(putstaticL.o, o);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void putstaticconst() {
- try {
- p("putstaticconst (I): ");
- if (doit) {
- putstaticconstI.i = 123;
- check(putstaticconstI.i, 123);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst (J): ");
- if (doit) {
- putstaticconstJ.l = 1234567890123L;
- check(putstaticconstJ.l, 1234567890123L);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst (F): ");
- if (doit) {
- putstaticconstF.f = 123.456F;
- check(putstaticconstF.f, 123.456F);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst (D): ");
- if (doit) {
- putstaticconstD.d = 789.012;
- check(putstaticconstD.d, 789.012);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst zero (I): ");
- if (doit) {
- putstaticconstI.i = 0;
- check(putstaticconstI.i, 0);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst zero (J): ");
- if (doit) {
- putstaticconstJ.l = 0L;
- check(putstaticconstJ.l, 0L);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst zero (F): ");
- if (doit) {
- putstaticconstF.f = 0.0F;
- check(putstaticconstF.f, 0.0F);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst zero (D): ");
- if (doit) {
- putstaticconstD.d = 0.0;
- check(putstaticconstD.d, 0.0);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst zero (L): ");
- if (doit) {
- putstaticconstL.o = null;
- check(putstaticconstL.o, null);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putstaticconst unresolved class: ");
- if (doit) {
- putstaticconstC.c = putstaticconstC.class;
- check(putstaticconstC.c, Class.forName("putstaticconstC"));
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- } catch (ClassNotFoundException t) {
- failed(t);
- }
- }
-
- private void getfield() {
- try {
- p("getfield (I): ");
- if (doit)
- check(new getfieldI().i, 123);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getfield (J): ");
- if (doit)
- check(new getfieldJ().l, 1234567890123L);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getfield (F): ");
- if (doit)
- check(new getfieldF().f, 123.456F);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getfield (D): ");
- if (doit)
- check(new getfieldD().d, 789.012);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("getfield (L): ");
- if (doit)
- check(new getfieldL().o, null);
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void putfield() {
- try {
- p("putfield (I): ");
- if (doit) {
- putfieldI pfi = new putfieldI();
- int i = 123;
- pfi.i = i;
- check(pfi.i, i);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfield (J): ");
- if (doit) {
- putfieldJ pfj = new putfieldJ();
- long l = 1234567890123L;
- pfj.l = l;
- check(pfj.l, l);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfield (F): ");
- if (doit) {
- putfieldF pff = new putfieldF();
- float f = 123.456F;
- pff.f = f;
- check(pff.f, f);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfield (D): ");
- if (doit) {
- putfieldD pfd = new putfieldD();
- double d = 789.012;
- pfd.d = d;
- check(pfd.d, d);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfield (L): ");
- if (doit) {
- putfieldL pfl = new putfieldL();
- Object o = null;
- pfl.o = o;
- check(pfl.o, o);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void putfieldconst() {
- try {
- p("putfieldconst (I): ");
- if (doit) {
- putfieldconstI pfci = new putfieldconstI();
- pfci.i = 123;
- check(pfci.i, 123);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst (J): ");
- if (doit) {
- putfieldconstJ pfcj = new putfieldconstJ();
- pfcj.l = 1234567890123L;
- check(pfcj.l, 1234567890123L);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst (F): ");
- if (doit) {
- putfieldconstF pfcf = new putfieldconstF();
- pfcf.f = 123.456F;
- check(pfcf.f, 123.456F);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst (D): ");
- if (doit) {
- putfieldconstD pfcd = new putfieldconstD();
- pfcd.d = 789.012;
- check(pfcd.d, 789.012);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst zero (I): ");
- if (doit) {
- putfieldconstI pfci = new putfieldconstI();
- pfci.i = 0;
- check(pfci.i, 0);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst zero (J): ");
- if (doit) {
- putfieldconstJ pfcj = new putfieldconstJ();
- pfcj.l = 0L;
- check(pfcj.l, 0L);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst zero (F): ");
- if (doit) {
- putfieldconstF pfcf = new putfieldconstF();
- pfcf.f = 0.0F;
- check(pfcf.f, 0.0F);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst zero (D): ");
- if (doit) {
- putfieldconstD pfcd = new putfieldconstD();
- pfcd.d = 0.0;
- check(pfcd.d, 0.0);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst zero (L): ");
- if (doit) {
- putfieldconstL pfcl = new putfieldconstL();
- pfcl.o = null;
- check(pfcl.o, null);
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("putfieldconst unresolved class: ");
- if (doit) {
- putfieldconstC pfcc = new putfieldconstC();
- pfcc.c = putfieldconstC.class;
- check(pfcc.c, Class.forName("putfieldconstC"));
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- } catch (ClassNotFoundException t) {
- failed(t);
- }
- }
-
- private void newarray() {
- try {
- p("newarray: ");
- if (doit) {
- newarray[] na = new newarray[1];
- }
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void multianewarray() {
- try {
- p("multianewarray: ");
- if (doit) {
- multianewarray[][] ma = new multianewarray[1][1];
- }
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void invokespecial() {
- try {
- p("invokespecial: ");
- if (doit)
- new invokespecial();
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void checkcast() {
- Object o = new Object();
-
- // class
- try {
- p("checkcast class: ");
- if (doit) {
- checkcastC cc = (checkcastC) o;
- failed();
- } else
- ok();
- } catch (ClassCastException e) {
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- // interface
- try {
- p("checkcast interface: ");
- if (doit) {
- checkcastI ci = (checkcastI) o;
- failed();
- } else
- ok();
- } catch (ClassCastException e) {
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
-
- // array
-
- Object[] oa = new Object[1];
-
- try {
- p("checkcast class array: ");
- if (doit) {
- checkcastC[] cca = (checkcastC[]) oa;
- failed();
- } else
- ok();
- } catch (ClassCastException e) {
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void _instanceof() {
- Object o = new Object();
-
- try {
- p("instanceof class: ");
- if (doit)
- if (o instanceof instanceofC)
- failed();
- else
- ok();
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
- try {
- p("instanceof interface: ");
- if (doit)
- if (o instanceof instanceofI)
- failed();
- else
- ok();
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
-
-
- // array
-
- Object[] oa = new Object[1];
-
- try {
- p("instanceof class array: ");
- if (doit)
- if (oa instanceof instanceofC[])
- failed();
- else
- ok();
- else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- }
- }
-
- private void aastoreconst() {
- Class[] ca = new Class[1];
-
- try {
- p("aastoreconst of unresolved class != NULL: ");
- if (doit) {
- ca[0] = aastoreconstClass.class;
-
- if (ca[0] != null)
- ok();
- else
- failed();
-
- p("aastoreconst of unresolved correct value: ");
- check(ca[0],Class.forName("aastoreconstClass"));
- } else
- ok();
- } catch (NoClassDefFoundError t) {
- failed(t);
- } catch (ClassNotFoundException t) {
- failed(t);
- }
- }
-
- private static final void ok() {
- pln("OK");
- }
-
- private static final void failed() {
- pln("FAILED");
- }
-
- private static final void failed(Throwable t) {
- pln("FAILED: " + t);
- }
-
- private static final void check(int a, int b) {
- if (a == b)
- ok();
- else
- pln("FAILED: " + a + " != " + b + " (0x" + Integer.toHexString(a) + " != 0x" + Integer.toHexString(b) + ")");
- }
-
- private static final void check(long a, long b) {
- if (a == b)
- ok();
- else
- pln("FAILED: " + a + " != " + b + " (0x" + Long.toHexString(a) + " != 0x" + Long.toHexString(b) + ")");
- }
-
- private static final void check(float a, float b) {
- if (a == b)
- ok();
- else
- pln("FAILED: " + a + " != " + b);
- }
-
- private static final void check(double a, double b) {
- if (a == b)
- ok();
- else
- pln("FAILED: " + a + " != " + b);
- }
-
- private static final void check(Object a, Object b) {
- if (a == b)
- ok();
- else
- pln("FAILED: " + a + " != " + b);
- }
-
- private static final void p(String s) {
- System.out.print(s);
- }
-
- private static final void pln(String s) {
- System.out.println(s);
- }
-}
-
-// vim: et ts=4 sw=4
-
## tests/regression/jasmin/Makefile.am
##
-## 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.
##
## 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
-## Edwin Steiner
-## Process this file with automake to produce Makefile.in
-
-JAVA = $(top_builddir)/src/cacao/cacao
-
-if WITH_CLASSPATH_GNU
-JAVAFLAGS = -Xbootclasspath:$(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
-else
-JAVAFLAGS = -Xbootclasspath:$(CLASSPATH_CLASSES)
-endif
-
-JASMIN_TESTS = \
- $(srcdir)/test_coalesce_simple_store.j \
- $(srcdir)/test_dup2.j \
- $(srcdir)/test_dup2_x1.j \
- $(srcdir)/test_dup2_x2.j \
- $(srcdir)/test_dup.j \
- $(srcdir)/test_dup_x1.j \
- $(srcdir)/test_dup_x1_interface_slots.j \
- $(srcdir)/test_dup_x2.j \
- $(srcdir)/test_dup_x2_interface_slots.j \
- $(srcdir)/test_dup_x2_to_dup_x1.j \
- $(srcdir)/test.j \
- $(srcdir)/test_iinc.j \
- $(srcdir)/test_load_store_conflict_by_exception.j \
- $(srcdir)/test_load_store_conflict_by_exception_not_thrown.j \
- $(srcdir)/test_load_store_conflict.j \
- $(srcdir)/test_load_store_conflict_via_dup.j \
- $(srcdir)/test_load_store_conflict_via_swap.j \
- $(srcdir)/test_many_dup.j \
- $(srcdir)/test_many_dup_x1.j \
- $(srcdir)/test_many_dup_x2.j \
- $(srcdir)/test_many_dup2.j \
- $(srcdir)/test_many_dup2_x1.j \
- $(srcdir)/test_many_dup2_x2.j \
- $(srcdir)/test_many_monitors.j \
- $(srcdir)/test_many_swap.j \
- $(srcdir)/test_no_store_load_conflict.j \
- $(srcdir)/test_no_store_store_conflict.j \
- $(srcdir)/test_nullpointerexception_monitorexit.j \
- $(srcdir)/test_simple_load_store.j \
- $(srcdir)/test_store_load_conflict.j \
- $(srcdir)/test_store_store_conflict_2.j \
- $(srcdir)/test_store_store_conflict.j \
- $(srcdir)/test_swap_interface_slots.j \
- $(srcdir)/test_swap.j \
- $(srcdir)/test_swap_locals.j \
- $(srcdir)/test_verify_fail_aload_retaddress.j \
- $(srcdir)/test_verify_fail_areturn_wrong_reftype.j \
- $(srcdir)/test_verify_fail_athrow_wrong_reftype.j \
- $(srcdir)/test_verify_fail_athrow_wrong_reftype_unresolved.j \
- $(srcdir)/test_verify_fail_backward_with_new_on_stack.j \
- $(srcdir)/test_verify_fail_double_local_index.j \
- $(srcdir)/test_verify_fail_double_overwritten.j \
- $(srcdir)/test_verify_fail_getfield_basic_type_instance.j \
- $(srcdir)/test_verify_fail_getfield_basic_type_lookup.j \
- $(srcdir)/test_verify_fail_getfield_basic_type_value.j \
- $(srcdir)/test_verify_fail_handler_bad_local.j \
- $(srcdir)/test_verify_fail_init_nullpointer.j \
- $(srcdir)/test_verify_fail_invoke_basic_type.j \
- $(srcdir)/test_verify_fail_invoke_return_basic_type.j \
- $(srcdir)/test_verify_fail_ireturn_wrong_type.j \
- $(srcdir)/test_verify_fail_jsr_called_with_different_stackdepths.j \
- $(srcdir)/test_verify_fail_jsr_exceptions.j \
- $(srcdir)/test_verify_fail_jsr_handler_in_sub.j \
- $(srcdir)/test_verify_fail_jsr_merge_subroutines.j \
- $(srcdir)/test_verify_fail_jsr_merge_subroutines_via_stack.j \
- $(srcdir)/test_verify_fail_jsr_polymorphic_pop.j \
- $(srcdir)/test_verify_fail_load_wrong_type.j \
- $(srcdir)/test_verify_fail_load_wrong_type_within_block.j \
- $(srcdir)/test_verify_fail_local_index.j \
- $(srcdir)/test_verify_fail_long_local_index.j \
- $(srcdir)/test_verify_fail_long_local.j \
- $(srcdir)/test_verify_fail_long_overwritten.j \
- $(srcdir)/test_verify_fail_merge_different_new_objects.j \
- $(srcdir)/test_verify_fail_merge_init_nullpointer.j \
- $(srcdir)/test_verify_fail_putfield_basic_type_instance.j \
- $(srcdir)/test_verify_fail_putfield_basic_type_lookup.j \
- $(srcdir)/test_verify_fail_putfield_basic_type_value.j \
- $(srcdir)/test_verify_fail_putfieldconst_basic_type_instance.j \
- $(srcdir)/test_verify_fail_putfieldconst_basic_type_value.j \
- $(srcdir)/test_verify_fail_putstatic_basic_type_value.j \
- $(srcdir)/test_verify_fail_putstaticconst_basic_type_value.j \
- $(srcdir)/test_verify_fail_retaddr_as_object.j \
- $(srcdir)/test_verify_fail_ret_bad_type.j \
- $(srcdir)/test_verify_fail_ret_uninit_var.j \
- $(srcdir)/test_verify_fail_split_local.j \
- $(srcdir)/test_verify_ok_jsr_handler_in_sub2.j \
- $(srcdir)/test_verify_ok_jsr_improper_nesting.j \
- $(srcdir)/test_verify_ok_jsr.j \
- $(srcdir)/test_verify_ok_jsr_multiple_blocks.j \
- $(srcdir)/test_verify_ok_jsr_pop.j \
- $(srcdir)/test_verify_ok_jsr_push.j \
- $(srcdir)/test_verify_ok_jsr_subroutine_loops_to_start.j \
- $(srcdir)/test_verify_ok_jsr_swap.j \
- $(srcdir)/test_verify_ok_jsr_through_variable.j \
- $(srcdir)/test_verify_ok_local_as_retaddr_and_reference.j \
- $(srcdir)/test_verify_ok_overwrite_local_type.j \
- $(srcdir)/test_verify_ok_untyped_local.j \
- $(srcdir)/test_verify_unspecced_ok_backward_with_new_in_local.j \
- $(srcdir)/test_verify_unspecced_ok_backward_with_new_on_stack.j \
- $(srcdir)/test_verify_unspecced_ok_new_in_local_within_try.j
+JAVA = LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(top_builddir)/src/cacao/cacao
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -bootclasspath $(BOOTCLASSPATH)
EXTRA_DIST = \
$(srcdir)/runtest \
$(srcdir)/show \
- $(JASMIN_TESTS)
+ $(srcdir)/*.j
CLEANFILES = \
*.class \
TESTLOG TESTEXPECT TESTOUT TESTERR TESTSIA
-check:
- @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs JAVA="$(JAVA)" JAVAFLAGS="$(JAVAFLAGS)" $(srcdir)/runtest $(JASMIN_TESTS)
+check: build run
+
+build:
+ $(JAVACMD) -cp /usr/share/java/jasmin-sable.jar jasmin.Main $(srcdir)/*.j
+
+run:
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs JAVA="$(top_builddir)/src/cacao/cacao -Xbootclasspath:$(BOOTCLASSPATH)" $(srcdir)/runtest $(srcdir)/*.j
+
## Local variables:
## mode: Makefile
ECHOFLAGS='-e'
fi
-if [ -z "$JASMIN_JAR" ] ; then
- JASMIN_JAR=/usr/share/java/jasmin-sable.jar
-fi
-
-if [ ! -r "$JASMIN_JAR" ] ; then
- echo >&2 "$0: warning: jasmin .jar is not available at $JASMIN_JAR"
- exit 0
-fi
-
-JASMIN="$JAVA $JAVAFLAGS -cp $JASMIN_JAR jasmin.Main"
-
echo "java command: $JAVA $JAVAFLAGS"
-echo "jasmin command: $JASMIN"
while [ -n "$1" ]
do
EXPECTSTATUS=0
CHECKICMD=0
- # compile the test
-
- $JASMIN "$TEST" || exit 2
-
if grep 'ERROR:' "$TEST" >/dev/null ; then
EXPECTSTATUS=1
EXPECTERROR=$(grep 'ERROR:.*' "$TEST" | sed 's,.*ERROR:[ \t]*,,')
# run the test
- $TIMEOUTRUN $JAVA $JAVAFLAGS "$TESTBASENAME" >"$TESTOUT" 2>"$TESTERR"
+ $TIMEOUTRUN $JAVA $JAVAFLAGS "$TESTBASENAME" >"$TESTOUT" 2>"$TESTERR"
TESTSTATUS=$?
if [ $TESTSTATUS -ne $EXPECTSTATUS ] ; then
--- /dev/null
+.class public test_load_store_conflict_different_types
+.super java/lang/Object
+
+; ======================================================================
+
+.method public <init>()V
+ aload_0
+ invokenonvirtual java/lang/Object/<init>()V
+ return
+.end method
+
+; ======================================================================
+
+.method public static checkI(I)V
+ .limit locals 1
+ .limit stack 10
+ getstatic java/lang/System/out Ljava/io/PrintStream;
+ iload_0
+ invokevirtual java/io/PrintStream/println(I)V
+ return
+.end method
+
+.method public static checkString(Ljava/lang/String;)V
+ .limit locals 1
+ .limit stack 10
+ getstatic java/lang/System/out Ljava/io/PrintStream;
+ aload_0
+ invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
+ return
+.end method
+
+; ======================================================================
+
+.method public static main([Ljava/lang/String;)V
+ .limit stack 3
+ .limit locals 3
+
+ ldc 35
+ istore 1
+ ldc 42
+ istore 2
+
+ aload 0
+ ifnull force_basic_block_boundary
+
+ ; --------------------------------------------------
+
+ iload 1 ; loads 35
+ ldc "Sepp"
+ astore 1
+ istore 2 ; stores 35
+
+ ; --------------------------------------------------
+
+ aload 1
+ invokestatic test_load_store_conflict_different_types/checkString(Ljava/lang/String;)V
+ ; OUTPUT: Sepp
+
+ iload 2
+ invokestatic test_load_store_conflict_different_types/checkI(I)V
+ ; OUTPUT: 35
+
+force_basic_block_boundary:
+
+ return
+.end method
+++ /dev/null
-.class public test_verify_fail_jsr_multiple_returns
-.super java/lang/Object
-
-; ======================================================================
-
-.method public <init>()V
- aload_0
- invokenonvirtual java/lang/Object/<init>()V
- return
-.end method
-
-; ======================================================================
-
-.method public static check(I)V
- .limit locals 1
- .limit stack 10
- getstatic java/lang/System/out Ljava/io/PrintStream;
- iload_0
- invokevirtual java/io/PrintStream/println(I)V
- return
-.end method
-
-.method public static check(Ljava/lang/String;)V
- .limit locals 1
- .limit stack 10
- getstatic java/lang/System/out Ljava/io/PrintStream;
- aload_0
- invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
- return
-.end method
-
-; ======================================================================
-
-.method public static main([Ljava/lang/String;)V
- .limit stack 2
- .limit locals 4
-
- ldc 0
- istore 1
-
- aload 0
- ifnull force_basic_block_boundary
-
- ; --------------------------------------------------
-
- jsr sbr_1
-
- jsr sbr_1
-
- ; --------------------------------------------------
-
-force_basic_block_boundary:
-
- iload 1
- invokestatic test_verify_fail_jsr_multiple_returns/check(I)V
-
- return
-
-sbr_1:
- astore 2
- ldc "one"
- invokestatic test_verify_fail_jsr_multiple_returns/check(Ljava/lang/String;)V
- jsr sbr_2
- ldc "one-B"
- invokestatic test_verify_fail_jsr_multiple_returns/check(Ljava/lang/String;)V
- iinc 1 1
- ret 2
-
-sbr_2:
- astore 3
- ldc "two"
- invokestatic test_verify_fail_jsr_multiple_returns/check(Ljava/lang/String;)V
- iload 1
- ifne second_time
- ret 3
-
-second_time:
- ret 2
- ; ERROR: VerifyError
-
-.end method
-
--- /dev/null
+.class public test_verify_fail_jsr_multiple_returns
+.super java/lang/Object
+
+; ======================================================================
+
+.method public <init>()V
+ aload_0
+ invokenonvirtual java/lang/Object/<init>()V
+ return
+.end method
+
+; ======================================================================
+
+.method public static check(I)V
+ .limit locals 1
+ .limit stack 10
+ getstatic java/lang/System/out Ljava/io/PrintStream;
+ iload_0
+ invokevirtual java/io/PrintStream/println(I)V
+ return
+.end method
+
+.method public static check(Ljava/lang/String;)V
+ .limit locals 1
+ .limit stack 10
+ getstatic java/lang/System/out Ljava/io/PrintStream;
+ aload_0
+ invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
+ return
+.end method
+
+; ======================================================================
+
+.method public static main([Ljava/lang/String;)V
+ .limit stack 2
+ .limit locals 4
+
+ ldc 0
+ istore 1
+
+ aload 0
+ ifnull force_basic_block_boundary
+
+ ; --------------------------------------------------
+
+ jsr sbr_1
+
+ jsr sbr_1
+
+ ; --------------------------------------------------
+
+force_basic_block_boundary:
+
+ iload 1
+ invokestatic test_verify_fail_jsr_multiple_returns/check(I)V
+
+ return
+
+sbr_1:
+ astore 2
+ ldc "one"
+ invokestatic test_verify_fail_jsr_multiple_returns/check(Ljava/lang/String;)V
+ jsr sbr_2
+ ldc "one-B"
+ invokestatic test_verify_fail_jsr_multiple_returns/check(Ljava/lang/String;)V
+ iinc 1 1
+ ret 2
+
+sbr_2:
+ astore 3
+ ldc "two"
+ invokestatic test_verify_fail_jsr_multiple_returns/check(Ljava/lang/String;)V
+ iload 1
+ ifne second_time
+ ret 3
+
+second_time:
+ ret 2
+ ; ERROR: VerifyError
+
+.end method
+
+++ /dev/null
-.class public test_verify_fail_jsr_recursion
-.super java/lang/Object
-
-; ======================================================================
-
-.method public <init>()V
- aload_0
- invokenonvirtual java/lang/Object/<init>()V
- return
-.end method
-
-; ======================================================================
-
-.method public static check(I)V
- .limit locals 1
- .limit stack 10
- getstatic java/lang/System/out Ljava/io/PrintStream;
- iload_0
- invokevirtual java/io/PrintStream/println(I)V
- return
-.end method
-
-; ======================================================================
-
-.method public static main([Ljava/lang/String;)V
- .limit stack 2
- .limit locals 4
-
- ldc 0
- istore 1
-
- aload 0
- ifnull force_basic_block_boundary
-
- ; --------------------------------------------------
-
- jsr sbr_1
- jsr sbr_1
-
- ; --------------------------------------------------
-
-force_basic_block_boundary:
-
- iload 1
- invokestatic test_verify_fail_jsr_recursion/check(I)V
-
- return
-
-sbr_1:
- astore 2
- iload 1
- invokestatic test_verify_fail_jsr_recursion/check(I)V
- iload 1
- ifne second_time
- iinc 1 1
- jsr sbr_1
- ; ERROR: VerifyError
-
-second_time:
- ret 2
-
-.end method
-
--- /dev/null
+.class public test_verify_fail_jsr_recursion
+.super java/lang/Object
+
+; ======================================================================
+
+.method public <init>()V
+ aload_0
+ invokenonvirtual java/lang/Object/<init>()V
+ return
+.end method
+
+; ======================================================================
+
+.method public static check(I)V
+ .limit locals 1
+ .limit stack 10
+ getstatic java/lang/System/out Ljava/io/PrintStream;
+ iload_0
+ invokevirtual java/io/PrintStream/println(I)V
+ return
+.end method
+
+; ======================================================================
+
+.method public static main([Ljava/lang/String;)V
+ .limit stack 2
+ .limit locals 4
+
+ ldc 0
+ istore 1
+
+ aload 0
+ ifnull force_basic_block_boundary
+
+ ; --------------------------------------------------
+
+ jsr sbr_1
+ jsr sbr_1
+
+ ; --------------------------------------------------
+
+force_basic_block_boundary:
+
+ iload 1
+ invokestatic test_verify_fail_jsr_recursion/check(I)V
+
+ return
+
+sbr_1:
+ astore 2
+ iload 1
+ invokestatic test_verify_fail_jsr_recursion/check(I)V
+ iload 1
+ ifne second_time
+ iinc 1 1
+ jsr sbr_1
+ ; ERROR: VerifyError
+
+second_time:
+ ret 2
+
+.end method
+
+++ /dev/null
-.class public test_verify_fail_jsr_recursion_terminates
-.super java/lang/Object
-
-; ======================================================================
-
-.method public <init>()V
- aload_0
- invokenonvirtual java/lang/Object/<init>()V
- return
-.end method
-
-; ======================================================================
-
-.method public static check(I)V
- .limit locals 1
- .limit stack 10
- getstatic java/lang/System/out Ljava/io/PrintStream;
- iload_0
- invokevirtual java/io/PrintStream/println(I)V
- return
-.end method
-
-.method public static check(Ljava/lang/String;)V
- .limit locals 1
- .limit stack 10
- getstatic java/lang/System/out Ljava/io/PrintStream;
- aload_0
- invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
- return
-.end method
-
-; ======================================================================
-
-.method public static main([Ljava/lang/String;)V
- .limit stack 2
- .limit locals 4
-
- ldc 0
- istore 1
-
- aload 0
- ifnull force_basic_block_boundary
-
- ; --------------------------------------------------
-
- jsr sbr_1
- jsr sbr_1
-
- ; --------------------------------------------------
-
-force_basic_block_boundary:
-
- iload 1
- invokestatic test_verify_fail_jsr_recursion_terminates/check(I)V
-
- return
-
-sbr_1:
- ldc "entry"
- invokestatic test_verify_fail_jsr_recursion_terminates/check(Ljava/lang/String;)V
- iload 1
- ifne second_time
-
- astore 2
- ldc "first"
- invokestatic test_verify_fail_jsr_recursion_terminates/check(Ljava/lang/String;)V
- iinc 1 1
- jsr sbr_1
- ; ERROR: VerifyError
- ret 2
-
-second_time:
- astore 3
- ldc "second"
- invokestatic test_verify_fail_jsr_recursion_terminates/check(Ljava/lang/String;)V
- ret 3
-
-.end method
-
--- /dev/null
+.class public test_verify_fail_jsr_recursion_terminates
+.super java/lang/Object
+
+; ======================================================================
+
+.method public <init>()V
+ aload_0
+ invokenonvirtual java/lang/Object/<init>()V
+ return
+.end method
+
+; ======================================================================
+
+.method public static check(I)V
+ .limit locals 1
+ .limit stack 10
+ getstatic java/lang/System/out Ljava/io/PrintStream;
+ iload_0
+ invokevirtual java/io/PrintStream/println(I)V
+ return
+.end method
+
+.method public static check(Ljava/lang/String;)V
+ .limit locals 1
+ .limit stack 10
+ getstatic java/lang/System/out Ljava/io/PrintStream;
+ aload_0
+ invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
+ return
+.end method
+
+; ======================================================================
+
+.method public static main([Ljava/lang/String;)V
+ .limit stack 2
+ .limit locals 4
+
+ ldc 0
+ istore 1
+
+ aload 0
+ ifnull force_basic_block_boundary
+
+ ; --------------------------------------------------
+
+ jsr sbr_1
+ jsr sbr_1
+
+ ; --------------------------------------------------
+
+force_basic_block_boundary:
+
+ iload 1
+ invokestatic test_verify_fail_jsr_recursion_terminates/check(I)V
+
+ return
+
+sbr_1:
+ ldc "entry"
+ invokestatic test_verify_fail_jsr_recursion_terminates/check(Ljava/lang/String;)V
+ iload 1
+ ifne second_time
+
+ astore 2
+ ldc "first"
+ invokestatic test_verify_fail_jsr_recursion_terminates/check(Ljava/lang/String;)V
+ iinc 1 1
+ jsr sbr_1
+ ; ERROR: VerifyError
+ ret 2
+
+second_time:
+ astore 3
+ ldc "second"
+ invokestatic test_verify_fail_jsr_recursion_terminates/check(Ljava/lang/String;)V
+ ret 3
+
+.end method
+
--- /dev/null
+/* tests/regression/junit/All.java - runs all CACAO regression unit tests
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+public class All extends TestCase {
+ /**
+ * Runs all CACAO regression unit tests using
+ * junit.textui.TestRunner
+ */
+ public static void main(String[] args) {
+ Test s = suite();
+ TestRunner.run(s);
+ }
+
+ /**
+ * Collects all CACAO regression unit tests as one suite.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("CACAO Regression Unit Tests");
+
+ // Add your test here.
+
+ suite.addTest(new TestSuite(TestPatcher.class));
+ suite.addTest(new TestSuite(TestExceptionInStaticClassInitializer.class));
+
+ return suite;
+ }
+}
--- /dev/null
+## tests/regression/junit/Makefile.am
+##
+## Copyright (C) 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+##
+## This file is part of CACAO.
+##
+## This program is free software; you can redistribute it and/or
+## modify it under the terms of the GNU General Public License as
+## published by the Free Software Foundation; either version 2, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+
+JAVA = LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(top_builddir)/src/cacao/cacao
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -source 1.5 -target 1.5 -nowarn -bootclasspath $(BOOTCLASSPATH)
+
+EXTRA_DIST = \
+ $(srcdir)/*.java
+
+CLEANFILES = \
+ *.class
+
+check: build run
+
+build:
+ $(JAVACCMD) -classpath /usr/share/java/junit4.jar -d . $(srcdir)/*.java
+
+run:
+ $(JAVACMD) -classpath /usr/share/java/junit4.jar:. org.junit.runner.JUnitCore All
+
+
+## Local variables:
+## mode: Makefile
+## indent-tabs-mode: t
+## c-basic-offset: 4
+## tab-width: 8
+## compile-command: "automake --add-missing"
+## End:
--- /dev/null
+/* tests/regression/bugzilla/TestExceptionInStaticClassInitializer.java
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+public class TestExceptionInStaticClassInitializer extends TestCase {
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestExceptionInStaticClassInitializer.class);
+ }
+
+ public void test() {
+ try {
+ TestExceptionInStaticClassInitializer_x.i = 1;
+ fail("Should throw ExceptionInInitializerError");
+ }
+ catch (ExceptionInInitializerError success) {
+ Throwable cause = success.getCause();
+
+ assertTrue("Cause should be RuntimeException but is " + cause.getClass(), cause.getClass() == RuntimeException.class);
+
+ StackTraceElement[] ste = cause.getStackTrace();
+
+ assertTrue("Linenumber should be " + LINE + " but is " + ste[0].getLineNumber(), ste[0].getLineNumber() == LINE);
+ }
+ }
+
+ // This linenumber must be the one from...
+ final static int LINE = 64;
+}
+
+class TestExceptionInStaticClassInitializer_x {
+ static int i;
+
+ static {
+ if (true)
+ // ...the following line.
+ throw new RuntimeException();
+ }
+}
--- /dev/null
+/* tests/regression/bugzilla/TestPatcher.java
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+import junit.framework.*;
+import junit.textui.*;
+
+import java.io.*;
+
+public class TestPatcher extends TestCase {
+ public static void main(String[] args) {
+ TestRunner.run(suite());
+ }
+
+ public static Test suite() {
+ return new TestSuite(TestPatcher.class);
+ }
+
+ static boolean doit = true;
+
+ final static int i = 123;
+ final static long l = 1234567890123L;
+ final static float f = 123.456F;
+ final static double d = 789.012;
+ final static Object o = new Object();
+
+ public void testNormal() {
+ invokestatic();
+ invokespecial();
+
+ getstatic();
+ putstatic();
+ putstaticconst();
+
+ getfield();
+ putfield();
+ putfieldconst();
+
+ newarray();
+ multianewarray();
+
+ checkcast();
+ _instanceof();
+
+ aastoreconst();
+ }
+
+ public void testWithoutClasses() {
+ // Delete all classes.
+ //new File("TestPatcher$invokestatic.class").delete();
+
+ invokestatic();
+ invokespecial();
+
+ getstatic();
+ putstatic();
+ putstaticconst();
+
+ getfield();
+ putfield();
+ putfieldconst();
+
+ newarray();
+ multianewarray();
+
+ checkcast();
+ _instanceof();
+
+ aastoreconst();
+ }
+
+ private void invokestatic() {
+ try {
+ if (doit)
+ invokestatic.sub();
+ } catch (NoClassDefFoundError e) {
+ fail(e.toString());
+ }
+ }
+
+ private void getstatic() {
+ try {
+ if (doit)
+ assertTrue(getstaticI.i + " != " + i, getstaticI.i == i);
+ } catch (NoClassDefFoundError e) {
+ fail(e.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(getstaticJ.l + " != " + l, getstaticJ.l == l);
+ } catch (NoClassDefFoundError e) {
+ fail(e.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(getstaticF.f + " != " + f, getstaticF.f == f);
+ } catch (NoClassDefFoundError e) {
+ fail(e.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(getstaticD.d + " != " + d, getstaticD.d == d);
+ } catch (NoClassDefFoundError e) {
+ fail(e.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(getstaticL.o + " != null", getstaticL.o == null);
+ } catch (NoClassDefFoundError e) {
+ fail(e.toString());
+ }
+ }
+
+ private void putstatic() {
+ try {
+ if (doit) {
+ putstaticI.i = i;
+ assertTrue(putstaticI.i + " != " + i, putstaticI.i == i);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticJ.l = l;
+ assertTrue(putstaticJ.l + " != " + l, putstaticJ.l == l);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticF.f = f;
+ assertTrue(putstaticF.f + " != " + f, putstaticF.f == f);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticD.d = d;
+ assertTrue(putstaticD.d + " != " + d, putstaticD.d == d);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+
+ try {
+ if (doit) {
+ putstaticL.o = o;
+ assertTrue(putstaticL.o + " != " + o, putstaticL.o == o);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void putstaticconst() {
+ try {
+ if (doit) {
+ putstaticconstI.i = i;
+ assertTrue(putstaticconstI.i + " != " + i, putstaticconstI.i == i);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstJ.l = l;
+ assertTrue(putstaticconstJ.l + " != " + l, putstaticconstJ.l == l);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstF.f = f;
+ assertTrue(putstaticconstF.f + " != " + f, putstaticconstF.f == f);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstD.d = d;
+ assertTrue(putstaticconstD.d + " != " + d, putstaticconstD.d == d);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstI.i = 0;
+ assertTrue(putstaticconstI.i + " != " + 0, putstaticconstI.i == 0);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstJ.l = 0L;
+ assertTrue(putstaticconstJ.l + " != " + 0L, putstaticconstJ.l == 0L);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstF.f = 0.0F;
+ assertTrue(putstaticconstF.f + " != " + 0.0F, putstaticconstF.f == 0.0F);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstD.d = 0.0;
+ assertTrue(putstaticconstD.d + " != " + 0.0, putstaticconstD.d == 0.0);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstL.o = null;
+ assertTrue(putstaticconstL.o + " != " + null, putstaticconstL.o == null);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putstaticconstC.c = putstaticconstC.class;
+ assertTrue(putstaticconstC.c + " != " + Class.forName("TestPatcher$putstaticconstC"), putstaticconstC.c == Class.forName("TestPatcher$putstaticconstC"));
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ } catch (ClassNotFoundException t) {
+ fail(t.toString());
+ }
+ }
+
+ private void getfield() {
+ try {
+ if (doit)
+ assertTrue(new getfieldI().i + " != " + i, new getfieldI().i == i);
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(new getfieldJ().l + " != " + l, new getfieldJ().l == l);
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(new getfieldF().f + " != " + f, new getfieldF().f == f);
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(new getfieldD().d + " != " + d, new getfieldD().d == d);
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit)
+ assertTrue(new getfieldL().o + " != " + null, new getfieldL().o == null);
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void putfield() {
+ try {
+ if (doit) {
+ TestPatcher.putfieldI pfi = new TestPatcher.putfieldI();
+ pfi.i = i;
+ assertTrue(pfi.i + " != " + i, pfi.i == i);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldJ pfj = new putfieldJ();
+ pfj.l = l;
+ assertTrue(pfj.l + " != " + l, pfj.l == l);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldF pff = new putfieldF();
+ pff.f = f;
+ assertTrue(pff.f + " != " + f, pff.f == f);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldD pfd = new putfieldD();
+ pfd.d = d;
+ assertTrue(pfd.d + " != " + d, pfd.d == d);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldL pfl = new putfieldL();
+ pfl.o = o;
+ assertTrue(pfl.o + " != " + o, pfl.o == o);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void putfieldconst() {
+ try {
+ if (doit) {
+ putfieldconstI pfci = new putfieldconstI();
+ pfci.i = i;
+ assertTrue(pfci.i + " != " + i, pfci.i == i);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstJ pfcj = new putfieldconstJ();
+ pfcj.l = l;
+ assertTrue(pfcj.l + " != " + l, pfcj.l == l);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstF pfcf = new putfieldconstF();
+ pfcf.f = f;
+ assertTrue(pfcf.f + " != " + f, pfcf.f == f);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstD pfcd = new putfieldconstD();
+ pfcd.d = d;
+ assertTrue(pfcd.d + " != " + d, pfcd.d == d);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstI pfci = new putfieldconstI();
+ pfci.i = 0;
+ assertTrue(pfci.i + " != " + 0, pfci.i == 0);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstJ pfcj = new putfieldconstJ();
+ pfcj.l = 0L;
+ assertTrue(pfcj.l + " != " + 0L, pfcj.l == 0L);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstF pfcf = new putfieldconstF();
+ pfcf.f = 0.0F;
+ assertTrue(pfcf.f + " != " + 0.0F, pfcf.f == 0.0F);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstD pfcd = new putfieldconstD();
+ pfcd.d = 0.0;
+ assertTrue(pfcd.d + " != " + 0.0, pfcd.d == 0.0);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstL pfcl = new putfieldconstL();
+ pfcl.o = null;
+ assertTrue(pfcl.o + " != " + null, pfcl.o == null);
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit) {
+ putfieldconstC pfcc = new putfieldconstC();
+ pfcc.c = putfieldconstC.class;
+ assertTrue(pfcc.c + " != " + Class.forName("TestPatcher$putfieldconstC"), pfcc.c == Class.forName("TestPatcher$putfieldconstC"));
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ } catch (ClassNotFoundException t) {
+ fail(t.toString());
+ }
+ }
+
+ private void newarray() {
+ try {
+ if (doit) {
+ newarray[] na = new newarray[1];
+ na[0] = null;
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void multianewarray() {
+ try {
+ if (doit) {
+ multianewarray[][] ma = new multianewarray[1][1];
+ ma[0][0] = null;
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void invokespecial() {
+ try {
+ if (doit)
+ new invokespecial();
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void checkcast() {
+ Object o = new Object();
+
+ // class
+ try {
+ if (doit) {
+ checkcastC cc = (checkcastC) o;
+ fail();
+ }
+ } catch (ClassCastException success) {
+ // This is OK.
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ // interface
+ try {
+ if (doit) {
+ checkcastI ci = (checkcastI) o;
+ fail();
+ }
+ } catch (ClassCastException success) {
+ // This is OK.
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+
+ // array
+ Object[] oa = new Object[1];
+
+ try {
+ if (doit) {
+ checkcastC[] cca = (checkcastC[]) oa;
+ fail();
+ }
+ } catch (ClassCastException e) {
+ // This is OK.
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void _instanceof() {
+ Object o = new Object();
+
+ try {
+ if (doit)
+ if (o instanceof instanceofC)
+ fail();
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+ try {
+ if (doit)
+ if (o instanceof instanceofI)
+ fail();
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+
+
+ // array
+ Object[] oa = new Object[1];
+
+ try {
+ if (doit)
+ if (oa instanceof instanceofC[])
+ fail();
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ }
+ }
+
+ private void aastoreconst() {
+ Class[] ca = new Class[1];
+
+ try {
+ if (doit) {
+ ca[0] = aastoreconstClass.class;
+
+ if (ca[0] == null)
+ fail();
+
+ assertTrue(ca[0] + " != " + Class.forName("TestPatcher$aastoreconstClass") , ca[0] == Class.forName("TestPatcher$aastoreconstClass"));
+ }
+ } catch (NoClassDefFoundError t) {
+ fail(t.toString());
+ } catch (ClassNotFoundException t) {
+ fail(t.toString());
+ }
+ }
+
+ static class invokestatic { static void sub() {} }
+ static class invokespecial { void invokespecial() {} }
+
+ static class getstaticI { static int i = TestPatcher.i; }
+ static class getstaticJ { static long l = TestPatcher.l; }
+ static class getstaticF { static float f = TestPatcher.f; }
+ static class getstaticD { static double d = TestPatcher.d; }
+ static class getstaticL { static Object o = null; }
+
+ static class putstaticI { static int i; }
+ static class putstaticJ { static long l; }
+ static class putstaticF { static float f; }
+ static class putstaticD { static double d; }
+ static class putstaticL { static Object o; }
+
+ static class putstaticconstI { static int i; }
+ static class putstaticconstJ { static long l; }
+ static class putstaticconstF { static float f; }
+ static class putstaticconstD { static double d; }
+ static class putstaticconstL { static Object o; }
+ static class putstaticconstC { static Class<putstaticconstC> c; }
+
+ static class getfieldI { int i = TestPatcher.i; }
+ static class getfieldJ { long l = TestPatcher.l; }
+ static class getfieldF { float f = TestPatcher.f; }
+ static class getfieldD { double d = TestPatcher.d; }
+ static class getfieldL { Object o = null; }
+
+ static class putfieldI { int i; }
+ static class putfieldJ { long l; }
+ static class putfieldF { float f; }
+ static class putfieldD { double d; }
+ static class putfieldL { Object o; }
+
+ static class putfieldconstI { int i; }
+ static class putfieldconstJ { long l; }
+ static class putfieldconstF { float f; }
+ static class putfieldconstD { double d; }
+ static class putfieldconstL { Object o; }
+ static class putfieldconstC { Class<putfieldconstC> c; }
+
+ static class newarray {}
+ static class multianewarray {}
+
+ static class instanceofC {}
+ static interface instanceofI {}
+
+ static class checkcastC {}
+ static interface checkcastI {}
+
+ static class aastoreconstClass {}
+}
## src/tests/regression/native/Makefile.am
##
-## 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.
##
## 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) -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR) -I$(top_builddir)
-JAVA = $(top_builddir)/src/cacao/cacao
-
-if WITH_CLASSPATH_GNU
-JAVAFLAGS = -Xbootclasspath:$(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
-else
-JAVAFLAGS = -Xbootclasspath:$(CLASSPATH_CLASSES)
-endif
-
-JAVAH = @CACAOH@
+JAVA = $(top_builddir)/src/cacao/cacao
+JAVAH = $(CACAOH)
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -bootclasspath $(BOOTCLASSPATH)
+JAVAHCMD = $(JAVAH) -bootclasspath $(BOOTCLASSPATH)
SOURCE_FILES = \
checkjni.java \
check: $(TESTNAMES)
$(TESTNAMES) $(NOTESTNAMES):
- @$(JAVAC) -nowarn -d . $(srcdir)/$@.java
- @$(JAVAH) $@
- @$(CC) -shared $(AM_CPPFLAGS) $(CFLAGS) $(srcdir)/$@.c -o lib$@.so -fPIC
- @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs:. $(SHELL) $(srcdir)/../Test.sh "$(JAVA) $(JAVAFLAGS)" $@ $(srcdir)
+ @$(JAVACCMD) -d . $(srcdir)/$@.java
+ @$(JAVAHCMD) $@
+ @$(CC) -shared $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS) $(srcdir)/$@.c -o lib$@.so -fPIC
+ @LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs:. $(SHELL) $(srcdir)/../Test.sh "$(JAVACMD)" $@ $(srcdir)
## Local variables:
## tests/regression/resolving/Makefile.am
##
-## Copyright (C) 2007 R. Grafl, A. Krall, C. Kruegel,
-## C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-## E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-## J. Wenninger, Institut f. Computersprachen - TU Wien
+## Copyright (C) 2007, 2008
+## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
##
## This file is part of CACAO.
##
classes2 \
classes3
+JAVA = $(top_builddir)/src/cacao/cacao
+JAVACMD = $(JAVA) -Xbootclasspath:$(BOOTCLASSPATH)
+JAVACCMD = $(JAVAC) -bootclasspath $(BOOTCLASSPATH)
+
HARNESS_SOURCE_FILES = \
$(srcdir)/TestController.java \
$(srcdir)/TestLoader.java
CLEANFILES = \
*.class
-JAVA = $(top_builddir)/src/cacao/cacao
-
-if WITH_CLASSPATH_GNU
-JAVAFLAGS = -Xbootclasspath:$(top_builddir)/src/lib/classes/:$(CLASSPATH_CLASSES)
-else
-JAVAFLAGS = -Xbootclasspath:$(CLASSPATH_CLASSES)
-endif
-
check: $(HARNESS_CLASS_FILES)
- @for t in $(TEST_NAMES) ; do echo "TEST $$t" ; { $(JAVAC) -d . -classpath . $(srcdir)/$$t.java && LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(JAVA) $(JAVAFLAGS) $$t ; } || exit 1 ; done
+ @for t in $(TEST_NAMES) ; do echo "TEST $$t" ; { $(JAVACCMD) -d . -classpath . $(srcdir)/$$t.java && LD_LIBRARY_PATH=$(top_builddir)/src/cacao/.libs $(JAVACMD) $$t ; } || exit 1 ; done
$(HARNESS_CLASS_FILES): $(HARNESS_SOURCE_FILES)
- $(JAVAC) -d . $(HARNESS_SOURCE_FILES)
-
+ $(JAVACCMD) -d . $(HARNESS_SOURCE_FILES)
&& ((loader2_ == ld2) || ((loader2_ != null) && (ld2 != null) && loader2_.equals(ld2)))
&& class_.equals(cls);
}
+
+ public String toString() {
+ return tag_ + ": " + loader1_ + " " + loader2_ + " class=" + class_;
+ }
}
public void setReportClassIDs(boolean rep) {
expect("loaded", loader, "<" + classname + ">");
}
- public void expectDelegationAndDefinition(ClassLoader loader1, ClassLoader loader2, String classname) {
+ public void expectDelegation(ClassLoader loader1, ClassLoader loader2, String classname) {
expect("requested", loader1, classname);
expect("delegated", loader1, loader2, classname);
expect("requested", loader2, classname);
+ }
+
+ public void expectDelegationDefinition(ClassLoader loader1, ClassLoader loader2, String classname) {
expect("defined", loader2, "<" + classname + ">");
expect("loaded", loader1, "<" + classname + ">");
}
+ public void expectDelegationAndDefinition(ClassLoader loader1, ClassLoader loader2, String classname) {
+ expectDelegation(loader1, loader2, classname);
+ expectDelegationDefinition(loader1, loader2, classname);
+ }
+
public void expectDelegationAndFound(ClassLoader loader1, ClassLoader loader2, String classname) {
- expect("requested", loader1, classname);
- expect("delegated", loader1, loader2, classname);
- expect("requested", loader2, classname);
+ expectDelegation(loader1, loader2, classname);
expect("found", loader2, "<" + classname + ">");
expect("loaded", loader1, "<" + classname + ">");
}
fail(message + ": " + tag + " " + ld1 + " " + ld2 + " class=" + cls);
}
+ void fail(String message, String tag, String ld1, String ld2, String cls, Expectation exp) {
+ fail(message + ": " + tag + " " + ld1 + " " + ld2 + " class=" + cls
+ + " (expected " + exp.toString() + ")");
+ }
+
void ok(String tag, String ld1, String ld2, String cls) {
ok(tag + " " + ld1 + " " + ld2 + " class=" + cls);
}
ok(tag, ld1, ld2, cls);
}
else {
- fail("unexpected", tag, ld1, ld2, cls);
+ fail("unmatched", tag, ld1, ld2, cls, exp);
}
}
}
ld3.addParentDelegation("java.lang.String");
- // loading BarPassFoo
+ // loading and linking BarPassFoo
ct.expect("requested", ld2, "BarPassFoo");
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
ct.expect("defined", ld2, "<BarPassFoo>");
ct.expect("loaded", ld2, "<BarPassFoo>");
Class cls = ct.loadClass(ld2, "BarPassFoo");
- // linking BarPassFoo
- ct.expectLoadFromSystem(ld2, "java.lang.Object");
-
// executing BarPassFoo.passDerivedFooInstance: new DerivedFoo
- ct.expectDelegationAndDefinition(ld2, ld3, "DerivedFoo");
+ ct.expectDelegation(ld2, ld3, "DerivedFoo");
// linking (ld3, DerivedFoo)
ct.expect("requested", ld3, "Foo");
- ct.expect("defined", ld3, "<Foo>");
ct.expectLoadFromSystem(ld3, "java.lang.Object");
+ ct.expect("defined", ld3, "<Foo>");
+ ct.expectDelegationDefinition(ld2, ld3, "DerivedFoo");
// resolving Foo.virtualId
// the deferred subtype check ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is done
- ct.expectDelegationAndDefinition(ld2, ld1, "Foo");
+ ct.expectDelegation(ld2, ld1, "Foo");
// ...linking (ld2, Foo) == (ld1, Foo)
ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ ct.expectDelegationDefinition(ld2, ld1, "Foo");
// the subtype constraint ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is violated
ct.expect("exception", "java.lang.LinkageError", "<BarPassFoo>");
ld2.addParentDelegation("java.lang.String");
- // loading BarPassFoo
+ // loading & linking BarPassFoo
ct.expect("requested", ld2, "BarPassFoo");
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
ct.expect("defined", ld2, "<BarPassFoo>");
ct.expect("loaded", ld2, "<BarPassFoo>");
Class cls = ct.loadClass(ld2, "BarPassFoo");
- // linking BarPassFoo
- ct.expectLoadFromSystem(ld2, "java.lang.Object");
-
// executing BarPassFoo.passit: new Foo
ct.expect("requested", ld2, "Foo");
ct.expect("defined", ld2, "<Foo>");
// executing BarPassFoo.passit: new BarUseFoo
- ct.expectDelegationAndDefinition(ld2, ld1, "BarUseFoo");
+ ct.expectDelegation(ld2, ld1, "BarUseFoo");
// ...linking BarUseFoo
ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ ct.expectDelegationDefinition(ld2, ld1, "BarUseFoo");
// resolving Foo.virtualId() from BarUseFoo
ct.expect("requested", ld1, "Foo");
ld3.addParentDelegation("java.lang.String");
- // loading BarPassFoo
+ // loading & linking BarPassFoo
ct.expect("requested", ld2, "BarPassFoo");
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
ct.expect("defined", ld2, "<BarPassFoo>");
ct.expect("loaded", ld2, "<BarPassFoo>");
Class cls = ct.loadClass(ld2, "BarPassFoo");
- // linking BarPassFoo
- ct.expectLoadFromSystem(ld2, "java.lang.Object");
-
// executing BarPassFoo.passDerivedFoo: new DerivedFoo
- ct.expectDelegationAndDefinition(ld2, ld3, "DerivedFoo");
+ ct.expectDelegation(ld2, ld3, "DerivedFoo");
// linking (ld3, DerivedFoo)
ct.expect("requested", ld3, "Foo");
- ct.expect("defined", ld3, "<Foo>");
ct.expectLoadFromSystem(ld3, "java.lang.Object");
+ ct.expect("defined", ld3, "<Foo>");
+ ct.expectDelegationDefinition(ld2, ld3, "DerivedFoo");
// executing BarPassFoo.passit: new BarUseFoo
- ct.expectDelegationAndDefinition(ld2, ld1, "BarUseFoo");
+ ct.expectDelegation(ld2, ld1, "BarUseFoo");
// linking BarUseFoo
ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ ct.expectDelegationDefinition(ld2, ld1, "BarUseFoo");
// resolving BarUseFoo.useFoo
// the deferred subtype check ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is done
ld3.addParentDelegation("java.lang.String");
- // loading BarPassFoo
+ // loading & linking BarPassFoo
ct.expect("requested", ld2, "BarPassFoo");
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
ct.expect("defined", ld2, "<BarPassFoo>");
ct.expect("loaded", ld2, "<BarPassFoo>");
Class cls = ct.loadClass(ld2, "BarPassFoo");
- // linking BarPassFoo
- ct.expectLoadFromSystem(ld2, "java.lang.Object");
-
// executing BarPassFoo.passDerivedFoo: new DerivedFoo
- ct.expectDelegationAndDefinition(ld2, ld3, "DerivedFoo");
+ ct.expectDelegation(ld2, ld3, "DerivedFoo");
// ...linking (ld3, DerivedFoo)
ct.expect("requested", ld3, "Foo");
- ct.expect("defined", ld3, "<Foo>");
ct.expectLoadFromSystem(ld3, "java.lang.Object");
+ ct.expect("defined", ld3, "<Foo>");
+ ct.expectDelegationDefinition(ld2, ld3, "DerivedFoo");
// executing BarPassFoo.passDerivedFoo: new BarUseFoo
- ct.expectDelegationAndDefinition(ld2, ld1, "BarUseFoo");
+ ct.expectDelegation(ld2, ld1, "BarUseFoo");
// ...linking BarUseFoo
ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ ct.expectDelegationDefinition(ld2, ld1, "BarUseFoo");
// resolving BarUseFoo.useFoo
// the deferred subtype check ((ld2, DerivedFoo) subtypeof (ld2, Foo)) is done
ld2.addParentDelegation("java.lang.Object");
ld2.addParentDelegation("java.lang.String");
- // loading BarPassFoo
+ // loading & linking BarPassFoo
ct.expect("requested", ld2, "BarPassFoo");
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
ct.expect("defined", ld2, "<BarPassFoo>");
ct.expect("loaded", ld2, "<BarPassFoo>");
Class cls = ct.loadClass(ld2, "BarPassFoo");
- // linking BarPassFoo
- ct.expectLoadFromSystem(ld2, "java.lang.Object");
-
// executing createDerivedFoo
- ct.expectDelegationAndDefinition(ld2, ld1, "DerivedFoo");
+ ct.expectDelegation(ld2, ld1, "DerivedFoo");
// ...linking (ld2, DerivedFoo)
ct.expect("requested", ld1, "Foo");
- ct.expect("defined", ld1, "<Foo>");
ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ ct.expect("defined", ld1, "<Foo>");
+ ct.expectDelegationDefinition(ld2, ld1, "DerivedFoo");
ct.checkStringGetter(cls, "getDerivedFoo", "no exception");
ct.expectEnd();
ld2.addParentDelegation("java.lang.Object");
ld2.addParentDelegation("java.lang.String");
- // loading BarPassFoo
+ // loading & linking BarPassFoo
ct.expect("requested", ld2, "BarPassFoo");
+ ct.expectLoadFromSystem(ld2, "java.lang.Object");
ct.expect("defined", ld2, "<BarPassFoo>");
ct.expect("loaded", ld2, "<BarPassFoo>");
Class cls = ct.loadClass(ld2, "BarPassFoo");
- // linking BarPassFoo
- ct.expectLoadFromSystem(ld2, "java.lang.Object");
-
// executing createDerivedFoo
- ct.expectDelegationAndDefinition(ld2, ld1, "DerivedFoo");
+ ct.expectDelegation(ld2, ld1, "DerivedFoo");
// ...linking (ld2, DerivedFoo)
ct.expect("requested", ld1, "Foo");
- ct.expect("defined", ld1, "<Foo>");
ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ ct.expect("defined", ld1, "<Foo>");
+ ct.expectDelegationDefinition(ld2, ld1, "DerivedFoo");
ct.checkStringGetter(cls, "getDerivedFoo", "no exception");
ct.expectEnd();
ld2.addParentDelegation("java.lang.String");
- // loading BarUseFoo
+ // loading & linking BarUseFoo
ct.expect("requested", ld1, "BarUseFoo");
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
ct.expect("defined", ld1, "<BarUseFoo>");
ct.expect("loaded", ld1, "<BarUseFoo>");
Class cls = ct.loadClass(ld1, "BarUseFoo");
- // linking BarUseFoo
- ct.expectLoadFromSystem(ld1, "java.lang.Object");
-
// executing BarUseFoo.useReturnedFoo: new BarPassFoo
- ct.expectDelegationAndDefinition(ld1, ld2, "BarPassFoo");
+ ct.expectDelegation(ld1, ld2, "BarPassFoo");
// ...linking BarPassFoo
ct.expectLoadFromSystem(ld2, "java.lang.Object");
+ ct.expectDelegationDefinition(ld1, ld2, "BarPassFoo");
// resolving BarPassFoo.createFoo
ct.expect("requested", ld2, "Foo");
TestLoader ld1 = new TestLoader(ClassLoader.getSystemClassLoader(), "ld1", ct);
ld1.addClassfile("BarUseFoo", "classes1/BarUseFoo.class");
+ ld1.addParentDelegation("java.lang.Object");
+
ct.expect("requested", ld1, "BarUseFoo");
+ ct.expectLoadFromSystem(ld1, "java.lang.Object");
ct.expect("defined", ld1, "<BarUseFoo>");
ct.expect("loaded", ld1, "<BarUseFoo>");
- Class cls = ct.loadClass(ld1, "BarUseFoo");
- ct.expectEnd();
- ld1.addParentDelegation("java.lang.Object");
- ct.expectLoadFromSystem(ld1, "java.lang.Object");
+ Class cls = ct.loadClass(ld1, "BarUseFoo");
ct.checkClassId(cls, "classes1/BarUseFoo");
ct.expectEnd();
+++ /dev/null
-import java.applet.*;
-import java.awt.*;
-
-public class scribble extends Applet {
- private int last_x=0;
- private int last_y=0;
-
-
- public void init()
- {
- this.setBackground(Color.white);
- }
-
-
- public boolean mouseDown(Event e, int x, int y)
- {
- last_x = x; last_y=y;
- return true;
- }
-
- public boolean mouseDrag(Event e, int x, int y)
- {
- Graphics g = getGraphics();
- g.setColor (Color.black);
- g.drawLine(last_x,last_y,x,y);
- last_x=x; last_y=y;
- return true;
- }
-}
--- /dev/null
+// This test has been added because of a bug in CACAO that allowed threads
+// blocked inside monitorenter to be interrupted. In the presence of the bug,
+// the program would not exit.
+//
+// The bug has been fixed as part of the sable lock implementation.
+// hg revision 2988182011bb ff (Wed Feb 06 18:46:34 2008 +0100)
+
+public class threadInterrupt {
+ public static class firstthread implements Runnable {
+ private threadInterrupt s;
+
+ public firstthread(threadInterrupt s_) {
+ s = s_;
+ }
+ public void run() {
+ try {
+ synchronized (s.o1) {
+ System.out.println("first thread!");
+ Thread.sleep(500);
+ System.out.println("interrupting");
+ s.t2.interrupt();
+ System.out.println("leaving");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static class secondthread implements Runnable {
+ private threadInterrupt s;
+
+ public secondthread(threadInterrupt s_) {
+ s = s_;
+ }
+ public void run() {
+ try {
+ Thread.sleep(250);
+ synchronized (s.o1) {
+ System.out.println("second thread!");
+ s.o1.wait();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public Object o1 = new Object();
+ public Thread t1 = null;
+ public Thread t2 = null;
+
+ public static void main(String args[]) {
+ System.out.println("should exit with java.lang.InterruptedException");
+ threadInterrupt s = new threadInterrupt();
+ firstthread r1 = new firstthread(s);
+ secondthread r2 = new secondthread(s);
+
+ s.t1 = new Thread(r1, "a");
+ s.t2 = new Thread(r2, "b");
+ s.t1.start();
+ s.t2.start();
+ }
+}
+
+/*
+ * These are local overrides for various environment variables in 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
+// This should run forever. If it stops, that's a good indication for a bug in
+// the VM.
+//
+// This test grew a bit more elaborate than anticipated...
+// It verifies that the JVM handles properly the case of a thread being
+// interrupted and notified at the same time.
+
+public class waitAndInterrupt {
+ private class semaphore {
+ private int v;
+ public semaphore(int v) {
+ this.v = v;
+ }
+ public synchronized void semwait() {
+ while (v == 0)
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ v--;
+ }
+ public synchronized void sempost() {
+ if (v == 0)
+ notify();
+ v++;
+ }
+ }
+
+ public static class firstthread implements Runnable {
+ private waitAndInterrupt s;
+
+ public firstthread(waitAndInterrupt s_) {
+ s = s_;
+ }
+ public void run() {
+ boolean iAmFirst = Thread.currentThread() == s.t1;
+ try {
+ int i = 0;
+ int count_not = 0;
+ int count_int = 0;
+ for (;;) {
+ if (iAmFirst) {
+ if (++i == 100) {
+ i = 0;
+ System.out.println(Thread.currentThread().getName() + " still running, notified " + Integer.toString(count_not) + ", interrupted " + Integer.toString(count_int));
+ }
+ synchronized (s) {
+ s.sem1.sempost();
+ try {
+ while (!s.notified)
+ s.wait();
+ try {
+ s.wait();
+ } catch (InterruptedException e) {
+ s.notify(); // wake t2
+ }
+ count_not++;
+ } catch (InterruptedException e) {
+ count_int++;
+ }
+ }
+
+ s.sem5.sempost();
+ s.sem8.semwait();
+ } else {
+ s.sem1.semwait();
+ if (++i == 100) {
+ i = 0;
+ System.out.println(Thread.currentThread().getName() + " still running");
+ }
+ synchronized (s) {
+ s.sem2.sempost();
+ try {
+ while (!s.notified)
+ s.wait();
+ s.notified = false;
+ count_not++;
+ } catch (InterruptedException e) {
+ count_int++;
+ }
+ }
+
+ s.sem6.sempost();
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static class otherthread implements Runnable {
+ private waitAndInterrupt s;
+
+ public otherthread(waitAndInterrupt s_) {
+ s = s_;
+ }
+ public void run() {
+ boolean iAmFirst = Thread.currentThread() == s.t3;
+ try {
+ int i = 0;
+ for (;;) {
+ if (iAmFirst) {
+ s.sem3.semwait();
+ if (++i == 100) {
+ i = 0;
+ System.out.println(Thread.currentThread().getName() + " still running");
+ }
+ synchronized (s) {
+ s.sem4.sempost();
+ }
+ s.t1.interrupt();
+ s.sem5.semwait();
+ } else {
+ s.sem4.semwait();
+ if (++i == 100) {
+ i = 0;
+ System.out.println(Thread.currentThread().getName() + " still running");
+ }
+ synchronized (s) {
+ if (s.notified)
+ System.out.println("shouldn't happen (1)");
+ s.notified = true;
+ s.notify();
+ }
+ s.sem6.semwait();
+ }
+ s.sem7.sempost();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static class controlthread implements Runnable {
+ private waitAndInterrupt s;
+
+ public controlthread(waitAndInterrupt s_) {
+ s = s_;
+ }
+ public void run() {
+ try {
+ for (;;) {
+ s.sem2.semwait();
+ synchronized (s) {
+ }
+ s.sem3.sempost();
+ s.sem7.semwait();
+ s.sem7.semwait();
+ s.sem8.sempost(); // wake first
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public Thread t1 = null;
+ public Thread t2 = null;
+ public Thread t3 = null;
+ public Thread t4 = null;
+ public semaphore sem1 = new semaphore(0);
+ public semaphore sem2 = new semaphore(0);
+ public semaphore sem3 = new semaphore(0);
+ public semaphore sem4 = new semaphore(0);
+ public semaphore sem5 = new semaphore(0);
+ public semaphore sem6 = new semaphore(0);
+ public semaphore sem7 = new semaphore(0);
+ public semaphore sem8 = new semaphore(0);
+ public boolean notified = false;
+
+ public static void main(String args[]) {
+ waitAndInterrupt s = new waitAndInterrupt();
+ firstthread r1 = new firstthread(s);
+ firstthread r2 = new firstthread(s);
+ otherthread r3 = new otherthread(s);
+ controlthread r5 = new controlthread(s);
+
+ s.t1 = new Thread(r1, "a");
+ s.t2 = new Thread(r2, "b");
+ s.t3 = new Thread(r3, "c");
+ s.t4 = new Thread(r3, "d");
+ Thread t5 = new Thread(r5, "e");
+ s.t1.start();
+ s.t2.start();
+ s.t3.start();
+ s.t4.start();
+ t5.start();
+ }
+}
+
+/*
+ * These are local overrides for various environment variables in 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
+import java.lang.ref.*;
+import java.util.HashSet;
+
+class weakref {
+ class OtherThread extends Thread {
+ public volatile boolean quitNow = false;
+ private final ReferenceQueue q;
+ private final HashSet h;
+ public OtherThread(ReferenceQueue q, HashSet h) {
+ this.q = q;
+ this.h = h;
+ }
+ public void run() {
+ while (!quitNow) {
+ try {
+ MyRef r = (MyRef) q.remove();
+ h.remove(r);
+ System.out.println("Integer: " + Integer.toString(r.val));
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+ }
+
+ class MyRef extends WeakReference {
+ public final int val;
+ MyRef(Object o, ReferenceQueue q, int val) {
+ super(o, q);
+ this.val = val;
+ }
+ }
+
+ private void test() {
+ System.out.println("This should print a long list of Integers if weak references are working.");
+ ReferenceQueue q = new ReferenceQueue();
+ HashSet h = new HashSet();
+ OtherThread t = new OtherThread(q, h);
+ t.start();
+ for (int i=0; i<1000000; i++) {
+ Object o = new Integer(i);
+ Reference r = new MyRef(o, q, i);
+ h.add(r);
+ }
+ Runtime.getRuntime().gc();
+ try {
+ Thread.sleep(1000);
+ t.quitNow = true;
+ t.interrupt();
+ t.join();
+ } catch (InterruptedException e) {
+ }
+ }
+
+ public static void main(String[] args) {
+ new weakref().test();
+ }
+}
+
+/*
+ * These are local overrides for various environment variables in 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:
+ */