Merged with michi branch at rev 1684fe51cf3d.
authorMichael Starzinger <michi@complang.tuwien.ac.at>
Mon, 16 Mar 2009 19:45:58 +0000 (20:45 +0100)
committerMichael Starzinger <michi@complang.tuwien.ac.at>
Mon, 16 Mar 2009 19:45:58 +0000 (20:45 +0100)
97 files changed:
INSTALL
src/mm/memory.cpp
src/native/jni.cpp
src/native/jni.hpp
src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp
src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp
src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp
src/native/vm/gnuclasspath/java_lang_VMThread.cpp
src/native/vm/nativevm.cpp
src/native/vm/nativevm.hpp
src/native/vm/sun_misc_Unsafe.cpp
src/threads/atomic.cpp
src/threads/atomic.hpp
src/threads/posix/thread-posix.cpp
src/threads/posix/thread-posix.hpp
src/threads/thread.cpp
src/threads/thread.hpp
src/threads/threadlist.hpp
src/vm/class.cpp
src/vm/class.hpp
src/vm/javaobjects.hpp
src/vm/jit/Makefile.am
src/vm/jit/alpha/codegen.c
src/vm/jit/alpha/emit.c
src/vm/jit/alpha/linux/md-os.c
src/vm/jit/alpha/md-atomic.hpp
src/vm/jit/alpha/md.c
src/vm/jit/arm/arch.h
src/vm/jit/arm/codegen.c
src/vm/jit/arm/codegen.h
src/vm/jit/arm/emit.c
src/vm/jit/arm/linux/md-os.c
src/vm/jit/arm/md-atomic.hpp
src/vm/jit/arm/md.c
src/vm/jit/builtin.cpp
src/vm/jit/emit-common.cpp
src/vm/jit/emit-common.hpp
src/vm/jit/i386/codegen.c
src/vm/jit/i386/codegen.h
src/vm/jit/i386/darwin/md-os.c
src/vm/jit/i386/emit.c
src/vm/jit/i386/emit.h
src/vm/jit/i386/freebsd/md-os.c
src/vm/jit/i386/linux/md-os.c
src/vm/jit/i386/md-atomic.hpp
src/vm/jit/i386/patcher.c
src/vm/jit/i386/solaris/md-os.c
src/vm/jit/m68k/codegen.c
src/vm/jit/m68k/emit.c
src/vm/jit/m68k/linux/md-os.c
src/vm/jit/m68k/md-atomic.hpp
src/vm/jit/mips/arch.h
src/vm/jit/mips/codegen.c
src/vm/jit/mips/emit.c
src/vm/jit/mips/linux/md-os.c
src/vm/jit/mips/md-atomic.hpp
src/vm/jit/oprofile-agent.cpp
src/vm/jit/patcher-common.cpp
src/vm/jit/powerpc/codegen.c
src/vm/jit/powerpc/emit.c
src/vm/jit/powerpc/linux/md-os.c
src/vm/jit/powerpc/md-atomic.hpp
src/vm/jit/powerpc64/codegen.c
src/vm/jit/powerpc64/emit.c
src/vm/jit/powerpc64/linux/md-os.c
src/vm/jit/powerpc64/md-atomic.hpp
src/vm/jit/powerpc64/md.c
src/vm/jit/s390/codegen.c
src/vm/jit/s390/emit.c
src/vm/jit/s390/md-atomic.hpp
src/vm/jit/s390/md.c
src/vm/jit/sparc64/linux/md-os.c
src/vm/jit/sparc64/md-atomic.hpp
src/vm/jit/sparc64/solaris/md-os.c
src/vm/jit/trap.c [deleted file]
src/vm/jit/trap.cpp [new file with mode: 0644]
src/vm/jit/trap.h [deleted file]
src/vm/jit/trap.hpp [new file with mode: 0644]
src/vm/jit/x86_64/codegen.c
src/vm/jit/x86_64/emit.c
src/vm/jit/x86_64/linux/md-os.c
src/vm/jit/x86_64/md-atomic.hpp
src/vm/jit/x86_64/solaris/md-os.c
src/vm/loader.cpp
src/vm/options.c
src/vm/options.h
src/vm/signal.cpp
src/vm/suck.cpp
src/vm/suck.hpp
src/vm/vm.cpp
src/vm/vm.hpp
tests/TestArrayClasses.java [deleted file]
tests/TestArrayClasses.output [deleted file]
tests/TestBase.java [deleted file]
tests/regression/base/All.java
tests/regression/base/TestArrayClasses.java [new file with mode: 0644]
tests/regression/base/TestCloning.java [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
index d3c5b40a94091285c27361905f591af64c1f7b21..f3869a941abc66166ca5ac152b1c526998c696cf 100644 (file)
--- a/INSTALL
+++ b/INSTALL
-Installation Instructions
-*************************
+Quick start instructions
+========================
 
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
-2006, 2007 Free Software Foundation, Inc.
+You can check the configure options via `./configure --help'. But the
+default settings should be ok. For building the package type:
 
-This file is free documentation; the Free Software Foundation gives
-unlimited permission to copy, distribute and modify it.
+   $ ./configure
+   $ make
+   $ make install
 
-Basic Installation
-==================
+The default installation prefix is `/usr/local/cacao'. You can change
+this destination by providing the `--prefix=PATH' option to configure.
 
-Briefly, the shell commands `./configure; make; make install' should
-configure, build, and install this package.  The following
-more-detailed instructions are generic; see the `README' file for
-instructions specific to this package.
+This version of cacao only supports the `--prefix' option, even if
+configure processes the other options (`--bindir', `--libdir', etc.),
+it will screw up your installation since CACAO tries to setup a
+directory tree like the JVMs from Sun or IBM do.
 
-   The `configure' shell script attempts to guess correct values for
-various system-dependent variables used during compilation.  It uses
-those values to create a `Makefile' in each directory of the package.
-It may also create one or more `.h' files containing system-dependent
-definitions.  Finally, it creates a shell script `config.status' that
-you can run in the future to recreate the current configuration, and a
-file `config.log' containing compiler output (useful mainly for
-debugging `configure').
 
-   It can also use an optional file (typically called `config.cache'
-and enabled with `--cache-file=config.cache' or simply `-C') that saves
-the results of its tests to speed up reconfiguring.  Caching is
-disabled by default to prevent problems with accidental use of stale
-cache files.
-
-   If you need to do unusual things to compile the package, please try
-to figure out how `configure' could check whether to do them, and mail
-diffs or instructions to the address given in the `README' so they can
-be considered for the next release.  If you are using the cache, and at
-some point `config.cache' contains results you don't want to keep, you
-may remove or edit it.
-
-   The file `configure.ac' (or `configure.in') is used to create
-`configure' by a program called `autoconf'.  You need `configure.ac' if
-you want to change it or regenerate `configure' using a newer version
-of `autoconf'.
-
-The simplest way to compile this package is:
-
-  1. `cd' to the directory containing the package's source code and type
-     `./configure' to configure the package for your system.
-
-     Running `configure' might take a while.  While running, it prints
-     some messages telling which features it is checking for.
-
-  2. Type `make' to compile the package.
-
-  3. Optionally, type `make check' to run any self-tests that come with
-     the package.
-
-  4. Type `make install' to install the programs and any data files and
-     documentation.
-
-  5. You can remove the program binaries and object files from the
-     source code directory by typing `make clean'.  To also remove the
-     files that `configure' created (so you can compile the package for
-     a different kind of computer), type `make distclean'.  There is
-     also a `make maintainer-clean' target, but that is intended mainly
-     for the package's developers.  If you use it, you may have to get
-     all sorts of other programs in order to regenerate files that came
-     with the distribution.
-
-  6. Often, you can also type `make uninstall' to remove the installed
-     files again.
-
-Compilers and Options
-=====================
-
-Some systems require unusual options for compilation or linking that the
-`configure' script does not know about.  Run `./configure --help' for
-details on some of the pertinent environment variables.
-
-   You can give `configure' initial values for configuration parameters
-by setting variables in the command line or in the environment.  Here
-is an example:
-
-     ./configure CC=c99 CFLAGS=-g LIBS=-lposix
-
-   *Note Defining Variables::, for more details.
-
-Compiling For Multiple Architectures
-====================================
-
-You can compile the package for more than one kind of computer at the
-same time, by placing the object files for each architecture in their
-own directory.  To do this, you can use GNU `make'.  `cd' to the
-directory where you want the object files and executables to go and run
-the `configure' script.  `configure' automatically checks for the
-source code in the directory that `configure' is in and in `..'.
-
-   With a non-GNU `make', it is safer to compile the package for one
-architecture at a time in the source code directory.  After you have
-installed the package for one architecture, use `make distclean' before
-reconfiguring for another architecture.
-
-Installation Names
-==================
-
-By default, `make install' installs the package's commands under
-`/usr/local/bin', include files under `/usr/local/include', etc.  You
-can specify an installation prefix other than `/usr/local' by giving
-`configure' the option `--prefix=PREFIX'.
-
-   You can specify separate installation prefixes for
-architecture-specific files and architecture-independent files.  If you
-pass the option `--exec-prefix=PREFIX' to `configure', the package uses
-PREFIX as the prefix for installing programs and libraries.
-Documentation and other data files still use the regular prefix.
-
-   In addition, if you use an unusual directory layout you can give
-options like `--bindir=DIR' to specify different values for particular
-kinds of files.  Run `configure --help' for a list of the directories
-you can set and what kinds of files go in them.
-
-   If the package supports it, you can cause programs to be installed
-with an extra prefix or suffix on their names by giving `configure' the
-option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
-
-Optional Features
-=================
-
-Some packages pay attention to `--enable-FEATURE' options to
-`configure', where FEATURE indicates an optional part of the package.
-They may also pay attention to `--with-PACKAGE' options, where PACKAGE
-is something like `gnu-as' or `x' (for the X Window System).  The
-`README' should mention any `--enable-' and `--with-' options that the
-package recognizes.
-
-   For packages that use the X Window System, `configure' can usually
-find the X include and library files automatically, but if it doesn't,
-you can use the `configure' options `--x-includes=DIR' and
-`--x-libraries=DIR' to specify their locations.
-
-Specifying the System Type
-==========================
-
-There may be some features `configure' cannot figure out automatically,
-but needs to determine by the type of machine the package will run on.
-Usually, assuming the package is built to be run on the _same_
-architectures, `configure' can figure that out, but if it prints a
-message saying it cannot guess the machine type, give it the
-`--build=TYPE' option.  TYPE can either be a short name for the system
-type, such as `sun4', or a canonical name which has the form:
-
-     CPU-COMPANY-SYSTEM
-
-where SYSTEM can have one of these forms:
-
-     OS KERNEL-OS
-
-   See the file `config.sub' for the possible values of each field.  If
-`config.sub' isn't included in this package, then this package doesn't
-need to know the machine type.
-
-   If you are _building_ compiler tools for cross-compiling, you should
-use the option `--target=TYPE' to select the type of system they will
-produce code for.
-
-   If you want to _use_ a cross compiler, that generates code for a
-platform different from the build platform, you should specify the
-"host" platform (i.e., that on which the generated programs will
-eventually be run) with `--host=TYPE'.
-
-Sharing Defaults
-================
-
-If you want to set default values for `configure' scripts to share, you
-can create a site shell script called `config.site' that gives default
-values for variables like `CC', `cache_file', and `prefix'.
-`configure' looks for `PREFIX/share/config.site' if it exists, then
-`PREFIX/etc/config.site' if it exists.  Or, you can set the
-`CONFIG_SITE' environment variable to the location of the site script.
-A warning: not all `configure' scripts look for a site script.
-
-Defining Variables
-==================
-
-Variables not defined in a site shell script can be set in the
-environment passed to `configure'.  However, some packages may run
-configure again during the build, and the customized values of these
-variables may be lost.  In order to avoid this problem, you should set
-them in the `configure' command line, using `VAR=value'.  For example:
-
-     ./configure CC=/usr/local2/bin/gcc
-
-causes the specified `gcc' to be used as the C compiler (unless it is
-overridden in the site shell script).
-
-Unfortunately, this technique does not work for `CONFIG_SHELL' due to
-an Autoconf bug.  Until the bug is fixed you can use this workaround:
-
-     CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
-
-`configure' Invocation
-======================
-
-`configure' recognizes the following options to control how it operates.
-
-`--help'
-`-h'
-     Print a summary of the options to `configure', and exit.
-
-`--version'
-`-V'
-     Print the version of Autoconf used to generate the `configure'
-     script, and exit.
-
-`--cache-file=FILE'
-     Enable the cache: use and save the results of the tests in FILE,
-     traditionally `config.cache'.  FILE defaults to `/dev/null' to
-     disable caching.
-
-`--config-cache'
-`-C'
-     Alias for `--cache-file=config.cache'.
-
-`--quiet'
-`--silent'
-`-q'
-     Do not print messages saying which checks are being made.  To
-     suppress all normal output, redirect it to `/dev/null' (any error
-     messages will still be shown).
-
-`--srcdir=DIR'
-     Look for the package's source code in directory DIR.  Usually
-     `configure' can determine that directory automatically.
-
-`configure' also accepts some other, not widely useful, options.  Run
-`configure --help' for more details.
+Requirements:
+-------------
 
+In order to compile the Java classes from GNU classpath, you need a
+Java compiler supported by GNU classpath. To get a working classpath
+in an appropriate time, we recommend IBM jikes 1.18 or newer. For
+further instructions concerning GNU classpath, please refer to
+`src/classpath/INSTALL'.
index f074e1d208e23b2db716635eee2c5eac0cd9ea9e..8c0c5b2a552e51ef553efb3d182f352e0f4fc449 100644 (file)
@@ -69,7 +69,7 @@
 void memory_mprotect(void *addr, size_t len, int prot)
 {
        if (os::mprotect(addr, len, prot) != 0)
-               vm_abort_errno("memory_mprotect: os::mprotect failed");
+               os::abort_errno("memory_mprotect: os::mprotect failed");
 }
 
 
index 34c090d4c0814c8171862a0358df4481579831fe..d33892469c10a7621c96efdc14b6e8dd2a921708 100644 (file)
@@ -793,9 +793,7 @@ jint _Jv_JNI_GetVersion(JNIEnv *env)
 {
        TRACEJNICALLS(("_Jv_JNI_GetVersion(env=%p)", env));
 
-       /* We support JNI 1.6. */
-
-       return JNI_VERSION_1_6;
+       return JNI_VERSION_SUPPORTED;
 }
 
 
@@ -4118,22 +4116,28 @@ jint JNI_GetDefaultJavaVMInitArgs(void *vm_args)
        /* GNU classpath currently supports JNI 1.2 */
 
        switch (_vm_args->version) {
-    case JNI_VERSION_1_1:
+       case JNI_VERSION_1_1:
                _vm_args->version = JNI_VERSION_1_1;
                break;
 
-    case JNI_VERSION_1_2:
-    case JNI_VERSION_1_4:
+       case JNI_VERSION_1_2:
+       case JNI_VERSION_1_4:
                _vm_args->ignoreUnrecognized = JNI_FALSE;
                _vm_args->options = NULL;
                _vm_args->nOptions = 0;
                break;
 
-    default:
-               return -1;
+       case JNI_VERSION_CACAO:
+               // We reveal ourselves by accepting this version number,
+               // this actually means we are using the supported JNI version.
+               _vm_args->version = JNI_VERSION_SUPPORTED;
+               break;
+
+       default:
+               return JNI_ERR;
        }
-  
-       return 0;
+
+       return JNI_OK;
 }
 
 
index 16933eca1c84c6df8932765c60d37a533f4c68bd..e26aca44ff4fba82520026ab813a8e885c45d0b0 100644 (file)
 //#include "vm/javaobjects.hpp"
 #include "vm/global.h"
 
+
+// Some additional JNI version numbers, we currently support JNI 1.6.
+#define JNI_VERSION_SUPPORTED JNI_VERSION_1_6
+#define JNI_VERSION_CACAO     0xcaca0000
+
+
 // Typedef the JNI types.
 typedef java_handle_t*              jobject;
 typedef java_handle_t*              jclass;
