-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'.
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");
}
{
TRACEJNICALLS(("_Jv_JNI_GetVersion(env=%p)", env));
- /* We support JNI 1.6. */
-
- return JNI_VERSION_1_6;
+ return JNI_VERSION_SUPPORTED;
}
/* 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;
}
//#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;
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) */
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)
#endif
#include "vm/global.h"
+#include "vm/os.hpp"
#include "vm/vm.hpp" /* REMOVE ME: temporarily */
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;
}
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;
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;
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;
}
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"
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);
/* 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 */
{
#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
}
{
#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
{
#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
}
{
#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:
#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"
*******************************************************************************/
-void nativevm_init(void)
+bool nativevm_init(void)
{
TRACESUBSYSTEMINITIALIZATION("nativevm_init");
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
#else
# error unknown Java configuration
#endif
+
+ return true;
}
/* 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)
*/
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;
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;
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;
// Gobal mutex for generic atomic instructions.
static Mutex lock;
+namespace Atomic {
/**
* A generic atomic compare and swap for 32-bit integer values. This
*
* @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;
*
* @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;
*
* @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;
if (oldval == result)
*p = newval;
- lock.lock();
+ lock.unlock();
return result;
}
* 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(); }
#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);
/* XXX cleanup these includes */
+#define __STDC_LIMIT_MACROS
+
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#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"
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
#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
}
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");
}
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 */
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;
}
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
}
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)
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)
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.
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;
}
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;
}
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);
}
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 */
#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.
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.
};
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();
static void release_thread(threadobject* t);
};
+struct ThreadListLocker {
+ ThreadListLocker() { ThreadList::lock(); }
+ ~ThreadListLocker() { ThreadList::unlock(); }
+};
+
inline void ThreadList::add_to_active_thread_list(threadobject* t)
{
bool class_isanysubclass(classinfo *sub, classinfo *super)
{
- uint32_t diffval;
- bool result;
+ bool result;
/* This is the trivial case. */
#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
}
+/* 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
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);
}
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);
}
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);
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;
};
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()
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()
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()
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()
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()
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()
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()
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()
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);
};
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)
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)
// 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);
};
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);
};
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;
};
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);
};
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();
};
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;
};
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;
};
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;
};
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;
};
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;
};
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
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;
};
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)
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)
// 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);
};
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);
};
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();
};
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;
};
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;
};
java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
// Getters.
- inline void* get_address() const;
+ void* get_address() const;
};
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);
};
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);
};
// 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);
};
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);
};
stack.h
TRAP_SOURCES = \
- trap.c \
- trap.h
+ trap.cpp \
+ trap.hpp
endif
if ENABLE_REPLACEMENT
#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"
#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 *******************************************************************
#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 ***************************************************
#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 temp;
uint32_t result;
*
* @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;
}
-/**
- * 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");
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("wmb" : : : "memory");
}
/**
* An instruction barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
{
__asm__ __volatile__ ("mb" : : : "memory");
}
+}
+
#endif // _MD_ATOMIC_HPP
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
/* global variables ***********************************************************/
#define REPLACEMENT_PATCH_SIZE 4 /* bytes */
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE 1
+
#endif /* _ARCH_H */
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);
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: /* ... ==> ... */
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);
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);
#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);
} else if(IS_IMM(-(val))) { \
M_CMN_IMM(reg, -(val)); \
} else { \
+ assert((reg) != REG_ITMP3); \
ICONST(REG_ITMP3, (val)); \
M_CMP(reg, REG_ITMP3); \
}
#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 */
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;
#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 ***************************************************
#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;
uint32_t temp;
*
* @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");
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* An instruction barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
+}
+
#endif // _MD_ATOMIC_HPP
/* 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. */
}
-/* 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
if (desc == NULL)
return 0;
- return builtin_descriptorscompatible(desc, targetclass->vftbl->arraydesc);
+ return class_is_arraycompatible(desc, targetclass->vftbl->arraydesc);
}
vftbl_t *componentvftbl;
vftbl_t *valuevftbl;
int32_t baseval;
- uint32_t diffval;
bool result;
if (o == NULL)
#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
}
else {
/* {o is an array} */
- result = builtin_descriptorscompatible(valuedesc, componentvftbl->arraydesc);
+ result = class_is_arraycompatible(valuedesc, componentvftbl->arraydesc);
}
/* return result */
vftbl_t *elementvftbl;
vftbl_t *valuevftbl;
int32_t baseval;
- uint32_t diffval;
bool result;
if (o == NULL)
#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
}
* 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;
#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;
#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);
#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
#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"
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)
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:
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:
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:
d = lm->parseddesc->returntype.type;
}
- M_MOV_IMM(disp, REG_ITMP2);
+ M_MOV_IMM2(disp, REG_ITMP2);
M_CALL(REG_ITMP2);
break;
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);
}
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));
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);
}
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));
#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))
#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 ***************************************************
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;
#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 ******************************************************************
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)
{
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);
#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 ***************************************************
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;
#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 ***************************************************
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;
#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;
}
*
* @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" );
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* 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
#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);
}
Machine code:
<patched call position>
- b8 00 00 00 00 mov $0x00000000,%eax
+ c7 c0 00 00 00 00 mov $0x00000000,%eax
*******************************************************************************/
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;
}
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;
}
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);
}
*((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;
}
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);
}
*((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;
}
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
*******************************************************************************/
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;
}
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;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch the classinfo pointer */
*((ptrint *) (ra + 4)) = (ptrint) c;
/* 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;
}
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
*******************************************************************************/
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;
}
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;
}
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]) -
*((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;
}
Machine code:
<patched call position>
- b9 00 00 00 00 mov $0x00000000,%ecx
+ c7 c1 00 00 00 00 mov $0x00000000,%ecx
*******************************************************************************/
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;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch super class index */
*((s4 *) (ra + 6 + 2)) = (s4) c->index;
*((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;
}
if (!(c = resolve_classref_eager(cr)))
return false;
- PATCH_BACK_ORIGINAL_MCODE;
-
/* patch super class index */
*((s4 *) (ra + 6 + 2)) = (s4) c->index;
*((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;
}
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
*******************************************************************************/
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;
}
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
*******************************************************************************/
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;
}
#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 ***************************************************
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;
#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)
#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 **************************************************************************
#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>
#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)
{
- return generic_compare_and_swap(p, oldval, newval);
+ return Atomic::generic_compare_and_swap(p, oldval, newval);
}
*
* @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();
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* An instruction barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
+}
+
#endif // _MD_ATOMIC_HPP
#define REPLACEMENT_PATCH_SIZE (2*4) /* bytes */
+/* subtype ********************************************************************/
+
+#define USES_NEW_SUBTYPE 1
+
#endif /* _ARCH_H */
#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"
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);
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);
#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 *******************************************************************
registerdata *rd;
methoddesc *md;
s4 disp;
- s4 i, j, t;
+ s4 i, s;
/* get required compiler data */
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 */
Generates the code for the call trace.
- void builtin_verbosecall_exit(s8 l, double d, float f, methodinfo *m);
-
*******************************************************************************/
#if !defined(NDEBUG)
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 */
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
/* md_init *********************************************************************
#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;
uint32_t temp;
*
* @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;
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
}
/**
* A memory barrier.
*/
-inline void Atomic::memory_barrier(void)
+inline void memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* An instruction barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
+}
+
#endif // _MD_ATOMIC_HPP
{
_handle = op_open_agent();
if (!_handle)
- vm_abort_errno("unable to open opagent handle:");
+ os::abort_errno("unable to open opagent handle:");
}
/**
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" },
#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"
#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 *******************************************************************
#endif
#include "vm/jit/patcher-common.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
/* md_signal_handler_sigsegv ***************************************************
#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 temp;
uint32_t result;
*
* @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");
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* An instruction barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
{
__asm__ __volatile__ ("isync" : : : "memory");
}
+}
+
#endif // _MD_ATOMIC_HPP
#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"
#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 *******************************************************************
#endif
#include "vm/jit/disass.h"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
/* md_signal_handler_sigsegv ***************************************************
#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 temp;
uint32_t result;
*
* @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;
}
-/**
- * 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");
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* An instruction memory barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
{
__asm__ __volatile__ ("isync" : : : "memory");
}
+}
+
#endif // _MD_ATOMIC_HPP
#include "vm/global.h"
#include "vm/jit/jit.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
/* md_init *********************************************************************
#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,
#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 *******************************************************************
#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 ompare_and_swap(volatile uint32_t *p, uint32_t oldval, uint32_t newval)
{
__asm__ __volatile__ (
"cs %0,%3,0(%2)\n"
*
* @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" );
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void rite_memory_barrier(void)
{
memory_barrier();
}
/**
* An instruction barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void nstruction_barrier(void)
{
memory_barrier();
}
+}
+
#endif // _MD_ATOMIC_HPP
#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 */
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.hpp"
-#include "vm/jit/trap.h"
+#include "vm/jit/trap.hpp"
typedef struct sigcontext sigcontext;
#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)
+
+}
{
#if 0
// This one should be correct.
return result;
#else
- return generic_compare_and_swap(p, oldval, newval);
+ return Atomic::generic_compare_and_swap(p, oldval, newval);
#endif
}
*
* @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;
}
-/**
- * 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" );
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("wmb" : : : "memory");
}
/**
* An instruction barrier.
*/
-inline void Atomic::instruction_barrier(void)
+inline void instruction_barrier(void)
{
__asm__ __volatile__ ("mb" : : : "memory");
}
+}
+
#endif // _MD_ATOMIC_HPP
#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)
+++ /dev/null
-/* src/vm/jit/trap.c - hardware traps
-
- Copyright (C) 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-/* Include machine dependent trap stuff. */
-
-#include "md.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:
- */
--- /dev/null
+/* 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:
+ */
+++ /dev/null
-/* src/vm/jit/trap.h - hardware traps
-
- Copyright (C) 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _TRAP_H
-#define _TRAP_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#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:
- */
--- /dev/null
+/* 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:
+ */
#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"
#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 *******************************************************************
#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"
#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;
}
*
* @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");
}
/**
* A write memory barrier.
*/
-inline void Atomic::write_memory_barrier(void)
+inline void write_memory_barrier(void)
{
__asm__ __volatile__ ("" : : : "memory");
}
/**
* 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
#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"
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;
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)
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)
bool opt_verbose = false;
bool opt_debugcolor = false; /* use ANSI terminal sequences */
-bool compileall = false;
bool loadverbose = false;
bool initverbose = false;
bool showconstantpool = false;
bool showutf = false;
-char *opt_method = NULL;
-char *opt_signature = NULL;
-
bool compileverbose = false; /* trace compiler actions */
bool showstack = false;
/* 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;
/* Debugging options which can be turned off. */
OPT_AlwaysEmitLongBranches,
+ OPT_CompileAll,
+ OPT_CompileMethod,
+ OPT_CompileSignature,
OPT_DebugExceptions,
OPT_DebugFinalizer,
OPT_DebugLocalReferences,
/* 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" },
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;
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;
extern bool opt_verbose;
extern bool opt_debugcolor;
-extern bool compileall;
extern bool loadverbose; /* Print debug messages during loading */
extern bool initverbose; /* Log class initialization */
extern bool showconstantpool;
extern bool showutf;
-extern char *opt_method;
-extern char *opt_signature;
-
extern bool compileverbose;
extern bool showstack;
/* 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;
#include "vm/globals.hpp"
#include "vm/method.hpp"
#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/signallocal.hpp"
#include "vm/vm.hpp"
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. */
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");
}
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 (;;) {
} 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);
#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.
}
-/* 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;
/* 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 */
}
-/* 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;
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)
#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"
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
#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 ********************************
#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);
# 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"
OPT_SHOW,
OPT_DEBUGCOLOR,
-#if !defined(NDEBUG)
- OPT_ALL,
- OPT_METHOD,
- OPT_SIGNATURE,
-#endif
-
#if defined(ENABLE_VERIFIER)
OPT_NOVERIFY,
OPT_XVERIFY_ALL,
{ "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
/* 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 },
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");
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]) {
/* 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.
// 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) */
/* 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 */
int status;
#if !defined(NDEBUG)
- if (compileall) {
+ if (opt_CompileAll) {
vm_compile_all();
return;
}
usage();
#if !defined(NDEBUG)
- if (opt_method != NULL) {
+ if (opt_CompileMethod != NULL) {
vm_compile_method(mainname);
return;
}
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);
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);
}
{
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();
}
}
#endif
#include "vm/properties.hpp"
+#include "vm/suck.hpp"
#include "vm/jit/optimizing/recompiler.hpp"
#endif
NativeLibraries _nativelibraries; ///< Native library table.
NativeMethods _nativemethods; ///< Native methods table.
+ SuckClasspath _suckclasspath; ///< Classpath entries list.
public:
// Constructor, Destructor.
#endif
NativeLibraries& get_nativelibraries() { return _nativelibraries; }
NativeMethods& get_nativemethods () { return _nativemethods; }
+ SuckClasspath& get_suckclasspath () { return _suckclasspath; }
};
#else
// 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
}
+++ /dev/null
-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();
- }
-}
+++ /dev/null
-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
+++ /dev/null
-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);
- }
-}
@RunWith(Suite.class)
@Suite.SuiteClasses({
+TestArrayClasses.class,
+TestCloning.class,
TestExceptionInStaticClassInitializer.class,
TestPatcher.class
})
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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));
+ }
+ }
+}