index 81742ad62ce502d395eaa2a96fadbefb56b52287..bdfaf37b160ca068148207499e7d392ad233167e 100644 (file)
@@ -192,7 +192,10 @@ JNIEXPORT jobject JNICALL Java_com_sun_cldc_io_ResourceInputStream_open(JNIEnv *
        char *path;
        utf *uname;
        java_handle_t* descriptor;
-       
+
+       // Get current list of classpath entries.
+       SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
+
        /* get the classname as char string (do it here for the warning at
        the end of the function) */
 
@@ -200,10 +203,10 @@ JNIEXPORT jobject JNICALL Java_com_sun_cldc_io_ResourceInputStream_open(JNIEnv *
        filenamelen = utf_bytes(uname) + strlen("0");
        filename = MNEW(char, filenamelen);
        utf_copy(filename, uname);
-       
+
        /* walk through all classpath entries */
 
-       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+       for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end(); it++) {
                list_classpath_entry* lce = *it;
 
 #if defined(ENABLE_ZLIB)
index 856745cfba274719d69ecd1be6b05cc4ab1b7ea7..02caed9ee9462a152e070a27b1df2bc6258eb61f 100644 (file)
@@ -44,6 +44,7 @@
 #endif
 
 #include "vm/global.h"
+#include "vm/os.hpp"
 #include "vm/vm.hpp" /* REMOVE ME: temporarily */
 
 
@@ -117,7 +118,7 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf(JNIEnv
                return -1;
        }
        else if (result < 0) {
-               vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf: recv failed");
+               os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readBuf: recv failed");
        }
 
        return result;
@@ -142,7 +143,7 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_readByte(JNIEnv
        }
        else if (result < 0) {
                // TODO Should throw an IOException.
-               vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readByte: recv failed");
+               os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_readByte: recv failed");
        }
 
        return byte;
@@ -166,7 +167,7 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf(JNIEnv
 
        if (result < 0) {
                // TODO Should throw an IOException.
-               vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf: send failed");
+               os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeBuf: send failed");
        }
 
        return result;
@@ -186,7 +187,7 @@ JNIEXPORT jint JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte(JNIEn
        ssize_t result = send(handle, &byte, 1, 0);
 
        if (result < 0)
-               vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte: send failed");
+               os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_writeByte: send failed");
 
        return result;
 }
@@ -215,7 +216,7 @@ JNIEXPORT void JNICALL Java_com_sun_cldc_io_j2me_socket_Protocol_close0(JNIEnv *
        int result = close(handle);
 
        if (result < 0)
-               vm_abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_close0: close failed");
+               os::abort_errno("Java_com_sun_cldc_io_j2me_socket_Protocol_close0: close failed");
 }
 
 } // extern "C"
index b67c8bc9ef48de663bc5034d189a81006380e26e..10e2d63eba6ba5e0b4a192d502e18488107e764e 100644 (file)
@@ -260,6 +260,9 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv
        struct stat           buf;       /* buffer for stat          */
        jboolean              ret;       /* return value of "add"    */
 
+       // Get current list of classpath entries.
+       SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
+
        /* get the resource name as utf string */
 
        utfname = javastring_toutf((java_handle_t *) name, false);
@@ -319,7 +322,7 @@ JNIEXPORT jobject JNICALL Java_java_lang_VMClassLoader_nativeGetResources(JNIEnv
 
        /* iterate over all classpath entries */
 
-       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+       for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end(); it++) {
                list_classpath_entry* lce = *it;
 
                /* clear path pointer */
index da561ab5aae1e30e7adc637f185475a33539a3b0..7fcbd3460dfccd502ca43a18eeb0069cc4641368 100644 (file)
@@ -85,13 +85,9 @@ JNIEXPORT void JNICALL Java_java_lang_VMThread_interrupt(JNIEnv *env, jobject _t
 {
 #if defined(ENABLE_THREADS)
        java_handle_t *h;
-       threadobject  *t;
 
        h = (java_handle_t *) _this;
-       t = thread_get_thread(h);
-       assert(t != NULL);
-
-       threads_thread_interrupt(t);
+       thread_handle_interrupt(h);
 #endif
 }
 
@@ -105,13 +101,9 @@ JNIEXPORT jboolean JNICALL Java_java_lang_VMThread_isInterrupted(JNIEnv *env, jo
 {
 #if defined(ENABLE_THREADS)
        java_handle_t *h;
-       threadobject  *t;
 
        h = (java_handle_t *) _this;
-       t = thread_get_thread(h);
-       assert(t != NULL);
-
-       return thread_is_interrupted(t);
+       return thread_handle_is_interrupted(h);
 #else
        return 0;
 #endif
@@ -153,13 +145,9 @@ JNIEXPORT void JNICALL Java_java_lang_VMThread_nativeSetPriority(JNIEnv *env, jo
 {
 #if defined(ENABLE_THREADS)
        java_handle_t *h;
-       threadobject  *t;
 
        h = (java_handle_t *) _this;
-       t = thread_get_thread(h);
-       assert(t != NULL);
-
-       threads_set_thread_priority(t->tid, priority);
+       thread_handle_set_priority(h, priority);
 #endif
 }
 
@@ -276,16 +264,13 @@ JNIEXPORT jstring JNICALL Java_java_lang_VMThread_getState(JNIEnv *env, jobject
 {
 #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);
-       assert(t != NULL);
 
-       state = cacaothread_get_state(t);
+       state = thread_handle_get_state(h);
        
        switch (state) {
        case THREAD_STATE_NEW:
index 675bacb8518215d0ff0fe8ca071ebe3efaa76817..837b4a0b76338fd5c9ba7760948fc5755ca01bdb 100644 (file)
@@ -30,6 +30,7 @@
 #include "native/vm/nativevm.hpp"
 
 #include "vm/class.hpp"
+#include "vm/exceptions.hpp"
 #include "vm/initialize.hpp"
 #include "vm/method.hpp"
 #include "vm/options.h"
@@ -161,7 +162,7 @@ void nativevm_preinit(void)
 
 *******************************************************************************/
 
-void nativevm_init(void)
+bool nativevm_init(void)
 {
        TRACESUBSYSTEMINITIALIZATION("nativevm_init");
 
@@ -180,10 +181,13 @@ void nativevm_init(void)
                                                                                         false);
 
        if (m == NULL)
-               os::abort("nativevm_init: Error resolving java.lang.System.initializeSystemClass()");
+               return false;
 
        (void) vm_call_method(m, NULL);
 
+       if (exceptions_get_exception() != NULL)
+               return false;
+
 # else
 #  error unknown classpath configuration
 # endif
@@ -195,6 +199,8 @@ void nativevm_init(void)
 #else
 # error unknown Java configuration
 #endif
+
+       return true;
 }
 
 
index 826643f6104b67d7728db8e578cee325d61781ba..9f651a6cec99c0b7de0b6531dc69fbb7882241af 100644 (file)
@@ -31,7 +31,7 @@
 /* function prototypes ********************************************************/
 
 void nativevm_preinit(void);
-void nativevm_init(void);
+bool nativevm_init(void);
 
 #if defined(ENABLE_JAVASE)
 # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
index 8c9779ecc0084e057cbbd915e267a40471860515..bcbfe0feceb955cc6b29e16bf83e8e49f34a5f0d 100644 (file)
@@ -903,14 +903,14 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_throwException(JNIEnv *env, jobject
  */
 JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_compareAndSwapObject(JNIEnv *env, jobject _this, jobject o, jlong offset, jobject expected, jobject x)
 {
-       volatile void **p;
+       void **p;
        void           *result;
 
        /* XXX Use LLNI */
 
-       p = (volatile void **) (((uint8_t *) o) + offset);
+       p = (void **) (((uint8_t *) o) + offset);
 
-       result = Atomic::compare_and_swap(p, expected, x);
+       result = Atomic::compare_and_swap(p, (void *) expected, (void *) x);
 
        if (result == expected)
                return true;
@@ -933,7 +933,7 @@ JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_compareAndSwapInt(JNIEnv *env, j
 
        p = (uint32_t *) (((uint8_t *) o) + offset);
 
-       result = Atomic::compare_and_swap(p, expected, x);
+       result = Atomic::compare_and_swap(p, (uint32_t) expected, (uint32_t) x);
 
        if (result == (uint32_t) expected)
                return true;
@@ -956,7 +956,7 @@ JNIEXPORT jboolean JNICALL Java_sun_misc_Unsafe_compareAndSwapLong(JNIEnv *env,
 
        p = (uint64_t *) (((uint8_t *) o) + offset);
 
-       result = Atomic::compare_and_swap(p, expected, x);
+       result = Atomic::compare_and_swap(p, (uint64_t) expected, (uint64_t) x);
 
        if (result == (uint64_t) expected)
                return true;
index e5ca7c8066b714c84761c19bb465a83da4bbfc69..b87b28cc5dabff3a67ef51fb3cbb4385c37fbc40 100644 (file)
@@ -33,6 +33,7 @@
 // Gobal mutex for generic atomic instructions.
 static Mutex lock;
 
+namespace Atomic {
 
 /**
  * A generic atomic compare and swap for 32-bit integer values.  This
@@ -44,7 +45,7 @@ static Mutex lock;
  *
  * @return value of the memory location before the store
  */
-uint32_t Atomic::generic_compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+uint32_t generic_compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t result;
 
@@ -73,7 +74,7 @@ uint32_t Atomic::generic_compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-uint64_t Atomic::generic_compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+uint64_t generic_compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
        uint64_t result;
 
@@ -102,7 +103,7 @@ uint64_t Atomic::generic_compare_and_swap(volatile uint64_t *p, uint64_t oldval,
  *
  * @return value of the memory location before the store
  */
-void* Atomic::generic_compare_and_swap(volatile void** p, void* oldval, void* newval)
+void* generic_compare_and_swap(volatile void** p, void* oldval, void* newval)
 {
        void* result;
 
@@ -115,7 +116,7 @@ void* Atomic::generic_compare_and_swap(volatile void** p, void* oldval, void* ne
        if (oldval == result)
                *p = newval;
 
-       lock.lock();
+       lock.unlock();
 
        return result;
 }
@@ -125,19 +126,20 @@ void* Atomic::generic_compare_and_swap(volatile void** p, void* oldval, void* ne
  * A generic memory barrier.  This function is using a mutex to
  * provide atomicity.
  */
-void Atomic::generic_memory_barrier(void)
+void generic_memory_barrier(void)
 {
        lock.lock();
        lock.unlock();
 }
 
+}
 
 // Legacy C interface.
 
 extern "C" {
-uint32_t Atomic_compare_and_swap_32(volatile uint32_t *p, uint32_t oldval, uint32_t newval) { return Atomic::compare_and_swap(p, oldval, newval); }
-uint64_t Atomic_compare_and_swap_64(volatile uint64_t *p, uint64_t oldval, uint64_t newval) { return Atomic::compare_and_swap(p, oldval, newval); }
-void*    Atomic_compare_and_swap_ptr(volatile void** p, void* oldval, void* newval) { return Atomic::compare_and_swap(p, oldval, newval); }
+uint32_t Atomic_compare_and_swap_32(uint32_t *p, uint32_t oldval, uint32_t newval) { return Atomic::compare_and_swap(p, oldval, newval); }
+uint64_t Atomic_compare_and_swap_64(uint64_t *p, uint64_t oldval, uint64_t newval) { return Atomic::compare_and_swap(p, oldval, newval); }
+void*    Atomic_compare_and_swap_ptr(void** p, void* oldval, void* newval) { return Atomic::compare_and_swap(p, oldval, newval); }
 void     Atomic_memory_barrier(void) { Atomic::memory_barrier(); }
 void     Atomic_write_memory_barrier(void) { Atomic::write_memory_barrier(); }
 void     Atomic_instruction_barrier(void) { Atomic::instruction_barrier(); }
index 382a8724bc2b5e3b7c1c9f60f02d7c32bef3a4ad..a3875d632921b9df564603fd7568c680155a75b3 100644 (file)
 
 #ifdef __cplusplus
 
-class Atomic {
-public:
+namespace Atomic_md {
+       // Machine dependent functions.
+       uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
+       uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
+
+       void     memory_barrier(void);
+       void     write_memory_barrier(void);
+       void     instruction_barrier(void);
+}
+
+namespace Atomic {
+
        // Generic functions.
-       static uint32_t generic_compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
-       static uint64_t generic_compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
-       static void*    generic_compare_and_swap(volatile void** p, void* oldval, void* newval);
-       static void     generic_memory_barrier(void);
+       uint32_t generic_compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
+       uint64_t generic_compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
+       void*    generic_compare_and_swap(volatile void** p, void* oldval, void* newval);
+       void     generic_memory_barrier(void);
 
-       // Machine dependent functions.
-       static uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
-       static uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
-       static void*    compare_and_swap(volatile void** p, void* oldval, void* newval);
-       static void     memory_barrier(void);
-       static void     write_memory_barrier(void);
-       static void     instruction_barrier(void);
-};
+}
 
 // Include machine dependent implementation.
 #include "md-atomic.hpp"
 
+namespace Atomic {
+
+       struct CAS_32_functor {
+               typedef uint32_t value_type;
+               static value_type compare_and_swap(value_type *p, value_type o, value_type n) {
+                       return Atomic_md::compare_and_swap(p, o, n);
+               }
+       };
+
+       struct CAS_64_functor {
+               typedef uint64_t value_type;
+               static value_type compare_and_swap(value_type *p, value_type o, value_type n) {
+                       return Atomic_md::compare_and_swap(p, o, n);
+               }
+       };
+
+       template<int N> class CAS_chooser;
+       template<> class CAS_chooser<4> {
+               public:
+                       typedef CAS_32_functor the_type;
+       };
+       template<> class CAS_chooser<8> {
+               public:
+                       typedef CAS_64_functor the_type;
+       };
+
+       template<class T> class CAS {
+               public:
+                       typedef typename CAS_chooser<sizeof(T)>::the_type S;
+                       static T compare_and_swap(T *p, T o, T n) {
+                               return (T) S::compare_and_swap((typename S::value_type*) p,
+                                               (typename S::value_type) o,
+                                               (typename S::value_type) n);
+                       }
+       };
+
+       template<class T> T compare_and_swap(T *p, T o, T n) {
+               return CAS<T>::compare_and_swap(p, o, n);
+       }
+
+       inline void     memory_barrier(void)       { Atomic_md::memory_barrier(); }
+       inline void     write_memory_barrier(void) { Atomic_md::write_memory_barrier(); }
+       inline void     instruction_barrier(void)  { Atomic_md::instruction_barrier(); }
+}
+
 #else
 
 // Legacy C interface.
 
-uint32_t Atomic_compare_and_swap_32(volatile uint32_t *p, uint32_t oldval, uint32_t newval);
-uint64_t Atomic_compare_and_swap_64(volatile uint64_t *p, uint64_t oldval, uint64_t newval);
-void*    Atomic_compare_and_swap_ptr(volatile void** p, void* oldval, void* newval);
+uint32_t Atomic_compare_and_swap_32(uint32_t *p, uint32_t oldval, uint32_t newval);
+uint64_t Atomic_compare_and_swap_64(uint64_t *p, uint64_t oldval, uint64_t newval);
+void*    Atomic_compare_and_swap_ptr(void** p, void* oldval, void* newval);
 void     Atomic_memory_barrier(void);
 void     Atomic_write_memory_barrier(void);
 void     Atomic_instruction_barrier(void);
index 40c59aa68c3b96e6f7263631bec314aaae2e9712..b91e50f1d6725fb3149f1a49ff4fb6d9922417da 100644 (file)
@@ -27,6 +27,8 @@
 
 /* XXX cleanup these includes */
 
+#define __STDC_LIMIT_MACROS
+
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
@@ -66,6 +68,7 @@
 #include "vm/globals.hpp"
 #include "vm/javaobjects.hpp"
 #include "vm/options.h"
+#include "vm/os.hpp"
 #include "vm/signallocal.hpp"
 #include "vm/string.hpp"
 #include "vm/vm.hpp"
@@ -545,21 +548,21 @@ void threads_impl_thread_free(threadobject *t)
        result = pthread_cond_destroy(&(t->flc_cond));
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+               os::abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
 
        delete t->waitmutex;
 
        result = pthread_cond_destroy(&(t->waitcond));
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+               os::abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
 
        delete t->suspendmutex;
 
        result = pthread_cond_destroy(&(t->suspendcond));
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
+               os::abort_errnum(result, "threads_impl_thread_free: pthread_cond_destroy failed");
 }
 #endif
 
@@ -595,7 +598,7 @@ void threads_impl_preinit(void)
 #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");
+               os::abort_errnum(result, "threads_impl_preinit: pthread_key_create failed");
 #endif
 }
 
@@ -669,12 +672,12 @@ void threads_impl_init(void)
        result = pthread_attr_init(&attr);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_init: pthread_attr_init failed");
+               os::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");
+               os::abort_errnum(result, "threads_impl_init: pthread_attr_setdetachstate failed");
 }
 
 
@@ -925,33 +928,33 @@ void threads_impl_thread_start(threadobject *thread, functionptr f)
        result = pthread_attr_init(&attr);
 
        if (result != 0)
-               vm_abort_errnum(result, "threads_impl_thread_start: pthread_attr_init failed");
+               os::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");
+               os::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");
+               os::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");
+               os::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");
+               os::abort_errnum(result, "threads_impl_thread_start: pthread_attr_destroy failed");
 
        /* signal that pthread_create has returned, so thread->tid is valid */
 
@@ -1455,20 +1458,26 @@ void threads_wait_with_timeout_relative(threadobject *thread, s8 millis,
 
 static void threads_calc_absolute_time(struct timespec *tm, s8 millis, s4 nanos)
 {
-       if ((millis != 0x7fffffffffffffffLLU) && (millis || nanos)) {
+       // (at least with GNU classpath) we know that 0 <= nanos <= 999999
+       do {
+               if (!millis && !nanos)
+                       break;
                struct timeval tv;
-               long nsec;
                gettimeofday(&tv, NULL);
-               tv.tv_sec += millis / 1000;
+               s8 secs = tv.tv_sec + millis / 1000;
+               if (secs > INT32_MAX)   // integer overflow
+                       break;
+               tv.tv_sec = secs;
                millis %= 1000;
-               nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
+               long nsec = tv.tv_usec * 1000 + (s4) millis * 1000000 + nanos;
                tm->tv_sec = tv.tv_sec + nsec / 1000000000;
+               if (tm->tv_sec < tv.tv_sec) // integer overflow
+                       break;
                tm->tv_nsec = nsec % 1000000000;
-       }
-       else {
-               tm->tv_sec = 0;
-               tm->tv_nsec = 0;
-       }
+               return;
+       } while (0);
+       tm->tv_sec = 0;
+       tm->tv_nsec = 0;
 }
 
 
index 8f0e55c71ad5fac2115d5143259408dfe0a8b1e1..7dafeae304d82d8c1c0a4f6ecabc181e920b26b9 100644 (file)
@@ -266,7 +266,9 @@ inline static void thread_set_current(threadobject* t)
        result = pthread_setspecific(thread_current_key, t);
 
        if (result != 0)
-               vm_abort_errnum(result, "thread_set_current: pthread_setspecific failed");
+#warning Use below method instead!
+               //os::abort_errnum(result, "thread_set_current: pthread_setspecific failed");
+               vm_abort("thread_set_current: pthread_setspecific failed");
 #endif
 }
 
index 1579fd4e1ed42269625109f877913ef3f1a9e67e..5eaf0c2b15554029b7751feca22ddda1d9b7e35d 100644 (file)
@@ -654,7 +654,9 @@ void threads_thread_start(java_handle_t *object)
        assert(jlvmt.get_handle() != NULL);
        assert(jlvmt.get_vmdata() == NULL);
 
+       ThreadList::lock();
        jlvmt.set_vmdata(t);
+       ThreadList::unlock();
 
 #elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
@@ -1164,6 +1166,10 @@ void thread_set_state_terminated(threadobject *t)
    RETURN VALUE:
        the thread object
 
+   NOTE:
+       Usage of this function without the thread list lock held is
+       almost certainly a bug.
+
 *******************************************************************************/
 
 threadobject *thread_get_thread(java_handle_t *h)
@@ -1225,6 +1231,118 @@ bool threads_thread_is_alive(threadobject *t)
        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
+
+*******************************************************************************/
+
+bool thread_is_interrupted(threadobject *t)
+{
+       /* We need the mutex because classpath will call this function when
+          a blocking system call is interrupted. The mutex ensures that it will
+          see the correct value for the interrupted flag. */
+
+       t->waitmutex->lock();
+       bool interrupted = t->interrupted;
+       t->waitmutex->unlock();
+
+       return interrupted;
+}
+
+
+/* thread_set_interrupted ******************************************************
+
+   Set the interrupted flag to the given value.
+
+   ARGUMENTS:
+       interrupted ... value to set
+
+*******************************************************************************/
+
+void thread_set_interrupted(threadobject *t, bool interrupted)
+{
+       t->waitmutex->lock();
+       t->interrupted = interrupted;
+       t->waitmutex->unlock();
+}
+
+/* thread_handle_set_priority **************************************************
+
+   Calls threads_set_thread_priority for the threadobject associated
+   with the thread indicated by handle th, while holding the thread
+   list lock.
+
+*******************************************************************************/
+
+void thread_handle_set_priority(java_handle_t *th, int priority)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       /* For GNU classpath, this should not happen, because both
+          setPriority() and start() are synchronized. */
+       assert(t != 0);
+       threads_set_thread_priority(t->tid, priority);
+}
+
+/* thread_handle_is_interrupted ************************************************
+
+   Calls thread_is_interrupted for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+bool thread_handle_is_interrupted(java_handle_t *th)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       return t ? thread_is_interrupted(t) : false;
+}
+
+/* thread_handle_interrupt *****************************************************
+
+   Calls threads_thread_interrupt for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+void thread_handle_interrupt(java_handle_t *th)
+{
+       ThreadListLocker l;
+       
+       threadobject *t = thread_get_thread(th);
+       /* For GNU classpath, this should not happen, because both
+          interrupt() and start() are synchronized. */
+       assert(t != 0);
+       threads_thread_interrupt(t);
+}
+
+/* thread_handle_get_state *****************************************************
+
+   Calls cacaothread_get_state for the threadobject associated with
+   the thread indicated by handle th, while holding the thread list
+   lock.
+
+*******************************************************************************/
+
+int thread_handle_get_state(java_handle_t *th)
+{
+       ThreadListLocker l;
+
+       threadobject *t = thread_get_thread(th);
+       return t ? cacaothread_get_state(t) : THREAD_STATE_NEW;
+}
+
 
 /*
  * These are local overrides for various environment variables in Emacs.
index c3563cf33ddb73d2f58624ba866071d149753f7c..ba599f15f21007fbdc861ed39f7319f2ec3f0674 100644 (file)
@@ -192,67 +192,7 @@ inline static bool thread_is_attached(threadobject *t)
 
        o = thread_get_object(t);
 
-       if (o != NULL)
-               return true;
-       else
-               return false;
-}
-
-
-/* thread_is_interrupted *******************************************************
-
-   Check if the given thread has been interrupted.
-
-   ARGUMENTS:
-       t ... the thread to check
-
-   RETURN VALUE:
-      true, if the given thread had been interrupted
-
-*******************************************************************************/
-
-inline static bool thread_is_interrupted(threadobject *t)
-{
-       bool interrupted;
-
-       /* We need the mutex because classpath will call this function when
-          a blocking system call is interrupted. The mutex ensures that it will
-          see the correct value for the interrupted flag. */
-
-#ifdef __cplusplus
-       t->waitmutex->lock();
-       interrupted = t->interrupted;
-       t->waitmutex->unlock();
-#else
-       Mutex_lock(t->waitmutex);
-       interrupted = t->interrupted;
-       Mutex_unlock(t->waitmutex);
-#endif
-
-       return interrupted;
-}
-
-
-/* thread_set_interrupted ******************************************************
-
-   Set the interrupted flag to the given value.
-
-   ARGUMENTS:
-       interrupted ... value to set
-
-*******************************************************************************/
-
-inline static void thread_set_interrupted(threadobject *t, bool interrupted)
-{
-#ifdef __cplusplus
-       t->waitmutex->lock();
-       t->interrupted = interrupted;
-       t->waitmutex->unlock();
-#else
-       Mutex_lock(t->waitmutex);
-       t->interrupted = interrupted;
-       Mutex_unlock(t->waitmutex);
-#endif
+       return o != NULL;
 }
 
 
@@ -271,10 +211,7 @@ inline static void thread_set_interrupted(threadobject *t, bool interrupted)
 
 inline static bool thread_is_daemon(threadobject *t)
 {
-       if (t->flags & THREAD_FLAG_DAEMON)
-               return true;
-       else
-               return false;
+       return (t->flags & THREAD_FLAG_DAEMON) != 0;
 }
 
 
@@ -291,16 +228,13 @@ inline static bool thread_is_daemon(threadobject *t)
 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;
+       return thread_is_attached(t);
 }
 
 
@@ -335,7 +269,8 @@ void          thread_set_state_terminated(threadobject *t);
 threadobject *thread_get_thread(java_handle_t *h);
 
 bool          threads_thread_is_alive(threadobject *t);
-
+bool          thread_is_interrupted(threadobject *t);
+void          thread_set_interrupted(threadobject *t, bool interrupted);
 
 /* implementation specific functions */
 
@@ -365,6 +300,11 @@ void          threads_yield(void);
 
 #endif // _THREAD_HPP
 
+void          thread_handle_set_priority(java_handle_t *th, int);
+bool          thread_handle_is_interrupted(java_handle_t *th);
+void          thread_handle_interrupt(java_handle_t *th);
+int           thread_handle_get_state(java_handle_t *th);
+
 
 /*
  * These are local overrides for various environment variables in Emacs.
index 4df7b93456df1d87f928b570658c0e350edafe25..b7f701d03995c89acf930c64b7939d05f8d95633 100644 (file)
@@ -51,9 +51,9 @@ private:
 
        static int32_t             _number_of_non_daemon_threads;
 
-       static inline void          remove_from_active_thread_list(threadobject* t);
-       static inline void          add_to_free_thread_list(threadobject* t);
-       static inline void          add_to_free_index_list(int32_t index);
+       static void                 remove_from_active_thread_list(threadobject* t);
+       static void                 add_to_free_thread_list(threadobject* t);
+       static void                 add_to_free_index_list(int32_t index);
 
 private:
        // Comparator class.
@@ -66,15 +66,15 @@ private:
        };
 
 public:
-       static inline void          lock()   { _mutex.lock(); }
-       static inline void          unlock() { _mutex.unlock(); }
+       static void                 lock()   { _mutex.lock(); }
+       static void                 unlock() { _mutex.unlock(); }
 
        // TODO make private
-       static inline void          add_to_active_thread_list(threadobject* t);
+       static void                 add_to_active_thread_list(threadobject* t);
 
        static void                 dump_threads();
        static void                 get_active_threads(list<threadobject*> &list);
-       static inline threadobject* get_main_thread();
+       static threadobject*        get_main_thread();
        static threadobject*        get_free_thread();
        static int32_t              get_free_thread_index();
        static int32_t              get_number_of_non_daemon_threads();
@@ -83,6 +83,11 @@ public:
        static void                 release_thread(threadobject* t);
 };
 
+struct ThreadListLocker {
+       ThreadListLocker()  { ThreadList::lock(); }
+       ~ThreadListLocker()  { ThreadList::unlock(); }
+};
+
 
 inline void ThreadList::add_to_active_thread_list(threadobject* t)
 {
index 07329bc319a48b57526a7f76160dff1d050bd332..ee17a20ca34b2cf212d14a819c07425fee45992c 100644 (file)
@@ -1445,8 +1445,7 @@ bool class_issubclass(classinfo *sub, classinfo *super)
 
 bool class_isanysubclass(classinfo *sub, classinfo *super)
 {
-       uint32_t diffval;
-       bool     result;
+       bool result;
 
        /* This is the trivial case. */
 
@@ -1476,8 +1475,8 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
 #else
                LOCK_CLASSRENUMBER_LOCK;
 
-               diffval = sub->vftbl->baseval - super->vftbl->baseval;
-               result  = diffval <= (uint32_t) super->vftbl->diffval;
+               uint32_t diffval = sub->vftbl->baseval - super->vftbl->baseval;
+               result = diffval <= (uint32_t) super->vftbl->diffval;
 
                UNLOCK_CLASSRENUMBER_LOCK;
 #endif
@@ -1487,6 +1486,54 @@ bool class_isanysubclass(classinfo *sub, classinfo *super)
 }
 
 
+/* class_is_arraycompatible ****************************************************
+
+   Checks if two array type descriptors are assignment compatible.
+
+   RETURN VALUE:
+      true .... target = desc is possible
+      false ... otherwise
+                       
+*******************************************************************************/
+
+bool class_is_arraycompatible(arraydescriptor *desc, arraydescriptor *target)
+{
+       if (desc == target)
+               return true;
+
+       if (desc->arraytype != target->arraytype)
+               return false;
+
+       if (desc->arraytype != ARRAYTYPE_OBJECT)
+               return true;
+       
+       /* {both arrays are arrays of references} */
+
+       if (desc->dimension == target->dimension) {
+               if (!desc->elementvftbl)
+                       return false;
+
+               /* an array which contains elements of interface types is
+                  allowed to be casted to array of Object (JOWENN) */
+
+               if ((desc->elementvftbl->baseval < 0) &&
+                       (target->elementvftbl->baseval == 1))
+                       return true;
+
+               return class_isanysubclass(desc->elementvftbl->clazz,
+                                                                  target->elementvftbl->clazz);
+       }
+
+       if (desc->dimension < target->dimension)
+               return false;
+
+       /* {desc has higher dimension than target} */
+
+       return class_isanysubclass(pseudo_class_Arraystub,
+                                                          target->elementvftbl->clazz);
+}
+
+
 /* class_is_assignable_from ****************************************************
 
    Return whether an instance of the "from" class parameter would be
@@ -1512,7 +1559,12 @@ bool class_is_assignable_from(classinfo *to, classinfo *from)
                if (!link_class(from))
                        return false;
 
-       return class_isanysubclass(from, to);
+       /* Decide whether we are dealing with array types or object types. */
+
+       if (class_is_array(to) && class_is_array(from))
+               return class_is_arraycompatible(from->vftbl->arraydesc, to->vftbl->arraydesc);
+       else
+               return class_isanysubclass(from, to);
 }
 
 
@@ -1536,7 +1588,12 @@ bool class_is_instance(classinfo *c, java_handle_t *h)
                if (!link_class(c))
                        return false;
 
-       return builtin_instanceof(h, c);
+       /* Decide whether we are dealing with array types or object types. */
+
+       if (class_is_array(c))
+               return builtin_arrayinstanceof(h, c);
+       else
+               return builtin_instanceof(h, c);
 }
 
 
index b09bcca47a72faddf93afb91035681c292848bf0..85f05618cafb5f6d2ec4e552bfa051bf6d2cbd2d 100644 (file)
@@ -399,6 +399,7 @@ methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, cla
 
 bool                       class_issubclass(classinfo *sub, classinfo *super);
 bool                       class_isanysubclass(classinfo *sub, classinfo *super);
+bool                       class_is_arraycompatible(arraydescriptor *desc, arraydescriptor *target);
 bool                       class_is_assignable_from(classinfo *to, classinfo *from);
 bool                       class_is_instance(classinfo *c, java_handle_t *h);
 
index 285e23572ab532443ef3e31e76a86b7c8480fe08..b8ee1215a26280226c6296bd90cfcfb2a268d55c 100644 (file)
@@ -200,13 +200,13 @@ public:
        virtual ~java_lang_Object() {}
 
        // Getters.
-       virtual inline java_handle_t* get_handle  () const { return _handle; }
-       inline vftbl_t*               get_vftbl   () const;
-       inline classinfo*             get_Class   () const;
-       inline int32_t                get_hashcode() const;
+       virtual java_handle_t* get_handle  () const { return _handle; }
+       vftbl_t*               get_vftbl   () const;
+       classinfo*             get_Class   () const;
+       int32_t                get_hashcode() const;
 
-       inline bool is_null    () const;
-       inline bool is_non_null() const;
+       bool is_null    () const;
+       bool is_non_null() const;
 };
 
 
@@ -268,8 +268,8 @@ private:
 public:
        java_lang_Boolean(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline uint8_t get_value();
-       inline void    set_value(uint8_t value);
+       uint8_t get_value();
+       void    set_value(uint8_t value);
 };
 
 inline uint8_t java_lang_Boolean::get_value()
@@ -300,8 +300,8 @@ private:
 public:
        java_lang_Byte(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline int8_t get_value();
-       inline void   set_value(int8_t value);
+       int8_t get_value();
+       void   set_value(int8_t value);
 };
 
 inline int8_t java_lang_Byte::get_value()
@@ -332,8 +332,8 @@ private:
 public:
        java_lang_Character(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline uint16_t get_value();
-       inline void     set_value(uint16_t value);
+       uint16_t get_value();
+       void     set_value(uint16_t value);
 };
 
 inline uint16_t java_lang_Character::get_value()
@@ -364,8 +364,8 @@ private:
 public:
        java_lang_Short(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline int16_t get_value();
-       inline void    set_value(int16_t value);
+       int16_t get_value();
+       void    set_value(int16_t value);
 };
 
 inline int16_t java_lang_Short::get_value()
@@ -396,8 +396,8 @@ private:
 public:
        java_lang_Integer(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline int32_t get_value();
-       inline void    set_value(int32_t value);
+       int32_t get_value();
+       void    set_value(int32_t value);
 };
 
 inline int32_t java_lang_Integer::get_value()
@@ -428,8 +428,8 @@ private:
 public:
        java_lang_Long(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline int64_t get_value();
-       inline void    set_value(int64_t value);
+       int64_t get_value();
+       void    set_value(int64_t value);
 };
 
 inline int64_t java_lang_Long::get_value()
@@ -460,8 +460,8 @@ private:
 public:
        java_lang_Float(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline float get_value();
-       inline void  set_value(float value);
+       float get_value();
+       void  set_value(float value);
 };
 
 inline float java_lang_Float::get_value()
@@ -492,8 +492,8 @@ private:
 public:
        java_lang_Double(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline double get_value();
-       inline void   set_value(double value);
+       double get_value();
+       void   set_value(double value);
 };
 
 inline double java_lang_Double::get_value()
@@ -529,8 +529,8 @@ public:
        sun_reflect_ConstantPool(java_handle_t* h, jclass constantPoolOop);
 
        // Setters.
-       inline void set_constantPoolOop(classinfo* value);
-       inline void set_constantPoolOop(jclass value);
+       void set_constantPoolOop(classinfo* value);
+       void set_constantPoolOop(jclass value);
 };
 
 
@@ -581,7 +581,7 @@ public:
        java_lang_Class(java_handle_t* h) : java_lang_Object(h) {}
 
        // Setters.
-       inline void set_pd(java_handle_t* value);
+       void set_pd(java_handle_t* value);
 };
 
 inline void java_lang_Class::set_pd(java_handle_t* value)
@@ -654,14 +654,14 @@ public:
        java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
 
        // Getters.
-       inline java_handle_chararray_t* get_value () const;
-       inline int32_t                  get_count () const;
-       inline int32_t                  get_offset() const;
+       java_handle_chararray_t* get_value () const;
+       int32_t                  get_count () const;
+       int32_t                  get_offset() const;
 
        // Setters.
-       inline void set_value (java_handle_chararray_t* value);
-       inline void set_count (int32_t value);
-       inline void set_offset(int32_t value);
+       void set_value (java_handle_chararray_t* value);
+       void set_count (int32_t value);
+       void set_offset(int32_t value);
 };
 
 inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
@@ -747,15 +747,15 @@ public:
 //     java_lang_Thread(threadobject* t);
 
        // Getters.
-       inline java_handle_t* get_vmThread        () const;
-       inline java_handle_t* get_group           () const;
-       inline java_handle_t* get_name            () const;
-       inline int32_t        get_daemon          () const;
-       inline int32_t        get_priority        () const;
-       inline java_handle_t* get_exceptionHandler() const;
+       java_handle_t* get_vmThread        () const;
+       java_handle_t* get_group           () const;
+       java_handle_t* get_name            () const;
+       int32_t        get_daemon          () const;
+       int32_t        get_priority        () const;
+       java_handle_t* get_exceptionHandler() const;
 
        // Setters.
-       inline void set_group(java_handle_t* value);
+       void set_group(java_handle_t* value);
 };
 
 
@@ -825,12 +825,12 @@ public:
        java_lang_VMThread(java_handle_t* h, java_handle_t* thread, threadobject* vmdata);
 
        // Getters.
-       inline java_handle_t* get_thread() const;
-       inline threadobject*  get_vmdata() const;
+       java_handle_t* get_thread() const;
+       threadobject*  get_vmdata() const;
 
        // Setters.
-       inline void set_thread(java_handle_t* value);
-       inline void set_vmdata(threadobject* value);
+       void set_thread(java_handle_t* value);
+       void set_vmdata(threadobject* value);
 };
 
 
@@ -887,9 +887,9 @@ public:
        java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
 
        // Getters.
-       inline java_handle_t* get_detailMessage() const;
-       inline java_handle_t* get_cause        () const;
-       inline java_handle_t* get_vmState      () const;
+       java_handle_t* get_detailMessage() const;
+       java_handle_t* get_cause        () const;
+       java_handle_t* get_vmState      () const;
 };
 
 
@@ -926,8 +926,8 @@ private:
 public:
        java_lang_VMThrowable(java_handle_t* h) : java_lang_Object(h) {}
 
-       inline java_handle_bytearray_t* get_vmdata() const;
-       inline void                     set_vmdata(java_handle_bytearray_t* value);
+       java_handle_bytearray_t* get_vmdata() const;
+       void                     set_vmdata(java_handle_bytearray_t* value);
 };
 
 
@@ -971,23 +971,23 @@ public:
        java_lang_reflect_VMConstructor(methodinfo* m);
 
        // Getters.
-       inline classinfo*               get_clazz               () const;
-       inline int32_t                  get_slot                () const;
-       inline java_handle_bytearray_t* get_annotations         () const;
-       inline java_handle_bytearray_t* get_parameterAnnotations() const;
-       inline java_handle_t*           get_declaredAnnotations () const;
-       inline java_handle_t*           get_cons                () const;
+       classinfo*               get_clazz               () const;
+       int32_t                  get_slot                () const;
+       java_handle_bytearray_t* get_annotations         () const;
+       java_handle_bytearray_t* get_parameterAnnotations() const;
+       java_handle_t*           get_declaredAnnotations () const;
+       java_handle_t*           get_cons                () const;
 
        // Setters.
-       inline void set_clazz               (classinfo* value);
-       inline void set_slot                (int32_t value);
-       inline void set_annotations         (java_handle_bytearray_t* value);
-       inline void set_parameterAnnotations(java_handle_bytearray_t* value);
-       inline void set_declaredAnnotations (java_handle_t* value);
-       inline void set_cons                (java_handle_t* value);
+       void set_clazz               (classinfo* value);
+       void set_slot                (int32_t value);
+       void set_annotations         (java_handle_bytearray_t* value);
+       void set_parameterAnnotations(java_handle_bytearray_t* value);
+       void set_declaredAnnotations (java_handle_t* value);
+       void set_cons                (java_handle_t* value);
 
        // Convenience functions.
-       inline methodinfo* get_method();
+       methodinfo* get_method();
 };
 
 
@@ -1103,15 +1103,15 @@ public:
        java_handle_t* new_instance(java_handle_objectarray_t* args);
 
        // Getters.
-       inline int32_t        get_flag() const;
-       inline java_handle_t* get_cons() const;
+       int32_t        get_flag() const;
+       java_handle_t* get_cons() const;
 
        // Setters.
-       inline void set_cons(java_handle_t* value);
+       void set_cons(java_handle_t* value);
 
        // Convenience functions.
-       inline methodinfo* get_method  () const;
-       inline int32_t     get_override() const;
+       methodinfo* get_method  () const;
+       int32_t     get_override() const;
 };
 
 
@@ -1191,22 +1191,22 @@ public:
        java_lang_reflect_VMField(fieldinfo* f);
 
        // Getters.
-       inline classinfo*               get_clazz              () const;
-       inline int32_t                  get_slot               () const;
-       inline java_handle_bytearray_t* get_annotations        () const;
-       inline java_handle_t*           get_declaredAnnotations() const;
-       inline java_handle_t*           get_f                  () const;
+       classinfo*               get_clazz              () const;
+       int32_t                  get_slot               () const;
+       java_handle_bytearray_t* get_annotations        () const;
+       java_handle_t*           get_declaredAnnotations() const;
+       java_handle_t*           get_f                  () const;
 
        // Setters.
-       inline void set_clazz              (classinfo* value);
-       inline void set_name               (java_handle_t* value);
-       inline void set_slot               (int32_t value);
-       inline void set_annotations        (java_handle_bytearray_t* value);
-       inline void set_declaredAnnotations(java_handle_t* value);
-       inline void set_f                  (java_handle_t* value);
+       void set_clazz              (classinfo* value);
+       void set_name               (java_handle_t* value);
+       void set_slot               (int32_t value);
+       void set_annotations        (java_handle_bytearray_t* value);
+       void set_declaredAnnotations(java_handle_t* value);
+       void set_f                  (java_handle_t* value);
 
        // Convenience functions.
-       inline fieldinfo* get_field() const;
+       fieldinfo* get_field() const;
 };
 
 
@@ -1316,14 +1316,14 @@ public:
        java_lang_reflect_Field(fieldinfo* f);
 
        // Getters.
-       inline int32_t        get_flag() const;
-       inline java_handle_t* get_f() const;
+       int32_t        get_flag() const;
+       java_handle_t* get_f() const;
 
        // Setters.
-       inline void set_f(java_handle_t* value);
+       void set_f(java_handle_t* value);
 
        // Convenience functions.
-       inline fieldinfo* get_field() const;
+       fieldinfo* get_field() const;
 };
 
 
@@ -1402,26 +1402,26 @@ public:
        java_lang_reflect_VMMethod(methodinfo* m);
 
        // Getters.
-       inline classinfo*               get_clazz               () const;
-       inline int32_t                  get_slot                () const;
-       inline java_handle_bytearray_t* get_annotations         () const;
-       inline java_handle_bytearray_t* get_parameterAnnotations() const;
-       inline java_handle_bytearray_t* get_annotationDefault   () const;
-       inline java_handle_t*           get_declaredAnnotations () const;
-       inline java_handle_t*           get_m                   () const;
+       classinfo*               get_clazz               () const;
+       int32_t                  get_slot                () const;
+       java_handle_bytearray_t* get_annotations         () const;
+       java_handle_bytearray_t* get_parameterAnnotations() const;
+       java_handle_bytearray_t* get_annotationDefault   () const;
+       java_handle_t*           get_declaredAnnotations () const;
+       java_handle_t*           get_m                   () const;
 
        // Setters.
-       inline void set_clazz               (classinfo* value);
-       inline void set_name                (java_handle_t* value);
-       inline void set_slot                (int32_t value);
-       inline void set_annotations         (java_handle_bytearray_t* value);
-       inline void set_parameterAnnotations(java_handle_bytearray_t* value);
-       inline void set_annotationDefault   (java_handle_bytearray_t* value);
-       inline void set_declaredAnnotations (java_handle_t* value);
-       inline void set_m                   (java_handle_t* value);
+       void set_clazz               (classinfo* value);
+       void set_name                (java_handle_t* value);
+       void set_slot                (int32_t value);
+       void set_annotations         (java_handle_bytearray_t* value);
+       void set_parameterAnnotations(java_handle_bytearray_t* value);
+       void set_annotationDefault   (java_handle_bytearray_t* value);
+       void set_declaredAnnotations (java_handle_t* value);
+       void set_m                   (java_handle_t* value);
 
        // Convenience functions.
-       inline methodinfo* get_method() const;
+       methodinfo* get_method() const;
 };
 
 
@@ -1555,15 +1555,15 @@ public:
        java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
 
        // Getters.
-       inline int32_t        get_flag() const;
-       inline java_handle_t* get_m() const;
+       int32_t        get_flag() const;
+       java_handle_t* get_m() const;
 
        // Setters.
-       inline void set_m(java_handle_t* value);
+       void set_m(java_handle_t* value);
 
        // Convenience functions.
-       inline methodinfo* get_method  () const;
-       inline int32_t     get_override() const;
+       methodinfo* get_method  () const;
+       int32_t     get_override() const;
 };
 
 
@@ -1640,7 +1640,7 @@ public:
        java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
 
        // Getters.
-       inline int32_t get_cap() const;
+       int32_t get_cap() const;
 };
 
 inline int32_t java_nio_Buffer::get_cap() const
@@ -1683,7 +1683,7 @@ public:
        java_nio_DirectByteBufferImpl(java_handle_t* h) : java_lang_Object(h) {}
 
        // Getters.
-       inline java_handle_t* get_address() const;
+       java_handle_t* get_address() const;
 };
 
 
@@ -1716,10 +1716,10 @@ public:
        gnu_classpath_Pointer(java_handle_t* h, void* data);
 
        // Setters.
-       inline void* get_data() const;
+       void* get_data() const;
 
        // Setters.
-       inline void set_data(void* value);
+       void set_data(void* value);
 };
 
 inline gnu_classpath_Pointer::gnu_classpath_Pointer(java_handle_t* h, void* data) : java_lang_Object(h)
@@ -1852,14 +1852,14 @@ public:
        java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
 
        // Getters.
-       inline java_handle_chararray_t* get_value () const;
-       inline int32_t                  get_offset() const;
-       inline int32_t                  get_count () const;
+       java_handle_chararray_t* get_value () const;
+       int32_t                  get_offset() const;
+       int32_t                  get_count () const;
 
        // Setters.
-       inline void set_value (java_handle_chararray_t* value);
-       inline void set_offset(int32_t value);
-       inline void set_count (int32_t value);
+       void set_value (java_handle_chararray_t* value);
+       void set_offset(int32_t value);
+       void set_count (int32_t value);
 };
 
 inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
@@ -1963,15 +1963,15 @@ public:
 //     java_lang_Thread(threadobject* t);
 
        // Getters.
-       inline int32_t        get_priority                () const;
-       inline int32_t        get_daemon                  () const;
-       inline java_handle_t* get_group                   () const;
-       inline java_handle_t* get_uncaughtExceptionHandler() const;
+       int32_t        get_priority                () const;
+       int32_t        get_daemon                  () const;
+       java_handle_t* get_group                   () const;
+       java_handle_t* get_uncaughtExceptionHandler() const;
 
        // Setters.
-       inline void set_priority    (int32_t value);
-       inline void set_group       (java_handle_t* value);
-       inline void set_threadStatus(int32_t value);
+       void set_priority    (int32_t value);
+       void set_group       (java_handle_t* value);
+       void set_threadStatus(int32_t value);
 };
 
 
@@ -2038,12 +2038,12 @@ public:
        java_lang_Throwable(java_handle_t* h, java_handle_bytearray_t* backtrace);
 
        // Getters.
-       inline java_handle_bytearray_t* get_backtrace    () const;
-       inline java_handle_t*           get_detailMessage() const;
-       inline java_handle_t*           get_cause        () const;
+       java_handle_bytearray_t* get_backtrace    () const;
+       java_handle_t*           get_detailMessage() const;
+       java_handle_t*           get_cause        () const;
 
        // Setters.
-       inline void set_backtrace(java_handle_bytearray_t* value);
+       void set_backtrace(java_handle_bytearray_t* value);
 };
 
 
@@ -2122,23 +2122,23 @@ public:
        java_handle_t* new_instance(java_handle_objectarray_t* args);
 
        // Getters.
-       inline int32_t                  get_override   () const;
-       inline classinfo*               get_clazz      () const;
-       inline int32_t                  get_slot       () const;
-       inline java_handle_bytearray_t* get_annotations() const;
+       int32_t                  get_override   () const;
+       classinfo*               get_clazz      () const;
+       int32_t                  get_slot       () const;
+       java_handle_bytearray_t* get_annotations() const;
 
        // Setters.
-       inline void set_clazz               (classinfo* value);
-       inline void set_slot                (int32_t value);
-       inline void set_parameterTypes      (java_handle_objectarray_t* value);
-       inline void set_exceptionTypes      (java_handle_objectarray_t* value);
-       inline void set_modifiers           (int32_t value);
-       inline void set_signature           (java_handle_t* value);
-       inline void set_annotations         (java_handle_bytearray_t* value);
-       inline void set_parameterAnnotations(java_handle_bytearray_t* value);
+       void set_clazz               (classinfo* value);
+       void set_slot                (int32_t value);
+       void set_parameterTypes      (java_handle_objectarray_t* value);
+       void set_exceptionTypes      (java_handle_objectarray_t* value);
+       void set_modifiers           (int32_t value);
+       void set_signature           (java_handle_t* value);
+       void set_annotations         (java_handle_bytearray_t* value);
+       void set_parameterAnnotations(java_handle_bytearray_t* value);
 
        // Convenience functions.
-       inline methodinfo* get_method();
+       methodinfo* get_method();
 };
 
 
@@ -2284,22 +2284,22 @@ public:
        java_lang_reflect_Field(fieldinfo* f);
 
        // Getters.
-       inline int32_t                  get_override   () const;
-       inline classinfo*               get_clazz      () const;
-       inline int32_t                  get_slot       () const;
-       inline java_handle_bytearray_t* get_annotations() const;
+       int32_t                  get_override   () const;
+       classinfo*               get_clazz      () const;
+       int32_t                  get_slot       () const;
+       java_handle_bytearray_t* get_annotations() const;
 
        // Setters.
-       inline void set_clazz      (classinfo* value);
-       inline void set_slot       (int32_t value);
-       inline void set_name       (java_handle_t* value);
-       inline void set_type       (classinfo* value);
-       inline void set_modifiers  (int32_t value);
-       inline void set_signature  (java_handle_t* value);
-       inline void set_annotations(java_handle_bytearray_t* value);
+       void set_clazz      (classinfo* value);
+       void set_slot       (int32_t value);
+       void set_name       (java_handle_t* value);
+       void set_type       (classinfo* value);
+       void set_modifiers  (int32_t value);
+       void set_signature  (java_handle_t* value);
+       void set_annotations(java_handle_bytearray_t* value);
 
        // Convenience functions.
-       inline fieldinfo* get_field() const;
+       fieldinfo* get_field() const;
 };
 
 
@@ -2442,17 +2442,17 @@ public:
        java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
 
        // Getters.
-       inline int32_t                  get_override            () const;
-       inline classinfo*               get_clazz               () const;
-       inline int32_t                  get_slot                () const;
-       inline java_handle_bytearray_t* get_annotations         () const;
-       inline java_handle_bytearray_t* get_parameterAnnotations() const;
-       inline java_handle_bytearray_t* get_annotationDefault   () const;
+       int32_t                  get_override            () const;
+       classinfo*               get_clazz               () const;
+       int32_t                  get_slot                () const;
+       java_handle_bytearray_t* get_annotations         () const;
+       java_handle_bytearray_t* get_parameterAnnotations() const;
+       java_handle_bytearray_t* get_annotationDefault   () const;
 
        // Setters.
 
        // Convenience functions.
-       inline methodinfo* get_method() const;
+       methodinfo* get_method() const;
 };
 
 
@@ -2543,7 +2543,7 @@ public:
        java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
 
        // Getters.
-       inline void* get_address() const;
+       void* get_address() const;
 };
 
 
@@ -2581,14 +2581,14 @@ public:
        com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, com_sun_cldchi_jvm_FileDescriptor& fd);
 
        // Getters.
-       inline int64_t get_pointer () const;
-       inline int32_t get_position() const;
-       inline int32_t get_length  () const;
+       int64_t get_pointer () const;
+       int32_t get_position() const;
+       int32_t get_length  () const;
 
        // Setters.
-       inline void set_pointer (int64_t value);
-       inline void set_position(int32_t value);
-       inline void set_length  (int32_t value);
+       void set_pointer (int64_t value);
+       void set_position(int32_t value);
+       void set_length  (int32_t value);
 };
 
 
@@ -2660,14 +2660,14 @@ public:
        java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
 
        // Getters.
-       inline java_handle_chararray_t* get_value () const;
-       inline int32_t                  get_offset() const;
-       inline int32_t                  get_count () const;
+       java_handle_chararray_t* get_value () const;
+       int32_t                  get_offset() const;
+       int32_t                  get_count () const;
 
        // Setters.
-       inline void set_value (java_handle_chararray_t* value);
-       inline void set_offset(int32_t value);
-       inline void set_count (int32_t value);
+       void set_value (java_handle_chararray_t* value);
+       void set_offset(int32_t value);
+       void set_count (int32_t value);
 };
 
 
@@ -2738,12 +2738,12 @@ public:
 //     java_lang_Thread(threadobject* t);
 
        // Getters.
-       inline int32_t                  get_priority () const;
-       inline threadobject*            get_vm_thread() const;
-       inline java_handle_chararray_t* get_name     () const;
+       int32_t                  get_priority () const;
+       threadobject*            get_vm_thread() const;
+       java_handle_chararray_t* get_name     () const;
 
        // Setters.
-       inline void set_vm_thread(threadobject* value);
+       void set_vm_thread(threadobject* value);
 };
 
 
@@ -2795,11 +2795,11 @@ public:
        java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
 
        // Getters.
-       inline java_handle_t*           get_detailMessage() const;
-       inline java_handle_bytearray_t* get_backtrace    () const;
+       java_handle_t*           get_detailMessage() const;
+       java_handle_bytearray_t* get_backtrace    () const;
 
        // Setters.
-       inline void set_backtrace(java_handle_bytearray_t* value);
+       void set_backtrace(java_handle_bytearray_t* value);
 };
 
 
index 7da89972163e791d47096097842bd88912f20016..42368fedd1df433c47b4c0c81c4be1f87d35202e 100644 (file)
@@ -110,8 +110,8 @@ STACK_SOURCES = \
        stack.h
 
 TRAP_SOURCES = \
-       trap.c \
-       trap.h
+       trap.cpp \
+       trap.hpp
 endif
 
 if ENABLE_REPLACEMENT
index bb4c1fcb9758d10148f7aead4ab8b83c4517c925..21e536f7cf806a610f7e0ad333e789b3e697d4a5 100644 (file)
@@ -62,7 +62,7 @@
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_SSA)
 # include "vm/jit/optimizing/lsra.h"
index 96fb6f0be0a72427f95e41a37e9ca06be35828b6..ac5d0ba12febe305ce5eb2bf8e0327ceb75d67e4 100644 (file)
@@ -48,7 +48,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load *******************************************************************
index 1fe5e80861fb0c0e766639bc63a2ff5282229c28..b81ff2bc733c59c22b79348514f80e6cb1d06dab 100644 (file)
@@ -45,7 +45,7 @@
 #include "vm/jit/asmpart.h"
 #include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_signal_handler_sigsegv ***************************************************
index 962852a55dfa4b085f73cc0957e789c3ebcf7102..07c3a85428a5c61dd98aeffd3930e9d5b8e91507 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,7 +43,7 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t temp;
        uint32_t result;
@@ -72,7 +73,7 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
        uint64_t temp;
        uint64_t result;
@@ -93,25 +94,10 @@ inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval,
 }
 
 
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
-}
-
-
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("mb" : : : "memory");
 }
@@ -120,7 +106,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("wmb" : : : "memory");
 }
@@ -129,11 +115,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
        __asm__ __volatile__ ("mb" : : : "memory");
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index 9ad99b7474b6f982d1c66ea557be178a04f453a7..f769b3f7892b846a313c56cbb0e19b24a395770c 100644 (file)
@@ -40,7 +40,7 @@ extern void ieee_set_fp_control(unsigned long fp_control);
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/jit.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* global variables ***********************************************************/
index b8bdeeb82146e6a32689ff012a7283426abb3067..8cd87690336f1d4ddf65add3affb498d81cc1ea6 100644 (file)
 
 #define REPLACEMENT_PATCH_SIZE           4 /* bytes */
 
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE                 1
+
 #endif /* _ARCH_H */
 
 
index a0085a806efce8d275e22c62404722e04352c67c..34bf177cab734d49574c1fc560215af76e45d409 100644 (file)
@@ -1638,10 +1638,14 @@ bool codegen_emit(jitdata *jd)
 
                        s1 = emit_load_s1(jd, iptr, REG_ITMP1);
                        M_INTMOVE(s1, REG_ITMP1_XPTR);
+
+#ifdef ENABLE_VERIFIER
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
-                                                                       iptr->sx.s23.s2.uc, 0);
+                               unresolved_class *uc = iptr->sx.s23.s2.uc;
+                               patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
                        }
+#endif /* ENABLE_VERIFIER */
+
                        disp = dseg_add_functionptr(cd, asm_handle_exception);
                        M_DSEG_LOAD(REG_ITMP3, disp);
                        M_MOV(REG_ITMP2_XPC, REG_PC);
@@ -2092,10 +2096,14 @@ bool codegen_emit(jitdata *jd)
                        REPLACEMENT_POINT_RETURN(cd, iptr);
                        s1 = emit_load_s1(jd, iptr, REG_RESULT);
                        M_INTMOVE(s1, REG_RESULT);
+
+#ifdef ENABLE_VERIFIER
                        if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
-                               patcher_add_patch_ref(jd, PATCHER_resolve_class,
-                                                                       iptr->sx.s23.s2.uc, 0);
+                               unresolved_class *uc = iptr->sx.s23.s2.uc;
+                               patcher_add_patch_ref(jd, PATCHER_resolve_class, uc, 0);
                        }
+#endif /* ENABLE_VERIFIER */
+
                        goto ICMD_RETURN_do;
 
                case ICMD_RETURN:       /* ...  ==> ...                               */
@@ -2547,17 +2555,67 @@ bool codegen_emit(jitdata *jd)
                                        emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
+                               // The following code checks whether object s is a subtype of class t.
+                               // Represents the following semantic:
+                               //    if (!fast_subtype_check(s->vftbl, t->vftbl)) throw;
+
                                M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                M_DSEG_LOAD(REG_ITMP3, disp);
 
-                               M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                               M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                               M_SUB(REG_ITMP2, REG_ITMP2, REG_ITMP3);
-                               M_DSEG_LOAD(REG_ITMP3, disp);
-                               M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       // Represents the following semantic:
+                                       //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) good;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                       M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                       M_CMP(REG_ITMP1, REG_ITMP3);
+                                       emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
+                                       emit_label_beq(cd, BRANCH_LABEL_6);  /* good */
+
+                                       // Represents the following semantic:
+                                       //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) throw;
+                                       // Preconditions:
+                                       //    REG_ITMP3==t->vftbl;
+                                       if (super == NULL) {
+                                               M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
+                                               emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
+                                               emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);  /* throw */
+                                       }
 
-                               M_CMP(REG_ITMP2, REG_ITMP3);
-                               emit_classcast_check(cd, iptr, BRANCH_UGT, 0, s1);
+                                       // Represents the following semantic:
+                                       //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) throw;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                       M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                       M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                       M_CMP(REG_ITMP1, REG_ITMP3);
+                                       emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
+                                       emit_classcast_check(cd, iptr, BRANCH_LT, 0, s1);  /* throw */
+
+                                       // Represents the following semantic:
+                                       //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) throw;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
+                                       M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2));  /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
+                                       M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
+                                       M_DSEG_LOAD(REG_ITMP3, disp);  /* reload REG_ITMP3, was destroyed */
+                                       M_CMP(REG_ITMP2, REG_ITMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);  /* throw */
+
+                                       emit_label(cd, BRANCH_LABEL_6);
+                               }
+                               else {
+                                       // Represents the following semantic:
+                                       //    if (*(s->vftbl + t->vftbl->subtype_offset) != t->vftbl) throw;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                       M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                       M_CMP(REG_ITMP2, REG_ITMP3);
+                                       emit_classcast_check(cd, iptr, BRANCH_NE, 0, s1);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
@@ -2739,19 +2797,74 @@ bool codegen_emit(jitdata *jd)
                                        emit_label_beq(cd, BRANCH_LABEL_5);
                                }
 
-                               M_LDR_INTERN(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
-                               M_DSEG_LOAD(REG_ITMP2, disp);
+                               // The following code checks whether object s is a subtype of class t.
+                               // Represents the following semantic:
+                               //    fast_subtype_check(s->vftbl, t->vftbl));
 
-                               M_LDR_INTERN(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                               M_LDR_INTERN(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                               M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                               M_LDR_INTERN(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
+                               M_DSEG_LOAD(REG_ITMP3, disp);
 
-                               M_SUB(REG_ITMP1, REG_ITMP1, REG_ITMP3);
-                               M_CMP(REG_ITMP1, REG_ITMP2);
-                               /* If d == REG_ITMP2, then it's destroyed */
-                               if (d == REG_ITMP2)
-                                       M_EOR(d, d, d);
-                               M_MOVLS_IMM(1, d);
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                       // Represents the following semantic:
+                                       //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) true;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                       M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                       M_LDR_REG(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                       M_CMP(REG_ITMP1, REG_ITMP3);
+                                       emit_label_beq(cd, BRANCH_LABEL_6);  /* true */
+
+                                       // Represents the following semantic:
+                                       //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) false;
+                                       // Preconditions:
+                                       //    REG_ITMP3==t->vftbl;
+                                       if (super == NULL) {
+                                               M_LDR_INTERN(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_CMP_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]));
+                                               emit_label_bne(cd, BRANCH_LABEL_7);  /* false */
+                                       }
+
+                                       // Represents the following semantic:
+                                       //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) false;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                       M_LDR_INTERN(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                       M_LDR_INTERN(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                       M_CMP(REG_ITMP1, REG_ITMP3);
+                                       emit_label_blt(cd, BRANCH_LABEL_8);  /* false */
+
+                                       // Represents the following semantic:
+                                       //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) false;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
+                                       M_LDR_INTERN(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                       M_ADD(REG_ITMP2, REG_ITMP2, REG_LSL(REG_ITMP3, 2));  /* REG_ITMP2 = REG_ITMP2 + 4 * REG_ITMP3 */
+                                       M_LDR_INTERN(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
+                                       M_DSEG_LOAD(REG_ITMP3, disp);  /* reload REG_ITMP3, was destroyed */
+                                       M_CMP(REG_ITMP2, REG_ITMP3);
+
+                                       emit_label(cd, BRANCH_LABEL_6);
+                                       if (super == NULL)
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                       emit_label(cd, BRANCH_LABEL_8);
+
+                                       /* If d == REG_ITMP2, then it's destroyed */
+                                       if (d == REG_ITMP2)
+                                               M_EOR(d, d, d);
+                                       M_MOVEQ_IMM(1, d);
+                               }
+                               else {
+                                       // Represents the following semantic:
+                                       //    *(s->vftbl + t->vftbl->subtype_offset) == t->vftbl;
+                                       // Preconditions:
+                                       //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                       M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                       M_CMP(REG_ITMP2, REG_ITMP3);
+                                       /* If d == REG_ITMP2, then it's destroyed */
+                                       if (d == REG_ITMP2)
+                                               M_EOR(d, d, d);
+                                       M_MOVEQ_IMM(1, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index 1a45898e86cec5442e37000df0f533bf6e920113..0191858b85e41bd36c910966dd224d36d1cc6276 100644 (file)
@@ -556,6 +556,8 @@ void asm_debug_intern(int a1, int a2, int a3, int a4);
 
 #define M_TRAP(a,i)        M_UNDEFINED(UNCOND,i,a);
 #define M_TRAPEQ(a,i)      M_UNDEFINED(COND_EQ,i,a);
+#define M_TRAPNE(a,i)      M_UNDEFINED(COND_NE,i,a);
+#define M_TRAPLT(a,i)      M_UNDEFINED(COND_LT,i,a);
 #define M_TRAPLE(a,i)      M_UNDEFINED(COND_LE,i,a);
 #define M_TRAPHI(a,i)      M_UNDEFINED(COND_HI,i,a);
 #define M_TRAPHS(a,i)      M_UNDEFINED(COND_CS,i,a);
@@ -1158,6 +1160,7 @@ do { \
        } else if(IS_IMM(-(val))) { \
                M_CMN_IMM(reg, -(val)); \
        } else { \
+               assert((reg) != REG_ITMP3); \
                ICONST(REG_ITMP3, (val)); \
                M_CMP(reg, REG_ITMP3); \
        }
index c6c922c2131a23f032395369989bd6a03925ca12..9f11ca5c2fb32d6d1a09ef15bf08ec505fb3ce3f 100644 (file)
@@ -47,7 +47,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #include "toolbox/logging.hpp" /* XXX for debugging only */
 
@@ -544,6 +544,14 @@ void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 r
                        M_TRAPEQ(s1, TRAP_ClassCastException);
                        break;
 
+               case BRANCH_NE:
+                       M_TRAPNE(s1, TRAP_ClassCastException);
+                       break;
+
+               case BRANCH_LT:
+                       M_TRAPLT(s1, TRAP_ClassCastException);
+                       break;
+
                case BRANCH_LE:
                        M_TRAPLE(s1, TRAP_ClassCastException);
                        break;
index 10e7c13a2a80ce5239e60c7ff7cad6060d1ef0cc..0788aa26a9ecc9341dd3625a4b8a2c56c9903216 100644 (file)
@@ -59,7 +59,7 @@ typedef struct ucontext {
 #include "vm/jit/disass.h"
 #include "vm/jit/executionstate.h"
 #include "vm/jit/patcher-common.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_signal_handler_sigsegv ***************************************************
index 81f0a3926ac8f0db71fe027c9cae9d66a1ed226d..f0e74eaa695b62b92dfdc9ac3bcaad412a77b2a9 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,7 +43,7 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t result;
        uint32_t temp;
@@ -76,31 +77,16 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
-       return generic_compare_and_swap(p, oldval, newval);
-}
-
-
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+       return Atomic::generic_compare_and_swap(p, oldval, newval);
 }
 
 
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -109,7 +95,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -118,11 +104,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index 30df98d484ba893b04a6925ec15d4c3b7ff2de6b..e4549a1b7a67bfd8eb8bc8c305adf67c5e63b658 100644 (file)
@@ -142,20 +142,41 @@ void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
        /* Case: We loaded from base REG_PV with positive offset. */
 
        else if (M_MEM_GET_Rbase(mcode) == REG_PV && (mcode & 0x00800000) == 0x00800000) {
-               /* We loaded from REG_METHODPTR with a larger displacement */
+               /* We loaded with a larger displacement. Normally this means we loaded
+                  from REG_METHODPTR. However there is a corner case if we loaded
+                  from the data segment at an address aligned to 12 bit, which leads to a
+                  zero (positive) displacement for the last instruction. */
 
                mcode = pc[-1];
 
                /* check for "ADD IP, FP, #??, ROTL 12" */
 
-               if ((mcode & 0xffffff00) == 0xe28bca00)
+               if ((mcode & 0xffffff00) == 0xe28bca00) {
+                       /* We loaded from REG_METHODPTR with a larger displacement. */
+
+                       assert(mptr != NULL);
+                       disp += (int32_t) ((mcode & 0x00ff) << 12);
+                       pa = ((uint8_t *) mptr) + disp;
+               }
+
+               /* check for "SUB IP, IP, #??, ROTL 12" (corner case) */
+
+               else if ((mcode & 0xffffff00) == 0xe24cca00 && disp == 0) {
+                       /* We loaded from data segment with a larger displacement aligned to 12 bit. */
+
                        disp += (int32_t) ((mcode & 0x00ff) << 12);
-               else
+                       pa = ((uint8_t *) pv) - disp;
+               }
+
+               /* Case is not covered, something is severely wrong. */
+
+               else {
                        vm_abort_disassemble(pc - 1, 4, "md_jit_method_patch_address: unknown instruction %x", mcode);
 
-               /* we loaded from REG_METHODPTR */
+                       /* Keep compiler happy. */
 
-               pa = ((uint8_t *) mptr) + disp;
+                       pa = NULL;
+               }
        }
 
        /* Case is not covered, something is severely wrong. */
index b7b2a54c0912d27c058cfc3f6c140fcae8c94e9c..ff1e2dd9c9c7ae9532d8cfa1a30241fa7d361cc9 100644 (file)
@@ -441,53 +441,6 @@ bool builtin_checkcast(java_handle_t *o, classinfo *c)
 }
 
 
-/* builtin_descriptorscompatible ***********************************************
-
-   Checks if two array type descriptors are assignment compatible.
-
-   RETURN VALUE:
-      1......target = desc is possible
-      0......otherwise
-                       
-*******************************************************************************/
-
-static bool builtin_descriptorscompatible(arraydescriptor *desc, arraydescriptor *target)
-{
-       if (desc == target)
-               return 1;
-
-       if (desc->arraytype != target->arraytype)
-               return 0;
-
-       if (desc->arraytype != ARRAYTYPE_OBJECT)
-               return 1;
-       
-       /* {both arrays are arrays of references} */
-
-       if (desc->dimension == target->dimension) {
-               if (!desc->elementvftbl)
-                       return 0;
-               /* an array which contains elements of interface types is
-           allowed to be casted to Object (JOWENN)*/
-
-               if ((desc->elementvftbl->baseval < 0) &&
-                       (target->elementvftbl->baseval == 1))
-                       return 1;
-
-               return class_isanysubclass(desc->elementvftbl->clazz,
-                                                                  target->elementvftbl->clazz);
-       }
-
-       if (desc->dimension < target->dimension)
-               return 0;
-
-       /* {desc has higher dimension than target} */
-
-       return class_isanysubclass(pseudo_class_Arraystub,
-                                                          target->elementvftbl->clazz);
-}
-
-
 /* builtin_arraycheckcast ******************************************************
 
    Checks if an object is really a subtype of the requested array
@@ -515,7 +468,7 @@ bool builtin_fast_arraycheckcast(java_object_t *o, classinfo *targetclass)
        if (desc == NULL)
                return 0;
  
-       return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
+       return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
 }
 
 
@@ -682,7 +635,6 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
        vftbl_t         *componentvftbl;
        vftbl_t         *valuevftbl;
        int32_t          baseval;
-       uint32_t         diffval;
        bool             result;
 
        if (o == NULL)
@@ -721,8 +673,8 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
 #if USES_NEW_SUBTYPE
                        result = fast_subtype_check(valuevftbl, componentvftbl);
 #else
-                       diffval = valuevftbl->baseval - componentvftbl->baseval;
-                       result  = diffval <= (uint32_t) componentvftbl->diffval;
+                       uint32_t diffval = valuevftbl->baseval - componentvftbl->baseval;
+                       result = diffval <= (uint32_t) componentvftbl->diffval;
 #endif
                }
 
@@ -739,7 +691,7 @@ bool builtin_fast_canstore(java_objectarray_t *oa, java_object_t *o)
        else {
                /* {o is an array} */
 
-               result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+               result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
        }
 
        /* return result */
@@ -755,7 +707,6 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
        vftbl_t         *elementvftbl;
        vftbl_t         *valuevftbl;
        int32_t          baseval;
-       uint32_t         diffval;
        bool             result;
        
        if (o == NULL)
@@ -791,8 +742,8 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
 #if USES_NEW_SUBTYPE
                result = fast_subtype_check(valuevftbl, elementvftbl);
 #else
-               diffval = valuevftbl->baseval - elementvftbl->baseval;
-               result  = diffval <= (uint32_t) elementvftbl->diffval;
+               uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
+               result = diffval <= (uint32_t) elementvftbl->diffval;
 #endif
        }
 
@@ -806,10 +757,9 @@ bool builtin_fast_canstore_onedim(java_objectarray_t *a, java_object_t *o)
  * one-dimensional array of a class type */
 bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
 {
-       vftbl_t  *elementvftbl;
-       vftbl_t  *valuevftbl;
-       uint32_t  diffval;
-       bool      result;
+       vftbl_t *elementvftbl;
+       vftbl_t *valuevftbl;
+       bool     result;
        
        if (o == NULL)
                return 1;
@@ -836,8 +786,8 @@ bool builtin_fast_canstore_onedim_class(java_objectarray_t *a, java_object_t *o)
 #if USES_NEW_SUBTYPE
        result = fast_subtype_check(valuevftbl, elementvftbl);
 #else
-       diffval = valuevftbl->baseval - elementvftbl->baseval;
-       result  = diffval <= (uint32_t) elementvftbl->diffval;
+       uint32_t diffval = valuevftbl->baseval - elementvftbl->baseval;
+       result = diffval <= (uint32_t) elementvftbl->diffval;
 #endif
 
        UNLOCK_CLASSRENUMBER_LOCK;
index 370a64bd024fd6463f35a6bb03e6077bcc67d076..e0837c2eee0d15e78911da3f94e024d7df0bbd4e 100644 (file)
@@ -690,6 +690,11 @@ void emit_label_bgtz(codegendata* cd, int label, int reg)
 
 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
 
+void emit_label_beq(codegendata* cd, int label, int s1, int s2)
+{
+       emit_label_bccz(cd, label, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
+}
+
 void emit_label_bne(codegendata* cd, int label, int s1, int s2)
 {
        emit_label_bccz(cd, label, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
index 611eca43d943175d53a70e6dba14fe1a9b107aef..c3c3af73db15566eef07ba2290ce158d883859e8 100644 (file)
@@ -168,6 +168,7 @@ void emit_label_bgtz(codegendata* cd, int label, int reg);
 #endif
 
 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
+void emit_label_beq(codegendata* cd, int label, int s1, int s2);
 void emit_label_bne(codegendata* cd, int label, int s1, int s2);
 #endif
 
index 8eab0fbf0511a4cce0d56cac92d930db7c06b8ed..10aa098df3c47c915ef9b88ec4a86c67ffd1b7f6 100644 (file)
@@ -64,7 +64,7 @@
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_SSA)
 # include "vm/jit/optimizing/lsra.h"
@@ -607,7 +607,7 @@ bool codegen_emit(jitdata *jd)
                                patcher_add_patch_ref(jd, PATCHER_aconst,
                                                                        iptr->sx.val.c.ref, 0);
 
-                               M_MOV_IMM(NULL, d);
+                               M_MOV_IMM2(NULL, d);
 
                        } else {
                                if (iptr->sx.val.anyptr == NULL)
@@ -2197,7 +2197,7 @@ bool codegen_emit(jitdata *jd)
                                        patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
                        }
 
-                       M_MOV_IMM(disp, REG_ITMP1);
+                       M_MOV_IMM2(disp, REG_ITMP1);
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_ADR:
@@ -2238,7 +2238,7 @@ bool codegen_emit(jitdata *jd)
                                        patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
                        }
 
-                       M_MOV_IMM(disp, REG_ITMP1);
+                       M_MOV_IMM2(disp, REG_ITMP1);
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_ADR:
@@ -2280,7 +2280,7 @@ bool codegen_emit(jitdata *jd)
                                        patcher_add_patch_ref(jd, PATCHER_initialize_class, fi->clazz, 0);
                        }
 
-                       M_MOV_IMM(disp, REG_ITMP1);
+                       M_MOV_IMM2(disp, REG_ITMP1);
                        switch (fieldtype) {
                        case TYPE_INT:
                        case TYPE_ADR:
@@ -3004,7 +3004,7 @@ gen_method:
                                        d = lm->parseddesc->returntype.type;
                                }
 
-                               M_MOV_IMM(disp, REG_ITMP2);
+                               M_MOV_IMM2(disp, REG_ITMP2);
                                M_CALL(REG_ITMP2);
                                break;
 
@@ -3126,7 +3126,7 @@ gen_method:
                                        patcher_add_patch_ref(jd, PATCHER_checkcast_instanceof_flags,
                                                                                iptr->sx.s23.s3.c.ref, 0);
 
-                                       M_MOV_IMM(0, REG_ITMP2);                  /* super->flags */
+                                       M_MOV_IMM2(0, REG_ITMP2);                 /* super->flags */
                                        M_AND_IMM32(ACC_INTERFACE, REG_ITMP2);
                                        emit_label_beq(cd, BRANCH_LABEL_2);
                                }
@@ -3183,7 +3183,7 @@ gen_method:
                                                                                        iptr->sx.s23.s3.c.ref,
                                                                                        0);
                                        }
-                                       M_MOV_IMM(supervftbl, REG_ITMP3);
+                                       M_MOV_IMM2(supervftbl, REG_ITMP3);
 
                                        if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
                                                M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
@@ -3296,7 +3296,7 @@ gen_method:
                                patcher_add_patch_ref(jd, PATCHER_checkcast_instanceof_flags,
                                                                        iptr->sx.s23.s3.c.ref, 0);
 
-                               M_MOV_IMM(0, REG_ITMP3);                      /* super->flags */
+                               M_MOV_IMM2(0, REG_ITMP3);                     /* super->flags */
                                M_AND_IMM32(ACC_INTERFACE, REG_ITMP3);
                                emit_label_beq(cd, BRANCH_LABEL_2);
                        }
@@ -3356,7 +3356,7 @@ gen_method:
                                        patcher_add_patch_ref(jd, PATCHER_instanceof_class,
                                                                                iptr->sx.s23.s3.c.ref, 0);
                                }
-                               M_MOV_IMM(supervftbl, REG_ITMP3);
+                               M_MOV_IMM2(supervftbl, REG_ITMP3);
 
                                if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
                                        M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
index ef28c246583b33a92fcc18363a20281d8f8e91ba..3f61d96a88833bc9b9ff8eedc1f1a7aa5595d3db 100644 (file)
 
 #define M_MOV(a,b)              emit_mov_reg_reg(cd, (a), (b))
 #define M_MOV_IMM(a,b)          emit_mov_imm_reg(cd, (u4) (a), (b))
+#define M_MOV_IMM2(a,b)         emit_mov_imm2_reg(cd, (u4) (a), (b))
 
 #define M_TEST(a)               emit_test_reg_reg(cd, (a), (a))
 #define M_TEST_IMM(a,b)         emit_test_imm_reg(cd, (a), (b))
index b9f3afd9de575a9b1697f2dc96553ee273ff33eb..157267d20e4f123b64bbc09477b6c452ca452adf 100644 (file)
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #include "vm/jit/i386/codegen.h"
 
+#if !__DARWIN_UNIX03
+#define __eax eax
+#define __ebx ebx
+#define __ecx ecx
+#define __edx edx
+#define __esi esi
+#define __edi edi
+#define __ebp ebp
+#define __esp esp
+#define __eip eip
+#define __ss ss
+#endif
 
 /* md_signal_handler_sigsegv ***************************************************
 
@@ -242,6 +254,22 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        xpc = (u1 *) _ss->__eip;
        ra  = xpc;                          /* return address is equal to xpc     */
 
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
+
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
+       }
+
        type = TRAP_PATCHER;
        val  = 0;
 
index 3a264f162542561af62ca4197e098192313699a4..181799832f5d0137447c5969a38b56f1ec4f99a3 100644 (file)
@@ -48,7 +48,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load ******************************************************************
@@ -805,6 +805,15 @@ void emit_mov_imm_reg(codegendata *cd, s4 imm, s4 reg)
        emit_imm32((imm));
 }
 
+/* 2-byte opcode for use with patchers */
+void emit_mov_imm2_reg(codegendata *cd, s4 imm, s4 reg)
+{
+       *(cd->mcodeptr++) = 0xc7;
+       emit_address_byte(3, 0, reg);
+       emit_imm32((imm));
+}
+
+
 
 void emit_movb_imm_reg(codegendata *cd, s4 imm, s4 reg)
 {
index a99eaeeb386c471a5b496f9b3ba67d2c9860ce0f..c17c0229f15e1ba1cd72f9bda33b0c94013e5e69 100644 (file)
 
 void emit_mov_reg_reg(codegendata *cd, s4 reg, s4 dreg);
 void emit_mov_imm_reg(codegendata *cd, s4 imm, s4 dreg);
+void emit_mov_imm2_reg(codegendata *cd, s4 imm, s4 dreg);
 void emit_movb_imm_reg(codegendata *cd, s4 imm, s4 dreg);
 void emit_mov_membase_reg(codegendata *cd, s4 basereg, s4 disp, s4 reg);
 void emit_mov_membase32_reg(codegendata *cd, s4 basereg, s4 disp, s4 reg);
index 9a18831478fc3f327233a3c0c7725ad10d788f24..b6a4c482807b606d8fef3d2b346db4ada2de6e6f 100644 (file)
@@ -41,7 +41,7 @@
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_signal_handler_sigsegv ***************************************************
@@ -225,6 +225,22 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        xpc = (u1 *) _mc->mc_eip;
        ra  = xpc;                            /* return address is equal to xpc   */
 
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
+
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
+       }
+
        type = TRAP_PATCHER;
        val  = 0;
 
index 19be0e4b7fed8ee85218560bfc617fd88233d9f6..1f72d58d2ffca4f21a73fbd7508651312c9abb18 100644 (file)
@@ -43,7 +43,7 @@
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_signal_handler_sigsegv ***************************************************
@@ -205,6 +205,22 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        xpc = (u1 *) _mc->gregs[REG_EIP];
        ra  = xpc;                            /* return address is equal to xpc   */
 
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
+
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
+       }
+
        type = TRAP_PATCHER;
        val  = 0;
 
index d6ea3d777f5b89451be85d0e76ac7980d84cd4c1..84f7b3df5e05b255aac0da4bf4a1936b1e3bb0f1 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t result;
 
        __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
                                                  : "=a" (result), "=m" (*p)
-                                                 : "r" (newval), "m" (*p), "0" (oldval));
+                                                 : "r" (newval), "m" (*p), "0" (oldval)
+                                                 : "cc");
 
        return result;
 }
@@ -63,32 +65,17 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
 #warning Should we use cmpxchg8b or a generic version?
-       return generic_compare_and_swap(p, oldval, newval);
-}
-
-
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+       return Atomic::generic_compare_and_swap(p, oldval, newval);
 }
 
 
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("lock; add $0, 0(%%esp)" : : : "memory" );
 }
@@ -97,7 +84,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -106,9 +93,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
-       // Nothing.
+       // We need the "memory" constraint here because compare_and_swap does not
+       // have it.
+       __asm__ __volatile__ ("" : : : "memory");
+}
+
 }
 
 #endif // _MD_ATOMIC_HPP
index fb04b86c4e1e2ac8a88bad0f5f35d963862e2383..2cf16f9b152f83e0fae2b2e63f263a9c0b0d9618 100644 (file)
@@ -49,8 +49,6 @@
 
 #define PATCH_BACK_ORIGINAL_MCODE                                                      \
        do {                                                                                                    \
-               *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode;          \
-               md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);     \
        } while (0)
 
 
 
 void patcher_patch_code(patchref_t *pr)
 {
-       PATCH_BACK_ORIGINAL_MCODE;
+       *((uint16_t*) pr->mpc) = (uint16_t) pr->mcode;
+       md_icacheflush((void*) pr->mpc, PATCHER_CALL_SIZE);
+}
+
+/**
+ * Check if the trap instruction at the given PC is valid.
+ *
+ * @param pc Program counter.
+ *
+ * @return true if valid, false otherwise.
+ */
+bool patcher_is_valid_trap_instruction_at(void* pc)
+{
+       uint16_t mcode = *((uint16_t*) pc);
+
+       // Check for the undefined instruction we use.
+       return (mcode == 0x0b0f);
 }
 
 
@@ -71,7 +85,7 @@ void patcher_patch_code(patchref_t *pr)
    Machine code:
 
    <patched call position>
-   b8 00 00 00 00             mov    $0x00000000,%eax
+   c7 c0 00 00 00 00          mov    $0x00000000,%eax
 
 *******************************************************************************/
 
@@ -97,11 +111,13 @@ bool patcher_get_putstatic(patchref_t *pr)
                if (!initialize_class(fi->clazz))
                        return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the field value's address */
 
-       *((intptr_t *) (ra + 1)) = (intptr_t) fi->value;
+       *((intptr_t *) (ra + 2)) = (intptr_t) fi->value;
+       md_icacheflush((void*) (ra + 2), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -132,16 +148,22 @@ bool patcher_getfield(patchref_t *pr)
        if (!(fi = resolve_field_eager(uf)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the field's offset */
 
        *((u4 *) (ra + 2)) = (u4) (fi->offset);
+       int clen = SIZEOF_VOID_P;
 
        /* if the field has type long, we need to patch the second move too */
 
-       if (fi->type == TYPE_LNG)
+       if (fi->type == TYPE_LNG) {
                *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
+               clen += 6;
+       }
+
+       md_icacheflush((void*) (ra + 2), clen);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -172,10 +194,9 @@ bool patcher_putfield(patchref_t *pr)
        if (!(fi = resolve_field_eager(uf)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the field's offset */
 
+       int clen = SIZEOF_VOID_P;
        if (fi->type != TYPE_LNG) {
                *((u4 *) (ra + 2)) = (u4) (fi->offset);
        }
@@ -188,8 +209,14 @@ bool patcher_putfield(patchref_t *pr)
 
                *((u4 *) (ra + 2))     = (u4) (fi->offset);
                *((u4 *) (ra + 6 + 2)) = (u4) (fi->offset + 4);
+               clen += 6;
        }
 
+       md_icacheflush((void*) (ra + 2), clen);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -219,10 +246,9 @@ bool patcher_putfieldconst(patchref_t *pr)
        if (!(fi = resolve_field_eager(uf)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the field's offset */
 
+       int clen = SIZEOF_VOID_P;
        if (!IS_2_WORD_TYPE(fi->type)) {
                *((u4 *) (ra + 2)) = (u4) (fi->offset);
        }
@@ -235,8 +261,14 @@ bool patcher_putfieldconst(patchref_t *pr)
 
                *((u4 *) (ra + 2))      = (u4) (fi->offset);
                *((u4 *) (ra + 10 + 2)) = (u4) (fi->offset + 4);
+               clen += 10;
        }
 
+       md_icacheflush((void*) (ra + 2), clen);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
+
        return true;
 }
 
@@ -246,8 +278,7 @@ bool patcher_putfieldconst(patchref_t *pr)
    Machine code:
 
    <patched call postition>
-   c7 04 24 00 00 00 00       movl   $0x0000000,(%esp)
-   b8 00 00 00 00             mov    $0x0000000,%eax
+   c7 c0 00 00 00 00          mov    $0x00000000,%eax
 
 *******************************************************************************/
 
@@ -267,11 +298,13 @@ bool patcher_aconst(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the classinfo pointer */
 
-       *((ptrint *) (ra + 1)) = (ptrint) c;
+       *((ptrint *) (ra + 2)) = (ptrint) c;
+       md_icacheflush((void*) (ra + 2), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -308,11 +341,13 @@ bool patcher_builtin_multianewarray(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the classinfo pointer */
 
        *((ptrint *) (ra + 7 + 4)) = (ptrint) c;
+       md_icacheflush((void*) (ra + 7 + 4), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -345,8 +380,6 @@ bool patcher_builtin_arraycheckcast(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch the classinfo pointer */
 
        *((ptrint *) (ra + 4)) = (ptrint) c;
@@ -354,6 +387,10 @@ bool patcher_builtin_arraycheckcast(patchref_t *pr)
        /* patch new function address */
 
        *((ptrint *) (ra + 8 + 1)) = (ptrint) BUILTIN_arraycheckcast;
+       md_icacheflush((void*) (ra + 4), SIZEOF_VOID_P + 8 + 1 - 4);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -364,7 +401,7 @@ bool patcher_builtin_arraycheckcast(patchref_t *pr)
    Machine code:
 
    <patched call position>
-   b9 00 00 00 00             mov    $0x00000000,%ecx
+   c7 c1 00 00 00 00          mov    $0x00000000,%ecx
    ff d1                      call   *%ecx
 
 *******************************************************************************/
@@ -385,11 +422,13 @@ bool patcher_invokestatic_special(patchref_t *pr)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch stubroutine */
 
-       *((ptrint *) (ra + 1)) = (ptrint) m->stubroutine;
+       *((ptrint *) (ra + 2)) = (ptrint) m->stubroutine;
+       md_icacheflush((void*) (ra + 2), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -422,12 +461,14 @@ bool patcher_invokevirtual(patchref_t *pr)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch vftbl index */
 
        *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, table[0]) +
                                                                   sizeof(methodptr) * m->vftblindex);
+       md_icacheflush((void*) (ra + 2 + 2), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -461,8 +502,6 @@ bool patcher_invokeinterface(patchref_t *pr)
        if (!(m = resolve_method_eager(um)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch interfacetable index */
 
        *((s4 *) (ra + 2 + 2)) = (s4) (OFFSET(vftbl_t, interfacetable[0]) -
@@ -472,6 +511,10 @@ bool patcher_invokeinterface(patchref_t *pr)
 
        *((s4 *) (ra + 2 + 6 + 2)) =
                (s4) (sizeof(methodptr) * (m - m->clazz->methods));
+       md_icacheflush((void*) (ra + 2 + 2), SIZEOF_VOID_P + 6);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -482,7 +525,7 @@ bool patcher_invokeinterface(patchref_t *pr)
    Machine code:
 
    <patched call position>
-   b9 00 00 00 00             mov    $0x00000000,%ecx
+   c7 c1 00 00 00 00          mov    $0x00000000,%ecx
 
 *******************************************************************************/
 
@@ -502,11 +545,13 @@ bool patcher_checkcast_instanceof_flags(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch class flags */
 
-       *((s4 *) (ra + 1)) = (s4) c->flags;
+       *((s4 *) (ra + 2)) = (s4) c->flags;
+       md_icacheflush((void*) (ra + 2), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -542,8 +587,6 @@ bool patcher_checkcast_interface(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch super class index */
 
        *((s4 *) (ra + 6 + 2)) = (s4) c->index;
@@ -551,6 +594,10 @@ bool patcher_checkcast_interface(patchref_t *pr)
        *((s4 *) (ra + 6 + 6 + 2 + 6 + 6 + 2)) =
                (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                          c->index * sizeof(methodptr*));
+       md_icacheflush((void*) (ra + 6 + 2), SIZEOF_VOID_P + 6 + 6 + 6 + 2);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -585,8 +632,6 @@ bool patcher_instanceof_interface(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch super class index */
 
        *((s4 *) (ra + 6 + 2)) = (s4) c->index;
@@ -594,6 +639,10 @@ bool patcher_instanceof_interface(patchref_t *pr)
        *((s4 *) (ra + 6 + 6 + 2 + 6 + 2)) =
                (s4) (OFFSET(vftbl_t, interfacetable[0]) -
                          c->index * sizeof(methodptr*));
+       md_icacheflush((void*) (ra + 6 + 2), SIZEOF_VOID_P + 6 + 6 + 2);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -604,11 +653,7 @@ bool patcher_instanceof_interface(patchref_t *pr)
    Machine code:
 
    <patched call position>
-   ba 00 00 00 00             mov    $0x00000000,%edx
-   8b 89 00 00 00 00          mov    0x00000000(%ecx),%ecx
-   8b 92 00 00 00 00          mov    0x00000000(%edx),%edx
-   29 d1                      sub    %edx,%ecx
-   ba 00 00 00 00             mov    $0x00000000,%edx
+   c7 c1 00 00 00 00          mov    $0x00000000,%ecx
 
 *******************************************************************************/
 
@@ -628,11 +673,13 @@ bool patcher_checkcast_class(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch super class' vftbl */
 
-       *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
+       *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
+       md_icacheflush((void*) (ra + 2), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
@@ -643,10 +690,7 @@ bool patcher_checkcast_class(patchref_t *pr)
    Machine code:
 
    <patched call position>
-   b9 00 00 00 00             mov    $0x0,%ecx
-   8b 40 14                   mov    0x14(%eax),%eax
-   8b 51 18                   mov    0x18(%ecx),%edx
-   8b 49 14                   mov    0x14(%ecx),%ecx
+   c7 c1 00 00 00 00          mov    $0x00000000,%ecx
 
 *******************************************************************************/
 
@@ -666,11 +710,13 @@ bool patcher_instanceof_class(patchref_t *pr)
        if (!(c = resolve_classref_eager(cr)))
                return false;
 
-       PATCH_BACK_ORIGINAL_MCODE;
-
        /* patch super class' vftbl */
 
-       *((ptrint *) (ra + 1)) = (ptrint) c->vftbl;
+       *((ptrint *) (ra + 2)) = (ptrint) c->vftbl;
+       md_icacheflush((void*) (ra + 2), SIZEOF_VOID_P);
+
+       // Patch back the original code.
+       patcher_patch_code(pr);
 
        return true;
 }
index 16e649d6d41d92936af8dfbcec3339cf3d941040..5526e4af1639d8a18405bb88dcff0e41b626c29d 100644 (file)
@@ -41,7 +41,7 @@
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_signal_handler_sigsegv ***************************************************
@@ -203,6 +203,22 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        xpc = (u1 *) _mc->gregs[EIP];
        ra  = xpc;                            /* return address is equal to xpc   */
 
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
+
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
+       }
+
        type = TRAP_PATCHER;
        val  = 0;
 
index 5c46894032a1423a32348317ed8de6b93f14b8be..12fd5184044329237c4489565e135ee28fdd25bc 100644 (file)
@@ -61,7 +61,7 @@
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 bool codegen_emit(jitdata *jd) 
index 63d74a8e6f5fed954cc43ca0bbcbdddbddd6102d..f0e3e5fbe7537981ad48419175ff565d6e923e6c 100644 (file)
@@ -37,7 +37,7 @@
 #include "vm/jit/asmpart.h"
 #include "vm/jit/emit-common.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_mov_imm_reg **************************************************************************
index 36e85035df313b7dc366bfcab3037a91f2029308..45e1a34ffde91dd53740b1483c8d95782fd42d83 100644 (file)
@@ -32,7 +32,7 @@
 #include "vm/vm.hpp"
 
 #include "vm/jit/asmpart.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #include <assert.h>
 #include <stdlib.h>
index ad5d4d247bd84d6abe7434ee5ff35b670e40d6f5..5ed395ea2f15db20ee1739f5a03c308e593bed24 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,9 +43,9 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
-       return generic_compare_and_swap(p, oldval, newval);
+       return Atomic::generic_compare_and_swap(p, oldval, newval);
 }
 
 
@@ -57,31 +58,16 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
-       return generic_compare_and_swap(p, oldval, newval);
-}
-
-
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return generic_compare_and_swap(p, oldval, newval);
+       return Atomic::generic_compare_and_swap(p, oldval, newval);
 }
 
 
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        generic_memory_barrier();
 }
@@ -90,7 +76,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -99,11 +85,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index e2ed877694cd5993a90e5f7b22e2e2a6c1a49faf..37b90494bebef6b0e88e36f2699750bb54179f43 100644 (file)
 
 #define REPLACEMENT_PATCH_SIZE           (2*4) /* bytes */
 
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE                 1
+
 #endif /* _ARCH_H */
 
 
index 7fac7239123a0ac7950dab501895bae3951acce0..4db7b0d74726fe0fab9b1864d38c99d401ebeaee 100644 (file)
@@ -58,7 +58,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
@@ -3298,26 +3298,75 @@ gen_method:
                                                emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                        }
 
+                                       // The following code checks whether object s is a subtype of class t.
+                                       // Represents the following semantic:
+                                       //    if (!fast_subtype_check(s->vftbl, t->vftbl)) throw;
+
                                        M_ALD(REG_ITMP2, s1, OFFSET(java_object_t, vftbl));
                                        M_ALD(REG_ITMP3, REG_PV, disp);
 
-                                       M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                                       /*                              if (s1 != REG_ITMP1) { */
-                                       /*                                      M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, baseval)); */
-                                       /*                                      M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval)); */
-                                       /* #if defined(ENABLE_THREADS) */
-                                       /*                                      codegen_threadcritstop(cd, cd->mcodeptr - cd->mcodebase); */
-                                       /* #endif */
-                                       /*                                      M_ISUB(REG_ITMP2, REG_ITMP1, REG_ITMP2); */
-                                       /*                              } else { */
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, baseval));
-                                       M_ISUB(REG_ITMP2, REG_ITMP3, REG_ITMP2); 
-                                       M_ALD(REG_ITMP3, REG_PV, disp);
-                                       M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, diffval));
+                                       if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                               // Represents the following semantic:
+                                               //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) good;
+                                               // Preconditions:
+                                               //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                               M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_AADD(REG_ITMP1, REG_ITMP2, REG_ITMP1);
+                                               M_ALD(REG_ITMP1, REG_ITMP1, 0);
+                                               emit_label_beq(cd, BRANCH_LABEL_6, REG_ITMP1, REG_ITMP3);  /* good */
+
+                                               // Represents the following semantic:
+                                               //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) throw;
+                                               // Preconditions:
+                                               //    REG_ITMP3==t->vftbl;
+                                               if (super == NULL) {
+                                                       M_ILD(REG_ITMP1, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                                       M_ISUB_IMM(REG_ITMP1, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP1);
+                                                       emit_label_bnez(cd, BRANCH_LABEL_9, REG_ITMP1);  /* throw */
+                                               }
 
-                                       /*                              } */
-                                       M_CMPULT(REG_ITMP3, REG_ITMP2, REG_ITMP3);
-                                       emit_classcast_check(cd, iptr, ICMD_IFNE, REG_ITMP3, s1);
+                                               // Represents the following semantic:
+                                               //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) throw;
+                                               // Preconditions:
+                                               //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                               M_ILD(REG_ITMP1, REG_ITMP2, OFFSET(vftbl_t, subtype_depth));
+                                               M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                               M_CMPULT(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                               emit_label_bnez(cd, BRANCH_LABEL_8, REG_ITMP1);  /* throw */
+
+                                               // Represents the following semantic:
+                                               //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) throw;
+                                               // Preconditions:
+                                               //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
+                                               M_ALD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, subtype_overflow));
+                                               M_ASLL_IMM(REG_ITMP3, POINTERSHIFT, REG_ITMP3);
+                                               M_AADD(REG_ITMP2, REG_ITMP3, REG_ITMP2);
+                                               M_ALD(REG_ITMP2, REG_ITMP2, -DISPLAY_SIZE * SIZEOF_VOID_P);
+                                               M_ALD(REG_ITMP3, REG_PV, disp);  /* reload REG_ITMP3, was destroyed */
+                                               emit_label_beq(cd, BRANCH_LABEL_7, REG_ITMP2, REG_ITMP3);  /* good */
+
+                                               // Throw case
+                                               emit_label(cd, BRANCH_LABEL_8);
+                                               if (super == NULL)
+                                                       emit_label(cd, BRANCH_LABEL_9);
+                                               emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
+                                               M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
+
+                                               // Good case
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                               emit_label(cd, BRANCH_LABEL_6);
+                                               emit_load_s1(jd, iptr, REG_ITMP1);  /* reload s1, might have been destroyed */
+                                       }
+                                       else {
+                                               // Represents the following semantic:
+                                               //    if (*(s->vftbl + t->vftbl->subtype_offset) != t->vftbl) throw;
+                                               // Preconditions:
+                                               //    REG_ITMP2==s->vftbl; REG_ITMP3==t->vftbl;
+                                               M_ALD(REG_ITMP2, REG_ITMP2, super->vftbl->subtype_offset);
+                                               M_BEQ(REG_ITMP2, REG_ITMP3, 2);
+                                               M_NOP;  /* delay slot */
+                                               M_ALD_INTERN(s1, REG_ZERO, TRAP_ClassCastException);
+                                       }
 
                                        if (super != NULL)
                                                emit_label(cd, BRANCH_LABEL_5);
@@ -3453,16 +3502,78 @@ gen_method:
                                        emit_label_beqz(cd, BRANCH_LABEL_5, s1);
                                }
 
+                               // The following code checks whether object s is a subtype of class t.
+                               // Represents the following semantic:
+                               //    fast_subtype_check(s->vftbl, t->vftbl));
+
                                M_ALD(REG_ITMP1, s1, OFFSET(java_object_t, vftbl));
-                               M_ALD(REG_ITMP2, REG_PV, disp);
+                               M_ALD(REG_ITMP3, REG_PV, disp);
+
+                               if (super == NULL || super->vftbl->subtype_depth >= DISPLAY_SIZE) {
+                                               // Represents the following semantic:
+                                               //    if (*(s->vftbl + t->vftbl->subtype_offset) == t->vftbl) true;
+                                               // Preconditions:
+                                               //    REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl;
+                                               M_ILD(REG_ITMP2, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                               M_AADD(REG_ITMP2, REG_ITMP1, REG_ITMP2);
+                                               M_ALD(REG_ITMP2, REG_ITMP2, 0);
+                                               emit_label_beq(cd, BRANCH_LABEL_6, REG_ITMP2, REG_ITMP3);  /* true */
+
+                                               // Represents the following semantic:
+                                               //    if (t->vftbl->subtype_offset != OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE])) false;
+                                               // Preconditions:
+                                               //    REG_ITMP3==t->vftbl;
+                                               if (super == NULL) {
+                                                       M_ILD(REG_ITMP2, REG_ITMP3, OFFSET(vftbl_t, subtype_offset));
+                                                       M_ISUB_IMM(REG_ITMP2, OFFSET(vftbl_t, subtype_display[DISPLAY_SIZE]), REG_ITMP2);
+                                                       emit_label_bnez(cd, BRANCH_LABEL_9, REG_ITMP2);  /* false */
+                                               }
 
-                               M_ILD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP3, REG_ITMP2, OFFSET(vftbl_t, baseval));
-                               M_ILD(REG_ITMP2, REG_ITMP2, OFFSET(vftbl_t, diffval));
+                                               // Represents the following semantic:
+                                               //    if (s->vftbl->subtype_depth < t->vftbl->subtype_depth) false;
+                                               // Preconditions:
+                                               //    REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl;
+                                               M_ILD(REG_ITMP2, REG_ITMP1, OFFSET(vftbl_t, subtype_depth));
+                                               M_ILD(REG_ITMP3, REG_ITMP3, OFFSET(vftbl_t, subtype_depth));
+                                               M_CMPULT(REG_ITMP2, REG_ITMP3, REG_ITMP2);
+                                               emit_label_bnez(cd, BRANCH_LABEL_8, REG_ITMP2);  /* false */
+
+                                               // Represents the following semantic:
+                                               //    if (s->vftbl->subtype_overflow[t->vftbl->subtype_depth - DISPLAY_SIZE] != t->vftbl) false;
+                                               // Preconditions:
+                                               //    REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl->subtype_depth;
+                                               M_ALD(REG_ITMP1, REG_ITMP1, OFFSET(vftbl_t, subtype_overflow));
+                                               M_ASLL_IMM(REG_ITMP3, POINTERSHIFT, REG_ITMP3);
+                                               M_AADD(REG_ITMP1, REG_ITMP3, REG_ITMP1);
+                                               M_ALD(REG_ITMP1, REG_ITMP1, -DISPLAY_SIZE * SIZEOF_VOID_P);
+                                               M_ALD(REG_ITMP3, REG_PV, disp);  /* reload REG_ITMP3, was destroyed */
+                                               emit_label_bne(cd, BRANCH_LABEL_7, REG_ITMP1, REG_ITMP3);  /* false */
+
+                                               // True case
+                                               emit_label(cd, BRANCH_LABEL_6);
+                                               M_MOV(1, d);
+                                               if (d == REG_ITMP2) {
+                                                       M_BR(2);  /* branch over M_CLR */
+                                                       M_NOP;  /* delay slot */
+                                               }
 
-                               M_ISUB(REG_ITMP1, REG_ITMP3, REG_ITMP1); 
-                               M_CMPULT(REG_ITMP2, REG_ITMP1, d);
-                               M_XOR_IMM(d, 1, d);
+                                               // False (fall-through) case
+                                               emit_label(cd, BRANCH_LABEL_7);
+                                               emit_label(cd, BRANCH_LABEL_8);
+                                               if (super == NULL)
+                                                       emit_label(cd, BRANCH_LABEL_9);
+                                               if (d == REG_ITMP2)
+                                                       M_CLR(d);  /* if d == REG_ITMP2, it was destroyed */
+                               }
+                               else {
+                                       // Represents the following semantic:
+                                       //    *(s->vftbl + t->vftbl->subtype_offset) == t->vftbl;
+                                       // Preconditions:
+                                       //    REG_ITMP1==s->vftbl; REG_ITMP3==t->vftbl;
+                                       M_ALD(REG_ITMP1, REG_ITMP1, super->vftbl->subtype_offset);
+                                       M_XOR(REG_ITMP1, REG_ITMP3, d);
+                                       M_CMPULT_IMM(d, 1, d);
+                               }
 
                                if (super != NULL)
                                        emit_label(cd, BRANCH_LABEL_5);
index 98e9b451fe4c21059433141c593cf52245bc19ae..d2edc03ee94e175423b2c73f808c20a7084e25c1 100644 (file)
@@ -47,7 +47,8 @@
 #include "vm/jit/jit.hpp"
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trace.hpp"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load *******************************************************************
@@ -656,7 +657,7 @@ void emit_verbosecall_enter(jitdata *jd)
        registerdata *rd;
        methoddesc   *md;
        s4            disp;
-       s4            i, j, t;
+       s4            i, s;
 
        /* get required compiler data */
 
@@ -671,98 +672,91 @@ void emit_verbosecall_enter(jitdata *jd)
 
        M_NOP;
 
-       M_LDA(REG_SP, REG_SP, -(PA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8));
-       M_AST(REG_RA, REG_SP, PA_SIZE + 1 * 8);
+       /* keep stack 16-byte aligned */
+
+       M_LDA(REG_SP, REG_SP, -(PA_SIZE + (md->paramcount + 2 + TMP_CNT) * 8));
+       M_AST(REG_RA, REG_SP, PA_SIZE + md->paramcount * 8);
 
        /* save argument registers (we store the registers as address
           types, so it's correct for MIPS32 too) */
 
-       for (i = 0; i < INT_ARG_CNT; i++)
-               M_AST(abi_registers_integer_argument[i], REG_SP, PA_SIZE + (2 + i) * 8);
-
-       for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DST(abi_registers_float_argument[i], REG_SP, PA_SIZE + (2 + INT_ARG_CNT + i) * 8);
+       for (i = 0; i < md->paramcount; i++) {
+               if (!md->params[i].inmemory) {
+                       s = md->params[i].regoff;
+                       switch (md->paramtypes[i].type) {
+                       case TYPE_ADR:
+                       case TYPE_INT:
+                               M_AST(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       case TYPE_LNG:
+                               M_LST(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       case TYPE_FLT:
+                               M_FST(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       case TYPE_DBL:
+                               M_DST(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       }
+               }
+       }
 
        /* save temporary registers for leaf methods */
 
        if (code_is_leafmethod(code)) {
                for (i = 0; i < INT_TMP_CNT; i++)
-                       M_AST(rd->tmpintregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + i) * 8);
+                       M_AST(rd->tmpintregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + i) * 8);
 
                for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DST(rd->tmpfltregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
-       }
-
-       /* Load float arguments into integer registers.  MIPS32 has less
-          float argument registers than integer ones, we need to check
-          that. */
-
-       for (i = 0; i < md->paramcount && i < INT_ARG_CNT && i < FLT_ARG_CNT; i++) {
-               t = md->paramtypes[i].type;
-
-               if (IS_FLT_DBL_TYPE(t)) {
-                       if (IS_2_WORD_TYPE(t)) {
-                               M_DST(abi_registers_float_argument[i], REG_SP, 0 * 8);
-                               M_LLD(abi_registers_integer_argument[i], REG_SP, 0 * 8);
-                       }
-                       else {
-                               M_FST(abi_registers_float_argument[i], REG_SP, 0 * 8);
-                               M_ILD(abi_registers_integer_argument[i], REG_SP, 0 * 8);
-                       }
-               }
+                       M_DST(rd->tmpfltregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + INT_TMP_CNT + i) * 8);
        }
 
-#if SIZEOF_VOID_P == 4
-               for (i = 0, j = 0; i < md->paramcount && i < TRACE_ARGS_NUM; i++) {
-                       t = md->paramtypes[i].type;
-
-                       if (IS_INT_LNG_TYPE(t)) {
-                               if (IS_2_WORD_TYPE(t)) {
-                                       M_ILD(abi_registers_integer_argument[j], REG_SP, PA_SIZE + (2 + i) * 8);
-                                       M_ILD(abi_registers_integer_argument[j + 1], REG_SP, PA_SIZE + (2 + i) * 8 + 4);
-                               }
-                               else {
-# if WORDS_BIGENDIAN == 1
-                                       M_MOV(REG_ZERO, abi_registers_integer_argument[j]);
-                                       M_ILD(abi_registers_integer_argument[j + 1], REG_SP, PA_SIZE + (2 + i) * 8);
-# else
-                                       M_ILD(abi_registers_integer_argument[j], REG_SP, PA_SIZE + (2 + i) * 8);
-                                       M_MOV(REG_ZERO, abi_registers_integer_argument[j + 1]);
-# endif
-                               }
-                               j += 2;
-                       }
-               }
-#endif
-
        disp = dseg_add_address(cd, m);
-       M_ALD(REG_ITMP1, REG_PV, disp);
-       M_AST(REG_ITMP1, REG_SP, PA_SIZE + 0 * 8);
-       disp = dseg_add_functionptr(cd, builtin_verbosecall_enter);
+       M_ALD(REG_A0, REG_PV, disp);
+       M_LDA(REG_A1, REG_SP, PA_SIZE);
+       M_LDA(REG_A2, REG_SP, PA_SIZE + (md->paramcount + 2 + TMP_CNT) * 8 + cd->stackframesize * 8);
+       disp = dseg_add_functionptr(cd, trace_java_call_enter);
        M_ALD(REG_ITMP3, REG_PV, disp);
        M_JSR(REG_RA, REG_ITMP3);
        M_NOP;
 
        /* restore argument registers */
 
-       for (i = 0; i < INT_ARG_CNT; i++)
-               M_ALD(abi_registers_integer_argument[i], REG_SP, PA_SIZE + (2 + i) * 8);
-
-       for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DLD(abi_registers_float_argument[i], REG_SP, PA_SIZE + (2 + INT_ARG_CNT + i) * 8);
+       for (i = 0; i < md->paramcount; i++) {
+               if (!md->params[i].inmemory) {
+                       s = md->params[i].regoff;
+                       switch (md->paramtypes[i].type) {
+                       case TYPE_ADR:
+                       case TYPE_INT:
+                               M_ALD(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       case TYPE_LNG:
+                               M_LLD(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       case TYPE_FLT:
+                               M_FLD(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       case TYPE_DBL:
+                               M_DLD(s, REG_SP, PA_SIZE + i * 8);
+                               break;
+                       }
+               }
+       }
 
        /* restore temporary registers for leaf methods */
 
        if (code_is_leafmethod(code)) {
                for (i = 0; i < INT_TMP_CNT; i++)
-                       M_ALD(rd->tmpintregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + i) * 8);
+                       M_ALD(rd->tmpintregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + i) * 8);
 
                for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DLD(rd->tmpfltregs[i], REG_SP, PA_SIZE + (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
+                       M_DLD(rd->tmpfltregs[i], REG_SP, PA_SIZE + (md->paramcount + 2 + INT_TMP_CNT + i) * 8);
        }
 
-       M_ALD(REG_RA, REG_SP, PA_SIZE + 1 * 8);
-       M_LDA(REG_SP, REG_SP, PA_SIZE + (2 + ARG_CNT + TMP_CNT) * 8);
+       /* keep stack 16-byte aligned */
+
+       M_ALD(REG_RA, REG_SP, PA_SIZE + md->paramcount * 8);
+       M_LDA(REG_SP, REG_SP, PA_SIZE + (md->paramcount + 2 + TMP_CNT) * 8);
 
        /* mark trace code */
 
@@ -775,8 +769,6 @@ void emit_verbosecall_enter(jitdata *jd)
 
    Generates the code for the call trace.
 
-   void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
-
 *******************************************************************************/
 
 #if !defined(NDEBUG)
@@ -800,67 +792,68 @@ void emit_verbosecall_exit(jitdata *jd)
 
        M_NOP;
 
-#if SIZEOF_VOID_P == 8
-       M_ASUB_IMM(REG_SP, 4 * 8, REG_SP);          /* keep stack 16-byte aligned */
-       M_AST(REG_RA, REG_SP, 0 * 8);
-
-       M_LST(REG_RESULT, REG_SP, 1 * 8);
-       M_DST(REG_FRESULT, REG_SP, 2 * 8);
+       /* keep stack 16-byte aligned */
 
-       M_MOV(REG_RESULT, REG_A0);
-       M_DMOV(REG_FRESULT, REG_FA1);
-       M_FMOV(REG_FRESULT, REG_FA2);
-
-       disp = dseg_add_address(cd, m);
-       M_ALD(REG_A4, REG_PV, disp);
-#else
-       M_ASUB_IMM(REG_SP, (8*4 + 4 * 8), REG_SP);
-       M_AST(REG_RA, REG_SP, 8*4 + 0 * 8);
+#if SIZEOF_VOID_P == 8
+       assert(0); // XXX: Revisit this code for MIPS64!
+#endif
+       M_ASUB_IMM(REG_SP, PA_SIZE + 2 * 8, REG_SP);
+       M_AST(REG_RA, REG_SP, PA_SIZE + 1 * 8);
 
-       M_LST(REG_RESULT_PACKED, REG_SP, 8*4 + 1 * 8);
-       M_DST(REG_FRESULT, REG_SP, 8*4 + 2 * 8);
+       /* save return value */
 
        switch (md->returntype.type) {
+       case TYPE_ADR:
+       case TYPE_INT:
+               M_AST(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
+               break;
        case TYPE_LNG:
-               M_LNGMOVE(REG_RESULT_PACKED, REG_A0_A1_PACKED);
+#if SIZEOF_VOID_P == 8
+               M_LST(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
+#else
+               M_LST(REG_RESULT_PACKED, REG_SP, PA_SIZE + 0 * 8);
+#endif
                break;
-
-       default:
-# if WORDS_BIGENDIAN == 1
-               M_MOV(REG_ZERO, REG_A0);
-               M_MOV(REG_RESULT, REG_A1);
-# else
-               M_MOV(REG_RESULT, REG_A0);
-               M_MOV(REG_ZERO, REG_A1);
-# endif
+       case TYPE_FLT:
+               M_FST(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
+               break;
+       case TYPE_DBL:
+               M_DST(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
        }
 
-       M_LLD(REG_A2_A3_PACKED, REG_SP, 8*4 + 2 * 8);
-       M_FST(REG_FRESULT, REG_SP, 4*4 + 0 * 4);
-
        disp = dseg_add_address(cd, m);
-       M_ALD(REG_ITMP1, REG_PV, disp);
-       M_AST(REG_ITMP1, REG_SP, 4*4 + 1 * 4);
-#endif
-
-       disp = dseg_add_functionptr(cd, builtin_verbosecall_exit);
+       M_ALD(REG_A0, REG_PV, disp);
+       M_AADD_IMM(REG_SP, PA_SIZE, REG_A1);
+       disp = dseg_add_functionptr(cd, trace_java_call_exit);
        M_ALD(REG_ITMP3, REG_PV, disp);
        M_JSR(REG_RA, REG_ITMP3);
        M_NOP;
 
-#if SIZEOF_VOID_P == 8
-       M_DLD(REG_FRESULT, REG_SP, 2 * 8);
-       M_LLD(REG_RESULT, REG_SP, 1 * 8);
+       /* restore return value */
 
-       M_ALD(REG_RA, REG_SP, 0 * 8);
-       M_AADD_IMM(REG_SP, 4 * 8, REG_SP);
+       switch (md->returntype.type) {
+       case TYPE_ADR:
+       case TYPE_INT:
+               M_ALD(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
+               break;
+       case TYPE_LNG:
+#if SIZEOF_VOID_P == 8
+               M_LLD(REG_RESULT, REG_SP, PA_SIZE + 0 * 8);
 #else
-       M_DLD(REG_FRESULT, REG_SP, 8*4 + 2 * 8);
-       M_LLD(REG_RESULT_PACKED, REG_SP, 8*4 + 1 * 8);
-
-       M_ALD(REG_RA, REG_SP, 8*4 + 0 * 8);
-       M_AADD_IMM(REG_SP, 8*4 + 4 * 8, REG_SP);
+               M_LLD(REG_RESULT_PACKED, REG_SP, PA_SIZE + 0 * 8);
 #endif
+               break;
+       case TYPE_FLT:
+               M_FLD(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
+               break;
+       case TYPE_DBL:
+               M_DLD(REG_FRESULT, REG_SP, PA_SIZE + 0 * 8);
+       }
+
+       /* keep stack 16-byte aligned */
+
+       M_ALD(REG_RA, REG_SP, PA_SIZE + 1 * 8);
+       M_AADD_IMM(REG_SP, PA_SIZE + 2 * 8, REG_SP);
 
        /* mark trace code */
 
index e707d6ee2ec446aa96a1b707175c5c27c8c30cac..eef2a2dc6f272bacbddb5b7c08239f41d36fb8cc 100644 (file)
@@ -45,7 +45,7 @@
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_init *********************************************************************
index 5cf0a3ef3ab059ca9d7ba0127c150d80b096f699..a099a99a132690a18fc275c06b9ecfc270f9a47e 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,7 +43,7 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t result;
        uint32_t temp;
@@ -75,7 +76,7 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
 #if SIZEOF_VOID_P == 8
        uint64_t result;
@@ -98,26 +99,7 @@ inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval,
 
        return result;
 #else
-       return generic_compare_and_swap(p, oldval, newval);
-#endif
-}
-
-
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-#if SIZEOF_VOID_P == 8
-       return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
-#else
-       return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+       return Atomic::generic_compare_and_swap(p, oldval, newval);
 #endif
 }
 
@@ -125,7 +107,7 @@ inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* new
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -134,7 +116,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -143,11 +125,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index 9c6f44ee4c3b264e94da04b39ef6c4be4c4040d2..0846f99410d49e11d2a06a40c7b0323ab6877997 100644 (file)
@@ -43,7 +43,7 @@ void OprofileAgent::initialize(void)
 {
        _handle = op_open_agent();
        if (!_handle)
-               vm_abort_errno("unable to open opagent handle:");
+               os::abort_errno("unable to open opagent handle:");
 }
 
 /**
index 146e52834fd672135a7f368b5f892f7c155368f9..b36e68dadaeddb7ae1a8c32b43545bdeefacd53a 100644 (file)
@@ -70,7 +70,9 @@ typedef struct patcher_function_list_t {
 
 static patcher_function_list_t patcher_function_list[] = {
        { PATCHER_initialize_class,              "initialize_class" },
+#ifdef ENABLE_VERIFIER
        { PATCHER_resolve_class,                 "resolve_class" },
+#endif /* ENABLE_VERIFIER */
        { PATCHER_resolve_native_function,       "resolve_native_function" },
        { PATCHER_invokestatic_special,          "invokestatic_special" },
        { PATCHER_invokevirtual,                 "invokevirtual" },
index 555f0cf8350dcdb650de97d349e35ab4fa183d28..832958f6b990731e06a83d98b066aa10f921f228 100644 (file)
@@ -64,7 +64,7 @@
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
index 9569377aad1d700a664beea758decf578d318057..6065246b943c8de4a401b28c7f928537b8adee51 100644 (file)
@@ -48,7 +48,7 @@
 #include "vm/jit/jit.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load *******************************************************************
index 5d2bf98e4a62ba77153fdddf5cdad099418258b9..3980348dbd1a29c6ace0fd5eddf1975b1d213bb9 100644 (file)
@@ -51,7 +51,7 @@
 #endif
 
 #include "vm/jit/patcher-common.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_signal_handler_sigsegv ***************************************************
index 09a3533e85fb580f1160f9556a2f939866007303..e6240f9097f4786deee3574cc75bff1f587365c9 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,7 +43,7 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t temp;
        uint32_t result;
@@ -73,31 +74,16 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
        return Atomic::generic_compare_and_swap(p, oldval, newval);
 }
 
 
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
-}
-
-
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("sync" : : : "memory");
 }
@@ -106,7 +92,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -114,11 +100,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
        __asm__ __volatile__ ("isync" : : : "memory");
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index 7c609638f81d49574abc9c015c5ecee2967a24bf..4bfc7120698e3ece4147896d3accd50ec5c28e5d 100644 (file)
@@ -64,7 +64,7 @@
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
index 0888baefe8a7696ca8e8db354b53a15ae67eec4d..3009eac9843545bcee8773b63c6a65f490127c61 100644 (file)
@@ -44,7 +44,7 @@
 #include "vm/jit/emit-common.hpp"
 #include "vm/jit/jit.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load *******************************************************************
index 203cb007c24e4e673ae2037242b3dbfa7ac3d79d..25d0b1bf4d19ddfffc47a64763ae45fea8b71e3f 100644 (file)
@@ -50,7 +50,7 @@
 #endif
 
 #include "vm/jit/disass.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_signal_handler_sigsegv ***************************************************
index f469e7515f61b9fccbbd5557311c022ccb9a722c..a72f184100150fb3729ba6657010d7e512d8c54e 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,7 +43,7 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t temp;
        uint32_t result;
@@ -73,7 +74,7 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
        uint64_t temp;
        uint64_t result;
@@ -95,25 +96,10 @@ inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval,
 }
 
 
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
-}
-
-
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("sync" : : : "memory");
 }
@@ -122,7 +108,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -131,11 +117,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction memory barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
        __asm__ __volatile__ ("isync" : : : "memory");
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index 15b564227e38b010872290989fd36e2874bfdd83..fd10194005ec08b1eda76b8b2dd65b2318f47424 100644 (file)
@@ -40,7 +40,7 @@
 #include "vm/global.h"
 
 #include "vm/jit/jit.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* md_init *********************************************************************
index b2780c05b58b1f3705da23e56a1a428e916b49ca..05055ba81b55bf7bf8f0de37697cf6d6f9659e09 100644 (file)
@@ -66,7 +66,7 @@
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* DO__LOG generates a call to do__log. No registers are destroyed,
index f4ed94218354bd2aee426b0a7943eb657343e3ac..0720e1387008dc512f22cb2aa7746bfb5adc7d79 100644 (file)
@@ -49,7 +49,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load *******************************************************************
index fafb6426de1f2491eeafbcf24e3211432e766915..7780ede7cdfe35d68c046f9cf30c1bac254d2f5e 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,7 +43,7 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t ompare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        __asm__ __volatile__ (
                "cs %0,%3,0(%2)\n"
@@ -63,31 +64,16 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t ompare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
-       return generic_compare_and_swap(p, oldval, newval);
-}
-
-
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint32_t*) p, (uint32_t) oldval, (uint32_t) newval);
+       return Atomic::generic_compare_and_swap(p, oldval, newval);
 }
 
 
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void emory_barrier(void)
 {
        __asm__ __volatile__ ("bcr 15,0" : : : "memory" );
 }
@@ -96,7 +82,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void rite_memory_barrier(void)
 {
        memory_barrier();
 }
@@ -104,11 +90,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void nstruction_barrier(void)
 {
        memory_barrier();
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index 0788e45a16cd0ff09be8918b80c1ae3d80960963..bee38bb7d6b37128f6cb7c8f688aa6f51c680986 100644 (file)
@@ -45,7 +45,7 @@
 #include "vm/jit/methodheader.h"
 #include "vm/jit/methodtree.h"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
 #include "vm/options.h" /* XXX debug */
index 97c10e3f6d42808c6329fcf7ff7063ff89a8c606..5f38666e82ed92714fef2bcbe9241d5df31001d2 100644 (file)
@@ -38,7 +38,7 @@
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 typedef struct sigcontext sigcontext;
index 5539c38db0e0b04f22fa4199b4c3a4dc42617ee4..3822152f1f364e583ec1688529c89b2d1c17c757 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
@@ -42,7 +43,9 @@
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+
+}
 {
 #if 0
        // This one should be correct.
@@ -56,7 +59,7 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
 
        return result;
 #else
-       return generic_compare_and_swap(p, oldval, newval);
+       return Atomic::generic_compare_and_swap(p, oldval, newval);
 #endif
 }
 
@@ -70,7 +73,7 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
        uint64_t result;
 
@@ -84,25 +87,10 @@ inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval,
 }
 
 
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
-}
-
-
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("membar 0x0F" : : : "memory" );
 }
@@ -111,7 +99,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("wmb" : : : "memory");
 }
@@ -120,11 +108,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
        __asm__ __volatile__ ("mb" : : : "memory");
 }
 
+}
+
 #endif // _MD_ATOMIC_HPP
 
 
index 8b13aa3f80d2fa1bbd5847e402ee68cf4c06db9b..f6911f670fe62b789c7d4ff5abc8cef2d43e5637 100644 (file)
@@ -41,7 +41,7 @@
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 ptrint md_get_reg_from_context(mcontext_t *_mc, u4 rindex)
diff --git a/src/vm/jit/trap.c b/src/vm/jit/trap.c
deleted file mode 100644 (file)
index a5ab451..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/* 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.h"
-#include "md-trap.h"
-
-#include "mm/memory.hpp"
-
-#include "native/llni.h"
-
-#include "toolbox/logging.hpp"
-
-#include "vm/exceptions.hpp"
-#include "vm/options.h"
-#include "vm/os.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit/asmpart.h"
-#include "vm/jit/code.hpp"
-#include "vm/jit/disass.h"
-#include "vm/jit/executionstate.h"
-#include "vm/jit/jit.hpp"
-#include "vm/jit/methodtree.h"
-#include "vm/jit/patcher-common.hpp"
-#include "vm/jit/replace.hpp"
-#include "vm/jit/stacktrace.hpp"
-
-
-/**
- * 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 = os_getpagesize();
-
-       (void) os_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)
-{
-       executionstate_t  es;
-       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;
-
-#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
-# if !defined(NDEBUG)
-       /* Perform a sanity check on our execution state functions. */
-
-       executionstate_sanity_check(context);
-# endif
-
-       /* Read execution state from current context. */
-
-       es.code = NULL;
-       md_executionstate_read(&es, context);
-#endif
-
-       /* wrap the value into a handle if it is a reference */
-       /* BEFORE: creating stackframeinfo */
-
-       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;
-
-#if defined(ENABLE_REPLACEMENT)
-       case TRAP_COUNTDOWN:
-#if defined(__I386__)
-               replace_me_wrapper((char*)xpc - 13, context);
-#endif
-               p = NULL;
-               break;
-#endif
-
-       default:
-               /* Let's try to get a backtrace. */
-
-               (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);
-
-#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
-       /* Update execution state and set registers. */
-       /* AFTER: removing stackframeinfo */
-
-       switch (type) {
-       case TRAP_COMPILER:
-               // The normal case for a compiler trap is to jump directly to
-               // the newly compiled method.
-
-               if (p != NULL) {
-                       es.pc = (uint8_t *) (uintptr_t) p;
-                       es.pv = (uint8_t *) (uintptr_t) p;
-                       break;
-               }
-
-               // In case of an exception during JIT compilation, we fetch
-               // the exception here and proceed with exception handling.
-
-               java_handle_t *e = exceptions_get_and_clear_exception();
-               assert(e != NULL);
-
-               // Get and set the PV from the parent Java method.
-
-               es.pv = md_codegen_get_pv_from_pc(ra);
-
-               // XXX: Make the code below a fall-through to default case!
-
-               es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(e);
-               es.intregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
-               es.pc                      = (uint8_t *) (uintptr_t) asm_handle_exception;
-               break;
-
-       case TRAP_PATCHER:
-               // The normal case for a patcher trap is to continue execution at
-               // the trap instruction. On some archs the PC may point after the
-               // trap instruction, so we reset it here.
-
-               if (p == NULL) {
-                       es.pc = (uint8_t *) (uintptr_t) xpc;
-                       break;
-               }
-
-               /* fall-through */
-
-       default:
-               if (p != NULL) {
-                       es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(p);
-                       es.intregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
-                       es.pc                      = (uint8_t *) (uintptr_t) asm_handle_exception;
-               }
-       }
-
-       /* Write back execution state to current context. */
-
-       md_executionstate_write(&es, context);
-#endif
-
-       /* unwrap and return the exception object */
-       /* AFTER: removing stackframeinfo */
-
-       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:
- */
diff --git a/src/vm/jit/trap.cpp b/src/vm/jit/trap.cpp
new file mode 100644 (file)
index 0000000..903faf5
--- /dev/null
@@ -0,0 +1,350 @@
+/* src/vm/jit/trap.cpp - 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.h"
+#include "md-trap.h"
+
+#include "mm/memory.hpp"
+
+#include "native/llni.h"
+
+#include "toolbox/logging.hpp"
+
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+#include "vm/jit/code.hpp"
+#include "vm/jit/disass.h"
+#include "vm/jit/executionstate.h"
+#include "vm/jit/jit.hpp"
+#include "vm/jit/methodtree.h"
+#include "vm/jit/patcher-common.hpp"
+#include "vm/jit/replace.hpp"
+#include "vm/jit/stacktrace.hpp"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * 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 = os::getpagesize();
+
+       (void) os::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)
+{
+       executionstate_t es;
+       stackframeinfo_t sfi;
+
+#if !defined(NDEBUG)
+       if (opt_TraceTraps)
+               log_println("[trap_handle: type=%d, val=%p, pv=%p, sp=%p, ra=%p, xpc=%p]", type, val, pv, sp, ra, xpc);
+#endif
+       
+#if defined(ENABLE_VMLOG)
+       vmlog_cacao_signl_type(type);
+#endif
+
+       /* Prevent compiler warnings. */
+
+       java_handle_t* o = NULL;
+       methodinfo*    m = NULL;
+
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
+# if !defined(NDEBUG)
+       /* Perform a sanity check on our execution state functions. */
+
+       executionstate_sanity_check(context);
+# endif
+
+       /* Read execution state from current context. */
+
+       es.code = NULL;
+       md_executionstate_read(&es, context);
+
+//# define TRAPS_VERBOSE
+# if !defined(NDEBUG) && defined(TRAPS_VERBOSE)
+       /* Dump contents of execution state */
+
+       if (opt_TraceTraps) {
+               log_println("[trap_handle: dumping execution state BEFORE ...]");
+               executionstate_println(&es);
+       }
+# endif
+#endif
+
+       /* Do some preparations before we enter the nativeworld. */
+       /* BEFORE: creating stackframeinfo */
+
+       switch (type) {
+       case TRAP_ClassCastException:
+               /* Wrap the value into a handle, as it is a reference. */
+
+               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);
+
+       /* Get resulting exception (or pointer to compiled method). */
+
+       int32_t        index;
+       java_handle_t* p;
+       void*          entry;
+
+       switch (type) {
+       case TRAP_NullPointerException:
+               p = exceptions_new_nullpointerexception();
+               break;
+
+       case TRAP_ArithmeticException:
+               p = exceptions_new_arithmeticexception();
+               break;
+
+       case TRAP_ArrayIndexOutOfBoundsException:
+               index = (int32_t) 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((uint8_t*) xpc, context)) {
+                       p = NULL;
+                       break;
+               }
+#endif
+               p = patcher_handler((uint8_t*) xpc);
+               break;
+
+       case TRAP_COMPILER:
+               entry = jit_compile_handle(m, sfi.pv, ra, (void*) val);
+               p = NULL;
+               break;
+
+#if defined(ENABLE_REPLACEMENT)
+       case TRAP_COUNTDOWN:
+# if defined(__I386__)
+               replace_me_wrapper((char*)xpc - 13, context);
+# endif
+               p = NULL;
+               break;
+#endif
+
+       default:
+               /* Let's try to get a backtrace. */
+
+               (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((uint8_t*) xpc);
+#endif
+
+               vm_abort("Exiting...");
+
+               /* keep compiler happy */
+
+               p = NULL;
+       }
+
+       /* Remove stackframeinfo. */
+
+       stacktrace_stackframeinfo_remove(&sfi);
+
+#if defined(__ALPHA__) || defined(__ARM__) || defined(__I386__) || defined(__POWERPC__) || defined(__POWERPC64__) || defined(__X86_64__)
+       /* Update execution state and set registers. */
+       /* AFTER: removing stackframeinfo */
+
+       switch (type) {
+       case TRAP_COMPILER:
+               // The normal case for a compiler trap is to jump directly to
+               // the newly compiled method.
+
+               if (entry != NULL) {
+                       es.pc = (uint8_t *) (uintptr_t) entry;
+                       es.pv = (uint8_t *) (uintptr_t) entry;
+                       break;
+               }
+
+               // In case of an exception during JIT compilation, we fetch
+               // the exception here and proceed with exception handling.
+
+               p = exceptions_get_and_clear_exception();
+               assert(p != NULL);
+
+               // Get and set the PV from the parent Java method.
+
+               es.pv = (uint8_t *) md_codegen_get_pv_from_pc(ra);
+
+               // Now fall-through to default exception handling.
+
+               goto trap_handle_exception;
+
+       case TRAP_PATCHER:
+               // The normal case for a patcher trap is to continue execution at
+               // the trap instruction. On some archs the PC may point after the
+               // trap instruction, so we reset it here.
+
+               if (p == NULL) {
+                       es.pc = (uint8_t *) (uintptr_t) xpc;
+                       break;
+               }
+
+               // Fall-through to default exception handling.
+
+       trap_handle_exception:
+       default:
+               if (p != NULL) {
+                       es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(p);
+                       es.intregs[REG_ITMP2_XPC]  = (uintptr_t) xpc;
+                       es.pc                      = (uint8_t *) (uintptr_t) asm_handle_exception;
+               }
+       }
+
+       /* Write back execution state to current context. */
+
+       md_executionstate_write(&es, context);
+
+# if !defined(NDEBUG) && defined(TRAPS_VERBOSE)
+       /* Dump contents of execution state */
+
+       if (opt_TraceTraps) {
+               log_println("[trap_handle: dumping execution state AFTER ...]");
+               executionstate_println(&es);
+       }
+# endif
+#endif
+
+       /* Unwrap and return the exception object. */
+       /* AFTER: removing stackframeinfo */
+
+       if (type == TRAP_COMPILER)
+               return entry;
+       else
+               return LLNI_UNWRAP(p);
+}
+
+#ifdef __cplusplus
+}
+#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:
+ */
diff --git a/src/vm/jit/trap.h b/src/vm/jit/trap.h
deleted file mode 100644 (file)
index 6a18c35..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/* 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>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* 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);
-
-#ifdef __cplusplus
-}
-#endif
-
-#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:
- */
diff --git a/src/vm/jit/trap.hpp b/src/vm/jit/trap.hpp
new file mode 100644 (file)
index 0000000..ce0c044
--- /dev/null
@@ -0,0 +1,66 @@
+/* src/vm/jit/trap.hpp - 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_HPP
+#define _TRAP_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TRAP_HPP */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 80c81af88b5c59ba9345d556d9b92f0adf58839d..0265db4591d859fb38544b217366a21eb613f8db 100644 (file)
@@ -68,7 +68,7 @@
 #include "vm/jit/reg.h"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_LSRA)
 # include "vm/jit/allocator/lsra.h"
index 5f6f0d87a76fcfa7323255f0f2b4ba83246806a5..778f74916edf10cd220470cc72c64fad6243a1e0 100644 (file)
@@ -48,7 +48,7 @@
 #include "vm/jit/patcher-common.hpp"
 #include "vm/jit/replace.hpp"
 #include "vm/jit/trace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 
 /* emit_load *******************************************************************
index 1c30b8bbf94fac72d746b7f3256e047461f258f6..ca42a1926749c1b32914fee6f36e6f4fe16db3be 100644 (file)
@@ -44,7 +44,7 @@
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 
index accef01af052a3cf426f335c05b12df494923042..d5d98a0c270ce3c0d0baee35e953d8d082e3fcdf 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "threads/atomic.hpp"
 
+namespace Atomic_md {
 
 /**
  * An atomic compare and swap for 32-bit integer values.
  *
  * @return value of the memory location before the store
  */
-inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
+inline uint32_t compare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
 {
        uint32_t result;
 
        __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
                                                  : "=a" (result), "=m" (*p)
-                                                 : "r" (newval), "m" (*p), "0" (oldval));
+                                                 : "r" (newval), "m" (*p), "0" (oldval)
+                                                 : "cc");
 
        return result;
 }
@@ -63,37 +65,23 @@ inline uint32_t Atomic::compare_and_swap(volatile uint32_t *p, uint32_t oldval,
  *
  * @return value of the memory location before the store
  */
-inline uint64_t Atomic::compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
+inline uint64_t compare_and_swap(volatile uint64_t *p, uint64_t oldval, uint64_t newval)
 {
        uint64_t result;
 
        __asm__ __volatile__ ("lock; cmpxchgq %2, %1"
                                                  : "=a" (result), "=m" (*p)
-                                                 : "r" (newval), "m" (*p), "0" (oldval));
+                                                 : "r" (newval), "m" (*p), "0" (oldval)
+                                                 : "cc");
 
        return result;
 }
 
 
-/**
- * An atomic compare and swap for pointer values.
- *
- * @param p      Pointer to memory address.
- * @param oldval Old value to be expected.
- * @param newval New value to be stored.
- *
- * @return value of the memory location before the store
- */
-inline void* Atomic::compare_and_swap(volatile void** p, void* oldval, void* newval)
-{
-       return (void*) compare_and_swap((volatile uint64_t*) p, (uint64_t) oldval, (uint64_t) newval);
-}
-
-
 /**
  * A memory barrier.
  */
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
 {
        __asm__ __volatile__ ("mfence" : : : "memory");
 }
@@ -102,7 +90,7 @@ inline void Atomic::memory_barrier(void)
 /**
  * A write memory barrier.
  */
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
 {
        __asm__ __volatile__ ("" : : : "memory");
 }
@@ -111,9 +99,13 @@ inline void Atomic::write_memory_barrier(void)
 /**
  * An instruction barrier.
  */
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
 {
-       // Nothing.
+       // We need the "memory" constraint here because compare_and_swap does not
+       // have it.
+       __asm__ __volatile__ ("" : : : "memory");
+}
+
 }
 
 #endif // _MD_ATOMIC_HPP
index cce569be9344dbbb9bc937103d9c7d1e99efb58e..6ff3c49dc936a85874d7aa2021cc469a1ae16d2c 100644 (file)
@@ -42,7 +42,7 @@
 
 #include "vm/jit/asmpart.h"
 #include "vm/jit/executionstate.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 #include "vm/jit/stacktrace.hpp"
 
 
@@ -295,6 +295,22 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
        xpc = (u1 *) _mc->gregs[REG_RIP];
        ra  = xpc;                          /* return address is equal to xpc     */
 
+       // Check if the trap instruction is valid.
+       // TODO Move this into patcher_handler.
+       if (patcher_is_valid_trap_instruction_at(xpc) == false) {
+               // Check if the PC has been patched during our way to this
+               // signal handler (see PR85).
+               if (patcher_is_patched_at(xpc) == true)
+                       return;
+
+               // We have a problem...
+               log_println("md_signal_handler_sigill: Unknown illegal instruction at 0x%lx", xpc);
+#if defined(ENABLE_DISASSEMBLER)
+               (void) disassinstr(xpc);
+#endif
+               vm_abort("Aborting...");
+       }
+
        /* This is a patcher. */
 
        type = TRAP_PATCHER;
index 7bc8ff4a177568738f2648857c824ef74c470099..083f00b30a7f8d2e6fa034fa7dc286af018de523 100644 (file)
@@ -100,9 +100,12 @@ void loader_preinit(void)
        TRACESUBSYSTEMINITIALIZATION("loader_preinit");
 
 #if defined(ENABLE_THREADS)
+       // Get current list of classpath entries.
+       SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
+
        /* Initialize the monitor pointer for zip/jar file locking. */
 
-       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+       for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end(); it++) {
                list_classpath_entry* lce = *it;
 
                if (lce->type == CLASSPATH_ARCHIVE)
@@ -398,7 +401,10 @@ void loader_load_all_classes(void)
        utf                     *u;
 #endif
 
-       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end(); it++) {
+       // Get current list of classpath entries.
+       SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
+
+       for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end(); it++) {
                list_classpath_entry* lce = *it;
 
 #if defined(ENABLE_ZLIB)
index b5b88a710336ff78ef428488af5da03a10489230..7ead267c6ef226f565a64d5ebd62b6508efdf35f 100644 (file)
@@ -62,7 +62,6 @@ s4   opt_stacksize     = 0;     /* thread stack size                          */
 
 bool opt_verbose = false;
 bool opt_debugcolor = false;   /* use ANSI terminal sequences                */
-bool compileall = false;
 
 bool loadverbose = false;
 bool initverbose = false;
@@ -76,9 +75,6 @@ bool showmethods = false;
 bool showconstantpool = false;
 bool showutf = false;
 
-char *opt_method = NULL;
-char *opt_signature = NULL;
-
 bool compileverbose =  false;           /* trace compiler actions             */
 bool showstack = false;
 
@@ -161,6 +157,9 @@ int      opt_ThreadStackSize              = 0;
 /* Debugging options which can be turned off. */
 
 bool     opt_AlwaysEmitLongBranches       = false;
+int      opt_CompileAll                   = 0;
+char*    opt_CompileMethod                = NULL;
+char*    opt_CompileSignature             = NULL;
 int      opt_DebugExceptions              = 0;
 int      opt_DebugFinalizer               = 0;
 int      opt_DebugLocalReferences         = 0;
@@ -232,6 +231,9 @@ enum {
        /* Debugging options which can be turned off. */
 
        OPT_AlwaysEmitLongBranches,
+       OPT_CompileAll,
+       OPT_CompileMethod,
+       OPT_CompileSignature,
        OPT_DebugExceptions,
        OPT_DebugFinalizer,
        OPT_DebugLocalReferences,
@@ -286,6 +288,9 @@ option_t options_XX[] = {
        /* Debugging options which can be turned off. */
 
        { "AlwaysEmitLongBranches",       OPT_AlwaysEmitLongBranches,       OPT_TYPE_BOOLEAN, "Always emit long-branches." },
+       { "CompileAll",                   OPT_CompileAll,                   OPT_TYPE_BOOLEAN, "compile all methods, no execution" },
+       { "CompileMethod",                OPT_CompileMethod,                OPT_TYPE_VALUE,   "compile only a specific method" },
+       { "CompileSignature",             OPT_CompileSignature,             OPT_TYPE_VALUE,   "specify signature for a specific method" },
        { "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" },
@@ -622,6 +627,22 @@ void options_xx(JavaVMInitArgs *vm_args)
                        opt_AlwaysEmitLongBranches = enable;
                        break;
 
+               case OPT_CompileAll:
+                       opt_CompileAll = enable;
+                       opt_run = false;
+                       makeinitializations = false;
+                       break;
+
+               case OPT_CompileMethod:
+                       opt_CompileMethod = value;
+                       opt_run = false;
+                       makeinitializations = false;
+                       break;
+
+               case OPT_CompileSignature:
+                       opt_CompileSignature = value;
+                       break;
+
                case OPT_DebugExceptions:
                        opt_DebugExceptions = enable;
                        break;
@@ -743,7 +764,9 @@ void options_xx(JavaVMInitArgs *vm_args)
                        file = fopen(filename, "w");
 
                        if (file == NULL)
-                               vm_abort_errno("options_xx: fopen failed");
+#warning Use below method instead!
+                               //os::abort_errno("options_xx: fopen failed");
+                               vm_abort("options_xx: fopen failed");
 
                        opt_ProfileMemoryUsageGNUPlot = file;
                        break;
index 1758add5c3a757ba8858a35ad51f1177f1d29667..18c1c0013ebe8e04af82c0b06544a5f953b11d5c 100644 (file)
@@ -88,7 +88,6 @@ extern s4   opt_stacksize;
 
 extern bool opt_verbose;
 extern bool opt_debugcolor;
-extern bool compileall;
 
 extern bool loadverbose;         /* Print debug messages during loading */
 extern bool initverbose;         /* Log class initialization */ 
@@ -102,9 +101,6 @@ extern bool showmethods;
 extern bool showconstantpool;
 extern bool showutf;
 
-extern char *opt_method;
-extern char *opt_signature;
-
 extern bool compileverbose;
 extern bool showstack;
 
@@ -183,6 +179,9 @@ extern int      opt_ThreadStackSize;
 /* Debugging options which can be turned off. */
 
 extern bool     opt_AlwaysEmitLongBranches;
+extern int      opt_CompileAll;
+extern char*    opt_CompileMethod;
+extern char*    opt_CompileSignature;
 extern int      opt_DebugExceptions;
 extern int      opt_DebugFinalizer;
 extern int      opt_DebugLocalReferences;
index 15d6263b6cd2d9d798fdf36886853843f6b981d1..9bfe3da3de9a83abfa6f80b206bd960e0a2adc39 100644 (file)
@@ -50,6 +50,7 @@
 #include "vm/globals.hpp"
 #include "vm/method.hpp"
 #include "vm/options.h"
+#include "vm/os.hpp"
 #include "vm/signallocal.hpp"
 #include "vm/vm.hpp"
 
@@ -86,22 +87,22 @@ bool signal_init(void)
           this thread. */
 
        if (sigemptyset(&mask) != 0)
-               vm_abort_errno("signal_init: sigemptyset failed");
+               os::abort_errno("signal_init: sigemptyset failed");
 
 #if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
        /* Let OpenJDK handle SIGINT itself. */
 
        if (sigaddset(&mask, SIGINT) != 0)
-               vm_abort_errno("signal_init: sigaddset failed");
+               os::abort_errno("signal_init: sigaddset failed");
 #endif
 
 #if !defined(__FREEBSD__)
        if (sigaddset(&mask, SIGQUIT) != 0)
-               vm_abort_errno("signal_init: sigaddset failed");
+               os::abort_errno("signal_init: sigaddset failed");
 #endif
 
        if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0)
-               vm_abort_errno("signal_init: sigprocmask failed");
+               os::abort_errno("signal_init: sigprocmask failed");
 
 #if defined(__LINUX__) && defined(ENABLE_THREADS)
        /* XXX Remove for exact-GC. */
@@ -229,13 +230,13 @@ void signal_register_signal(int signum, functionptr handler, int flags)
        function = (void (*)(int, siginfo_t *, void *)) handler;
 
        if (sigemptyset(&act.sa_mask) != 0)
-               vm_abort_errno("signal_register_signal: sigemptyset failed");
+               os::abort_errno("signal_register_signal: sigemptyset failed");
 
        act.sa_sigaction = function;
        act.sa_flags     = flags;
 
        if (sigaction(signum, &act, NULL) != 0)
-               vm_abort_errno("signal_register_signal: sigaction failed");
+               os::abort_errno("signal_register_signal: sigaction failed");
 }
 
 
@@ -257,18 +258,18 @@ static void signal_thread(void)
        t = THREADOBJECT;
 
        if (sigemptyset(&mask) != 0)
-               vm_abort_errno("signal_thread: sigemptyset failed");
+               os::abort_errno("signal_thread: sigemptyset failed");
 
 #if !defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
        /* Let OpenJDK handle SIGINT itself. */
 
        if (sigaddset(&mask, SIGINT) != 0)
-               vm_abort_errno("signal_thread: sigaddset failed");
+               os::abort_errno("signal_thread: sigaddset failed");
 #endif
 
 #if !defined(__FREEBSD__)
        if (sigaddset(&mask, SIGQUIT) != 0)
-               vm_abort_errno("signal_thread: sigaddset failed");
+               os::abort_errno("signal_thread: sigaddset failed");
 #endif
 
        for (;;) {
@@ -285,7 +286,7 @@ static void signal_thread(void)
                } while (result == EINTR);
 
                if (result != 0)
-                       vm_abort_errnum(result, "signal_thread: sigwait failed");
+                       os::abort_errnum(result, "signal_thread: sigwait failed");
 
 #if defined(ENABLE_THREADS)
                thread_set_state_runnable(t);
index 1c801c5636fb2756ec89acb067fdc5ed7e0d8247..ecf0a70c3ee5ed2927469e430692661fe3d54b0e 100644 (file)
 #include "vm/zip.hpp"
 
 
-/* global variables ***********************************************************/
-
-List<list_classpath_entry*>* list_classpath_entries;
-
-
-/* suck_init *******************************************************************
-
-   Initializes the suck subsystem like initializing the classpath
-   entries list.
-
-*******************************************************************************/
-
-bool suck_init(void)
-{
-       TRACESUBSYSTEMINITIALIZATION("suck_init");
-
-#warning Move this list into VM.
-       list_classpath_entries = new List<list_classpath_entry*>();
-
-       /* everything's ok */
-
-       return true;
-}
-
-
 /* scandir_filter **************************************************************
 
    Filters for zip/jar files.
@@ -99,13 +74,10 @@ static int scandir_filter(const struct dirent *a)
 }
 
 
-/* suck_add ********************************************************************
-
-   Adds a classpath to the global classpath entries list.
-
-*******************************************************************************/
-
-void suck_add(char *classpath)
+/**
+ * Adds a classpath to the global classpath entries list.
+ */
+void SuckClasspath::add(char *classpath)
 {
        list_classpath_entry *lce;
        char                 *start;
@@ -206,7 +178,7 @@ void suck_add(char *classpath)
                        /* add current classpath entry, if no error */
 
                        if (lce != NULL)
-                               list_classpath_entries->push_back(lce);
+                               push_back(lce);
                }
 
                /* goto next classpath entry, skip ':' delimiter */
@@ -219,14 +191,11 @@ void suck_add(char *classpath)
 }
 
 
-/* suck_add_from_property ******************************************************
-
-   Adds a classpath form a property entry to the global classpath
-   entries list.
-
-*******************************************************************************/
-
-void suck_add_from_property(const char *key)
+/**
+ * Adds a classpath form a property entry to the global classpath
+ * entries list.
+ */
+void SuckClasspath::add_from_property(const char *key)
 {
        const char     *value;
        const char     *start;
@@ -516,9 +485,12 @@ classbuffer *suck_start(classinfo *c)
        utf_copy(filename, c->name);
        strcat(filename, ".class");
 
+       // Get current list of classpath entries.
+       SuckClasspath& suckclasspath = VM::get_current()->get_suckclasspath();
+
        /* walk through all classpath entries */
 
-       for (List<list_classpath_entry*>::iterator it = list_classpath_entries->begin(); it != list_classpath_entries->end() && cb == NULL; it++) {
+       for (SuckClasspath::iterator it = suckclasspath.begin(); it != suckclasspath.end() && cb == NULL; it++) {
                lce = *it;
 
 #if defined(ENABLE_ZLIB)
index 20e2580518a807ef4d7e069805237284dc192943..ff7077387636fb569662d9639708ad8210335707 100644 (file)
 
 #include "config.h"
 
+#ifdef __cplusplus
+#include <list>
+#endif
+
 #include "vm/types.h"
 
 #include "threads/mutex.hpp"
 
 #include "toolbox/hashtable.h"
-#include "toolbox/list.hpp"
 
 #include "vm/class.hpp"
 #include "vm/global.h"
@@ -47,9 +50,7 @@ enum {
        CLASSPATH_ARCHIVE
 };
 
-typedef struct list_classpath_entry list_classpath_entry;
-
-struct list_classpath_entry {
+typedef struct list_classpath_entry {
 #if defined(ENABLE_THREADS)
        Mutex             *mutex;               /* mutex locking on zip/jar files */
 #endif
@@ -59,8 +60,28 @@ struct list_classpath_entry {
 #if defined(ENABLE_ZLIB)
        hashtable         *htclasses;
 #endif
+} list_classpath_entry;
+
+
+#ifdef __cplusplus
+
+/**
+ * Classpath entries list.
+ */
+class SuckClasspath : protected std::list<list_classpath_entry*> {
+public:
+       void add(char *classpath);
+       void add_from_property(const char *key);
+
+       // make iterator of std::list visible
+       using std::list<list_classpath_entry*>::iterator;
+
+       // make functions of std::list visible
+       using std::list<list_classpath_entry*>::begin;
+       using std::list<list_classpath_entry*>::end;
 };
 
+#endif
 
 /* macros to read LE and BE types from a buffer ********************************
 
@@ -148,25 +169,12 @@ struct list_classpath_entry {
 #define suck_s8(a)    (s8) suck_u8((a))
 
 
-/* export variables ***********************************************************/
-
-#ifdef __cplusplus
-extern List<list_classpath_entry*>* list_classpath_entries;
-#else
-extern List* list_classpath_entries;
-#endif
-
 /* function prototypes ********************************************************/
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-bool suck_init(void);
-
-void suck_add(char *classpath);
-void suck_add_from_property(const char *key);
-
 bool suck_check_classbuffer_size(classbuffer *cb, s4 len);
 
 u1 suck_u1(classbuffer *cb);
index 497d75490a2d2f61cf2bba6d2c900b78d2006c17..23518fd85435b4100e6971781c716dd0c7f632b0 100644 (file)
 # include "vm/jit/python.h"
 #endif
 
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
 
 #if defined(ENABLE_JVMTI)
 # include "native/jvmti/cacaodbg.h"
@@ -206,12 +206,6 @@ enum {
        OPT_SHOW,
        OPT_DEBUGCOLOR,
 
-#if !defined(NDEBUG)
-       OPT_ALL,
-       OPT_METHOD,
-       OPT_SIGNATURE,
-#endif
-
 #if defined(ENABLE_VERIFIER)
        OPT_NOVERIFY,
        OPT_XVERIFY_ALL,
@@ -325,11 +319,6 @@ opt_struct opts[] = {
        { "c",                 true,  OPT_CHECK },
        { "l",                 false, OPT_LOAD },
 
-#if !defined(NDEBUG)
-       { "all",               false, OPT_ALL },
-       { "sig",               true,  OPT_SIGNATURE },
-#endif
-
 #if defined(ENABLE_LOOP)
        { "oloop",             false, OPT_OLOOP },
 #endif
@@ -390,10 +379,6 @@ opt_struct opts[] = {
 
        /* keep these at the end of the list */
 
-#if !defined(NDEBUG)
-       { "m",                 true,  OPT_METHOD },
-#endif
-
        { "s",                 true,  OPT_SHOW },
        { "debug-color",      false,  OPT_DEBUGCOLOR },
 
@@ -525,11 +510,6 @@ static void XXusage(void)
        puts("    -oloop                   optimize array accesses in loops");
 #endif
        puts("    -l                       don't start the class after loading");
-#if !defined(NDEBUG)
-       puts("    -all                     compile all methods, no execution");
-       puts("    -m                       compile only a specific method");
-       puts("    -sig                     specify signature for a specific method");
-#endif
 
        puts("    -s...                    show...");
        puts("      (c)onstants            the constant pool");
@@ -1084,24 +1064,6 @@ VM::VM(JavaVMInitArgs* vm_args)
                        makeinitializations = false;
                        break;
 
-#if !defined(NDEBUG)
-               case OPT_ALL:
-                       compileall = true;
-                       opt_run = false;
-                       makeinitializations = false;
-                       break;
-
-               case OPT_METHOD:
-                       opt_run = false;
-                       opt_method = opt_arg;
-                       makeinitializations = false;
-                       break;
-
-               case OPT_SIGNATURE:
-                       opt_signature = opt_arg;
-                       break;
-#endif
-
                case OPT_SHOW:       /* Display options */
                        for (unsigned int i = 0; i < strlen(opt_arg); i++) {            
                                switch (opt_arg[i]) {
@@ -1370,10 +1332,7 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        /* AFTER: thread_preinit */
 
-       if (!suck_init())
-               os::abort("vm_create: suck_init failed");
-
-       suck_add_from_property("java.endorsed.dirs");
+       _suckclasspath.add_from_property("java.endorsed.dirs");
 
        /* Now we have all options handled and we can print the version
           information.
@@ -1387,7 +1346,7 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        // FIXME Make boot_class_path const char*.
        boot_class_path = (char*) _properties.get("sun.boot.class.path");
-       suck_add(boot_class_path);
+       _suckclasspath.add(boot_class_path);
 
        /* initialize the classcache hashtable stuff: lock, hashtable
           (must be done _after_ threads_preinit) */
@@ -1472,7 +1431,8 @@ VM::VM(JavaVMInitArgs* vm_args)
        /* Initialize the native VM subsystem. */
        /* AFTER: threads_init (at least for SUN's classes) */
 
-       nativevm_init();
+       if (!nativevm_init())
+               os::abort("vm_create: nativevm_init failed");
 
 #if defined(ENABLE_PROFILING)
        /* initialize profiling */
@@ -1621,7 +1581,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
        int         status;
 
 #if !defined(NDEBUG)
-       if (compileall) {
+       if (opt_CompileAll) {
                vm_compile_all();
                return;
        }
@@ -1667,7 +1627,7 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
                usage();
 
 #if !defined(NDEBUG)
-       if (opt_method != NULL) {
+       if (opt_CompileMethod != NULL) {
                vm_compile_method(mainname);
                return;
        }
@@ -2259,16 +2219,16 @@ static void vm_compile_method(char* mainname)
        if (!link_class(mainclass))
                exceptions_print_stacktrace();
 
-       if (opt_signature != NULL) {
+       if (opt_CompileSignature != NULL) {
                m = class_resolveclassmethod(mainclass,
-                                                                        utf_new_char(opt_method),
-                                                                        utf_new_char(opt_signature),
+                                                                        utf_new_char(opt_CompileMethod),
+                                                                        utf_new_char(opt_CompileSignature),
                                                                         mainclass,
                                                                         false);
        }
        else {
                m = class_resolveclassmethod(mainclass,
-                                                                        utf_new_char(opt_method),
+                                                                        utf_new_char(opt_CompileMethod),
                                                                         NULL,
                                                                         mainclass,
                                                                         false);
@@ -2276,7 +2236,7 @@ static void vm_compile_method(char* mainname)
 
        if (m == NULL)
                os::abort("vm_compile_method: java.lang.NoSuchMethodException: %s.%s",
-                                opt_method, opt_signature ? opt_signature : "");
+                                opt_CompileMethod, opt_CompileSignature ? opt_CompileSignature : "");
                
        jit_compile(m);
 }
@@ -2556,27 +2516,22 @@ void vm_abort(const char* text, ...)
 {
        va_list ap;
 
-       va_start(ap, text);
-       os::abort(text, ap);
-       va_end(ap);
-}
+       log_println("vm_abort: WARNING, port me to C++ and use os::abort() instead.");
 
-void vm_abort_errnum(int errnum, const char* text, ...)
-{
-       va_list ap;
+       // Print the log message.
+       log_start();
 
        va_start(ap, text);
-       os::abort_errnum(errnum, text, ap);
+       log_vprint(text, ap);
        va_end(ap);
-}
 
-void vm_abort_errno(const char* text, ...)
-{
-       va_list ap;
+       log_finish();
 
-       va_start(ap, text);
-       os::abort_errno(text, ap);
-       va_end(ap);
+       // Print a backtrace.
+       os::print_backtrace();
+
+       // Now abort the VM.
+       os::abort();
 }
 
 }
index 4a73ecc351cc86456f08dba13ef3d366d3267745..30242d4f07e6b604d212c121d4f6059b27269307 100644 (file)
@@ -41,6 +41,7 @@
 #endif
 
 #include "vm/properties.hpp"
+#include "vm/suck.hpp"
 
 #include "vm/jit/optimizing/recompiler.hpp"
 
@@ -76,6 +77,7 @@ private:
 #endif
        NativeLibraries _nativelibraries; ///< Native library table.
        NativeMethods   _nativemethods;   ///< Native methods table.
+       SuckClasspath   _suckclasspath;   ///< Classpath entries list.
 
 public:
        // Constructor, Destructor.
@@ -105,6 +107,7 @@ public:
 #endif
        NativeLibraries& get_nativelibraries() { return _nativelibraries; }
        NativeMethods&   get_nativemethods  () { return _nativemethods; }
+       SuckClasspath&   get_suckclasspath  () { return _suckclasspath; }
 };
 
 #else
@@ -190,8 +193,6 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o, java_
 
 // Legacy C interface.
 void vm_abort(const char* text, ...);
-void vm_abort_errnum(int errnum, const char* text, ...);
-void vm_abort_errno(const char* text, ...);
 
 #ifdef __cplusplus
 }
diff --git a/tests/TestArrayClasses.java b/tests/TestArrayClasses.java
deleted file mode 100644 (file)
index a3d6914..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-import java.io.Serializable;
-
-public class TestArrayClasses extends TestBase {
-  public static class Foo {
-  }
-
-  public static class FooChild extends Foo {
-  }
-  
-  public static void test_store(Object[] array,Object obj,boolean oktostore,String msg) {
-    try {
-      array[0] = obj;
-      ok(oktostore,msg);
-    }
-    catch (ArrayStoreException x) {
-      System.out.println("    ArrayStoreException");
-      ok(!oktostore,msg);
-    }
-  }
-
-  public static void test_clone() {
-    int[] ia1 = new int[100];
-    Integer[] Ia1 = new Integer[ia1.length];
-    int i;
-    
-    for (i=0; i<ia1.length; ++i) {
-      ia1[i] = i*i;
-      Ia1[i] = new Integer(ia1[i]);
-    }
-
-    int[] ia2 = (int[]) ia1.clone();
-
-    is(ia2.length,ia1.length,"cloned int array length");
-
-    boolean eq = true;
-    for (i=0; i<ia1.length; ++i) {
-      if (ia2[i] != ia1[i])
-        eq = false;
-      //      System.out.println(ia2[i]);
-    }
-    ok(eq,"cloned int array data");
-
-    Integer[] Ia2 = (Integer[]) Ia1.clone();
-    
-    is(Ia2.length,Ia1.length,"cloned Integer array length");
-    
-    eq = true;
-    for (i=0; i<ia1.length; ++i) {
-      if (Ia2[i].intValue() != ia1[i])
-        eq = false;
-      //      System.out.println(ia2[i]);
-    }
-    ok(eq,"cloned Integer array data");
-  }
-
-  public static void test_arraycopy() {
-    int len;
-    int i;
-
-    long[] la1 = new long[1024];
-    long[] la2 = (long[]) la1.clone();
-    int size = la1.length;
-    Long[] La1 = new Long[size];
-    Long[] La2 = (Long[]) La1.clone();
-    Number[] Na2 = new Number[size];
-
-    for (i=0; i<la1.length; ++i) {
-      la1[i] = i*i;
-      La1[i] = new Long(la1[i]);
-    }
-
-    i = size;
-    while (i>1) {
-      if ((i & 1) != 0)
-        System.err.println("ERROR: arracopy test only works for powers of two");
-      i >>= 1;
-    }
-    
-    // reverse array
-    len = size / 2;
-    while (len>0) {
-      for (int j=0;j<(size/2)/len;++j) {
-        //        System.err.println(len);
-        //        System.err.println(j);
-        System.arraycopy(la1,(2*j+1)*len,la2,2*j*len,len);
-        System.arraycopy(la1,2*j*len,la1,(2*j+1)*len,len);
-        System.arraycopy(la2,2*j*len,la1,2*j*len,len);
-      }
-      len /= 2;
-    }
-
-    boolean eq = true;
-    for (i=0; i<size; ++i) {
-      if (la1[i] != (size-i-1)*(size-i-1))
-        eq = false;
-      //      System.out.println(la1[i]);
-    }
-    ok(eq,"arraycopy primitive");
-    
-    // reverse array
-    len = size / 2;
-    while (len>0) {
-      for (int j=0;j<(size/2)/len;++j) {
-        //        System.err.println(len);
-        //        System.err.println(j);
-        System.arraycopy(La1,(2*j+1)*len,La2,2*j*len,len);
-        System.arraycopy(La1,2*j*len,La1,(2*j+1)*len,len);
-        System.arraycopy(La2,2*j*len,La1,2*j*len,len);
-      }
-      len /= 2;
-    }
-
-    eq = true;
-    for (i=0; i<size; ++i) {
-      if (La1[i].intValue() != (size-i-1)*(size-i-1))
-        eq = false;
-    }
-    ok(eq,"arraycopy ref");
-    
-    // reverse array
-    len = size / 2;
-    while (len>0) {
-      for (int j=0;j<(size/2)/len;++j) {
-        //        System.err.println(len);
-        //        System.err.println(j);
-        System.arraycopy(La1,(2*j+1)*len,Na2,2*j*len,len);
-        System.arraycopy(La1,2*j*len,La1,(2*j+1)*len,len);
-        System.arraycopy(Na2,2*j*len,La1,2*j*len,len);
-      }
-      len /= 2;
-    }
-
-    eq = true;
-    for (i=0; i<size; ++i) {
-      if (La1[i].intValue() != i*i)
-        eq = false;
-    }
-    ok(eq,"arraycopy ref different classes");
-
-    Integer[] Ia = new Integer[size];
-
-    try {
-      System.arraycopy(Ia,0,Na2,0,1);
-      ok(true,"arraycopy Integer to Number");
-    }
-    catch (ArrayStoreException x) {
-      System.out.println("    ArrayStoreException");
-      ok(false,"arraycopy Integer to Number");
-    }
-
-    try {
-      System.arraycopy(Na2,1,Ia,1,1);
-      ok(false,"!arraycopy Number to Integer");
-    }
-    catch (ArrayStoreException x) {
-      System.out.println("    ArrayStoreException");
-      ok(true,"!arraycopy Number to Integer");
-    }
-  }
-  
-  public static void main(String[] args) {
-    int[] ia = new int[5];
-    Object[] oa = new Object[2];
-    Object[][] oaa = new Object[1][1];
-    String[] sa = new String[3];
-    String[][] saa = new String[1][1];
-    String[][] saa2 = new String[2][];
-    String[][][] saaa = new String[1][2][3];
-    Object o = new Object();
-    java.io.Serializable[] sera = new java.io.Serializable[1];
-    Cloneable[] cloa = new Cloneable[1];
-    StringBuffer[][] sbaa = new StringBuffer[1][1];
-    Foo[] fooa = new Foo[1];
-    FooChild[] fooca = new FooChild[1];
-
-    Class[] ifs = String[].class.getInterfaces();
-    is(ifs.length,2,"String[] implements 2 interfaces");
-    ok(ifs[0] == java.lang.Cloneable.class || ifs[1] == java.lang.Cloneable.class,"String[] implements Cloneable");
-    ok(ifs[0] == java.io.Serializable.class || ifs[1] == java.io.Serializable.class,"String[] implements Serializable");
-
-    is(String[].class.getModifiers(),1041,"String[] is public final abstract");
-
-    is(oa.getClass().getName(),"[Ljava.lang.Object;","classname ref");
-    is(ia.getClass().getName(),"[I","classname primitive");
-    is(ia.length,5,"arraylength primitive");
-    is(oa.length,2,"arraylength ref");
-
-    is(saa2.length,2,"arraylength of saa2");
-    saa2[1] = new String[4];
-    is(saa2[1].length,4,"arraylength of saa2[1]");
-
-    is(saaa.length,1,"arraylength of saaa");
-    is(saaa[0].length,2,"arraylength of saaa[0]");
-    is(saaa[0][1].length,3,"arraylength of saaa[0][1]");
-
-    ok(oa.getClass().isArray(),"Object[].isArray");
-    ok(ia.getClass().isArray(),"int[].isArray");
-    ok(!o.getClass().isArray(),"!Object.isArray");
-    ok(!o.getClass().isPrimitive(),"!Object.isPrimitive");
-
-    is(oa.getClass().getComponentType().getName(),"java.lang.Object","component ref");
-    ok(!oa.getClass().getComponentType().isPrimitive(),"component ref !isPrimitive");
-    is(ia.getClass().getComponentType().getName(),"int","component primitive");
-    ok(ia.getClass().getComponentType().isPrimitive(),"component primitive isPrimitive");
-
-    ok(saa.getClass().getComponentType().equals(sa.getClass()),"component of String[][] equals String[]");
-    ok(!saa.getClass().getComponentType().equals(oa.getClass()),"component of String[][] !equals Object[]");
-
-    ok(saa[0].getClass().equals(saa.getClass().getComponentType()),"saa[0].getClass equals component of String[][]");
-
-    test_store(sa,new Object(),false,"!store Object in String[]");
-    test_store(sa,new String("test"),true,"store String in String[]");
-    test_store(oa,new Object(),true,"store Object in Object[]");
-    test_store(oa,new String("test"),true,"store String in Object[]");
-
-    test_store(oaa,sa,true,"store String[] in Object[][]");
-    test_store(saa,oa,false,"!store Object[] in String[][]");
-
-    test_store(sera,sa,true,"store String[] in java.io.Serializable[]");
-    test_store(cloa,sa,true,"store String[] in Cloneable[]");
-    
-    test_store(sbaa,sa,false,"!store String[] in StringBuffer[][]");
-
-    test_store(fooa,new Foo(),true,"store Foo in Foo[]");
-    test_store(fooa,new FooChild(),true,"store FooChild in Foo[]");
-    test_store(fooca,new Foo(),false,"!store Foo in FooChild[]");
-    test_store(fooca,new FooChild(),true,"store FooChild in FooChild[]");
-    
-    try {
-      Object[] oa2 = (Object[]) sa;
-      ok(true,"cast String[] to Object[]");
-    }
-    catch (ClassCastException x) {
-      System.out.println("    ClassCastException");
-      ok(false,"cast String[] to Object[]");
-    }
-
-    try {
-      String[] sa2 = (String[]) oa;
-      ok(false,"!cast Object[] to String[]");
-    }
-    catch (ClassCastException x) {
-      System.out.println("    ClassCastException");
-      ok(true,"!cast Object[] to String[]");
-    }
-
-    ok(sa instanceof String[],"String[] instanceof String[]");
-    ok(sa instanceof Object[],"String[] instanceof Object[]");
-    ok(!(oa instanceof String[]),"Object[] !instanceof String[]");
-    ok(oa instanceof Object[],"Object[] instanceof Object[]");
-
-    ok(oaa instanceof Object[],"Object[][] instanceof Object[]");
-    ok(saa instanceof Object[],"String[][] instanceof Object[]");
-
-    ok(sa instanceof java.io.Serializable,"String[] instanceof java.io.Serializable");
-    ok(sa instanceof java.lang.Cloneable,"String[] instanceof java.lang.Cloneable");
-    ok(sa instanceof java.lang.Object,"String[] instanceof java.lang.Object");
-    ok(saa[0] instanceof java.io.Serializable,"saa[0] instanceof java.io.Serializable");
-    ok(saa[0] instanceof java.lang.Cloneable,"saa[0] instanceof java.lang.Cloneable");
-    ok(saa[0] instanceof java.lang.Object,"saa[0] instanceof java.lang.Object");
-
-    test_clone();
-    test_arraycopy();
-  }
-}
diff --git a/tests/TestArrayClasses.output b/tests/TestArrayClasses.output
deleted file mode 100644 (file)
index f9ad359..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-ok String[] implements 2 interfaces
-ok String[] implements Cloneable
-ok String[] implements Serializable
-ok String[] is public final abstract
-ok classname ref
-ok classname primitive
-ok arraylength primitive
-ok arraylength ref
-ok arraylength of saa2
-ok arraylength of saa2[1]
-ok arraylength of saaa
-ok arraylength of saaa[0]
-ok arraylength of saaa[0][1]
-ok Object[].isArray
-ok int[].isArray
-ok !Object.isArray
-ok !Object.isPrimitive
-ok component ref
-ok component ref !isPrimitive
-ok component primitive
-ok component primitive isPrimitive
-ok component of String[][] equals String[]
-ok component of String[][] !equals Object[]
-ok saa[0].getClass equals component of String[][]
-    ArrayStoreException
-ok !store Object in String[]
-ok store String in String[]
-ok store Object in Object[]
-ok store String in Object[]
-ok store String[] in Object[][]
-    ArrayStoreException
-ok !store Object[] in String[][]
-ok store String[] in java.io.Serializable[]
-ok store String[] in Cloneable[]
-    ArrayStoreException
-ok !store String[] in StringBuffer[][]
-ok store Foo in Foo[]
-ok store FooChild in Foo[]
-    ArrayStoreException
-ok !store Foo in FooChild[]
-ok store FooChild in FooChild[]
-ok cast String[] to Object[]
-    ClassCastException
-ok !cast Object[] to String[]
-ok String[] instanceof String[]
-ok String[] instanceof Object[]
-ok Object[] !instanceof String[]
-ok Object[] instanceof Object[]
-ok Object[][] instanceof Object[]
-ok String[][] instanceof Object[]
-ok String[] instanceof java.io.Serializable
-ok String[] instanceof java.lang.Cloneable
-ok String[] instanceof java.lang.Object
-ok saa[0] instanceof java.io.Serializable
-ok saa[0] instanceof java.lang.Cloneable
-ok saa[0] instanceof java.lang.Object
-ok cloned int array length
-ok cloned int array data
-ok cloned Integer array length
-ok cloned Integer array data
-ok arraycopy primitive
-ok arraycopy ref
-ok arraycopy ref different classes
-ok arraycopy Integer to Number
-    ArrayStoreException
-ok !arraycopy Number to Integer
diff --git a/tests/TestBase.java b/tests/TestBase.java
deleted file mode 100644 (file)
index b8d134c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-public class TestBase {
-  public static boolean ok(boolean test,String msg) {
-    if (test) {
-      System.out.println("ok "+msg);
-      return true;
-    }
-    else {
-      System.out.println("NOT ok "+msg);
-      return false;
-    }
-  }
-
-  public static boolean is(String a,String b,String msg) {
-    if (ok(a.equals(b),msg)) return true;
-    System.out.println("    a='"+a+"' b='"+b+"'");
-    return false;
-  }
-
-  public static boolean is(int a,int b,String msg) {
-    return ok(a == b,msg);
-  }
-
-  public static boolean equals(Object a,Object b,String msg) {
-    return ok(a.equals(b),msg);
-  }
-}
index 9d9c8e8b7d357bd6aefac1f9eae81e003f4b575e..4f421c76388ad1dd2570d309334927c8959a9b58 100644 (file)
@@ -29,6 +29,8 @@ import org.junit.runners.Suite;
 @RunWith(Suite.class)
 
 @Suite.SuiteClasses({
+TestArrayClasses.class,
+TestCloning.class,
 TestExceptionInStaticClassInitializer.class,
 TestPatcher.class
 })
diff --git a/tests/regression/base/TestArrayClasses.java b/tests/regression/base/TestArrayClasses.java
new file mode 100644 (file)
index 0000000..db56f1d
--- /dev/null
@@ -0,0 +1,288 @@
+/* tests/regression/base/TestArrayClasses.java
+
+   Copyright (C) 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+import java.io.Serializable;
+
+public class TestArrayClasses {
+  public static class Foo {
+  }
+
+  public static class FooChild extends Foo {
+  }
+  
+  private void doStore(Object[] array, Object obj, boolean oktostore, String msg) {
+    try {
+      array[0] = obj;
+      assertTrue(msg, oktostore);
+    }
+    catch (ArrayStoreException x) {
+      assertFalse(msg, oktostore);
+    }
+  }
+
+  @Test
+  public void testClone() {
+    int[] ia1 = new int[100];
+    Integer[] Ia1 = new Integer[ia1.length];
+    int i;
+    
+    for (i=0; i<ia1.length; ++i) {
+      ia1[i] = i*i;
+      Ia1[i] = new Integer(ia1[i]);
+    }
+
+    int[] ia2 = (int[]) ia1.clone();
+
+    assertEquals("cloned int array length", ia1.length, ia2.length);
+
+    boolean eq = true;
+    for (i=0; i<ia1.length; ++i) {
+      if (ia2[i] != ia1[i])
+        eq = false;
+      //      System.out.println(ia2[i]);
+    }
+    assertTrue("cloned int array data", eq);
+
+    Integer[] Ia2 = (Integer[]) Ia1.clone();
+    
+    assertEquals("cloned Integer array length", Ia1.length, Ia2.length);
+    
+    eq = true;
+    for (i=0; i<ia1.length; ++i) {
+      if (Ia2[i].intValue() != ia1[i])
+        eq = false;
+      //      System.out.println(ia2[i]);
+    }
+    assertTrue("cloned Integer array data", eq);
+  }
+
+  @Test
+  public void testArraycopy() {
+    int len;
+    int i;
+
+    long[] la1 = new long[1024];
+    long[] la2 = (long[]) la1.clone();
+    int size = la1.length;
+    Long[] La1 = new Long[size];
+    Long[] La2 = (Long[]) La1.clone();
+    Number[] Na2 = new Number[size];
+
+    for (i=0; i<la1.length; ++i) {
+      la1[i] = i*i;
+      La1[i] = new Long(la1[i]);
+    }
+
+    i = size;
+    while (i>1) {
+      if ((i & 1) != 0)
+        System.err.println("ERROR: arracopy test only works for powers of two");
+      i >>= 1;
+    }
+    
+    // reverse array
+    len = size / 2;
+    while (len>0) {
+      for (int j=0;j<(size/2)/len;++j) {
+        //        System.err.println(len);
+        //        System.err.println(j);
+        System.arraycopy(la1,(2*j+1)*len,la2,2*j*len,len);
+        System.arraycopy(la1,2*j*len,la1,(2*j+1)*len,len);
+        System.arraycopy(la2,2*j*len,la1,2*j*len,len);
+      }
+      len /= 2;
+    }
+
+    boolean eq = true;
+    for (i=0; i<size; ++i) {
+      if (la1[i] != (size-i-1)*(size-i-1))
+        eq = false;
+      //      System.out.println(la1[i]);
+    }
+    assertTrue("arraycopy primitive", eq);
+    
+    // reverse array
+    len = size / 2;
+    while (len>0) {
+      for (int j=0;j<(size/2)/len;++j) {
+        //        System.err.println(len);
+        //        System.err.println(j);
+        System.arraycopy(La1,(2*j+1)*len,La2,2*j*len,len);
+        System.arraycopy(La1,2*j*len,La1,(2*j+1)*len,len);
+        System.arraycopy(La2,2*j*len,La1,2*j*len,len);
+      }
+      len /= 2;
+    }
+
+    eq = true;
+    for (i=0; i<size; ++i) {
+      if (La1[i].intValue() != (size-i-1)*(size-i-1))
+        eq = false;
+    }
+    assertTrue("arraycopy ref", eq);
+    
+    // reverse array
+    len = size / 2;
+    while (len>0) {
+      for (int j=0;j<(size/2)/len;++j) {
+        //        System.err.println(len);
+        //        System.err.println(j);
+        System.arraycopy(La1,(2*j+1)*len,Na2,2*j*len,len);
+        System.arraycopy(La1,2*j*len,La1,(2*j+1)*len,len);
+        System.arraycopy(Na2,2*j*len,La1,2*j*len,len);
+      }
+      len /= 2;
+    }
+
+    eq = true;
+    for (i=0; i<size; ++i) {
+      if (La1[i].intValue() != i*i)
+        eq = false;
+    }
+    assertTrue("arraycopy ref different classes", eq);
+
+    Integer[] Ia = new Integer[size];
+
+    try {
+      System.arraycopy(Ia,0,Na2,0,1);
+      assertTrue("arraycopy Integer to Number", true);
+    }
+    catch (ArrayStoreException x) {
+      fail("arraycopy Integer to Number");
+    }
+
+    try {
+      System.arraycopy(Na2,1,Ia,1,1);
+      fail("!arraycopy Number to Integer");
+    }
+    catch (ArrayStoreException x) {
+      assertTrue("!arraycopy Number to Integer", true);
+    }
+  }
+
+  @Test
+  public void testMain() {
+    int[] ia = new int[5];
+    Object[] oa = new Object[2];
+    Object[][] oaa = new Object[1][1];
+    String[] sa = new String[3];
+    String[][] saa = new String[1][1];
+    String[][] saa2 = new String[2][];
+    String[][][] saaa = new String[1][2][3];
+    Object o = new Object();
+    java.io.Serializable[] sera = new java.io.Serializable[1];
+    Cloneable[] cloa = new Cloneable[1];
+    StringBuffer[][] sbaa = new StringBuffer[1][1];
+    Foo[] fooa = new Foo[1];
+    FooChild[] fooca = new FooChild[1];
+
+    Class[] ifs = String[].class.getInterfaces();
+    assertEquals("String[] implements 2 interfaces", 2, ifs.length);
+    assertTrue("String[] implements Cloneable", ifs[0] == java.lang.Cloneable.class || ifs[1] == java.lang.Cloneable.class);
+    assertTrue("String[] implements Serializable", ifs[0] == java.io.Serializable.class || ifs[1] == java.io.Serializable.class);
+
+    assertEquals("String[] is public final abstract", 1041, String[].class.getModifiers());
+
+    assertEquals("classname ref", "[Ljava.lang.Object;", oa.getClass().getName());
+    assertEquals("classname primitive", "[I", ia.getClass().getName());
+    assertEquals("arraylength primitive", 5, ia.length);
+    assertEquals("arraylength ref", 2, oa.length);
+
+    assertEquals("arraylength of saa2", 2, saa2.length);
+    saa2[1] = new String[4];
+    assertEquals("arraylength of saa2[1]", 4, saa2[1].length);
+
+    assertEquals("arraylength of saaa", 1, saaa.length);
+    assertEquals("arraylength of saaa[0]", 2, saaa[0].length);
+    assertEquals("arraylength of saaa[0][1]", 3, saaa[0][1].length);
+
+    assertTrue("Object[].isArray", oa.getClass().isArray());
+    assertTrue("int[].isArray", ia.getClass().isArray());
+    assertFalse("!Object.isArray", o.getClass().isArray());
+    assertFalse("!Object.isPrimitive", o.getClass().isPrimitive());
+
+    assertEquals("component ref", "java.lang.Object", oa.getClass().getComponentType().getName());
+    assertFalse("component ref !isPrimitive", oa.getClass().getComponentType().isPrimitive());
+    assertEquals("component primitive", "int", ia.getClass().getComponentType().getName());
+    assertTrue("component primitive isPrimitive", ia.getClass().getComponentType().isPrimitive());
+
+    assertTrue("component of String[][] equals String[]", saa.getClass().getComponentType().equals(sa.getClass()));
+    assertFalse("component of String[][] !equals Object[]", saa.getClass().getComponentType().equals(oa.getClass()));
+
+    assertTrue("saa[0].getClass equals component of String[][]", saa[0].getClass().equals(saa.getClass().getComponentType()));
+
+    doStore(sa, new Object(), false, "!store Object in String[]");
+    doStore(sa, new String("test"), true, "store String in String[]");
+    doStore(oa, new Object(), true, "store Object in Object[]");
+    doStore(oa, new String("test"), true, "store String in Object[]");
+
+    doStore(oaa, sa, true, "store String[] in Object[][]");
+    doStore(saa, oa, false, "!store Object[] in String[][]");
+
+    doStore(sera, sa, true, "store String[] in java.io.Serializable[]");
+    doStore(cloa, sa, true, "store String[] in Cloneable[]");
+    
+    doStore(sbaa, sa, false, "!store String[] in StringBuffer[][]");
+
+    doStore(fooa, new Foo(), true, "store Foo in Foo[]");
+    doStore(fooa, new FooChild(), true, "store FooChild in Foo[]");
+    doStore(fooca, new Foo(), false, "!store Foo in FooChild[]");
+    doStore(fooca, new FooChild(), true, "store FooChild in FooChild[]");
+    
+    try {
+      Object[] oa2 = (Object[]) sa;
+      assertTrue("cast String[] to Object[]", true);
+    }
+    catch (ClassCastException x) {
+      fail("cast String[] to Object[]");
+    }
+
+    try {
+      String[] sa2 = (String[]) oa;
+      fail("!cast Object[] to String[]");
+    }
+    catch (ClassCastException x) {
+      assertTrue("!cast Object[] to String[]", true);
+    }
+
+    assertTrue("String[] instanceof String[]", sa instanceof String[]);
+    assertTrue("String[] instanceof Object[]", sa instanceof Object[]);
+    assertFalse("Object[] !instanceof String[]", oa instanceof String[]);
+    assertTrue("Object[] instanceof Object[]", oa instanceof Object[]);
+
+    assertTrue("Object[][] instanceof Object[]", oaa instanceof Object[]);
+    assertTrue("String[][] instanceof Object[]", saa instanceof Object[]);
+
+    assertTrue("String[] instanceof java.io.Serializable", sa instanceof java.io.Serializable);
+    assertTrue("String[] instanceof java.lang.Cloneable", sa instanceof java.lang.Cloneable);
+    assertTrue("String[] instanceof java.lang.Object", sa instanceof java.lang.Object);
+    assertTrue("saa[0] instanceof java.io.Serializable", saa[0] instanceof java.io.Serializable);
+    assertTrue("saa[0] instanceof java.lang.Cloneable", saa[0] instanceof java.lang.Cloneable);
+    assertTrue("saa[0] instanceof java.lang.Object", saa[0] instanceof java.lang.Object);
+  }
+}
diff --git a/tests/regression/base/TestCloning.java b/tests/regression/base/TestCloning.java
new file mode 100644 (file)
index 0000000..35dad40
--- /dev/null
@@ -0,0 +1,101 @@
+/* tests/regression/base/TestCloning.java
+
+   Copyright (C) 2008
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class TestCloning
+{
+       private static class FooUncloneable {
+               public Object clone() throws CloneNotSupportedException {
+                       return super.clone();
+               }
+       }
+
+       private static class FooCloneable implements Cloneable {
+               public String s;
+               public FooCloneable(String s) {
+                       this.s = s;
+               }
+               public Object clone() throws CloneNotSupportedException {
+                       return super.clone();
+               }
+       }
+
+       private static class FooOverridden {
+               public Object clone() {
+                       return this;
+               }
+       }
+
+       @Test
+       public void testObject() throws CloneNotSupportedException {
+               // Test cloning of cloneable object.
+               FooCloneable o1 = new FooCloneable("Simple Test");
+               Object oc1 = o1.clone();
+               assertNotNull(oc1);
+               assertNotSame(o1, oc1);
+               assertEquals(o1.getClass(), oc1.getClass());
+               assertSame(o1.s, ((FooCloneable) oc1).s);
+
+               // Test cloning of uncloneable object.
+               try {
+                       FooUncloneable o2 = new FooUncloneable();
+                       Object oc2 = o2.clone();
+                       fail("Exception expected");
+               } catch (CloneNotSupportedException e) {
+               }
+
+               // Test cloning of object with overridden clone method.
+               FooOverridden o3 = new FooOverridden();
+               Object oc3 = o3.clone();
+               assertNotNull(oc3);
+               assertSame(o3, oc3);
+       }
+
+       @Test
+       public void testArray() {
+               // Test cloning of integer array.
+               int[] a = { 1, 23, 42 };
+               int[] ac = a.clone();
+               assertNotNull(ac);
+               assertNotSame(a, ac);
+               assertEquals(a.getClass(), ac.getClass());
+               assertEquals(a.length, ac.length);
+               assertArrayEquals(a, ac);
+       }
+
+       @Test
+       public void testLocked() throws CloneNotSupportedException {
+               // Test cloning of locked object.
+               FooCloneable o = new FooCloneable("Locked Test");
+               synchronized(o) {
+                       Object oc = o.clone();
+                       assertNotNull(oc);
+                       assertTrue(Thread.holdsLock(o));
+                       assertFalse(Thread.holdsLock(oc));
+               }
+       }
+}