merged volatile memory barriers
authorsr <none@none>
Tue, 17 Nov 2009 07:40:45 +0000 (08:40 +0100)
committersr <none@none>
Tue, 17 Nov 2009 07:40:45 +0000 (08:40 +0100)
108 files changed:
configure.ac
m4/jvmti.m4
m4/version.m4 [new file with mode: 0644]
src/cacao/cacao.cpp
src/mm/codememory.c
src/mm/gc-none.cpp
src/mm/tlh.c
src/native/jni.cpp
src/native/native.cpp
src/native/vm/cldc1.1/com_sun_cldc_io_ResourceInputStream.cpp
src/native/vm/cldc1.1/com_sun_cldc_io_j2me_socket_Protocol.cpp
src/native/vm/cldc1.1/java_lang_Object.cpp
src/native/vm/gnuclasspath/gnu_java_lang_management_VMClassLoadingMXBeanImpl.cpp
src/native/vm/gnuclasspath/gnu_java_lang_management_VMMemoryMXBeanImpl.cpp
src/native/vm/gnuclasspath/gnu_java_lang_management_VMThreadMXBeanImpl.cpp
src/native/vm/gnuclasspath/java_lang_VMClassLoader.cpp
src/native/vm/gnuclasspath/java_lang_VMObject.cpp
src/native/vm/gnuclasspath/java_lang_VMRuntime.cpp
src/native/vm/nativevm.cpp
src/native/vm/nativevm.hpp
src/native/vm/openjdk/Makefile.am
src/native/vm/openjdk/jvm.cpp
src/native/vm/openjdk/management.cpp
src/native/vm/openjdk/sun_misc_Perf.cpp [new file with mode: 0644]
src/native/vm/sun_misc_Unsafe.cpp
src/threads/mutex.hpp
src/threads/posix/thread-posix.cpp
src/threads/posix/thread-posix.hpp
src/threads/thread.cpp
src/threads/threadlist.cpp
src/threads/threadlist.hpp
src/toolbox/hashtable.hpp [new file with mode: 0644]
src/toolbox/util.c
src/toolbox/util.h
src/vm/Makefile.am
src/vm/classcache.cpp
src/vm/classcache.hpp
src/vm/cycles-stats.h
src/vm/exceptions.cpp
src/vm/global.h
src/vm/hook.hpp [new file with mode: 0644]
src/vm/javaobjects.cpp
src/vm/javaobjects.hpp
src/vm/jit/alpha/arch.h
src/vm/jit/alpha/linux/md-os.c
src/vm/jit/arm/arch.h
src/vm/jit/arm/codegen.c
src/vm/jit/arm/codegen.h
src/vm/jit/arm/linux/md-os.c
src/vm/jit/asmpart.h
src/vm/jit/codegen-common.cpp
src/vm/jit/executionstate.c
src/vm/jit/executionstate.h
src/vm/jit/i386/arch.h
src/vm/jit/i386/asmpart.S
src/vm/jit/i386/darwin/md-asm.h
src/vm/jit/i386/freebsd/md-os.c
src/vm/jit/i386/linux/md-os.c
src/vm/jit/i386/md.h
src/vm/jit/i386/solaris/md-os.c
src/vm/jit/jit.cpp
src/vm/jit/m68k/arch.h
src/vm/jit/m68k/linux/md-os.c
src/vm/jit/mips/arch.h
src/vm/jit/mips/codegen.c
src/vm/jit/mips/linux/md-os.c
src/vm/jit/oprofile-agent.cpp
src/vm/jit/patcher-common.cpp
src/vm/jit/patcher-common.hpp
src/vm/jit/powerpc/arch.h
src/vm/jit/powerpc/linux/md-os.c
src/vm/jit/powerpc/md.c
src/vm/jit/powerpc64/arch.h
src/vm/jit/replace.cpp
src/vm/jit/replace.hpp
src/vm/jit/s390/arch.h
src/vm/jit/sparc64/arch.h
src/vm/jit/stubs.cpp
src/vm/jit/stubs.hpp
src/vm/jit/trace.cpp
src/vm/jit/trap.cpp
src/vm/jit/x86_64/arch.h
src/vm/jit/x86_64/asmpart.S
src/vm/jit/x86_64/linux/md-os.c
src/vm/jit/x86_64/md.h
src/vm/jit/x86_64/solaris/md-os.c
src/vm/linker.cpp
src/vm/loader.cpp
src/vm/method.cpp
src/vm/method.hpp
src/vm/options.c
src/vm/options.h
src/vm/os.cpp
src/vm/os.hpp
src/vm/primitive.cpp
src/vm/primitive.hpp
src/vm/properties.cpp
src/vm/signal.cpp
src/vm/signallocal.hpp
src/vm/suck.cpp
src/vm/types.h
src/vm/utf8.c
src/vm/utf8.h
src/vm/vm.cpp
src/vm/vm.hpp
src/vm/zip.cpp
tests/regression/base/All.java
tests/regression/base/TestAbstractMethodError.java [new file with mode: 0644]

index 11d06e9ac7866a5a7425a46fefbcf8a4a1f37b46..d33d8591ad43cda403ced9218b323ead3f02af3f 100644 (file)
@@ -286,7 +286,9 @@ AC_CHECK_HEADERS([string.h])
 AC_CHECK_HEADERS([time.h])
 AC_CHECK_HEADERS([ucontext.h])
 AC_CHECK_HEADERS([unistd.h])
+AC_CHECK_HEADERS([mach/mach.h])
 AC_CHECK_HEADERS([sys/ioctl.h])
+AC_CHECK_HEADERS([sys/loadavg.h])
 AC_CHECK_HEADERS([sys/mman.h])
 AC_CHECK_HEADERS([sys/resource.h])
 AC_CHECK_HEADERS([sys/select.h])
@@ -294,6 +296,7 @@ AC_CHECK_HEADERS([sys/socket.h])
 AC_CHECK_HEADERS([sys/stat.h])
 AC_CHECK_HEADERS([sys/time.h])
 AC_CHECK_HEADERS([sys/types.h])
+AC_CHECK_HEADERS([sys/utsname.h])
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
@@ -344,7 +347,9 @@ AC_CHECK_FUNCS([getcwd])
 AC_CHECK_FUNCS([getenv])
 AC_CHECK_FUNCS([gethostbyname])
 AC_CHECK_FUNCS([gethostname])
+AC_CHECK_FUNCS([getloadavg])
 AC_CHECK_FUNCS([getpagesize])
+AC_CHECK_FUNCS([getpid])
 AC_CHECK_FUNCS([getrusage])
 AC_CHECK_FUNCS([getsockname])
 AC_CHECK_FUNCS([getsockopt])
@@ -591,6 +596,11 @@ dnl The check for jni_md.h must be before jni.h.
 AC_CHECK_WITH_JNI_MD_H
 AC_CHECK_WITH_JNI_H
 
+dnl The jvmti.h header is only required if JVMTI is enabled.
+if test x"${ENABLE_JVMTI}" = "xyes"; then
+    AC_CHECK_WITH_JVMTI_H
+fi
+
 dnl JVM, HPI, and JMM is only required for OpenJDK.
 case "${WITH_JAVA_RUNTIME_LIBRARY}" in
     openjdk)
@@ -645,14 +655,9 @@ AZ_PYTHON_VERSION_ENSURE( [2.4] )
 AZ_PYTHON_CSPEC
 AZ_PYTHON_LSPEC
 
-
-dnl define some stuff required for --fullversion
-AC_DEFINE_UNQUOTED(VERSION_CONFIGURE_ARGS, "$ac_configure_args", [configure arguments])
-AC_DEFINE_UNQUOTED(VERSION_CC, "$CC", [CC used])
-AC_DEFINE_UNQUOTED(VERSION_CXX, "$CXX", [CXX used])
-AC_DEFINE_UNQUOTED(VERSION_CFLAGS, "$OPT_CFLAGS $ARCH_CFLAGS $CC_FLAGS $CPPFLAGS", [CFLAGS used])
-AC_DEFINE_UNQUOTED(VERSION_CXXFLAGS, "$OPT_CXXFLAGS $ARCH_CXXFLAGS $CXX_FLAGS $CPPFLAGS", [CXXFLAGS used])
-
+dnl Define version numbers.
+AC_VERSION_DETAIL
+AC_VERSION_CONFIG
 
 dnl Finally pass flags to Makefiles.
 CFLAGS="$OPT_CFLAGS"
index 7ee27ad7506cb90d3661bbc610e76841e1781f99..62e989948cd1930d5e132a4be77a226fa95d0f7e 100644 (file)
@@ -1,6 +1,6 @@
 dnl m4/jvmti.m4
 dnl
-dnl Copyright (C) 2008
+dnl Copyright (C) 2008, 2009
 dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 dnl 
 dnl This file is part of CACAO.
@@ -39,3 +39,26 @@ if test x"${ENABLE_JVMTI}" = "xyes"; then
     AC_DEFINE([ENABLE_JVMTI], 1, [use JVMTI])
 fi
 ])
+
+
+dnl where jvmti.h is installed
+
+AC_DEFUN([AC_CHECK_WITH_JVMTI_H],[
+AC_MSG_CHECKING(where jvmti.h is installed)
+AC_ARG_WITH([jvmti_h],
+            [AS_HELP_STRING(--with-jvmti_h=<dir>,path to jvmti.h (only with --enable-jvmti) [[default=(openjdk:${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export,*:${JAVA_RUNTIME_LIBRARY_PREFIX}/include)]])],
+            [WITH_JVMTI_H=${withval}],
+            [case "${WITH_JAVA_RUNTIME_LIBRARY}" in
+                 openjdk)
+                     WITH_JVMTI_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/jdk/src/share/javavm/export
+                     ;;
+                 *)
+                     WITH_JVMTI_H=${JAVA_RUNTIME_LIBRARY_PREFIX}/include
+                     ;;
+            esac])
+AC_MSG_RESULT(${WITH_JVMTI_H})
+
+AC_CHECK_HEADER([${WITH_JVMTI_H}/jvmti.h],
+                [AC_DEFINE_UNQUOTED([INCLUDE_JVMTI_H], "${WITH_JVMTI_H}/jvmti.h", [Java runtime library jvmti.h header])],
+                [AC_MSG_ERROR(cannot find jvmti.h)])
+])
diff --git a/m4/version.m4 b/m4/version.m4
new file mode 100644 (file)
index 0000000..ba7c0e4
--- /dev/null
@@ -0,0 +1,56 @@
+dnl m4/version.m4
+dnl
+dnl Copyright (C) 2009
+dnl CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+dnl
+dnl This file is part of CACAO.
+dnl
+dnl This program is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU General Public License as
+dnl published by the Free Software Foundation; either version 2, or (at
+dnl your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful, but
+dnl WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+dnl General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+
+
+dnl define detailed version numbers
+
+AC_DEFUN([AC_VERSION_DETAIL],[
+version="$PACKAGE_VERSION"
+if test x`echo "$version" | $SED -e 's/[[0-9a-z+]]*//g'` = "x..";
+then
+    major=`echo "$version" | $SED -e 's/\.[[0-9a-z.+]]*$//'`
+    minor=`echo "$version" | $SED -e 's/^[[0-9]]*\.//' -e 's/\.[[0-9a-z.+]]*$//'`
+    micro=`echo "$version" | $SED -e 's/^[[0-9]]*\.[[0-9]]*\.//' -e 's/[[a-z.+]]*$//'`
+    extra=`echo "$version" | $SED -e 's/^[[0-9]]*\.[[0-9]]*\.[[0-9]]*//'`
+else
+    major=`echo "$version" | $SED -e 's/\.[[0-9a-z.+]]*$//'`
+    minor=`echo "$version" | $SED -e 's/^[[0-9]]*\.//' -e 's/[[a-z.+]]*$//'`
+    micro=0
+    extra=`echo "$version" | $SED -e 's/^[[0-9]]*\.[[0-9]]*//'`
+fi
+
+AC_DEFINE_UNQUOTED(VERSION_MAJOR, $major, [major version number])
+AC_DEFINE_UNQUOTED(VERSION_MINOR, $minor, [minor version number])
+AC_DEFINE_UNQUOTED(VERSION_MICRO, $micro, [micro version number])
+AC_DEFINE_UNQUOTED(VERSION_EXTRA, "$extra", [extra version info])
+])
+
+
+dnl define some stuff required for -XX:+PrintConfig
+
+AC_DEFUN([AC_VERSION_CONFIG],[
+AC_DEFINE_UNQUOTED(VERSION_CONFIGURE_ARGS, "$ac_configure_args", [configure arguments])
+AC_DEFINE_UNQUOTED(VERSION_CC, "$CC", [CC used])
+AC_DEFINE_UNQUOTED(VERSION_CXX, "$CXX", [CXX used])
+AC_DEFINE_UNQUOTED(VERSION_CFLAGS, "$OPT_CFLAGS $ARCH_CFLAGS $CC_FLAGS $CPPFLAGS", [CFLAGS used])
+AC_DEFINE_UNQUOTED(VERSION_CXXFLAGS, "$OPT_CXXFLAGS $ARCH_CXXFLAGS $CXX_FLAGS $CPPFLAGS", [CXXFLAGS used])
+])
index 9bf7c0588469488b08f0d89c3e38cb604f1b8582..0745caa7b7970e60a295b36a771891e32ec6d530 100644 (file)
 #include "native/jni.hpp"
 #include "native/native.hpp"
 
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/jvmti.h"
-# include "native/jvmti/cacaodbg.h"
-#endif
-
 #include "vm/os.hpp"
 #include "vm/vm.hpp"
 
@@ -160,12 +155,6 @@ int main(int argc, char **argv)
 
        (void) VM_create(&vm, &env, vm_args);
 
-#if defined(ENABLE_JVMTI)
-# error This should be a JVMTI function.
-       Mutex_init(&dbgcomlock);
-       if (jvmti) jvmti_set_phase(JVMTI_PHASE_START);
-#endif
-
 #if defined(ENABLE_LIBJVM)
        libjvm_vm_run = os::dlsym(libjvm_handle, "vm_run");
 
index c3e00384cabd03751410120125a8d08eeb40dd85..38edd13b7637deafddc01988818a040d94c5ba60 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <stdint.h>
 #include <stdlib.h>
-#include <sys/mman.h> /* REMOVEME */
 
 #include "threads/mutex.hpp"
 #include "threads/thread.hpp"
index 0ef0cf3f0909c0a95022080a7582c783770644c1..55eedeb0fb0a97f7228dd3719671a788c88af39f 100644 (file)
 
 #include <stdlib.h>
 
-#if defined(HAVE_SYS_MMAN_H)
-# include <sys/mman.h>
-#endif
-
 #include "vm/types.h"
 
 #include "boehm-gc/include/gc.h"
@@ -44,6 +40,7 @@
 #include "vm/global.h"
 #include "vm/loader.hpp"
 #include "vm/options.h"
+#include "vm/os.hpp"
 #include "vm/vm.hpp"
 
 
index 6fcaf5a7a42b0e5192f0252bb278437c3394b656..07646cb1a5d1b28d3a6138dd1742e1d6797b4bb3 100644 (file)
@@ -27,9 +27,9 @@
 #include "mm/tlh.h"
 
 #include "vm/global.h"
+#include "vm/os.hpp"
 
 #include <assert.h>
-#include <sys/mman.h>
 
 static const int TLH_MAX_SIZE = (20 * 1024 * 1024);
 
index f6eb7082a502a5a70239897fd48a54549b198e89..6e850fd2bac0db539175b06ad3fe7c06ea6b6b8a 100644 (file)
@@ -2890,7 +2890,7 @@ void _Jv_JNI_Release##name##ArrayElements(JNIEnv *env, type##Array array,  \
 }
 
 JNI_RELEASE_ARRAY_ELEMENTS(Boolean, jboolean, boolean, u1)
-JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    int8_t)
+JNI_RELEASE_ARRAY_ELEMENTS(Byte,    jbyte,    byte,    s1)
 JNI_RELEASE_ARRAY_ELEMENTS(Char,    jchar,    char,    u2)
 JNI_RELEASE_ARRAY_ELEMENTS(Short,   jshort,   short,   s2)
 JNI_RELEASE_ARRAY_ELEMENTS(Int,     jint,     int,     s4)
@@ -2921,7 +2921,7 @@ void _Jv_JNI_Get##name##ArrayRegion(JNIEnv *env, type##Array array,     \
 }
 
 JNI_GET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
-JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    int8_t)
+JNI_GET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
 JNI_GET_ARRAY_REGION(Char,    jchar,    char,    u2)
 JNI_GET_ARRAY_REGION(Short,   jshort,   short,   s2)
 JNI_GET_ARRAY_REGION(Int,     jint,     int,     s4)
@@ -2952,7 +2952,7 @@ void _Jv_JNI_Set##name##ArrayRegion(JNIEnv *env, type##Array array,          \
 }
 
 JNI_SET_ARRAY_REGION(Boolean, jboolean, boolean, u1)
-JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    int8_t)
+JNI_SET_ARRAY_REGION(Byte,    jbyte,    byte,    s1)
 JNI_SET_ARRAY_REGION(Char,    jchar,    char,    u2)
 JNI_SET_ARRAY_REGION(Short,   jshort,   short,   s2)
 JNI_SET_ARRAY_REGION(Int,     jint,     int,     s4)
@@ -2979,14 +2979,10 @@ jint jni_RegisterNatives(JNIEnv* env, jclass clazz, const JNINativeMethod* metho
 
        classinfo* c = LLNI_classinfo_unwrap(clazz);
 
-       /* XXX: if implemented this needs a call to jvmti_NativeMethodBind
-       if (jvmti) jvmti_NativeMethodBind(method, address,  new_address_ptr);
-       */
-
        NativeMethods& nm = VM::get_current()->get_nativemethods();
        nm.register_methods(c->name, methods, nMethods);
 
-    return 0;
+       return 0;
 }
 
 
index bc47238e881de7587ce3fe5a815a7cfa93748e92..5515218363e8f88cbeac21682ac5d3dd05734205 100644 (file)
@@ -47,6 +47,7 @@
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/os.hpp"
@@ -452,6 +453,9 @@ void* NativeMethods::resolve_method(methodinfo* m)
                exceptions_throw_unsatisfiedlinkerror(m->name);
        }
 
+       // Hook point just after method resolving finished.
+       Hook::native_resolved(m, symbol, &symbol);
+
        return symbol;
 }
 
@@ -500,12 +504,8 @@ void* NativeLibrary::open()
                if (opt_verbosejni)
                        printf("failed ]\n");
 
-               if (opt_verbose) {
-                       log_start();
-                       log_print("NativeLibrary::open: os::dlopen failed: ");
-                       log_print(os::dlerror());
-                       log_finish();
-               }
+               if (opt_PrintWarnings)
+                       log_println("NativeLibrary::open: os::dlopen failed: %s", os::dlerror());
 
                return NULL;
        }
@@ -540,12 +540,8 @@ void NativeLibrary::close()
                if (opt_verbosejni)
                        printf("failed ]\n");
 
-               if (opt_verbose) {
-                       log_start();
-                       log_print("NativeLibrary::close: os::dlclose failed: ");
-                       log_print(os::dlerror());
-                       log_finish();
-               }
+               if (opt_PrintWarnings)
+                       log_println("NativeLibrary::close: os::dlclose failed: %s", os::dlerror());
        }
 
        if (opt_verbosejni)
index 30efeaa2cc45d069883695cc8182088208cc76f6..520a4018f539d5d92d86db132171d74e72f7e3f9 100644 (file)
@@ -25,9 +25,6 @@
 
 #include "config.h"
 
-#include <sys/stat.h>
-#include <sys/mman.h>
-#include <fcntl.h>
 #include <errno.h>
 #include <zlib.h>
 
@@ -45,6 +42,7 @@
 #include "vm/array.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/javaobjects.hpp"
+#include "vm/os.hpp"
 #include "vm/string.hpp"
 #include "vm/types.h"
 #include "vm/vm.hpp" /* REMOVE ME: temporarily */
index cf99a13a98df8356fd8e6cb9236e796782aa4cb7..b03e49c2d4e7eca95492b8603b7d6200a1a6f33b 100644 (file)
@@ -30,7 +30,6 @@
 #include <netdb.h>
 #include <unistd.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 
 #include "vm/types.h"
 
index ac38a3751ed2a2cf2f4a2b5c34f97c354fb8f352..8d4fa016b57107a5a144bc658b0f2d0a965d9dbf 100644 (file)
@@ -109,20 +109,9 @@ JNIEXPORT void JNICALL Java_java_lang_Object_notifyAll(JNIEnv *env, jobject _thi
  */
 JNIEXPORT void JNICALL Java_java_lang_Object_wait(JNIEnv *env, jobject _this, jlong timeout)
 {
-#if defined(ENABLE_JVMTI)
-       /* Monitor Wait */
-       if (jvmti) jvmti_MonitorWaiting(true, _this, timeout);
-#endif
-
 #if defined(ENABLE_THREADS)
        lock_wait_for_object((java_handle_t *) _this, timeout, 0);
 #endif
-
-#if defined(ENABLE_JVMTI)
-       /* Monitor Waited */
-       /* XXX: How do you know if wait timed out ?*/
-       if (jvmti) jvmti_MonitorWaiting(false, _this, 0);
-#endif
 }
 
 } // extern "C"
index c00c3e9a45402de02189d21b77698ece61da2cfd..edf439da894b15bf71518e41a7f46850f72738e5 100644 (file)
@@ -39,6 +39,7 @@
 #include "toolbox/logging.hpp"
 
 #include "vm/classcache.hpp"
+#include "vm/options.h"
 #include "vm/utf8.h"
 #include "vm/vm.hpp"
 
@@ -68,9 +69,12 @@ JNIEXPORT jint JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_ge
  */
 JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount(JNIEnv *env, jclass clazz)
 {
-       log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_getUnloadedClassCount: IMPLEMENT ME!");
+       int32_t count;
+
+       // XXX Fix this once we support class unloading!
+       count = 0;
 
-       return 0;
+       return count;
 }
 
 
@@ -81,10 +85,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_g
  */
 JNIEXPORT jboolean JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
 {
-/*     return _Jv_jvm->Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose; */
-#warning Move to C++
-       log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_isVerbose: MOVE TO C++!");
-       return 0;
+       return opt_verboseclass;
 }
 
 
@@ -95,9 +96,7 @@ JNIEXPORT jboolean JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImp
  */
 JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, jboolean verbose)
 {
-/*     _Jv_jvm->Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_verbose = verbose; */
-#warning Move to C++
-       log_println("Java_gnu_java_lang_management_VMClassLoadingMXBeanImpl_setVerbose: MOVE TO C++!");
+       opt_verboseclass = verbose;
 }
 
 } // extern "C"
index 96a848d11eae6c1da2c5f4bc0819ee24fa61c631..55952ab6864006874e2dab40d1a7179125ed0773 100644 (file)
 # include "native/vm/include/gnu_java_lang_management_VMMemoryMXBeanImpl.h"
 #endif
 
-#include "vm/jit/builtin.hpp"
 #include "vm/class.hpp"
 #include "vm/global.h"
-#include "vm/loader.hpp"               /* XXX only for load_class_bootstrap */
+#include "vm/javaobjects.hpp"
 #include "vm/options.h"
 #include "vm/vm.hpp"
 
@@ -54,50 +53,17 @@ extern "C" {
  */
 JNIEXPORT jobject JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getHeapMemoryUsage(JNIEnv *env, jclass clazz)
 {
-       classinfo     *class_java_lang_management_MemoryUsage;
-       java_handle_t *o;
-       methodinfo    *m;
-       int64_t        init;
-       int64_t        used;
-       int64_t        commited;
-       int64_t        maximum;
+       // Get values from the VM.
+       // XXX If we ever support more than one VM, change this.
+       int64_t init     = opt_heapstartsize;
+       int64_t used     = gc_get_total_bytes();
+       int64_t commited = gc_get_heap_size();
+       int64_t maximum  = gc_get_max_heap_size();
 
-       /* get the class */
-       /* XXX optimize me! sometime... */
+       // Construct a new java.lang.management.MemoryUsage object.
+       java_lang_management_MemoryUsage jlmmu(init, used, commited, maximum);
 
-       if (!(class_java_lang_management_MemoryUsage = load_class_bootstrap(utf_new_char("java/lang/management/MemoryUsage"))))
-               return false;
-
-       /* create the object */
-
-       o = builtin_new(class_java_lang_management_MemoryUsage);
-       
-       if (o == NULL)
-               return NULL;
-
-       /* find initializer */
-
-       m = class_findmethod(class_java_lang_management_MemoryUsage,
-                                                utf_init, utf_new_char("(JJJJ)V"));
-                                                     
-       /* initializer not found */
-
-       if (m == NULL)
-               return NULL;
-
-       /* get values from the VM */
-       /* XXX if we ever support more than one VM, change this */
-
-       init     = opt_heapstartsize;
-       used     = gc_get_total_bytes();
-       commited = gc_get_heap_size();
-       maximum  = gc_get_max_heap_size();
-
-       /* call initializer */
-
-       (void) vm_call_method(m, o, init, used, commited, maximum);
-
-       return (jobject) o;
+       return jlmmu.get_handle();
 }
 
 
@@ -134,10 +100,7 @@ JNIEXPORT jint JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_getObjec
  */
 JNIEXPORT jboolean JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose(JNIEnv *env, jclass clazz)
 {
-/*     return _Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose; */
-#warning Move to C++
-       log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVerbose: MOVE TO C++!");
-       return 0;
+       return opt_verbosegc;
 }
 
 
@@ -148,9 +111,7 @@ JNIEXPORT jboolean JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_isVe
  */
 JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose(JNIEnv *env, jclass clazz, jboolean verbose)
 {
-/*     _Jv_jvm->Java_gnu_java_lang_management_VMMemoryMXBeanImpl_verbose = verbose; */
-#warning Move to C++
-       log_println("Java_gnu_java_lang_management_VMMemoryMXBeanImpl_setVerbose: MOVE TO C++!");
+       opt_verbosegc = verbose;
 }
 
 } // extern "C"
index 359931c254fe82d3b79a60699afaa6a63c062460..dd11f7c4628ea0cea176b985e49956ac09ba8094 100644 (file)
@@ -36,6 +36,8 @@
 # include "native/vm/include/gnu_java_lang_management_VMThreadMXBeanImpl.h"
 #endif
 
+#include "threads/threadlist.hpp"
+
 #include "toolbox/logging.hpp"
 
 #include "vm/classcache.hpp"
@@ -92,10 +94,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getCurr
  */
 JNIEXPORT jint JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getPeakThreadCount(JNIEnv *env, jclass clazz)
 {
-/*     return _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount; */
-#warning Move to C++
-       log_println("Java_gnu_java_lang_management_ThreadMXBean_getPeakThreadCount: MOVE TO C++!");
-       return 0;
+       return ThreadList::get_peak_of_active_java_threads();
 }
 
 
@@ -145,10 +144,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getThre
  */
 JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTotalStartedThreadCount(JNIEnv *env, jclass clazz)
 {
-/*     return _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount; */
-#warning Move to C++
-       log_println("Java_gnu_java_lang_management_ThreadMXBean_getTotalStartedThreadCount: MOVE TO C++!");
-       return 0;
+       return ThreadList::get_number_of_started_java_threads();
 }
 
 
@@ -159,10 +155,7 @@ JNIEXPORT jlong JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_getTota
  */
 JNIEXPORT void JNICALL Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount(JNIEnv *env, jclass clazz)
 {
-/*     _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
-/*             _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
-#warning Move to C++
-       log_println("Java_gnu_java_lang_management_VMThreadMXBeanImpl_resetPeakThreadCount: MOVE TO C++!");
+       return ThreadList::reset_peak_of_active_java_threads();
 }
 
 } // extern "C"
index 10e2d63eba6ba5e0b4a192d502e18488107e764e..65d5f96ed8943f46b0899d327ed1c2f0f8aa0dc0 100644 (file)
@@ -27,7 +27,6 @@
 
 #include <assert.h>
 #include <stdint.h>
-#include <sys/stat.h>
 
 #include "mm/memory.hpp"
 
@@ -57,6 +56,7 @@
 #include "vm/linker.hpp"
 #include "vm/loader.hpp"
 #include "vm/options.h"
+#include "vm/os.hpp"
 #include "vm/primitive.hpp"
 #include "vm/statistics.h"
 #include "vm/string.hpp"
index 769d1a071f9390dd00bc4aec1c55734bc54db02d..95e7e8cbb350f93c36213e1fdb468499cf0e0d11 100644 (file)
@@ -108,20 +108,9 @@ JNIEXPORT void JNICALL Java_java_lang_VMObject_notifyAll(JNIEnv* env, jclass cla
  */
 JNIEXPORT void JNICALL Java_java_lang_VMObject_wait(JNIEnv* env, jclass clazz, jobject o, jlong ms, jint ns)
 {
-#if defined(ENABLE_JVMTI)
-       /* Monitor Wait */
-       if (jvmti) jvmti_MonitorWaiting(true, o, ms);
-#endif
-
 #if defined(ENABLE_THREADS)
        lock_wait_for_object(o, ms, ns);
 #endif
-
-#if defined(ENABLE_JVMTI)
-       /* Monitor Waited */
-       /* XXX: How do you know if wait timed out ?*/
-       if (jvmti) jvmti_MonitorWaiting(false, o, 0);
-#endif
 }
 
 } // extern "C"
index 2a885667889121a6f8d78e290b960cbbd9ce1ee2..d22fb2bcd7877c97e7be4c7353c8dfb97cfd4675 100644 (file)
 #include <stdint.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <sys/utsname.h>
-
-#if defined(__DARWIN__)
-# if defined(__POWERPC__)
-#  define OS_INLINE    /* required for <libkern/ppc/OSByteOrder.h> */
-# endif
-# include <mach/mach.h>
-#endif
 
 #include "mm/memory.hpp"
 #include "mm/gc.hpp"
index 4b2e9bee4350e9471c98124d5956309f021c7343..6ad36aa861aa5ef988b8d0217ae86e7cec0d270b 100644 (file)
@@ -124,8 +124,16 @@ void nativevm_preinit(void)
        HPI& hpi = vm->get_hpi();
        hpi.initialize();
 
+       _Jv_sun_misc_Perf_init();
        _Jv_sun_misc_Unsafe_init();
 
+#  if !defined(NDEBUG)
+       // Sanity check current time in milliseconds, because negative values
+       // might confuse OpenJDKs sanity checks.
+       if (opt_PrintWarnings && (builtin_currenttimemillis() < 0))
+               log_println("nativevm_preinit: Current time in milliseconds is negative, please check your time!");
+#  endif
+
 # else
 #  error unknown classpath configuration
 # endif
index 9f651a6cec99c0b7de0b6531dc69fbb7882241af..6410cb94e686782c54f61f0a6ee200ed8c842205 100644 (file)
@@ -66,6 +66,7 @@ void _Jv_sun_reflect_ConstantPool_init();
 
 # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
 
+void _Jv_sun_misc_Perf_init();
 void _Jv_sun_misc_Unsafe_init();
 
 # else
index 1e5bfd3bd19ff7cab27660b9c572ac09b8e0c953..f917a10ef407f6bb5fb0dfb674ae17d5f85340d7 100644 (file)
@@ -1,6 +1,6 @@
 ## src/native/vm/openjdk/Makefile.am
 ##
-## Copyright (C) 2007, 2008
+## Copyright (C) 2007, 2008, 2009
 ## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 ##
 ## This file is part of CACAO.
@@ -33,7 +33,8 @@ libnativevmcore_la_SOURCES = \
        hpi.hpp \
        jvm.cpp \
        management.cpp \
-       management.hpp
+       management.hpp \
+       sun_misc_Perf.cpp
 
 
 ## Local variables:
index 5186c6add1311a9e017e60cdaecdc31c06a49fd2..945f22157a3d6556bc1e28753fa81e496a0d661b 100644 (file)
@@ -1,6 +1,6 @@
 /* src/native/vm/openjdk/jvm.cpp - HotSpot VM interface functions
 
-   Copyright (C) 2007, 2008
+   Copyright (C) 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
    Copyright (C) 2009 Theobroma Systems Ltd.
 
@@ -38,8 +38,6 @@
 #include <sys/ioctl.h>
 #endif
 
-#include <sys/socket.h>
-#include <sys/stat.h>
 #include <sys/types.h>
 
 // Include our JNI header before the JVM headers, because the JVM
@@ -2147,7 +2145,23 @@ jboolean JVM_IsThreadAlive(JNIEnv* env, jobject jthread)
 
 void JVM_SuspendThread(JNIEnv* env, jobject jthread)
 {
-       log_println("JVM_SuspendThread: Deprecated.  Not implemented.");
+       java_handle_t *h;
+       threadobject  *t;
+
+       TRACEJVMCALLS(("JVM_SuspendThread(env=%p, jthread=%p)", env, jthread));
+
+       if (opt_PrintWarnings)
+               log_println("JVM_SuspendThread: Deprecated, do not use!");
+
+       h = (java_handle_t *) jthread;
+       t = thread_get_thread(h);
+
+       /* The threadobject is null when a thread is created in Java. */
+
+       if (t == NULL)
+               return;
+
+       threads_suspend_thread(t, SUSPEND_REASON_JAVA);
 }
 
 
@@ -2155,7 +2169,23 @@ void JVM_SuspendThread(JNIEnv* env, jobject jthread)
 
 void JVM_ResumeThread(JNIEnv* env, jobject jthread)
 {
-       log_println("JVM_ResumeThread: Deprecated.  Not implemented.");
+       java_handle_t *h;
+       threadobject  *t;
+
+       TRACEJVMCALLS(("JVM_ResumeThread(env=%p, jthread=%p)", env, jthread));
+
+       if (opt_PrintWarnings)
+               log_println("JVM_ResumeThread: Deprecated, do not use!");
+
+       h = (java_handle_t *) jthread;
+       t = thread_get_thread(h);
+
+       /* The threadobject is null when a thread is created in Java. */
+
+       if (t == NULL)
+               return;
+
+       threads_resume_thread(t, SUSPEND_REASON_JAVA);
 }
 
 
@@ -3187,7 +3217,7 @@ jobjectArray JVM_GetAllThreads(JNIEnv *env, jclass dummy)
 {
        // Get a list of all active threads.
        List<threadobject*> active_threads;
-       ThreadList::get_active_threads(active_threads);
+       ThreadList::get_active_java_threads(active_threads);
 
        // Allocate array to hold the java.lang.Thread objects.
        int32_t length = active_threads.size();
@@ -3560,7 +3590,15 @@ jobjectArray JVM_GetThreadStateNames(JNIEnv* env, jint javaThreadState, jintArra
 
 void JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size)
 {
-       log_println("JVM_GetVersionInfo: IMPLEMENT ME!");
+       TRACEJVMCALLS(("JVM_GetVersionInfo(env=%p, info=%p, info_size=%zd)", env, info, info_size));
+
+       memset(info, 0, info_size);
+
+       info->jvm_version = ((VERSION_MAJOR & 0xff) << 24) | ((VERSION_MINOR & 0xff) << 16) | (VERSION_MICRO & 0xff);
+       info->update_version = 0;
+       info->special_update_version = 0;
+       info->is_attach_supported = 0;
+       info->is_kernel_jvm = 0;
 }
 
 
index 5bfb6c63b8eb90392fb66924bb50aa6f5be14697..0b7098b9370cf140231c19ace6fc7977a530d793 100644 (file)
@@ -1,6 +1,8 @@
  /* src/native/vm/openjdk/management.cpp - HotSpot management interface functions
 
-   Copyright (C) 2008 Theobroma Systems Ltd.
+   Copyright (C) 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2008, 2009 Theobroma Systems Ltd.
 
    This file is part of CACAO.
 
 
 #include "native/vm/openjdk/management.hpp"
 
+#include "threads/threadlist.hpp"
+
 #include "toolbox/logging.hpp"
 
+#include "vm/array.hpp"
+#include "vm/classcache.hpp"
+#include "vm/globals.hpp" // XXX Remove!!!
+#include "vm/options.h"
 #include "vm/os.hpp"
 #include "vm/vm.hpp"
 
 
+/* debugging macros ***********************************************************/
+
+#if !defined(NDEBUG)
+
+# define TRACEJMMCALLS(x)               \
+       do {                                \
+               if (opt_TraceJMMCalls) {        \
+                       log_println x;              \
+               }                               \
+       } while (0)
+
+#else
+
+# define TRACEJMMCALLS(x)
+
+#endif
+
+
 /**
  * Initialize the Management subsystem.
  */
@@ -80,16 +106,12 @@ const jmmOptionalSupport& Management::get_optional_support() const
 // Interface functions are exported as C functions.
 extern "C" {
 
-// Returns a version string and sets major and minor version if the
-// input parameters are non-null.
 jint jmm_GetVersion(JNIEnv* env)
 {
        return JMM_VERSION;
 }
 
 
-// Gets the list of VM monitoring and management optional supports
-// Returns 0 if succeeded; otherwise returns non-zero.
 jint jmm_GetOptionalSupport(JNIEnv* env, jmmOptionalSupport* support)
 {
        if (support == NULL) {
@@ -121,15 +143,25 @@ jobjectArray jmm_GetInputArgumentArray(JNIEnv* env)
 
 jobjectArray jmm_GetMemoryPools(JNIEnv* env, jobject obj)
 {
-       log_println("jmm_GetMemoryPools: IMPLEMENT ME!");
-       return NULL;
+       TRACEJMMCALLS(("jmm_GetMemoryPools(env=%p, obj=%p)", env, obj));
+
+       // XXX This should be an array of java/lang/management/MemoryPoolMXBean.
+       log_println("jmm_GetMemoryPools: FIX ME!");
+       ObjectArray oa(0, class_java_lang_String);
+
+       return oa.get_handle();
 }
 
 
 jobjectArray jmm_GetMemoryManagers(JNIEnv* env, jobject obj)
 {
-       log_println("jmm_GetMemoryManagers: IMPLEMENT ME!");
-       return NULL;
+       TRACEJMMCALLS(("jmm_GetMemoryManagers(env=%p, obj=%p)", env, obj));
+
+       // XXX This should be an array of java/lang/management/MemoryManagerMXBean.
+       log_println("jmm_GetMemoryManagers: FIX ME!");
+       ObjectArray oa(0, class_java_lang_String);
+
+       return oa.get_handle();
 }
 
 
@@ -176,22 +208,84 @@ jobject jmm_GetMemoryUsage(JNIEnv* env, jboolean heap)
 
 jboolean jmm_GetBoolAttribute(JNIEnv* env, jmmBoolAttribute att)
 {
-       log_println("jmm_GetBoolAttribute: IMPLEMENT ME!");
-       return 0;
+       TRACEJMMCALLS(("jmm_GetBoolAttribute(env=%p, att=%d)", env, att));
+
+       jboolean result;
+
+       switch (att) {
+       case JMM_VERBOSE_GC:
+               result = opt_verbosegc;
+               break;
+       case JMM_VERBOSE_CLASS:
+               result = opt_verboseclass;
+               break;
+       default:
+               log_println("jmm_GetBoolAttribute: Unknown attribute %d", att);
+               return false;
+       }
+
+       return result;
 }
 
 
 jboolean jmm_SetBoolAttribute(JNIEnv* env, jmmBoolAttribute att, jboolean flag)
 {
-       log_println("jmm_SetBoolAttribute: IMPLEMENT ME!");
-       return 0;
+       TRACEJMMCALLS(("jmm_SetBoolAttribute(env=%p, att=%d, flag=%d)", env, att, flag));
+
+       switch (att) {
+       case JMM_VERBOSE_GC:
+               opt_verbosegc = flag;
+               break;
+       case JMM_VERBOSE_CLASS:
+               opt_verboseclass = flag;
+               break;
+       default:
+               log_println("jmm_SetBoolAttribute: Unknown attribute %d", att);
+               return false;
+       }
+
+       return true;
 }
 
 
 jlong jmm_GetLongAttribute(JNIEnv* env, jobject obj, jmmLongAttribute att)
 {
-       log_println("jmm_GetLongAttribute: IMPLEMENT ME!");
-       return 0;
+       TRACEJMMCALLS(("jmm_GetLongAttribute(env=%p, obj=%p, att=%d)", env, obj, att));
+
+       jlong result;
+
+       switch (att) {
+       case JMM_CLASS_LOADED_COUNT:
+               result = classcache_get_loaded_class_count();
+               break;
+       case JMM_CLASS_UNLOADED_COUNT:
+               // XXX Fix this once we support class unloading!
+               result = 0;
+               break;
+       case JMM_THREAD_TOTAL_COUNT:
+               result = ThreadList::get_number_of_started_java_threads();
+               break;
+       case JMM_THREAD_LIVE_COUNT:
+               result = ThreadList::get_number_of_active_java_threads();
+               break;
+       case JMM_THREAD_PEAK_COUNT:
+               result = ThreadList::get_peak_of_active_java_threads();
+               break;
+       case JMM_THREAD_DAEMON_COUNT:
+               result = ThreadList::get_number_of_daemon_java_threads();
+               break;
+       case JMM_JVM_INIT_DONE_TIME_MS:
+               result = VM::get_current()->get_inittime();
+               break;
+       case JMM_OS_PROCESS_ID:
+               result = os::getpid();
+               break;
+       default:
+               log_println("jmm_GetLongAttribute: Unknown attribute %d", att);
+               return -1;
+       }
+
+       return result;
 }
 
 
@@ -225,8 +319,18 @@ jobjectArray jmm_GetLoadedClasses(JNIEnv* env)
 
 jboolean jmm_ResetStatistic(JNIEnv* env, jvalue obj, jmmStatisticType type)
 {
-       log_println("jmm_ResetStatistic: IMPLEMENT ME!");
-       return 0;
+       TRACEJMMCALLS(("jmm_ResetStatistic(env=%p, obj=%p, type=%d)", env, obj, type));
+
+       switch (type) {
+       case JMM_STAT_PEAK_THREAD_COUNT:
+               ThreadList::reset_peak_of_active_java_threads();
+               break;
+       default:
+               log_println("jmm_ResetStatistic: Unknown statistic type %d", type);
+               return false;
+       }
+
+       return true;
 }
 
 
diff --git a/src/native/vm/openjdk/sun_misc_Perf.cpp b/src/native/vm/openjdk/sun_misc_Perf.cpp
new file mode 100644 (file)
index 0000000..8fb75bb
--- /dev/null
@@ -0,0 +1,165 @@
+/* src/native/vm/openjdk/sun_misc_Perf.cpp - sun/misc/Perf
+
+   Copyright (C) 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include "native/jni.hpp"
+#include "native/native.hpp"
+
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+// Native functions are exported as C functions.
+extern "C" {
+
+/*
+ * Class:     sun/misc/Perf
+ * Method:    registerNatives
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Perf_registerNatives(JNIEnv *env, jclass clazz)
+{
+       /* The native methods of this function are already registered in
+          _Jv_sun_misc_Perf_init() which is called during VM
+          startup. */
+}
+
+
+/*
+ * Class:     sun/misc/Perf
+ * Method:    attach
+ * Signature: (Ljava/lang/String;II)Ljava/nio/ByteBuffer;
+ */
+JNIEXPORT jobject JNICALL Java_sun_misc_Perf_attach(JNIEnv *env, jobject _this, jstring user, jint lvmid, jint mode)
+{
+       log_println("Java_sun_misc_Perf_attach: Not supported!");
+       return NULL;
+}
+
+
+/*
+ * Class:     sun/misc/Perf
+ * Method:    createByteArray
+ * Signature: (Ljava/lang/String;II[BI)Ljava/nio/ByteBuffer;
+ */
+JNIEXPORT jobject JNICALL Java_sun_misc_Perf_createByteArray(JNIEnv *env, jobject _this, jstring name, jint variability, jint units, jbyteArray value, jint max_length)
+{
+       log_println("Java_sun_misc_Perf_createByteArray: Not supported!");
+       return NULL;
+}
+
+
+/*
+ * Class:     sun/misc/Perf
+ * Method:    createLong
+ * Signature: (Ljava/lang/String;IIJ)Ljava/nio/ByteBuffer;
+ */
+JNIEXPORT jobject JNICALL Java_sun_misc_Perf_createLong(JNIEnv *env, jobject _this, jstring name, jint variability, jint units, jlong value)
+{
+       log_println("Java_sun_misc_Perf_createLong: Not supported!");
+       return NULL;
+}
+
+
+/*
+ * Class:     sun/misc/Perf
+ * Method:    detach
+ * Signature: (Ljava/nio/ByteBuffer;)V
+ */
+JNIEXPORT void JNICALL Java_sun_misc_Perf_detach(JNIEnv *env, jobject _this, jobject bb)
+{
+       log_println("Java_sun_misc_Perf_detach: Not supported!");
+}
+
+
+/*
+ * Class:     sun/misc/Perf
+ * Method:    highResCounter
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Perf_highResCounter(JNIEnv *env, jobject _this)
+{
+       log_println("Java_sun_misc_Perf_highResCounter: IMPLEMENT ME!");
+       return 0;
+}
+
+
+/*
+ * Class:     sun/misc/Perf
+ * Method:    highResFrequency
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_sun_misc_Perf_highResFrequency(JNIEnv *env, jobject _this)
+{
+       log_println("Java_sun_misc_Perf_highResFrequency: IMPLEMENT ME!");
+       return 0;
+}
+
+} // extern "C"
+
+
+/* native methods implemented by this file ************************************/
+
+static JNINativeMethod methods[] = {
+       { (char*) "registerNatives",  (char*) "()V",                                            (void*) (uintptr_t) &Java_sun_misc_Perf_registerNatives  },
+       { (char*) "attach",           (char*) "(Ljava/lang/String;II)Ljava/nio/ByteBuffer;",    (void*) (uintptr_t) &Java_sun_misc_Perf_attach           },
+       { (char*) "createByteArray",  (char*) "(Ljava/lang/String;II[BI)Ljava/nio/ByteBuffer;", (void*) (uintptr_t) &Java_sun_misc_Perf_createByteArray  },
+       { (char*) "createLong",       (char*) "(Ljava/lang/String;IIJ)Ljava/nio/ByteBuffer;",   (void*) (uintptr_t) &Java_sun_misc_Perf_createLong       },
+       { (char*) "detach",           (char*) "(Ljava/nio/ByteBuffer;)V",                       (void*) (uintptr_t) &Java_sun_misc_Perf_detach           },
+       { (char*) "highResCounter",   (char*) "()J",                                            (void*) (uintptr_t) &Java_sun_misc_Perf_highResCounter   },
+       { (char*) "highResFrequency", (char*) "()J",                                            (void*) (uintptr_t) &Java_sun_misc_Perf_highResFrequency },
+};
+
+
+/* _Jv_sun_misc_Perf_init ******************************************************
+
+   Register native functions.
+
+*******************************************************************************/
+
+void _Jv_sun_misc_Perf_init(void)
+{
+       utf* u = utf_new_char("sun/misc/Perf");
+
+       NativeMethods& nm = VM::get_current()->get_nativemethods();
+       nm.register_methods(u, methods, NATIVE_METHODS_COUNT);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index baeae5775df920f498e530639e7f62d3babf676e..7e76974657ac41983f55297edf38b74f23e6d9a8 100644 (file)
@@ -1157,6 +1157,36 @@ JNIEXPORT void JNICALL Java_sun_misc_Unsafe_park(JNIEnv *env, jobject _this, jbo
        threads_park(isAbsolute, time);
 }
 
+
+/*
+ * Class:     sun/misc/Unsafe
+ * Method:    getLoadAverage
+ * Signature: ([DI)I
+ */
+JNIEXPORT jint JNICALL Java_sun_misc_Unsafe_getLoadAverage(JNIEnv *env, jobject _this, jdoubleArray loadavg, jint nelem)
+{
+       DoubleArray da(loadavg);
+
+#define MAX_SAMPLES 3
+
+       // Check the passed number of samples.
+       if ((nelem < 0) || (nelem > da.get_length()) || nelem > MAX_SAMPLES) {
+               exceptions_throw_arrayindexoutofboundsexception();
+               return -1;
+       }
+
+       // Actually retrieve samples.
+       double values[MAX_SAMPLES];
+       int result = os::getloadavg(values, nelem);
+
+       // Save samples into the given array.
+       for (int i = 0; i < result; i++) {
+               da.set_element(i, values[i]);
+       }
+
+       return result;
+}
+
 } // extern "C"
 
 
@@ -1235,6 +1265,7 @@ static JNINativeMethod methods[] = {
        { (char*) "putOrderedLong",         (char*) "(Ljava/lang/Object;JJ)V",                                    (void*) (uintptr_t) &Java_sun_misc_Unsafe_putOrderedLong                   },
        { (char*) "unpark",                 (char*) "(Ljava/lang/Object;)V",                                      (void*) (uintptr_t) &Java_sun_misc_Unsafe_unpark                           },
        { (char*) "park",                   (char*) "(ZJ)V",                                                      (void*) (uintptr_t) &Java_sun_misc_Unsafe_park                             },
+       { (char*) "getLoadAverage",         (char*) "([DI)I",                                                     (void*) (uintptr_t) &Java_sun_misc_Unsafe_getLoadAverage                   },
 };
 
 
index e8bbce33cbae7e69926bd38176d5acd496ef0722..d4e7c6b1112148eeced9609fa176edf35e0ee0ee 100644 (file)
 # include "threads/posix/mutex-posix.hpp"
 #endif
 
+#if __cplusplus
+
+/**
+ * Helper class used to implicitly acquire and release a mutex
+ * within a method scope.
+ */
+class MutexLocker {
+private:
+       Mutex& _mutex;
+
+public:
+       MutexLocker(Mutex& mutex) : _mutex(mutex) { _mutex.lock(); }
+       ~MutexLocker()                            { _mutex.unlock(); }
+};
+
+#endif
+
 #endif /* _MUTEX_HPP */
 
 
index b91e50f1d6725fb3149f1a49ff4fb6d9922417da..8e855c90bed103e4784f7f862137f0f72a42b5f5 100644 (file)
@@ -66,6 +66,7 @@
 #include "vm/exceptions.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/javaobjects.hpp"
 #include "vm/options.h"
 #include "vm/os.hpp"
 
 #include "vm/jit/asmpart.h"
 
-#if !defined(__DARWIN__)
+#if defined(__DARWIN__)
+
+typedef struct {
+       Mutex* mutex;
+       Condition* cond;
+       int value;
+} sem_t;
+
+#else
 # include <semaphore.h>
 #endif
 
 # include "mm/boehm-gc/include/gc.h"
 #endif
 
-#if defined(ENABLE_JVMTI)
-#include "native/jvmti/cacaodbg.h"
-#endif
-
 
 #if defined(__DARWIN__)
 /* Darwin has no working semaphore implementation.  This one is taken
@@ -795,12 +800,8 @@ static void *threads_startup_thread(void *arg)
                thread->_global_sp = (Cell *) (intrp_thread_stack + opt_stacksize);
 #endif
 
-#if defined(ENABLE_JVMTI)
-       /* fire thread start event */
-
-       if (jvmti) 
-               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_START);
-#endif
+       // Hook point just before the threads initial method is executed.
+       Hook::thread_start(t);
 
        DEBUGTHREADS("starting", t);
 
@@ -824,17 +825,6 @@ static void *threads_startup_thread(void *arg)
                if (m == NULL)
                        vm_abort("threads_startup_thread: run() method not found in class");
 
-               /* set ThreadMXBean variables */
-
-/*             _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
-/*             _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
-
-/*             if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
-/*                     _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
-/*                     _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
-/*                             _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
-#warning Move to C++
-
 #if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
 
                // We need to start the run method of java.lang.VMThread.
@@ -854,17 +844,6 @@ static void *threads_startup_thread(void *arg)
                (void) vm_call_method(m, h);
        }
        else {
-               /* set ThreadMXBean variables */
-
-/*             _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++; */
-/*             _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++; */
-
-/*             if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount > */
-/*                     _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount) */
-/*                     _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount = */
-/*                             _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount; */
-#warning Move to C++
-
                /* call passed function, e.g. finalizer_thread */
 
                (function)();
@@ -872,22 +851,13 @@ static void *threads_startup_thread(void *arg)
 
        DEBUGTHREADS("stopping", t);
 
-#if defined(ENABLE_JVMTI)
-       /* fire thread end event */
-
-       if (jvmti)
-               jvmti_ThreadStartEnd(JVMTI_EVENT_THREAD_END);
-#endif
+       // Hook point just after the threads initial method returned.
+       Hook::thread_end(t);
 
        /* We ignore the return value. */
 
        (void) thread_detach_current_thread();
 
-       /* set ThreadMXBean variables */
-
-/*     _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount--; */
-#warning Move to C++
-
        return NULL;
 }
 
@@ -1139,134 +1109,146 @@ bool thread_detach_current_thread(void)
 }
 
 
-/* threads_suspend_thread ******************************************************
-
-   Suspend the passed thread. Execution stops until the thread
-   is explicitly resumend again.
-
-   IN:
-     reason.....Reason for suspending this thread.
-
-*******************************************************************************/
-
-bool threads_suspend_thread(threadobject *thread, s4 reason)
+/**
+ * Internal helper function which suspends the current thread. This is
+ * the core method of the suspension mechanism actually blocking the
+ * execution until the suspension reason is cleared again. Note that
+ * the current thread needs to hold the suspension mutex while calling
+ * this function.
+ */
+static void threads_suspend_self()
 {
-       /* acquire the suspendmutex */
-       thread->suspendmutex->lock();
-
-       if (thread->suspended) {
-               thread->suspendmutex->unlock();
-               return false;
-       }
+       threadobject* thread = THREADOBJECT;
 
-       /* set the reason for the suspension */
-       thread->suspend_reason = reason;
+       DEBUGTHREADS("suspending", thread);
 
-       /* send the suspend signal to the thread */
-       assert(thread != THREADOBJECT);
-       if (pthread_kill(thread->tid, SIGUSR1) != 0)
-               vm_abort("threads_suspend_thread: pthread_kill failed: %s",
-                                strerror(errno));
+       // Mark thread as suspended.
+       assert(!thread->suspended);
+       assert(thread->suspend_reason != SUSPEND_REASON_NONE);
+       thread->suspended = true;
 
-       /* REMEMBER: do not release the suspendmutex, this is done
-          by the thread itself in threads_suspend_ack().  */
+       // Acknowledge the suspension.
+       thread->suspendcond->broadcast();
 
-       return true;
-}
+#if defined(ENABLE_GC_CACAO)
+       // If we are stopping the world, we should send a global ack.
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD)
+               threads_sem_post(&suspend_ack);
+#endif
 
+       // Release the suspension mutex and wait till we are resumed.
+       thread->suspendcond->wait(thread->suspendmutex);
 
-/* threads_suspend_ack *********************************************************
+#if defined(ENABLE_GC_CACAO)
+       // XXX This is propably not ok!
+       // If we are starting the world, we should send a global ack.
+       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD)
+               threads_sem_post(&suspend_ack);
+#endif
 
-   Acknowledges the suspension of the current thread.
+       // Mark thread as not suspended.
+       assert(thread->suspended);
+       assert(thread->suspend_reason == SUSPEND_REASON_NONE);
+       thread->suspended = false;
 
-   IN:
-     pc.....The PC where the thread suspended its execution.
-     sp.....The SP before the thread suspended its execution.
+       DEBUGTHREADS("resuming", thread);
+}
 
-*******************************************************************************/
 
-#if defined(ENABLE_GC_CACAO)
-void threads_suspend_ack(u1* pc, u1* sp)
+/**
+ * Suspend the passed thread. Execution of that thread stops until the thread
+ * is explicitly resumend again.
+ *
+ * @param thread The thread to be suspended.
+ * @param reason Reason for suspending the given thread.
+ * @return True of operation was successful, false otherwise.
+ */
+bool threads_suspend_thread(threadobject *thread, int32_t reason)
 {
-       threadobject *thread;
+       // Sanity check.
+       assert(reason != SUSPEND_REASON_NONE);
 
-       thread = THREADOBJECT;
+       // Guard this with the suspension mutex.
+       MutexLocker ml(*thread->suspendmutex);
 
-       assert(thread->suspend_reason != 0);
-
-       /* TODO: remember dump memory size */
-
-       /* inform the GC about the suspension */
-       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD && gc_pending) {
+       // Check if thread is already suspended.
+       if (thread->suspended)
+               return false;
 
-               /* check if the GC wants to leave the thread running */
-               if (!gc_suspend(thread, pc, sp)) {
+       // Check if thread is in the process of suspending.
+       if (thread->suspend_reason != SUSPEND_REASON_NONE)
+               return false;
 
-                       /* REMEMBER: we do not unlock the suspendmutex because the thread
-                          will suspend itself again at a later time */
-                       return;
+       // Set the reason for suspending the thread.
+       thread->suspend_reason = reason;
 
-               }
+       if (thread == THREADOBJECT) {
+               // We already hold the suspension mutex and can suspend ourselves
+               // immediately without using signals at all.
+               threads_suspend_self();
        }
-
-       /* mark this thread as suspended and remember the PC */
-       thread->pc        = pc;
-       thread->suspended = true;
-
-       /* if we are stopping the world, we should send a global ack */
-       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
-               threads_sem_post(&suspend_ack);
+       else {
+               // Send the suspend signal to the other thread.
+               if (pthread_kill(thread->tid, SIGUSR1) != 0)
+                       os::abort_errno("threads_suspend_thread: pthread_kill failed");
+
+               // Wait for the thread to acknowledge the suspension.
+               // XXX A possible optimization would be to not wait here, but you
+               //     better think this through twice before trying it!
+               thread->suspendcond->wait(thread->suspendmutex);
        }
 
-       DEBUGTHREADS("suspending", thread);
+       return true;
+}
 
-       /* release the suspension mutex and wait till we are resumed */
-       thread->suspendcond->wait(thread->suspendmutex);
 
-       DEBUGTHREADS("resuming", thread);
+/**
+ * Resumes execution of the passed thread.
+ *
+ * @param thread The thread to be resumed.
+ * @param reason Reason for suspending the given thread.
+ * @return True of operation was successful, false otherwise.
+ */
+bool threads_resume_thread(threadobject *thread, int32_t reason)
+{
+       // Sanity check.
+       assert(thread != THREADOBJECT);
+       assert(reason != SUSPEND_REASON_NONE);
 
-       /* if we are stopping the world, we should send a global ack */
-       if (thread->suspend_reason == SUSPEND_REASON_STOPWORLD) {
-               threads_sem_post(&suspend_ack);
-       }
+       // Guard this with the suspension mutex.
+       MutexLocker ml(*thread->suspendmutex);
 
-       /* TODO: free dump memory */
+       // Check if thread really is suspended.
+       if (!thread->suspended)
+               return false;
 
-       /* release the suspendmutex */
-       thread->suspendmutex->unlock();
-}
-#endif
+       // Threads can only be resumed for the same reason they were suspended.
+       if (thread->suspend_reason != reason)
+               return false;
 
+       // Clear the reason for suspending the thread.
+       thread->suspend_reason = SUSPEND_REASON_NONE;
 
-/* threads_resume_thread *******************************************************
+       // Tell everyone that the thread should resume.
+       thread->suspendcond->broadcast();
 
-   Resumes the execution of the passed thread.
+       return true;
+}
 
-*******************************************************************************/
 
-#if defined(ENABLE_GC_CACAO)
-bool threads_resume_thread(threadobject *thread)
+/**
+ * Acknowledges the suspension of the current thread.
+ */
+void threads_suspend_ack()
 {
-       /* acquire the suspendmutex */
-       thread->suspendmutex->lock();
-
-       if (!thread->suspended) {
-               thread->suspendmutex->unlock();
-               return false;
-       }
-
-       thread->suspended = false;
-
-       /* tell everyone that the thread should resume */
-       assert(thread != THREADOBJECT);
-       thread->suspendcond->broadcast();
+       threadobject* thread = THREADOBJECT;
 
-       /* release the suspendmutex */
-       thread->suspendmutex->unlock();
+       // Guard this with the suspension mutex.
+       MutexLocker ml(*thread->suspendmutex);
 
-       return true;
+       // Suspend ourselves while holding the suspension mutex.
+       threads_suspend_self();
 }
-#endif
 
 
 /* threads_join_all_threads ****************************************************
index 7dafeae304d82d8c1c0a4f6ecabc181e920b26b9..32503c4da1a20bb7395b27ff561811d5231694c2 100644 (file)
 #define THREAD_FLAG_DAEMON      0x04    /* daemon thread                      */
 #define THREAD_FLAG_IN_NATIVE   0x08    /* currently executing native code    */
 
-#define SUSPEND_REASON_JNI       1      /* suspended from JNI                 */
-#define SUSPEND_REASON_STOPWORLD 2      /* suspended from stop-thw-world      */
+#define SUSPEND_REASON_NONE      0      /* no reason to suspend               */
+#define SUSPEND_REASON_JAVA      1      /* suspended from java.lang.Thread    */
+#define SUSPEND_REASON_STOPWORLD 2      /* suspended from stop-the-world      */
+#define SUSPEND_REASON_DUMP      3      /* suspended from threadlist dumping  */
+#define SUSPEND_REASON_JVMTI     4      /* suspended from JVMTI agent         */
 
 
 typedef struct threadobject threadobject;
@@ -211,19 +214,6 @@ inline static threadobject* thread_get_current(void);
 #include "vm/jit/intrp/intrp.h"
 #endif
 
-#if defined(__DARWIN__)
-# include <mach/mach.h>
-
-typedef struct {
-       Mutex* mutex;
-       Condition* cond;
-       int value;
-} sem_t;
-
-#else
-# include <semaphore.h>
-#endif
-
 
 // FIXME
 #ifdef __cplusplus
@@ -286,19 +276,13 @@ inline static void threads_set_current_stackframeinfo(struct stackframeinfo_t* s
 
 /* functions ******************************************************************/
 
-void threads_sem_init(sem_t *sem, bool shared, int value);
-void threads_sem_wait(sem_t *sem);
-void threads_sem_post(sem_t *sem);
-
 void threads_start_thread(threadobject *thread, functionptr function);
 
 void threads_set_thread_priority(pthread_t tid, int priority);
 
-#if defined(ENABLE_GC_CACAO)
-bool threads_suspend_thread(threadobject *thread, s4 reason);
-void threads_suspend_ack(u1* pc, u1* sp);
-bool threads_resume_thread(threadobject *thread);
-#endif
+bool threads_suspend_thread(threadobject *thread, int32_t reason);
+bool threads_resume_thread(threadobject *thread, int32_t reason);
+void threads_suspend_ack();
 
 void threads_join_all_threads(void);
 
index 5eaf0c2b15554029b7751feca22ddda1d9b7e35d..bae8161187875bfa5451d69c81704d1892f67db9 100644 (file)
@@ -80,7 +80,7 @@ bool threads_pthreads_implementation_nptl;
 
 static void          thread_create_initial_threadgroups(void);
 static void          thread_create_initial_thread(void);
-static threadobject *thread_new(void);
+static threadobject *thread_new(int32_t flags);
 
 
 /* threads_preinit *************************************************************
@@ -138,7 +138,7 @@ void threads_preinit(void)
 
        /* Create internal thread data-structure for the main thread. */
 
-       mainthread = thread_new();
+       mainthread = thread_new(THREAD_FLAG_JAVA);
 
        /* The main thread should always have index 1. */
 
@@ -146,9 +146,8 @@ void threads_preinit(void)
                vm_abort("threads_preinit: main thread index not 1: %d != 1",
                                 mainthread->index);
 
-       /* thread is a Java thread and running */
+       /* Thread is already running. */
 
-       mainthread->flags |= THREAD_FLAG_JAVA;
        mainthread->state = THREAD_STATE_RUNNABLE;
 
        /* Store the internal thread data-structure in the TSD. */
@@ -440,7 +439,7 @@ static void thread_create_initial_thread(void)
 
 *******************************************************************************/
 
-static threadobject *thread_new(void)
+static threadobject *thread_new(int32_t flags)
 {
        int32_t       index;
        threadobject *t;
@@ -509,7 +508,7 @@ static threadobject *thread_new(void)
 
        t->index     = index;
        t->thinlock  = Lockword::pre_compute_thinlock(t->index);
-       t->flags     = 0;
+       t->flags     = flags;
        t->state     = THREAD_STATE_NEW;
 
 #if defined(ENABLE_GC_CACAO)
@@ -578,9 +577,7 @@ bool threads_thread_start_internal(utf *name, functionptr f)
 
        /* Create internal thread data-structure. */
 
-       t = thread_new();
-
-       t->flags |= THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON;
+       t = thread_new(THREAD_FLAG_INTERNAL | THREAD_FLAG_DAEMON);
 
        /* The thread is flagged as (non-)daemon thread, we can leave the
           mutex. */
@@ -624,11 +621,7 @@ void threads_thread_start(java_handle_t *object)
 
        /* Create internal thread data-structure. */
 
-       threadobject* t = thread_new();
-
-       /* this is a normal Java thread */
-
-       t->flags |= THREAD_FLAG_JAVA;
+       threadobject* t = thread_new(THREAD_FLAG_JAVA);
 
 #if defined(ENABLE_JAVASE)
        /* Is this a daemon thread? */
@@ -710,11 +703,7 @@ bool thread_attach_current_thread(JavaVMAttachArgs *vm_aargs, bool isdaemon)
 
        /* Create internal thread data structure. */
 
-       t = thread_new();
-
-       /* Thread is a Java thread and running. */
-
-       t->flags = THREAD_FLAG_JAVA;
+       t = thread_new(THREAD_FLAG_JAVA);
 
        if (isdaemon)
                t->flags |= THREAD_FLAG_DAEMON;
index 546aa06822984303e1e701368dacb5674bfa61e7..70ad276835fb61cb07e10f95bf53e122172faa53 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/threadlist.cpp - thread list
 
-   Copyright (C) 2008
+   Copyright (C) 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -47,6 +47,9 @@ List<threadobject*> ThreadList::_active_thread_list;   // list of active threads
 List<threadobject*> ThreadList::_free_thread_list;     // list of free threads
 List<int32_t>       ThreadList::_free_index_list;      // list of free thread indexes
 
+int32_t             ThreadList::_number_of_started_java_threads;
+int32_t             ThreadList::_number_of_active_java_threads;
+int32_t             ThreadList::_peak_of_active_java_threads;
 int32_t             ThreadList::_number_of_non_daemon_threads;
 
 
@@ -56,13 +59,15 @@ int32_t             ThreadList::_number_of_non_daemon_threads;
  */
 void ThreadList::dump_threads()
 {
-       // XXX we should stop the world here
+       // XXX we should stop the world here and remove explicit
+       //     thread suspension from the loop below.
        // Lock the thread lists.
        lock();
 
        printf("Full thread dump CACAO "VERSION":\n");
 
        // Iterate over all started threads.
+       threadobject* self = THREADOBJECT;
        for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
                threadobject* t = *it;
 
@@ -70,13 +75,10 @@ void ThreadList::dump_threads()
                if (t->state == THREAD_STATE_NEW)
                        continue;
 
-#if defined(ENABLE_GC_CACAO)
-               /* Suspend the thread. */
-               /* XXX Is the suspend reason correct? */
+               /* Suspend the thread (and ignore return value). */
 
-               if (threads_suspend_thread(t, SUSPEND_REASON_JNI) == false)
-                       vm_abort("threads_dump: threads_suspend_thread failed");
-#endif
+               if (t != self)
+                       (void) threads_suspend_thread(t, SUSPEND_REASON_DUMP);
 
                /* Print thread info. */
 
@@ -88,12 +90,10 @@ void ThreadList::dump_threads()
 
                stacktrace_print_of_thread(t);
 
-#if defined(ENABLE_GC_CACAO)
-               /* Resume the thread. */
+               /* Resume the thread (and ignore return value). */
 
-               if (threads_resume_thread(t) == false)
-                       vm_abort("threads_dump: threads_resume_thread failed");
-#endif
+               if (t != self)
+                       (void) threads_resume_thread(t, SUSPEND_REASON_DUMP);
        }
 
        // Unlock the thread lists.
@@ -121,6 +121,34 @@ void ThreadList::get_active_threads(List<threadobject*> &list)
 }
 
 
+/**
+ * Fills the passed list with all currently active threads which should be
+ * visible to Java. Creating a copy of the thread list here, is the only way
+ * to ensure we do not end up in a dead-lock when iterating over the list.
+ *
+ * @param list list class to be filled
+ */
+void ThreadList::get_active_java_threads(List<threadobject*> &list)
+{
+       // Lock the thread lists.
+       lock();
+
+       // Iterate over all active threads.
+       for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+               threadobject* t = *it;
+
+               // We skip internal threads.
+               if (t->flags & THREAD_FLAG_INTERNAL)
+                       continue;
+
+               list.push_back(t);
+       }
+
+       // Unlock the thread lists.
+       unlock();
+}
+
+
 /**
  * Return a free thread object.
  *
@@ -165,6 +193,40 @@ int32_t ThreadList::get_free_thread_index()
 }
 
 
+/**
+ * Return the number of daemon threads visible to Java.
+ *
+ * NOTE: This function does a linear-search over the threads list,
+ *       because it is only used by the management interface.
+ *
+ * @return number of daemon threads
+ */
+int32_t ThreadList::get_number_of_daemon_java_threads(void)
+{
+       int number = 0;
+
+       // Lock the thread lists.
+       lock();
+
+       // Iterate over all active threads.
+       for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
+               threadobject* t = *it;
+
+               // We skip internal threads.
+               if (t->flags & THREAD_FLAG_INTERNAL)
+                       continue;
+
+               if (thread_is_daemon(t))
+                       number++;
+       }
+
+       // Unlock the thread lists.
+       unlock();
+
+       return number;
+}
+
+
 /**
  * Return the number of non-daemon threads.
  *
index 40e33171dfb3777ef206b397deddfd3bec64ce8a..fdcdd6e5ffbb3019463e74e25d1f4981beda2bcc 100644 (file)
@@ -1,6 +1,6 @@
 /* src/threads/threadlist.hpp - different thread-lists
 
-   Copyright (C) 2008
+   Copyright (C) 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -34,6 +34,8 @@
 
 #include "toolbox/list.hpp"
 
+#include "vm/global.h"
+
 
 /* ThreadList *****************************************************************/
 
@@ -47,6 +49,12 @@ private:
        static List<threadobject*> _free_thread_list;   // list of free threads
        static List<int32_t>       _free_index_list;    // list of free thread indexes
 
+       // Thread counters visible to Java.
+       static int32_t             _number_of_started_java_threads;
+       static int32_t             _number_of_active_java_threads;
+       static int32_t             _peak_of_active_java_threads;
+
+       // Thread counters for internal usage.
        static int32_t             _number_of_non_daemon_threads;
 
        static void                 remove_from_active_thread_list(threadobject* t);
@@ -70,15 +78,31 @@ public:
        // TODO make private
        static void                 add_to_active_thread_list(threadobject* t);
 
-       static void                 dump_threads();
-       static void                 get_active_threads(List<threadobject*> &list);
+       // Thread management methods.
        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 threadobject*        get_thread_by_index(int32_t index);
        static threadobject*        get_thread_from_java_object(java_handle_t* h);
        static void                 release_thread(threadobject* t);
+
+       // Thread listing methods.
+       static void                 get_active_threads(List<threadobject*> &list);
+       static void                 get_active_java_threads(List<threadobject*> &list);
+
+       // Thread counting methods visible to Java.
+       static int32_t              get_number_of_started_java_threads();
+       static int32_t              get_number_of_active_java_threads();
+       static int32_t              get_number_of_daemon_java_threads();
+       static int32_t              get_peak_of_active_java_threads();
+       static void                 reset_peak_of_active_java_threads();
+
+       // Thread counting methods for internal use.
+       static int32_t              get_number_of_active_threads();
+       static int32_t              get_number_of_non_daemon_threads();
+
+       // Debugging methods.
+       static void                 dump_threads();
 };
 
 struct ThreadListLocker {
@@ -90,11 +114,23 @@ struct ThreadListLocker {
 inline void ThreadList::add_to_active_thread_list(threadobject* t)
 {
        _active_thread_list.push_back(t);
+
+       // Update counter variables.
+       if ((t->flags & THREAD_FLAG_INTERNAL) == 0) {
+               _number_of_started_java_threads++;
+               _number_of_active_java_threads++;
+               _peak_of_active_java_threads = MAX(_peak_of_active_java_threads, _number_of_active_java_threads);
+       }
 }
 
 inline void ThreadList::remove_from_active_thread_list(threadobject* t)
 {
        _active_thread_list.remove(t);
+
+       // Update counter variables.
+       if ((t->flags & THREAD_FLAG_INTERNAL) == 0) {
+               _number_of_active_java_threads--;
+       }
 }
 
 inline void ThreadList::add_to_free_thread_list(threadobject* t)
@@ -112,6 +148,31 @@ inline threadobject* ThreadList::get_main_thread()
        return _active_thread_list.front();
 }
 
+inline int32_t ThreadList::get_number_of_active_threads()
+{
+       return _active_thread_list.size();
+}
+
+inline int32_t ThreadList::get_number_of_started_java_threads()
+{
+       return _number_of_started_java_threads;
+}
+
+inline int32_t ThreadList::get_number_of_active_java_threads()
+{
+       return _number_of_active_java_threads;
+}
+
+inline int32_t ThreadList::get_peak_of_active_java_threads()
+{
+       return _peak_of_active_java_threads;
+}
+
+inline void ThreadList::reset_peak_of_active_java_threads()
+{
+       _peak_of_active_java_threads = _number_of_active_java_threads;
+}
+
 #else
 
 typedef struct ThreadList ThreadList;
diff --git a/src/toolbox/hashtable.hpp b/src/toolbox/hashtable.hpp
new file mode 100644 (file)
index 0000000..0c34db6
--- /dev/null
@@ -0,0 +1,105 @@
+/* src/toolbox/hashtable.hpp - hashtable classes
+
+   Copyright (C) 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+   Copyright (C) 2009 Theobroma Systems Ltd.
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+*/
+
+
+#ifndef _HASHTABLE_HPP
+#define _HASHTABLE_HPP
+
+#include "config.h"
+
+#if __cplusplus
+
+// XXX This is a TR1 header and not (yet) part of the C++ standard, so we
+// should not use it. The solution is to implement the below stuff
+// ourselves. This will be done, sometimes, soon, I hope ...
+#include <tr1/unordered_map>
+
+
+/**
+ * Default hashing function for hashtable implementation.
+ */
+template<class T> class Hasher {
+       // XXX Implement me!
+};
+
+
+/**
+ * Hashtable implementation.
+ */
+template<class Key, class T,
+               class Hash = Hasher<Key>,
+               class Pred = std::equal_to<Key> >
+class Hashtable :
+               protected std::tr1::unordered_map<Key,T,Hash,Pred> {
+public:
+       // Constructor.
+       Hashtable(size_t n) : std::tr1::unordered_map<Key,T,Hash,Pred>(n) {}
+
+       // Make iterator of TR1 unordered map visible.
+       using std::tr1::unordered_map<Key,T,Hash,Pred>::iterator;
+
+       // Make functions of TR1 unordered map visible.
+       using std::tr1::unordered_map<Key,T,Hash,Pred>::end;
+       using std::tr1::unordered_map<Key,T,Hash,Pred>::find;
+       using std::tr1::unordered_map<Key,T,Hash,Pred>::insert;
+};
+
+
+// Required by LockableHashtable.
+#include "threads/mutex.hpp"
+
+
+/**
+ * Hashtable implementation with a Mutex.
+ */
+template<class Key, class T,
+               class Hash = Hasher<Key>,
+               class Pred = std::equal_to<Key> >
+class LockableHashtable :
+               public Hashtable<Key,T,Hash,Pred>,
+               public Mutex {
+public:
+       // Constructor.
+       LockableHashtable(size_t n) : Hashtable<Key,T,Hash,Pred>(n) {}
+};
+
+#endif
+
+#endif /* _HASHTABLE_HPP */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 4adb970f5f00d0c0ffa97d1a37f8d8a6a13eedb0..fc5a1c4b3696038f631ab257d1740abe72688c1b 100644 (file)
 #include "vm/vm.hpp"
 
 
-/* _Jv_getcwd ******************************************************************
-
-   Return the current working directory.
-
-   RETURN VALUE:
-       pointer to a char array allocated by MNEW, or
-          NULL if memory could not be allocated.
-
-*******************************************************************************/
-
-char *_Jv_getcwd(void)
-{
-       char *buf;
-       s4    size;
-
-       size = 1024;
-
-       buf = MNEW(char, size);
-
-       while (buf) {
-               if (getcwd(buf, size) != NULL)
-                       return buf;
-
-               MFREE(buf, char, size);
-
-               /* too small buffer or a more serious problem */
-
-               if (errno != ERANGE)
-                       vm_abort("getcwd failed: %s", strerror(errno));
-
-               /* double the buffer size */
-
-               size *= 2;
-
-               buf = MNEW(char, size);
-       }
-
-       return NULL;
-}
-
-
 /* get_variable_message_length *************************************************
 
    This function simluates the print of a variable message and
index 659ab0eb967aaa913edacc8eb5544aad606fc82a..fd1143b6549351a9f49b49f650e58eb0495e3d34 100644 (file)
@@ -39,7 +39,6 @@
 extern "C" {
 #endif
 
-char *_Jv_getcwd(void);
 int   get_variable_message_length(const char *fmt, va_list ap);
 
 #ifdef __cplusplus
index f443c78cd29ae33b26822dbd801abeb94ad08b04..93778b11e762e2cc439599978f2f8b38141f66cb 100644 (file)
@@ -99,6 +99,7 @@ libvm_la_SOURCES = \
        finalizer.hpp \
        globals.cpp \
        globals.hpp \
+       hook.hpp \
        initialize.cpp \
        initialize.hpp \
        javaobjects.cpp \
index f0900e2289860f5c4af9d62a47b072610289abad..9023da15045778be679990f9f01536fd5ffb7d23 100644 (file)
@@ -1388,66 +1388,6 @@ s4 classcache_get_loaded_class_count(void)
 }
 
 
-/* classcache_get_loaded_classes ***********************************************
-
-   Returns an array of all loaded classes as array.  The array is
-   allocaed on the Java heap.
-
-*******************************************************************************/
-
-#if defined(ENABLE_JVMTI)
-void classcache_get_loaded_classes(s4 *class_count_ptr,
-                                                                  classinfo ***classes_ptr)
-{
-       classinfo              **classes;
-       s4                       class_count;
-       classcache_name_entry   *en;
-       classcache_class_entry  *clsen;
-       s4                       i;
-       s4                       j;
-
-       CLASSCACHE_LOCK();
-
-       /* get the number of loaded classes and allocate the array */
-
-       class_count = classcache_number_of_loaded_classes();
-
-       classes = GCMNEW(classinfo*, class_count);
-
-       /* look in every slot of the hashtable */
-
-       for (i = 0, j = 0; i < hashtable_classcache.size; i++) {
-               /* iterate over hashlink */
-
-               for (en = hashtable_classcache.ptr[i]; en != NULL; en = en->hashlink) {
-                       /* filter pseudo classes $NEW$, $NULL$, $ARRAYSTUB$ out */
-
-                       if (en->name->text[0] == '$')
-                               continue;
-
-                       /* iterate over classes with same name */
-
-                       for (clsen = en->classes; clsen != NULL; clsen = clsen->next) {
-                               /* get only loaded classes */
-
-                               if (clsen->classobj != NULL) {
-                                       classes[j] = clsen->classobj;
-                                       j++;
-                               }
-                       }
-               }
-       }
-
-       /* pass the return values */
-
-       *class_count_ptr = class_count;
-       *classes_ptr     = classes;
-
-       CLASSCACHE_UNLOCK();
-}
-#endif /* defined(ENABLE_JVMTI) */
-
-
 /* classcache_foreach_loaded_class *********************************************
 
    Calls the given function for each loaded class.
index aef65e21c4e4af5fccea718c8f8a04cbd2410a4e..d3ea496533748034d752967e0a34f43e29fd611e 100644 (file)
@@ -146,11 +146,6 @@ s4 classcache_get_loaded_class_count(void);
 void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
                                                                         void *data);
 
-#if defined(ENABLE_JVMTI)
-void classcache_get_loaded_classes(s4 *class_count_ptr,
-                                                                  classinfo ***classes_ptr);
-#endif
-
 #ifndef NDEBUG
 void classcache_debug_dump(FILE *file,utf *only);
 #endif
index d70c9d1cbde582cad5bc9ce380875dd45a1c1a64..53e267f93f78aa1b12ead1b33b58a1a271cd8762 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/cycles-stats.h - macros for cycle count statistics
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Edwin Steiner
-
-   Changes:
-
 */
 
 #ifndef _CYCLES_STATS_H
@@ -40,6 +32,8 @@
 
 #include <stdio.h>
 
+#include "md.h"
+
 #define CYCLES_STATS_DECLARE(name,nbins,divisor)                            \
     static const int CYCLES_STATS_##name##_MAX = (nbins);                   \
     static const int CYCLES_STATS_##name##_DIV = (divisor);                 \
@@ -50,7 +44,7 @@
     static u8 cycles_stats_##name##_min = 1000000000;
 
 #define CYCLES_STATS_GET(var)                                               \
-       (var) = asm_get_cycle_count()                                           \
+       (var) = md_get_cycle_count()                                            \
 
 #define CYCLES_STATS_COUNT(name,cyclesexpr)                                 \
     do {                                                                    \
     } while (0)
 
 #define CYCLES_STATS_DECLARE_AND_START                                      \
-    u8 cycles_start = asm_get_cycle_count();                                \
+    u8 cycles_start = md_get_cycle_count();                                 \
     u8 cycles_end;
 
 #define CYCLES_STATS_DECLARE_AND_START_WITH_OVERHEAD                        \
-    u8 cycles_start = asm_get_cycle_count();                                \
-    u8 cycles_overhead = asm_get_cycle_count();                             \
+    u8 cycles_start = md_get_cycle_count();                                 \
+    u8 cycles_overhead = md_get_cycle_count();                              \
     u8 cycles_end;
 
 #define CYCLES_STATS_END(name)                                              \
-    cycles_end = asm_get_cycle_count();                                     \
+    cycles_end = md_get_cycle_count();                                      \
     CYCLES_STATS_COUNT(name, cycles_end - cycles_start);
 
 #define CYCLES_STATS_END_WITH_OVERHEAD(name,ovname)                         \
-    cycles_end = asm_get_cycle_count();                                     \
+    cycles_end = md_get_cycle_count();                                      \
     CYCLES_STATS_COUNT(ovname, cycles_overhead - cycles_start);             \
     CYCLES_STATS_COUNT(name, cycles_end - cycles_overhead);
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 void cycles_stats_print(FILE *file,
                                            const char *name, int nbins, int div,
                                            u4 *bins, u8 count, u8 total, u8 min, u8 max,
                                                int overhead);
 
+#ifdef __cplusplus
+}
+#endif
+
 
 #else /* !defined(ENABLE_CYCLES_STATS) */
 
index 332fca04b15e1c1304b1921a9b7c292fc84a96d3..69a748febd18f67a0678c9cb31dbe91857730d03 100644 (file)
@@ -29,7 +29,6 @@
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
-#include <sys/mman.h>
 
 #include "vm/types.h"
 
index 4443a806f0782a9c3974ddbd55371c86e8e51e87..45287193b1bcab37471c04ca56d04be3132fc8e4 100644 (file)
@@ -97,6 +97,10 @@ typedef union {
 # define MIN(a,b)  (((a) < (b)) ? (a) : (b))
 #endif
 
+#ifndef MAX
+# define MAX(a,b)  (((a) > (b)) ? (a) : (b))
+#endif
+
 
 /* forward typedefs ***********************************************************/
 
diff --git a/src/vm/hook.hpp b/src/vm/hook.hpp
new file mode 100644 (file)
index 0000000..0e6656b
--- /dev/null
@@ -0,0 +1,180 @@
+/* src/vm/hook.hpp - hook points inside the VM
+
+   Copyright (C) 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public 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 _HOOK_HPP
+#define _HOOK_HPP
+
+#include "config.h"
+
+#if defined(ENABLE_OPAGENT)
+#include "vm/jit/oprofile-agent.hpp"
+#endif
+
+
+/**
+ * Hook points are inline functions acting as probes scattered throughout
+ * several VM subsystems. They can be used to implement event generation
+ * or statistics gathering without polluting the source code. Hence all
+ * compiler macro and runtime checks should be done in this file. One
+ * example of where hooks are useful is JVMTI event firing.
+ */
+namespace Hook {
+       void breakpoint     (Breakpoint *bp);
+       void class_linked   (classinfo *c);
+       void class_loaded   (classinfo *c);
+       void jit_generated  (methodinfo *m, codeinfo *code);
+       void jit_recycled   (methodinfo *m, codeinfo *code);
+       void method_enter   (methodinfo *m);
+       void method_exit    (methodinfo *m);
+       void method_unwind  (methodinfo *m);
+       void native_resolved(methodinfo *m, void *symbol, void **symbolptr);
+       void thread_start   (threadobject *t);
+       void thread_end     (threadobject *t);
+       void vm_init        ();
+       void vm_preinit     ();
+       void vm_shutdown    ();
+}
+
+
+inline void Hook::breakpoint(Breakpoint *bp)
+{
+#if defined(ENABLE_JVMTI)
+       methodinfo* m = bp->method;
+       int32_t     l = bp->location;
+
+       log_message_method("JVMTI: Reached breakpoint in method ", m);
+       log_println("JVMTI: Reached breakpoint at location %d", l);
+#endif
+}
+
+inline void Hook::class_linked(classinfo *c)
+{
+       /* nop */
+}
+
+inline void Hook::class_loaded(classinfo *c)
+{
+       /* nop */
+}
+
+/**
+ * Hook point just after code was generated. Note that one method can have
+ * multiple code realizations, the hook is fired for each of them. The code
+ * was not yet executed.
+ *
+ * @param m The method for which code was generated.
+ * @param code The fully initialized codeinfo for the generated code.
+ */
+inline void Hook::jit_generated(methodinfo *m, codeinfo *code)
+{
+#if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::newmethod(m);
+#endif
+}
+
+inline void Hook::method_enter(methodinfo *m)
+{
+       /* nop */
+}
+
+inline void Hook::method_exit(methodinfo *m)
+{
+       /* nop */
+}
+
+inline void Hook::method_unwind(methodinfo *m)
+{
+       /* nop */
+}
+
+inline void Hook::native_resolved(methodinfo *m, void *symbol, void **symbolptr)
+{
+       /* nop */
+}
+
+inline void Hook::thread_start(threadobject *t)
+{
+       /* nop */
+}
+
+inline void Hook::thread_end(threadobject *t)
+{
+       /* nop */
+}
+
+/**
+ * Hook point after the VM is initialized. At this point the VM is fully
+ * operating and ready to execute Java code. Final intializations and thread
+ * startup should be done here.
+ */
+inline void Hook::vm_init()
+{
+       /* nop */
+}
+
+/**
+ * Hook point before the VM is initialized. At this point the VM can not
+ * yet execute Java code but some central native subsystems are initialized.
+ * Only basic initialization steps should be done here.
+ */
+inline void Hook::vm_preinit()
+{
+#if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::initialize();
+#endif
+}
+
+/**
+ * Hook point before the VM is actually destroyed. At this point the VM is
+ * still running, but all non-daemon threads have terminated and resources
+ * are ready to be reclaimed. Final cleanup tasks should be done here.
+ */
+inline void Hook::vm_shutdown()
+{
+#if defined(ENABLE_OPAGENT)
+       if (opt_EnableOpagent)
+               OprofileAgent::close();
+#endif
+}
+
+
+#endif /* _HOOK_HPP */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
index 901756534cd4441f25d5f03a5e2b7e706f402e52..2bd0a19ddd81ea35dd496ab2af783328283015b8 100644 (file)
@@ -74,6 +74,38 @@ java_handle_t* java_lang_ClassLoader::invoke_getSystemClassLoader()
 }
 
 
+/**
+ * Constructs a new instance of the class by calling the
+ * appropriate Java initializer.
+ */
+java_lang_management_MemoryUsage::java_lang_management_MemoryUsage(int64_t init, int64_t used, int64_t commited, int64_t maximum)
+{
+       // Load the class.
+       // XXX Maybe this should be made global at some points.
+       classinfo* class_java_lang_management_MemoryUsage;
+       if (!(class_java_lang_management_MemoryUsage = load_class_bootstrap(utf_new_char("java/lang/management/MemoryUsage"))))
+               return;
+
+       // Find the appropriate initializer.
+       // XXX Maybe this should be made global at some points.
+       methodinfo* m = class_findmethod(class_java_lang_management_MemoryUsage,
+                                                                        utf_init,
+                                                                        utf_new_char("(JJJJ)V"));
+
+       if (m == NULL)
+               return;
+
+       // Instantiate a new object.
+       _handle = builtin_new(class_java_lang_management_MemoryUsage);
+
+       if (is_null())
+               return;
+
+       // Call initializer.
+       (void) vm_call_method(m, _handle, init, used, commited, maximum);
+}
+
+
 /**
  * Constructs a Java object with the given
  * java.lang.reflect.Constructor.
index 71f58abb11147bfe1de4996a6df396331f529237..199fa8b612ebbb9cc17520f9e29a7230d226ef91 100644 (file)
@@ -509,6 +509,21 @@ inline void java_lang_Double::set_value(double value)
 
 #if defined(ENABLE_JAVASE)
 
+/**
+ * java/lang/management/MemoryUsage
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * [other fields are not used]
+ */
+class java_lang_management_MemoryUsage : public java_lang_Object, private FieldAccess {
+public:
+       java_lang_management_MemoryUsage(java_handle_t* h) : java_lang_Object(h) {}
+       java_lang_management_MemoryUsage(int64_t init, int64_t used, int64_t commited, int64_t maximum);
+};
+
+
 # if defined(ENABLE_ANNOTATIONS)
 /**
  * OpenJDK sun/reflect/ConstantPool
index e3f96f6a2e7d6a37ea95c087b268c5ebbf24c5ec..1a01e0ab314a965d9a2448cce837f5a7aff9f313 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              0
 #define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        1
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
 
index c6eb6b1287c335d294206761d3e7d5fd6e0ff38e..2d02d8c48c261cade25bbcff46aa138540a95e3c 100644 (file)
@@ -77,33 +77,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _mc->sc_pc;
-       sp = (u1 *) _mc->sc_regs[REG_SP];
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index 2d282f9570a5be8bd5c8456c2c7f72253051e2b8..1d0a49028630d30837437e70f6470efb5d82c77b 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              0
 #define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        1
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
 
index 05d3613cf8dcc1599cff51a08c68f98863b20c2c..4a87bc94929db6f1850d72eee4ce31e8f9e63341 100644 (file)
@@ -2405,14 +2405,14 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
        /* calculate stackframe size */
 
        cd->stackframesize =
-               4 +                                                /* return address  */
-               sizeof(stackframeinfo_t) +                         /* stackframeinfo  */
-               sizeof(localref_table) +                           /* localref_table  */
-               nmd->memuse * 4;                                   /* stack arguments */
+               1 +                                                /* return address  */
+               sizeof(stackframeinfo_t) / SIZEOF_VOID_P +         /* stackframeinfo  */
+               sizeof(localref_table) / SIZEOF_VOID_P +           /* localref_table  */
+               nmd->memuse;                                       /* stack arguments */
 
        /* align stack to 8-byte */
 
-       cd->stackframesize = (cd->stackframesize + 4) & ~4;
+       cd->stackframesize = (cd->stackframesize + 1) & ~1;
 
        /* create method header */
 
@@ -2425,12 +2425,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
        /* generate stub code */
 
        M_STMFD(1<<REG_LR, REG_SP);
-       M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
-
-#if !defined(NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_enter(jd);
-#endif
+       M_SUB_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
 
 #if defined(ENABLE_GC_CACAO)
        /* Save callee saved integer registers in stackframeinfo (GC may
@@ -2503,7 +2498,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
                        }
                }
                else {
-                       s1 = md->params[i].regoff + cd->stackframesize;
+                       s1 = md->params[i].regoff + cd->stackframesize * 8;
                        s2 = nmd->params[j].regoff;
 
                        if (IS_2_WORD_TYPE(t)) {
@@ -2561,11 +2556,6 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
        }
 #endif
 
-#if !defined(NDEBUG)
-       if (JITDATA_HAS_FLAG_VERBOSECALL(jd))
-               emit_verbosecall_exit(jd);
-#endif
-
        /* remove native stackframe info */
        /* TODO: improve this store/load */
 
@@ -2593,7 +2583,7 @@ void codegen_emit_stub_native(jitdata *jd, methoddesc *nmd, functionptr f, int s
 
        /* finish stub code, but do not yet return to caller */
 
-       M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize / 4 - 1);
+       M_ADD_IMM_EXT_MUL4(REG_SP, REG_SP, cd->stackframesize * 2 - 1);
        M_LDMFD(1<<REG_LR, REG_SP);
 
        /* check for exception */
index f7fd56ab04b490d4495c40ef69ffd09e60d7ac93..59ee5c27ec00620bedadf246e4062ac23c69811d 100644 (file)
@@ -961,11 +961,11 @@ do { \
 
 #define M_STR(d, base, offset) \
 do { \
-       assert((d) != REG_ITMP3); \
        CHECK_OFFSET(offset, 0x0fffff); \
        if (IS_OFFSET(offset, 0x000fff)) { \
                M_STR_INTERN(d, base, offset); \
        } else { \
+               assert((d) != REG_ITMP3); \
                if ((offset) > 0) { \
                        M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 12, 6)); \
                        M_STR_INTERN(d, REG_ITMP3, (offset) & 0x000fff); \
@@ -978,8 +978,6 @@ do { \
 
 #define M_STRD(d, base, offset) \
 do { \
-       assert(GET_LOW_REG(d) != REG_ITMP3); \
-       assert(GET_HIGH_REG(d) != REG_ITMP3); \
        CHECK_OFFSET(offset, 0x0fffff - 4); \
        if (IS_OFFSET(offset, 0x000fff - 4)) { \
                M_STRD_INTERN(d,base,offset); \
@@ -987,6 +985,8 @@ do { \
                dolog("M_STRD: this offset seems to be complicated (%d)", offset); \
                assert(0); \
        } else { \
+               assert(GET_LOW_REG(d) != REG_ITMP3); \
+               assert(GET_HIGH_REG(d) != REG_ITMP3); \
                if ((offset) > 0) { \
                        M_ADD_IMM(REG_ITMP3, base, IMM_ROTL((offset) >> 12, 6)); \
                        M_STRD_INTERN(d, REG_ITMP3, (offset) & 0x000fff); \
index f8d29c56757faf36fa79ee8932f71249d67c794e..bd1475985669790e6c93e192877a40644fd284c3 100644 (file)
@@ -94,33 +94,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       scontext_t *_sc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _sc = &_uc->uc_mcontext;
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _sc->arm_pc;
-       sp = (u1 *) _sc->arm_sp;
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index 9ea6f4da5c97ce6efaca10364e1e50a84fb40d84..8769403d7392d8aae2776f220cd5489846f349d7 100644 (file)
@@ -102,8 +102,6 @@ void asm_patcher_wrapper(void);
 /* cache flush function */
 void asm_cacheflush(void* addr, int nbytes);
 
-u8 asm_get_cycle_count(void);
-
 void *md_asm_codegen_get_pv_from_pc(void *ra);
 
 #if defined(ENABLE_ESCAPE_CHECK)
index 9dc00a90bc10f91ff7d1d637f16b88be837bd65c..5536ba819c29871a28a64885a8905814e161f586 100644 (file)
@@ -1356,9 +1356,13 @@ bool codegen_emit(jitdata *jd)
                        case ICMD_IMUL:       /* ..., val1, val2  ==> ..., val1 * val2    */
                        case ICMD_IMULCONST:  /* ..., value  ==> ..., value * constant    */
                                              /* sx.val.i = constant                      */
+                       case ICMD_IMULPOW2:   /* ..., value  ==> ..., value * (2 ^ constant) */
+                                             /* sx.val.i = constant                      */
                        case ICMD_LMUL:       /* ..., val1, val2  ==> ..., val1 * val2    */
                        case ICMD_LMULCONST:  /* ..., value  ==> ..., value * constant    */
                                              /* sx.val.l = constant                      */
+                       case ICMD_LMULPOW2:   /* ..., value  ==> ..., value * (2 ^ constant) */
+                                             /* sx.val.l = constant                      */
                        case ICMD_IDIV:       /* ..., val1, val2  ==> ..., val1 / val2    */
                        case ICMD_IREM:       /* ..., val1, val2  ==> ..., val1 % val2    */
                        case ICMD_IDIVPOW2:   /* ..., value  ==> ..., value >> constant   */
@@ -1535,7 +1539,6 @@ bool codegen_emit(jitdata *jd)
                                /* This approach is much faster than moving the field
                                   address inline into a register. */
 
-                               // XXX ARM: M_DSEG_LOAD(REG_ITMP3, disp);
                                M_ALD_DSEG(REG_ITMP1, disp);
 
                                switch (fieldtype) {
@@ -1599,7 +1602,6 @@ bool codegen_emit(jitdata *jd)
                                /* This approach is much faster than moving the field
                                   address inline into a register. */
 
-                               // XXX ARM: M_DSEG_LOAD(REG_ITMP3, disp);
                                M_ALD_DSEG(REG_ITMP1, disp);
 
                                switch (fieldtype) {
@@ -1857,16 +1859,22 @@ bool codegen_emit(jitdata *jd)
 
                                REPLACEMENT_POINT_RETURN(cd, iptr);
                                s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                               // XXX ARM: Here this was M_CAST_F2I(s1, REG_RESULT);
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
                                emit_fmove(cd, s1, REG_FRESULT);
+#else
+                               M_CAST_F2I(s1, REG_RESULT);
+#endif
                                goto nowperformreturn;
 
                        case ICMD_DRETURN:    /* ..., retvalue ==> ...                    */
 
                                REPLACEMENT_POINT_RETURN(cd, iptr);
                                s1 = emit_load_s1(jd, iptr, REG_FRESULT);
-                               // XXX ARM: Here this was M_CAST_D2L(s1, REG_RESULT_PACKED);
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
                                emit_dmove(cd, s1, REG_FRESULT);
+#else
+                               M_CAST_D2L(s1, REG_LRESULT);
+#endif
                                goto nowperformreturn;
 
 nowperformreturn:
@@ -1972,36 +1980,36 @@ gen_method:
                                                continue;
 
                                        if (!md->params[i].inmemory) {
-                                               assert(ARG_CNT > 0);
-                                               s1 = emit_load(jd, iptr, var, d);
-
                                                switch (var->type) {
                                                case TYPE_ADR:
                                                case TYPE_INT:
-                                                       assert(INT_ARG_CNT > 0);
+                                                       s1 = emit_load(jd, iptr, var, d);
                                                        emit_imove(cd, s1, d);
                                                        break;
 
-#if 0 //XXX For ARM:
-if (!md->params[s3].inmemory) {
-       s1 = emit_load(jd, iptr, var, REG_FTMP1);
-       if (IS_2_WORD_TYPE(var->type))
-               M_CAST_D2L(s1, d);
-       else
-               M_CAST_F2I(s1, d);
-}
-#endif //XXX End of ARM!
-
                                                case TYPE_LNG:
+                                                       s1 = emit_load(jd, iptr, var, d);
                                                        emit_lmove(cd, s1, d);
                                                        break;
 
                                                case TYPE_FLT:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+                                                       s1 = emit_load(jd, iptr, var, d);
                                                        emit_fmove(cd, s1, d);
+#else
+                                                       s1 = emit_load(jd, iptr, var, REG_FTMP1);
+                                                       M_CAST_F2I(s1, d);
+#endif
                                                        break;
 
                                                case TYPE_DBL:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
+                                                       s1 = emit_load(jd, iptr, var, d);
                                                        emit_dmove(cd, s1, d);
+#else
+                                                       s1 = emit_load(jd, iptr, var, REG_FTMP1);
+                                                       M_CAST_D2L(s1, d);
+#endif
                                                        break;
                                                }
                                        }
@@ -2089,27 +2097,25 @@ if (!md->params[s3].inmemory) {
                                        emit_store_dst(jd, iptr, s1);
                                        break;
 
-#if 0 //XXX For ARM!!!
-#if !defined(ENABLE_SOFTFLOAT)
-                               } else {
-                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
-                                       if (IS_2_WORD_TYPE(d))
-                                               M_CAST_L2D(REG_RESULT_PACKED, s1);
-                                       else
-                                               M_CAST_I2F(REG_RESULT, s1);
-                               }
-#endif /* !defined(ENABLE_SOFTFLOAT) */
-#endif //XXX End of ARM
-
                                case TYPE_FLT:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
                                        s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
                                        emit_fmove(cd, REG_FRESULT, s1);
+#else
+                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                                       M_CAST_I2F(REG_RESULT, s1);
+#endif
                                        emit_store_dst(jd, iptr, s1);
                                        break;
 
                                case TYPE_DBL:
+#if !defined(SUPPORT_PASS_FLOATARGS_IN_INTREGS)
                                        s1 = codegen_reg_of_dst(jd, iptr, REG_FRESULT);
                                        emit_dmove(cd, REG_FRESULT, s1);
+#else
+                                       s1 = codegen_reg_of_dst(jd, iptr, REG_FTMP1);
+                                       M_CAST_L2D(REG_LRESULT, s1);
+#endif
                                        emit_store_dst(jd, iptr, s1);
                                        break;
 
index 2a7958deac3b2af7435d49cc681d3e32e694d865..953c832a215439a90dfa12e14a4bf17697d853f6 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/executionstate.c - execution-state handling
 
-   Copyright (C) 2007, 2008
+   Copyright (C) 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -28,6 +28,8 @@
 #include <stdint.h>
 #include <stdio.h>
 
+#include "arch.h"
+#include "md.h"
 #include "md-abi.h"
 
 #include "vm/descriptor.hpp"
 #include "vm/jit/executionstate.h"
 
 
+/**
+ * Restore callee-saved registers (including the RA register),
+ * set the stack pointer to the next stackframe,
+ * set the PC to the return address of the popped frame.
+ *
+ * *** This function imitates the effects of the method epilog ***
+ * *** and returning from the method call.                     ***
+ *
+ * @param es Execution state to be modified.
+ *        NOTE: es->code and es->pv are NOT updated.
+ */
+void executionstate_pop_stackframe(executionstate_t *es)
+{
+       int32_t reg;
+       int32_t i;
+
+       // Sanity checks.
+       assert(es->code != NULL);
+
+       // Calculate the size of the stackframe.
+       int32_t framesize = md_stacktrace_get_framesize(es->code);
+
+       // Read the return address.
+       uint8_t* ra;
+#if STACKFRAME_LEAFMETHODS_RA_REGISTER
+       if (code_is_leafmethod(es->code))
+               ra = es->ra;
+       else
+#endif
+               ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
+
+       // Calculate the base of the stack frame.
+       uintptr_t sp     = (uintptr_t) es->sp;
+       uintptr_t basesp = sp + es->code->stackframesize * SIZE_OF_STACKSLOT;
+
+       // Restore return address, if part of frame.
+#if STACKFRAME_RA_TOP_OF_FRAME
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
+       if (!code_is_leafmethod(es->code)) {
+# endif
+               basesp -= 1 * SIZE_OF_STACKSLOT;
+               es->ra = *((uint8_t**) basesp);
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
+       }
+# endif
+#endif /* STACKFRAME_RA_TOP_OF_FRAME */
+
+       // Restore return address, if inside linkage area.
+#if STACKFRAME_RA_LINKAGE_AREA
+# if STACKFRAME_LEAFMETHODS_RA_REGISTER
+       if (!code_is_leafmethod(es->code))
+# endif
+               es->ra = *((uint8_t**) (basesp + LA_LR_OFFSET));
+#endif /* STACKFRAME_RA_LINKAGE_AREA */
+
+       // Restore saved int registers.
+       reg = INT_REG_CNT;
+       for (i=0; i<es->code->savedintcount; ++i) {
+               while (nregdescint[--reg] != REG_SAV)
+                       ;
+               basesp -= 1 * SIZE_OF_STACKSLOT;
+               es->intregs[reg] = *((uintptr_t*) basesp);
+       }
+
+       // Restore saved flt registers.
+       // XXX align?
+       reg = FLT_REG_CNT;
+       for (i=0; i<es->code->savedfltcount; ++i) {
+               while (nregdescfloat[--reg] != REG_SAV)
+                       ;
+               basesp -= STACK_SLOTS_PER_FLOAT * SIZE_OF_STACKSLOT;
+               es->fltregs[reg] = *((double*) basesp);
+       }
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       // Restore saved adr registers.
+       reg = ADR_REG_CNT;
+       for (i=0; i<es->code->savedadrcount; ++i) {
+               while (nregdescadr[--reg] != REG_SAV)
+                       ;
+               basesp -= 1 * SIZE_OF_STACKSLOT;
+               es->adrregs[reg] = *((uintptr_t*) basesp);
+       }
+#endif
+
+       // Adjust the stackpointer.
+       es->sp += framesize;
+#if STACKFRMAE_RA_BETWEEN_FRAMES
+       es->sp += SIZEOF_VOID_P; /* skip return address */
+#endif
+
+       // Set the program counter to the return address.
+       es->pc = ra;
+
+       // In debugging mode clobber non-saved registers.
+#if !defined(NDEBUG)
+       for (i=0; i<INT_REG_CNT; ++i)
+               if (nregdescint[i] != REG_SAV)
+                       es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
+       for (i=0; i<FLT_REG_CNT; ++i)
+               if (nregdescfloat[i] != REG_SAV)
+                       *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
+# if defined(HAS_ADDRESS_REGISTER_FILE)
+       for (i=0; i<ADR_REG_CNT; ++i)
+               if (nregdescadr[i] != REG_SAV)
+                       es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
+# endif
+#endif /* !defined(NDEBUG) */
+}
+
+
+// XXX Move this prototype somewhere else!
+void *exceptions_handle_exception(java_object_t *xptro, void *xpc, void *pv, void *sp);
+
+
+/**
+ * Performs stack unwinding in case of an exception. This is done by
+ * popping frames off the given execution state until a frame is reached
+ * for which there is a handler. Execution will continue at the handler
+ * site once the execution state is written back to the machine.
+ *
+ * @param es Execution state to be modified.
+ * @param e The thrown exception object.
+ *
+ * This is specified in:
+ *    The Java(TM) Virtual Machine Specification, Second Edition
+ *    Section 3.6.5: Abrupt Method Invocation Completion
+ */
+void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e)
+{
+       void* handler = NULL;
+
+       // Iterate until we find an exception handler.
+       while (handler == NULL) {
+
+               // Search an exception handler in the current frame.
+               handler = exceptions_handle_exception(e, es->pc, es->pv, es->sp);
+
+               // Jump directly into the handler in case we found one.
+               if (handler != NULL)
+                       break;
+
+               // Find the codeinfo structure for the current frame.
+               es->code = code_get_codeinfo_for_pv(es->pv);
+
+               // Pop one frame off the stack.
+               executionstate_pop_stackframe(es);
+
+               // Get the PV for the parent Java method.
+               es->pv = md_codegen_get_pv_from_pc(es->pc);
+
+               // After popping the frame the PC points to the instruction just after
+               // the invocation. To get the XPC we need to correct the PC to point
+               // just before the invocation. But we do not know how big the
+               // invocation site actually is, so we subtract one, which should be
+               // sufficient for our purposes.
+               es->pc -= 1;
+       }
+
+       // Update the execution state to continue at the handler site.
+       es->pc = (uint8_t*) handler;
+}
+
+
 /* executionstate_sanity_check *************************************************
 
    Perform some sanity checks for the md_executionstate_read and
index 59e14ea4be23ef7e8ce7c6c47e12e0feff8842f5..e97707d60a8d5955079688af3093b3d7ca0ff5a2 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/executionstate.h - execution-state handling
 
-   Copyright (C) 2007, 2008
+   Copyright (C) 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -41,6 +41,13 @@ typedef struct executionstate_t executionstate_t;
 #include "vm/jit/code.hpp"
 
 
+/* configuration of native stack slot size ************************************/
+
+#define SIZE_OF_STACKSLOT      8
+#define STACK_SLOTS_PER_FLOAT  1
+typedef uint64_t stackslot_t;
+
+
 /* executionstate_t ************************************************************
 
    An execution-state represents the state of a thread containing all
@@ -72,6 +79,10 @@ struct executionstate_t {
 extern "C" {
 #endif
 
+void executionstate_pop_stackframe(executionstate_t *es);
+
+void executionstate_unwind_exception(executionstate_t* es, java_handle_t* e);
+
 #if !defined(NDEBUG)
 void executionstate_sanity_check(void *context);
 void executionstate_println(executionstate_t *es);
index 29c0603eab8a8d1ec2590f6a781fe83798ed6307..e9aef93f765f3e6116fcef3d051ee3511b70ee9b 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              1
 #define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
 
index 72653f436afe572c8b5df04d783478245f0e48b2..b9be6e191288c242139bfc018248b49e875043d0 100644 (file)
@@ -62,8 +62,6 @@
        .globl asm_compare_and_swap
        .globl asm_memory_barrier
 
-       .globl asm_get_cycle_count
-
 #if defined(ENABLE_ESCAPE_CHECK)
        .globl asm_escape_check
 #endif
@@ -416,16 +414,6 @@ asm_memory_barrier:
        lock; add $0,0(sp)
        ret
 
-               
-/* asm_get_cycle_count *********************************************************
-
-   Get the current time-stamp counter from the CPU.
-
-*******************************************************************************/
-
-asm_get_cycle_count:
-       rdtsc
-       ret
 
 #if defined(ENABLE_ESCAPE_CHECK)
 asm_escape_check:
index d610cc3ce1dc3a24803ccab9cf12b4332aa7eb40..588811a39a7844d92d52d7966dac589c755e9480 100644 (file)
 #define builtin_d2i                           _builtin_d2i
 #define builtin_d2l                           _builtin_d2l
 
-#define asm_get_cycle_count                   _asm_get_cycle_count
-
 #endif /* _MD_ASM_H */
 
 
index b6a4c482807b606d8fef3d2b346db4ada2de6e6f..a65dd4a2c894f609c51f2c658479019c247688de 100644 (file)
@@ -250,33 +250,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _mc->mc_eip;
-       sp = (u1 *) _mc->mc_esp;
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index 1417ec01a073347972182d543c5e6f1ac661c1bb..15320a670002ea998c9ad4c813d07e305d88f715 100644 (file)
@@ -90,33 +90,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _mc->gregs[REG_EIP];
-       sp = (u1 *) _mc->gregs[REG_ESP];
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index 9bfa133732d07630da8dfad573d31a59e366fbeb..0756bb26a1db78dbc07a19eb7538b34116e9b38e 100644 (file)
@@ -139,6 +139,23 @@ inline static void md_dcacheflush(void *addr, int nbytes)
        __asm__ __volatile__ ("" : : : "memory");
 }
 
+
+/* md_get_cycle_count **********************************************************
+
+   Get the current time-stamp counter from the CPU.
+
+*******************************************************************************/
+
+inline static uint64_t md_get_cycle_count()
+{
+       uint64_t cycles;
+
+       // Get current cycles count from the CPU.
+       __asm__ __volatile__ ("rdtsc" : "=A" (cycles));
+
+       return cycles;
+}
+
 #endif /* _VM_JIT_I386_MD_H */
 
 
index 2fb36877828935d981cc999b2361c8553eb494a6..1cc718e87d2b4e0d9f2f1547848ad23733fc8fe8 100644 (file)
@@ -90,33 +90,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _mc->gregs[EIP];
-       sp = (u1 *) _mc->gregs[UESP];
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index a8ac2b160a196c7f7c1873db3e80bf196fab7e86..b633292c04ea796831a4f08049c4052f0683432a 100644 (file)
@@ -43,6 +43,7 @@
 #include "vm/class.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/initialize.hpp"
 #include "vm/loader.hpp"
 #include "vm/method.hpp"
 #include "vm/jit/stack.h"
 #include "vm/jit/stubs.hpp"
 
-#if defined(ENABLE_OPAGENT)
-#include "vm/jit/oprofile-agent.hpp"
-#endif
-
 #include "vm/jit/allocator/simplereg.h"
 #if defined(ENABLE_LSRA) && !defined(ENABLE_SSA)
 # include "vm/jit/allocator/lsra.h"
@@ -173,11 +170,6 @@ void jit_init(void)
 #else
        intrp_md_init();
 #endif
-
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent::initialize();
-#endif
 }
 
 
@@ -189,10 +181,7 @@ void jit_init(void)
 
 void jit_close(void)
 {
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent::close();
-#endif
+       /* nop */
 }
 
 
@@ -401,10 +390,8 @@ u1 *jit_compile(methodinfo *m)
                compilingtime_stop();
 #endif
 
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent::newmethod(m);
-#endif
+       // Hook point just after code was generated.
+       Hook::jit_generated(m, m->code);
 
        /* leave the monitor */
 
@@ -512,10 +499,8 @@ u1 *jit_recompile(methodinfo *m)
                compilingtime_stop();
 #endif
 
-#if defined(ENABLE_OPAGENT)
-       if (opt_EnableOpagent)
-               OprofileAgent::newmethod(m);
-#endif
+       // Hook point just after code was generated.
+       Hook::jit_generated(m, m->code);
 
        DEBUG_JIT_COMPILEVERBOSE("Recompiling done: ");
 
index 77a189f2551d7dfc08f7eeceae95c202f23d91c0..e2b70b55fe26643a74a336f0c51df2924e22f0de 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              1
 #define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
 
index 45e1a34ffde91dd53740b1483c8d95782fd42d83..359541fb2e34cb922e21b769a2962a1f6a4facd7 100644 (file)
@@ -253,33 +253,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _mc->gregs[R_PC];
-       sp = (u1 *) _mc->gregs[R_SP];
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#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
index 6f6cad855e203a893438580ce2f7ce998fb44ed9..7d6f1875e13224597ac03a5c98da646bf962b522 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              0
 #define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        1
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
 
index ebc4b52172093d61a1fbf92ef2cec8ce1e1665f4..5d323820121d98bcf922afe2e90416c52f141d0c 100644 (file)
@@ -477,19 +477,19 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                                M_IADD(GET_HIGH_REG(s1), REG_ITMP3, GET_HIGH_REG(d));
                        }
                        else if ((iptr->sx.val.l >= (-32768 + 1)) && (iptr->sx.val.l < 0)) {
-                               s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
+                               s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                                M_ISUB_IMM(s1, -(iptr->sx.val.l), GET_LOW_REG(d));
                                M_CMPULT_IMM(GET_LOW_REG(d), iptr->sx.val.l, REG_ITMP3);
-                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
+                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                M_ISUB_IMM(s1, 1, GET_HIGH_REG(d));
                                M_IADD(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d));
                        }
                        else {
-                               ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
+                               ICONST(REG_ITMP1, iptr->sx.val.l & 0xffffffff);
                                s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_IADD(s1, REG_ITMP2, GET_LOW_REG(d));
+                               M_IADD(s1, REG_ITMP1, GET_LOW_REG(d));
                                M_CMPULT(GET_LOW_REG(d), s1, REG_ITMP3);
-                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
+                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                M_IADD(s1, REG_ITMP3, GET_HIGH_REG(d));
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_IADD(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d));
@@ -534,7 +534,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
                        M_ISUB(s1, s2, GET_HIGH_REG(d));
                        s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                       s2 = emit_load_s2_low(jd, iptr, REG_ITMP1);
+                       s2 = emit_load_s2_low(jd, iptr, REG_ITMP2);
                        M_CMPULT(s1, s2, REG_ITMP3);
                        M_ISUB(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d));
                        /* if s1 is equal to REG_ITMP3 we have to reload it, since
@@ -562,10 +562,10 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
 #else
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
                        if ((iptr->sx.val.l >= 0) && (iptr->sx.val.l <= 32768)) {
-                               s1 = emit_load_s1_low(jd, iptr, REG_ITMP2);
+                               s1 = emit_load_s1_low(jd, iptr, REG_ITMP1);
                                M_ISUB_IMM(s1, iptr->sx.val.l, GET_LOW_REG(d));
                                M_CMPULT_IMM(GET_LOW_REG(d), -(iptr->sx.val.l), REG_ITMP3);
-                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
+                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                M_ISUB_IMM(s1, 1, GET_HIGH_REG(d));
                                M_IADD(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d));
                        }
@@ -576,11 +576,11 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                                M_IADD(GET_HIGH_REG(s1), REG_ITMP3, GET_HIGH_REG(d));
                        }
                        else {
-                               ICONST(REG_ITMP2, iptr->sx.val.l & 0xffffffff);
+                               ICONST(REG_ITMP1, iptr->sx.val.l & 0xffffffff);
                                s1 = emit_load_s1_low(jd, iptr, REG_ITMP3);
-                               M_ISUB(s1, REG_ITMP2, GET_LOW_REG(d));
-                               M_CMPULT(s1, REG_ITMP2, REG_ITMP3);
-                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
+                               M_ISUB(s1, REG_ITMP1, GET_LOW_REG(d));
+                               M_CMPULT(s1, REG_ITMP1, REG_ITMP3);
+                               s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                                M_ISUB(s1, REG_ITMP3, GET_HIGH_REG(d));
                                ICONST(REG_ITMP3, iptr->sx.val.l >> 32);
                                M_ISUB(GET_HIGH_REG(d), REG_ITMP3, GET_HIGH_REG(d));
@@ -780,12 +780,12 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                                M_AND_IMM(d, iptr->sx.val.i, d);
                        }
                        else {
-                               ICONST(REG_ITMP2, iptr->sx.val.i);
-                               M_AND(s1, REG_ITMP2, d);
+                               ICONST(REG_ITMP3, iptr->sx.val.i);
+                               M_AND(s1, REG_ITMP3, d);
                                M_BGEZ(s1, 4);
                                M_NOP;
                                M_ISUB(REG_ZERO, s1, d);
-                               M_AND(d, REG_ITMP2, d);
+                               M_AND(d, REG_ITMP3, d);
                        }
                        M_ISUB(REG_ZERO, d, d);
                        emit_store_dst(jd, iptr, d);
@@ -1010,7 +1010,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
                        M_AND(s1, s2, GET_LOW_REG(d));
-                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
+                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
                        M_AND(s1, s2, GET_HIGH_REG(d));
 #endif
@@ -1082,7 +1082,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
                        M_OR(s1, s2, GET_LOW_REG(d));
-                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
+                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
                        M_OR(s1, s2, GET_HIGH_REG(d));
 #endif
@@ -1154,7 +1154,7 @@ void codegen_emit_instruction(jitdata* jd, instruction* iptr)
                        s2 = emit_load_s2_low(jd, iptr, REG_ITMP3);
                        d = codegen_reg_of_dst(jd, iptr, REG_ITMP12_PACKED);
                        M_XOR(s1, s2, GET_LOW_REG(d));
-                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP2);
+                       s1 = emit_load_s1_high(jd, iptr, REG_ITMP1);
                        s2 = emit_load_s2_high(jd, iptr, REG_ITMP3);
                        M_XOR(s1, s2, GET_HIGH_REG(d));
 #endif
index 2fec3a5bf1b66c97d2a5236058f92b4eaedaf9fb..f48ca785803a4468b54bd94fa0db3976747b3174 100644 (file)
@@ -80,10 +80,41 @@ void md_init(void)
  */
 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
 {
+       int disp = 0;
+       int cause;
        ucontext_t* _uc = (struct ucontext *) _p;
        mcontext_t* _mc = &_uc->uc_mcontext;
+       void *xpc;
 
-       void* xpc = (void*) (_mc->pc - 4);
+#if !defined(__UCLIBC__)
+# if ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 5))
+       /* NOTE: We only need this for pre glibc-2.5. */
+
+       /* get the cause of this exception */
+
+       cause = _mc->cause;
+
+       /* check the cause to find the faulting instruction */
+
+       /* TODO: use defines for that stuff */
+
+       switch (cause & 0x0000003c) {
+       case 0x00000008:
+               /* TLBL: XPC is ok */
+               break;
+
+       case 0x00000010:
+               /* AdEL: XPC is of the following instruction */
+               disp -= 4;
+               break;
+       }
+       xpc = (void*) (_mc->pc + disp);
+# else
+       xpc = (void*) _mc->pc;
+# endif
+#else
+       xpc = (void*) _gregs[CTX_EPC];
+#endif
 
        // Handle the trap.
        trap_handle(TRAP_SIGSEGV, xpc, _p);
@@ -98,7 +129,11 @@ void md_signal_handler_sigill(int sig, siginfo_t* siginfo, void* _p)
        ucontext_t* _uc = (struct ucontext *) _p;
        mcontext_t* _mc = &_uc->uc_mcontext;
 
-       void* xpc = (void*) (_mc->pc - 4);
+#if !defined(__UCLIBC__)
+       void* xpc = (void*) _mc->pc;
+#else
+       void* xpc = (void*) _gregs[CTX_EPC];
+#endif
 
        // Handle the trap.
        trap_handle(TRAP_SIGILL, xpc, _p);
index 0846f99410d49e11d2a06a40c7b0323ab6877997..5d35c222f1f0e9351a25ba3003d9b5308420f54b 100644 (file)
@@ -43,7 +43,7 @@ void OprofileAgent::initialize(void)
 {
        _handle = op_open_agent();
        if (!_handle)
-               os::abort_errno("unable to open opagent handle:");
+               os::abort_errno("unable to open opagent handle");
 }
 
 /**
index dcafac7b7eedad04c3333d23124af04a9e970710..6acd9687c493440c8548b4509a9c584a8642b4d6 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "vm/breakpoint.hpp"
 #include "vm/exceptions.hpp"
+#include "vm/hook.hpp"
 #include "vm/initialize.hpp"
 #include "vm/options.h"
 #include "vm/os.hpp"
@@ -360,7 +361,7 @@ static int patcher_depth = 0;
 #define TRACE_PATCHER_INDENT for (i=0; i<patcher_depth; i++) printf("\t")
 #endif /* !defined(NDEBUG) */
 
-java_handle_t *patcher_handler(u1 *pc)
+bool patcher_handler(u1 *pc)
 {
        codeinfo      *code;
        patchref_t    *pr;
@@ -396,7 +397,7 @@ java_handle_t *patcher_handler(u1 *pc)
                }
 #endif
                code->patchers->unlock();
-               return NULL;
+               return true;
        }
 
 #if !defined(NDEBUG)
@@ -450,24 +451,17 @@ java_handle_t *patcher_handler(u1 *pc)
        }
 #endif
 
-       // Check for return value and exit accordingly.
-       if (result == false) {
-               // Mangle the pending exception.
+       // Check return value and mangle the pending exception.
+       if (result == false)
                resolve_handle_pending_exception(true);
 
-               // Get the exception and return it.
-               java_handle_t* e = exceptions_get_and_clear_exception();
-
-               code->patchers->unlock();
-
-               return e;
-       }
-
-       pr->done = true; /* XXX this is only preliminary to prevent double-patching */
+       // XXX This is only preliminary to prevent double-patching.
+       else
+               pr->done = true;
 
        code->patchers->unlock();
 
-       return NULL;
+       return result;
 }
 
 
@@ -581,13 +575,8 @@ bool patcher_breakpoint(patchref_t *pr)
        // Get stuff from the patcher reference.
        Breakpoint* breakp = (Breakpoint*) pr->ref;
 
-#if defined(ENABLE_JVMTI)
-       methodinfo* m = breakp->method;
-       int32_t     l = breakp->location;
-
-       log_message_method("JVMTI: Reached breakpoint in method ", m);
-       log_println("JVMTI: Reached breakpoint at location %d", l);
-#endif
+       // Hook point when a breakpoint was triggered.
+       Hook::breakpoint(breakp);
 
        // In case the breakpoint wants to be kept active, we simply
        // fail to "patch" at this point.
index e51582d72eda21f94793df501417af814b576151..684b41c13a8c28f846aa398237af6ea390da78bd 100644 (file)
@@ -86,7 +86,7 @@ bool patcher_is_patched_at(void* pc);
 // MD function.
 bool patcher_is_valid_trap_instruction_at(void* pc);
 
-java_handle_t *patcher_handler(u1 *pc);
+bool patcher_handler(u1 *pc);
 
 
 /* empty patcher (just patches back original mcode) ***************************/
index 6e0f1fce58f313191cdd64be9082dffd0f1a375c..6544790a22429b47c361bca15ac725ec9bc07841 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              0
 #define STACKFRAME_RA_TOP_OF_FRAME                0
-#define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
+#define STACKFRAME_RA_LINKAGE_AREA                1
+#define STACKFRAME_LEAFMETHODS_RA_REGISTER        1
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
 
 
index 2a6899381867ef9aef8817eccefd3ea169243b91..d0f378dcc392fd0c1044cfd69aca51b39c70893f 100644 (file)
@@ -117,43 +117,6 @@ void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t    *_uc;
-       mcontext_t    *_mc;
-       unsigned long *_gregs;
-       u1            *pc;
-       u1            *sp;
-
-       _uc = (ucontext_t *) _p;
-
-#if defined(__UCLIBC__)
-       _mc    = &(_uc->uc_mcontext);
-       _gregs = _mc->regs->gpr;
-#else
-       _mc    = _uc->uc_mcontext.uc_regs;
-       _gregs = _mc->gregs;
-#endif
-
-       /* get the PC and SP for this thread */
-
-       pc = (u1 *) _gregs[PT_NIP];
-       sp = (u1 *) _gregs[REG_SP];
-
-       /* now suspend the current thread */
-
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index 2c9333b359d38a2a5fff55cdf66c43f18ef17603..ee362634644c1892e6b39e200a1c569b3dc79b7d 100644 (file)
@@ -240,8 +240,8 @@ void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
                /* save the current machine code */
                *(u4*)(savedmcode) = *(u4*)(pc);
 
-               /* build the machine code for the patch */
-               assert(0); /* XXX build trap instruction below */
+               // Build the machine code for the patch. On PowerPC we use
+               // an illegal instruction which really is just 0, believe me!
                mcode = 0;
 
                /* write the new machine code */
index 0488a1d7c6eee658318700def09b58c1c8199aec..5d9469609ca5ad300c69413881948c8a5a743dff 100644 (file)
@@ -97,6 +97,7 @@
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              0
 #define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_RA_LINKAGE_AREA                1
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
 
index 1e6650f2048eb196a7210ee6cf4b4a6261aaaff0..8b080b8753bc3680a072e088f41f9c5335d2634b 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/replace.cpp - on-stack replacement of methods
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 #include <vmlog_cacao.h>
 #endif
 
-/*** architecture-dependent configuration *************************************/
-
-/* first unset the macros (default) */
-#undef REPLACE_RA_LINKAGE_AREA
-
-/* powerpc */
-#if defined(__POWERPC__)
-# define REPLACE_RA_LINKAGE_AREA
-#endif
-
-
-/*** configuration of native stack slot size **********************************/
-
-/* XXX this should be in md-abi.h files, probably */
-
-#define SIZE_OF_STACKSLOT      8
-#define STACK_SLOTS_PER_FLOAT  1
-typedef u8 stackslot_t;
-
 
 /*** debugging ****************************************************************/
 
@@ -1471,130 +1452,6 @@ static void replace_write_executionstate(rplpoint *rp,
 }
 
 
-/* md_pop_stackframe ***********************************************************
-
-   Restore callee-saved registers (including the RA register),
-   set the stack pointer to the next stackframe,
-   set the PC to the return address of the popped frame.
-
-   *** This function imitates the effects of the method epilog ***
-   *** and returning from the method call.                     ***
-
-   IN:
-       es...............execution state
-
-   OUT:
-       *es..............the execution state after popping the stack frame
-                        NOTE: es->code and es->pv are NOT updated.
-
-*******************************************************************************/
-
-void md_pop_stackframe(executionstate_t *es)
-{
-       u1 *ra;
-       s4 framesize;
-       s4 reg;
-       s4 i;
-       stackslot_t *basesp;
-       stackslot_t *sp;
-
-       assert(es->code);
-
-       /* calculate the size of the stackframe */
-
-       framesize = md_stacktrace_get_framesize(es->code);
-
-       /* read the return address */
-
-#if STACKFRAME_LEAFMETHODS_RA_REGISTER
-       if (code_is_leafmethod(es->code))
-               ra = es->ra;
-       else
-#endif
-               ra = (u1*) md_stacktrace_get_returnaddress(es->sp, framesize);
-
-       /* calculate the base of the stack frame */
-
-       sp = (stackslot_t *) es->sp;
-       basesp = sp + es->code->stackframesize;
-
-       /* restore return address, if part of frame */
-
-#if STACKFRAME_RA_TOP_OF_FRAME
-# if STACKFRAME_LEAFMETHODS_RA_REGISTER
-       if (!code_is_leafmethod(es->code))
-# endif
-               es->ra = (u1*) (ptrint) *--basesp;
-#endif /* STACKFRAME_RA_TOP_OF_FRAME */
-
-#if defined(REPLACE_RA_LINKAGE_AREA)
-# if STACKFRAME_LEAFMETHODS_RA_REGISTER
-       if (!code_is_leafmethod(es->code))
-# endif
-               es->ra = (u1*) (ptrint) basesp[LA_LR_OFFSET / sizeof(stackslot_t)];
-#endif /* REPLACE_RA_LINKAGE_AREA */
-
-       /* restore saved int registers */
-
-       reg = INT_REG_CNT;
-       for (i=0; i<es->code->savedintcount; ++i) {
-               while (nregdescint[--reg] != REG_SAV)
-                       ;
-               es->intregs[reg] = *--basesp;
-       }
-
-       /* restore saved flt registers */
-
-       /* XXX align? */
-       reg = FLT_REG_CNT;
-       for (i=0; i<es->code->savedfltcount; ++i) {
-               while (nregdescfloat[--reg] != REG_SAV)
-                       ;
-               basesp -= STACK_SLOTS_PER_FLOAT;
-               es->fltregs[reg] = *(double*)basesp;
-       }
-
-#if defined(HAS_ADDRESS_REGISTER_FILE)
-       /* restore saved adr registers */
-
-       reg = ADR_REG_CNT;
-       for (i=0; i<es->code->savedadrcount; ++i) {
-               while (nregdescadr[--reg] != REG_SAV)
-                       ;
-               es->adrregs[reg] = *--basesp;
-       }
-#endif
-
-       /* adjust the stackpointer */
-
-       es->sp += framesize;
-#if STACKFRMAE_RA_BETWEEN_FRAMES
-       es->sp += SIZEOF_VOID_P; /* skip return address */
-#endif
-
-       /* set the program counter to the return address */
-
-       es->pc = ra;
-
-       /* in debugging mode clobber non-saved registers */
-
-#if !defined(NDEBUG)
-       /* for debugging */
-       for (i=0; i<INT_REG_CNT; ++i)
-               if (nregdescint[i] != REG_SAV)
-                       es->intregs[i] = (ptrint) 0x33dead3333dead33ULL;
-       for (i=0; i<FLT_REG_CNT; ++i)
-               if (nregdescfloat[i] != REG_SAV)
-                       *(u8*)&(es->fltregs[i]) = 0x33dead3333dead33ULL;
-# if defined(HAS_ADDRESS_REGISTER_FILE)
-       for (i=0; i<ADR_REG_CNT; ++i)
-               if (nregdescadr[i] != REG_SAV)
-                       es->adrregs[i] = (ptrint) 0x33dead3333dead33ULL;
-# endif
-#endif /* !defined(NDEBUG) */
-}
-
-
 /* md_push_stackframe **********************************************************
 
    Save the given return address, build the new stackframe,
@@ -1673,12 +1530,12 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
                *--basesp = (ptrint) ra;
 #endif /* STACKFRAME_RA_TOP_OF_FRAME */
 
-#if defined(REPLACE_RA_LINKAGE_AREA)
+#if STACKFRAME_RA_LINKAGE_AREA
 # if STACKFRAME_LEAFMETHODS_RA_REGISTER
        if (!code_is_leafmethod(calleecode))
 # endif
-               basesp[LA_LR_OFFSET / sizeof(stackslot_t)] = (ptrint) ra;
-#endif /* REPLACE_RA_LINKAGE_AREA */
+               *((uint8_t**) ((intptr_t) basesp + LA_LR_OFFSET)) = ra;
+#endif /* STACKFRAME_RA_LINKAGE_AREA */
 
        /* save int registers */
 
@@ -1686,7 +1543,8 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
        for (i=0; i<calleecode->savedintcount; ++i) {
                while (nregdescint[--reg] != REG_SAV)
                        ;
-               *--basesp = es->intregs[reg];
+               basesp -= 1;
+               *((uintptr_t*) basesp) = es->intregs[reg];
 
                /* XXX may not clobber saved regs used by native code! */
 #if !defined(NDEBUG) && 0
@@ -1702,7 +1560,7 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
                while (nregdescfloat[--reg] != REG_SAV)
                        ;
                basesp -= STACK_SLOTS_PER_FLOAT;
-               *(double*)basesp = es->fltregs[reg];
+               *((double*) basesp) = es->fltregs[reg];
 
                /* XXX may not clobber saved regs used by native code! */
 #if !defined(NDEBUG) && 0
@@ -1717,7 +1575,8 @@ void md_push_stackframe(executionstate_t *es, codeinfo *calleecode, u1 *ra)
        for (i=0; i<calleecode->savedadrcount; ++i) {
                while (nregdescadr[--reg] != REG_SAV)
                        ;
-               *--basesp = es->adrregs[reg];
+               basesp -= 1;
+               *((uintptr_t*) basesp) = es->adrregs[reg];
 
                /* XXX may not clobber saved regs used by native code! */
 #if !defined(NDEBUG) && 0
@@ -1768,12 +1627,12 @@ u1* replace_pop_activation_record(executionstate_t *es,
        frame->syncslotcount = count;
        frame->syncslots = (replace_val_t*) DumpMemory::allocate(sizeof(replace_val_t) * count);
        for (i=0; i<count; ++i) {
-               frame->syncslots[i].p = sp[es->code->memuse + i]; /* XXX md_ function */
+               frame->syncslots[i].p = *((intptr_t*) (sp + es->code->memuse + i)); /* XXX md_ function */
        }
 
        /* pop the stackframe */
 
-       md_pop_stackframe(es);
+       executionstate_pop_stackframe(es);
 
        ra = es->pc;
 
@@ -2096,7 +1955,7 @@ void replace_push_activation_record(executionstate_t *es,
        count = code_get_sync_slot_count(calleecode);
        assert(count == calleeframe->syncslotcount);
        for (i=0; i<count; ++i) {
-               sp[calleecode->memuse + i] = calleeframe->syncslots[i].p;
+               *((intptr_t*) (sp + calleecode->memuse + i)) = calleeframe->syncslots[i].p;
        }
 
        /* redirect future invocations */
@@ -2935,7 +2794,7 @@ static void replace_me(rplpoint *rp, executionstate_t *es)
 }
 
 
-/* replace_me_wrapper **********************************************************
+/* replace_handler *************************************************************
 
    This function is called by the signal handler. It determines if there
    is an active replacement point pending at the given PC and returns
@@ -2945,23 +2804,22 @@ static void replace_me(rplpoint *rp, executionstate_t *es)
 
    IN:
        pc...............the program counter that triggered the replacement.
-       context..........the context (machine state) to which the
+       es...............the execution state (machine state) to which the
                            replacement should be applied.
 
    OUT:
-       context..........the context after replacement finished.
+       es...............the execution state after replacement finished.
 
    RETURN VALUE:
        true.............replacement done, everything went ok
-       false............no replacement done, context unchanged
+       false............no replacement done, execution state unchanged
 
 *******************************************************************************/
 
-bool replace_me_wrapper(u1 *pc, void *context)
+bool replace_handler(u1 *pc, executionstate_t *es)
 {
        codeinfo         *code;
        rplpoint         *rp;
-       executionstate_t  es;
 #if defined(ENABLE_RT_TIMING)
        struct timespec time_start, time_end;
 #endif
@@ -2982,20 +2840,9 @@ bool replace_me_wrapper(u1 *pc, void *context)
 
                DOLOG( printf("valid replacement point\n"); );
 
-#if !defined(NDEBUG)
-               executionstate_sanity_check(context);
-#endif
-
                /* set codeinfo pointer in execution state */
 
-               es.code = code;
-
-               /* read execution state from current context */
-
-               md_executionstate_read(&es, context);
-
-               DOLOG( printf("REPLACEMENT READ: ");
-                          executionstate_println(&es); );
+               es->code = code;
 
                /* do the actual replacement */
 
@@ -3003,20 +2850,13 @@ bool replace_me_wrapper(u1 *pc, void *context)
                RT_TIMING_GET_TIME(time_start);
 #endif
 
-               replace_me(rp, &es);
+               replace_me(rp, es);
 
 #if defined(ENABLE_RT_TIMING)
                RT_TIMING_GET_TIME(time_end);
                RT_TIMING_TIME_DIFF(time_start, time_end, RT_TIMING_REPLACE);
 #endif
 
-               /* write execution state to current context */
-
-               md_executionstate_write(&es, context);
-
-               DOLOG( printf("REPLACEMENT WRITE: ");
-                          executionstate_println(&es); );
-
                /* new code is entered after returning */
 
                DOLOG( printf("JUMPING IN!\n"); fflush(stdout); );
index 5c520d5ec462c9eb6a8cdbe67886dd4e1c13c0d6..e83134904b8a49ad4f1016bb9ff27913266b9a20 100644 (file)
@@ -59,6 +59,7 @@ typedef union  replace_val_t replace_val_t;
 
 #include "vm/method.hpp"
 
+#include "vm/jit/executionstate.h"
 #include "vm/jit/reg.h"
 #include "vm/jit/stacktrace.hpp"
 
@@ -249,7 +250,7 @@ void replace_free_replacement_points(codeinfo *code);
 void replace_activate_replacement_points(codeinfo *code, bool mappable);
 void replace_deactivate_replacement_points(codeinfo *code);
 
-bool replace_me_wrapper(u1 *pc, void *context);
+bool replace_handler(u1 *pc, executionstate_t *es);
 
 #if !defined(NDEBUG)
 void replace_show_replacement_points(codeinfo *code);
index e5c26995547822fa8999df4bd5fe16537636fcbe..8259e04e60ead24035541d81dad21c7d3b84bfbc 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              0
 #define STACKFRAME_RA_TOP_OF_FRAME                1
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           1
 
index 48c674101ca8bf66fb34b78b1546a231026c73ae..0197ab4fe0c4e20d4cb9f0014279daf78d7f9d57 100644 (file)
 #error Set the values below correctly!!!
 #define STACKFRMAE_RA_BETWEEN_FRAMES              0
 #define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
 
index 66489b627a05f24eb5462a780e43708b26c21f50..7ab8382d2b99efd66e5d735a4e3ac5f1965df4df 100644 (file)
@@ -412,18 +412,6 @@ void NativeStub::remove(void* stub)
 }
 
 
-// Legacy C interface.
-
-extern "C" {
-       void*     CompilerStub_generate(methodinfo* m) { return CompilerStub::generate(m); }
-       void      CompilerStub_remove(void* stub) { CompilerStub::remove(stub); }
-
-       void      BuiltinStub_generate(methodinfo* m, builtintable_entry* bte) { BuiltinStub::generate(m, bte); }
-
-       void      NativeStub_remove(void* stub) { NativeStub::remove(stub); }
-}
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where
index a8af31404f485e21832921db925c92ec16d42b59..28d4eb1b93c908bb4a169a80ad9c5690476dc442 100644 (file)
@@ -70,15 +70,6 @@ public:
 // Include machine dependent implementation.
 #include "md-stubs.hpp"
 
-#else
-
-// Legacy C interface.
-
-void*     CompilerStub_generate(methodinfo* m);
-void*     CompilerStub_remove(void* stub);
-void      BuiltinStub_generate(methodinfo* m, builtintable_entry* bte);
-void      NativeStub_remove(void* stub);
-
 #endif
 
 #endif // _STUBS_HPP
index d515db09c5750a683cc6d7fd7867e3f18308c1a5..c57c702c59bcae603a5fdc47ba5527433779d300 100644 (file)
@@ -41,6 +41,7 @@
 #include "vm/array.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/javaobjects.hpp"
 #include "vm/options.h"
 #include "vm/string.hpp"
@@ -225,6 +226,9 @@ void trace_java_call_enter(methodinfo *m, uint64_t *arg_regs, uint64_t *stack)
        return;
 #endif
 
+       // Hook point on entry into Java method.
+       Hook::method_enter(m);
+
        md = m->parseddesc;
 
        /* calculate message length */
@@ -361,6 +365,9 @@ void trace_java_call_exit(methodinfo *m, uint64_t *return_regs)
        return;
 #endif
 
+       // Hook point upon exit from Java method.
+       Hook::method_exit(m);
+
        md = m->parseddesc;
 
        /* outdent the log message */
index 6d9340c18377cf6dbd5d891a1740b4a26366123d..e15a77a18c834c06bc8abceb34f00c5b962b86ff 100644 (file)
@@ -103,10 +103,6 @@ void trap_handle(int sig, void *xpc, void *context)
        stackframeinfo_t sfi;
        trapinfo_t       trp;
 
-       // Prevent compiler warnings.
-       java_handle_t* o = NULL;
-       methodinfo*    m = NULL;
-
 #if !defined(NDEBUG)
        // Sanity checking the XPC.
        if (xpc == NULL)
@@ -172,7 +168,18 @@ void trap_handle(int sig, void *xpc, void *context)
        /* Do some preparations before we enter the nativeworld. */
        /* BEFORE: creating stackframeinfo */
 
+       // Prevent compiler warnings.
+       int32_t        index = 0;
+       java_handle_t* o     = NULL;
+       methodinfo*    m     = NULL;
+
        switch (type) {
+       case TRAP_ArrayIndexOutOfBoundsException:
+               /* Get the index into the array causing the exception. */
+
+               index = (int32_t) val;
+               break;
+
        case TRAP_ClassCastException:
                /* Wrap the value into a handle, as it is a reference. */
 
@@ -217,9 +224,12 @@ void trap_handle(int sig, void *xpc, void *context)
 
        /* Get resulting exception (or pointer to compiled method). */
 
-       int32_t        index;
        java_handle_t* p;
        void*          entry;
+       bool           was_patched;
+#if defined(ENABLE_REPLACEMENT)
+       bool           was_replaced;
+#endif
 
        switch (type) {
        case TRAP_NullPointerException:
@@ -231,7 +241,6 @@ void trap_handle(int sig, void *xpc, void *context)
                break;
 
        case TRAP_ArrayIndexOutOfBoundsException:
-               index = (int32_t) val;
                p = exceptions_new_arrayindexoutofboundsexception(index);
                break;
 
@@ -248,26 +257,25 @@ void trap_handle(int sig, void *xpc, void *context)
                break;
 
        case TRAP_PATCHER:
+               p = NULL;
 #if defined(ENABLE_REPLACEMENT)
-               if (replace_me_wrapper((uint8_t*) xpc, context)) {
-                       p = NULL;
+               was_replaced = replace_handler((uint8_t*) xpc, &es);
+               if (was_replaced)
                        break;
-               }
 #endif
-               p = patcher_handler((uint8_t*) xpc);
+               was_patched = patcher_handler((uint8_t*) xpc);
                break;
 
        case TRAP_COMPILER:
-               entry = jit_compile_handle(m, sfi.pv, ra, (void*) val);
                p = NULL;
+               entry = jit_compile_handle(m, sfi.pv, ra, (void*) val);
                break;
 
-#if defined(ENABLE_REPLACEMENT)
+#if defined(__I386__) && defined(ENABLE_REPLACEMENT)
+# warning Port the below stuff to use the patching subsystem.
        case TRAP_COUNTDOWN:
-# if defined(__I386__)
-               replace_me_wrapper((uint8_t*) xpc - 13, context);
-# endif
                p = NULL;
+               (void) replace_handler((uint8_t*) xpc - 13, &es);
                break;
 #endif
 
@@ -323,12 +331,47 @@ void trap_handle(int sig, void *xpc, void *context)
                goto trap_handle_exception;
 
        case TRAP_PATCHER:
+#if defined(ENABLE_REPLACEMENT)
+               // If on-stack-replacement suceeded, we are not allowed to touch
+               // the execution state. We assume that there was no exception.
+
+               if (was_replaced) {
+                       assert(exceptions_get_exception() == NULL);
+                       break;
+               }
+#endif
+
                // 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 (was_patched) {
+                       assert(exceptions_get_exception() == NULL);
+                       es.pc = (uint8_t *) (uintptr_t) xpc;
+                       break;
+               }
+
+               // In case patching was not successful, we try to fetch the pending
+               // exception here.
+
+               p = exceptions_get_and_clear_exception();
+
+               // If there is no pending exception, we continue execution behind
+               // the position still in need of patching. Normally this would
+               // indicate an error in the patching subsystem, but others might
+               // want to piggyback patchers and we want to be able to provide
+               // "reusable trap points" and avoid inifinite loops here. This is
+               // especially useful to implement breakpoints or profiling points
+               // of any kind. So before changing the trap logic, think about
+               // utilizing the patching subsystem on your quest. :)
+
                if (p == NULL) {
+#if !defined(NDEBUG)
+                       if (opt_PrintWarnings)
+                               log_println("trap_handle: Detected reusable trap at %p", xpc);
+#endif
                        es.pc = (uint8_t *) (uintptr_t) xpc;
+                       es.pc += REPLACEMENT_PATCH_SIZE;
                        break;
                }
 
@@ -337,9 +380,19 @@ void trap_handle(int sig, void *xpc, void *context)
        trap_handle_exception:
        default:
                if (p != NULL) {
+#if defined(__ALPHA__) || defined(__I386__) || defined(__X86_64__)
+                       // Perform stack unwinding for exceptions on execution state.
+                       es.pc = (uint8_t *) (uintptr_t) xpc;
+                       es.pv = (uint8_t *) (uintptr_t) sfi.pv;
+                       executionstate_unwind_exception(&es, p);
+
+                       // Pass the exception object to the exception handler.
+                       es.intregs[REG_ITMP1_XPTR] = (uintptr_t) LLNI_DIRECT(p);
+#else
                        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;
+#endif
                }
        }
 
index ef425cb2148fa98812c8c205de464d3f913bd3f7..ff74f82bbc5847bc9f75646066230cba39778139 100644 (file)
 
 #define STACKFRMAE_RA_BETWEEN_FRAMES              1
 #define STACKFRAME_RA_TOP_OF_FRAME                0
+#define STACKFRAME_RA_LINKAGE_AREA                0
 #define STACKFRAME_LEAFMETHODS_RA_REGISTER        0
 #define STACKFRAME_SYNC_NEEDS_TWO_SLOTS           0
 
index 5807491ecbac01e65242b9c65be0c10615d4faaa..e72711d14ba9788a007f937a30100bf510d4f696 100644 (file)
@@ -56,8 +56,6 @@
        .globl asm_builtin_d2i
        .globl asm_builtin_d2l
 
-       .globl asm_get_cycle_count
-
 
 /********************* function asm_calljavafunction ***************************
 *                                                                              *
@@ -389,20 +387,6 @@ asm_builtin_d2l:
        ret
 
 
-/* asm_get_cycle_count *********************************************************
-
-   Get the current time-stamp counter from the CPU.
-
-*******************************************************************************/
-
-asm_get_cycle_count:
-       rdtsc
-       shl $0x20, %rdx
-       mov %eax, %eax
-       or %rdx, %rax
-       ret
-
-
 /* disable exec-stacks ********************************************************/
 
 #if defined(__linux__) && defined(__ELF__)
index ad8fbd9fdbbe56596bf8ee76789aa97cf90946cf..6f3d2ce2d8785d46d300b0be5d2ab4f0fff352b1 100644 (file)
@@ -101,36 +101,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
-          different to the ones in <ucontext.h>. */
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _mc->gregs[REG_RIP];
-       sp = (u1 *) _mc->gregs[REG_RSP];
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index 9a65d6b6597df307116132f144011ea18d49bd45..68f99e57e88d3529630bfa20cc65e20c29f151ef 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/x86_64/md.h - machine dependent x86_64 functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -130,6 +130,23 @@ inline static void md_dcacheflush(void* addr, int nbytes)
        __asm__ __volatile__ ("" : : : "memory");
 }
 
+
+/* md_get_cycle_count **********************************************************
+
+   Get the current time-stamp counter from the CPU.
+
+*******************************************************************************/
+
+inline static uint64_t md_get_cycle_count()
+{
+       uint64_t cycles;
+
+       // Get current cycles count from the CPU.
+       __asm__ __volatile__ ("rdtsc" : "=A" (cycles));
+
+       return cycles;
+}
+
 #endif /* _VM_JIT_X86_64_MD_H */
 
 
index 96f22f04080ee426f3df9859bd262e2da0ba00df..6f97d8831e58cf3699419b636676c2b7ff3ec7d6 100644 (file)
@@ -99,36 +99,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p)
 }
 
 
-/* md_signal_handler_sigusr1 ***************************************************
-
-   Signal handler for suspending threads.
-
-*******************************************************************************/
-
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
-{
-       ucontext_t *_uc;
-       mcontext_t *_mc;
-       u1         *pc;
-       u1         *sp;
-
-       _uc = (ucontext_t *) _p;
-       _mc = &_uc->uc_mcontext;
-
-       /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
-          different to the ones in <ucontext.h>. */
-
-       /* get the PC and SP for this thread */
-       pc = (u1 *) _mc->gregs[REG_RIP];
-       sp = (u1 *) _mc->gregs[REG_RSP];
-
-       /* now suspend the current thread */
-       threads_suspend_ack(pc, sp);
-}
-#endif
-
-
 /* md_signal_handler_sigusr2 ***************************************************
 
    Signal handler for profiling sampling.
index d956341e88bd873662de15b804a2ce9e6ba9e1cf..42e82954adc96c6be5c9b4aa7192adeb4a25f1bd 100644 (file)
@@ -45,6 +45,7 @@
 #include "vm/classcache.hpp"
 #include "vm/exceptions.hpp"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/loader.hpp"
 #include "vm/options.h"
 #include "vm/primitive.hpp"
@@ -425,6 +426,9 @@ classinfo *link_class(classinfo *c)
 
        RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
 
+       // Hook point just after a class was linked.
+       Hook::class_linked(r);
+
        return r;
 }
 
index c509c094e08c13888c4b0e9937f8945bc714adf1..9ff93a4aa527601af3b90c97b4180b271a1585ba 100644 (file)
@@ -49,6 +49,7 @@
 #include "vm/field.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/javaobjects.hpp"
 #include "vm/linker.hpp"
 #include "vm/loader.hpp"
 
 #include "vm/jit/stubs.hpp"
 
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
 
 /* global variables ***********************************************************/
 
@@ -1177,12 +1174,6 @@ classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
                        printf("]\n");
                }
 
-#if defined(ENABLE_JVMTI)
-               /* fire Class Load JVMTI event */
-               if (jvmti) jvmti_ClassLoadPrepare(false, c);
-#endif
-
-
                return c;
        } 
 
@@ -1972,18 +1963,14 @@ classinfo *load_class_from_classbuffer(classbuffer *cb)
 
        c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
 
-#if defined(ENABLE_JVMTI)
-       /* fire Class Prepare JVMTI event */
-
-       if (jvmti)
-               jvmti_ClassLoadPrepare(true, c);
-#endif
-
 #if !defined(NDEBUG)
        if (loadverbose)
                log_message_class("Loading done class: ", c);
 #endif
 
+       // Hook point just after a class was loaded.
+       Hook::class_loaded(c);
+
        return c;
 }
 
index 6e7827f2d8a75d9645b78e8ebcb87f632ac7ea2f..a0c3a4ab233ef65d624c22556fd50eda5f6dd81f 100644 (file)
@@ -127,6 +127,19 @@ void method_init(void)
           } line_number_table[line_number_table_length];
    }
 
+   LocalVariableTable_attribute {
+       u2 attribute_name_index;
+       u4 attribute_length;
+       u2 local_variable_table_length;
+       {
+           u2 start_pc;
+           u2 length;
+           u2 name_index;
+           u2 descriptor_index;
+           u2 index;
+       } local_variable_table[local_variable_table_length];
+   }
+
 *******************************************************************************/
 
 bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
@@ -433,7 +446,48 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
                                        if (!stackmap_load_attribute_stackmaptable(cb, m))
                                                return false;
                                }
-#endif
+# if defined(ENABLE_JVMTI)
+                               else if (code_attribute_name == utf_LocalVariableTable) {
+                                       /* LocalVariableTable */
+
+                                       if (m->localvars != NULL) {
+                                               exceptions_throw_classformaterror(c, "Multiple LocalVariableTable attributes");
+                                               return false;
+                                       }
+
+                                       if (!suck_check_classbuffer_size(cb, 4 + 2))
+                                               return false;
+
+                                       // Attribute length.
+                                       (void) suck_u4(cb);
+
+                                       m->localvarcount = suck_u2(cb);
+
+                                       if (!suck_check_classbuffer_size(cb, 10 * m->localvarcount))
+                                               return false;
+
+                                       m->localvars = MNEW(localvarinfo, m->localvarcount);
+
+                                       for (l = 0; l < m->localvarcount; l++) {
+                                               m->localvars[l].start_pc = suck_u2(cb);
+                                               m->localvars[l].length   = suck_u2(cb);
+
+                                               uint16_t name_index = suck_u2(cb);
+                                               if (!(m->localvars[l].name = (utf*) class_getconstant(c, name_index, CONSTANT_Utf8)))
+                                                       return false;
+
+                                               uint16_t descriptor_index = suck_u2(cb);
+                                               if (!(m->localvars[l].descriptor = (utf*) class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
+                                                       return false;
+
+                                               m->localvars[l].index = suck_u2(cb);
+
+                                               // XXX Check if index is in range.
+                                               // XXX Check if index already taken.
+                                       }
+                               }
+# endif /* defined(ENABLE_JVMTI) */
+#endif /* defined(ENABLE_JAVASE) */
                                else {
                                        /* unknown code attribute */
 
@@ -479,7 +533,7 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
                                return false;
                }
 
-#if defined(ENABLE_ANNOTATIONS)
+# if defined(ENABLE_ANNOTATIONS)
                else if (attribute_name == utf_RuntimeVisibleAnnotations) {
                        /* RuntimeVisibleAnnotations */
                        if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
@@ -505,7 +559,7 @@ bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
                        if (!annotation_load_method_attribute_annotationdefault(cb, m))
                                return false;
                }
-#endif
+# endif
 #endif
                else {
                        /* unknown attribute */
index 7d3b81a475b9bea710b62779a1812bcd2d4ab3a0..6ab842c92f923112802a98e9a62588e10d165555 100644 (file)
@@ -30,7 +30,8 @@
 
 typedef struct methodinfo          methodinfo; 
 typedef struct raw_exception_entry raw_exception_entry;
-typedef struct lineinfo            lineinfo; 
+typedef struct lineinfo            lineinfo;
+typedef struct localvarinfo        localvarinfo;
 typedef struct method_assumption   method_assumption;
 typedef struct method_worklist     method_worklist;
 typedef struct codeinfo            codeinfo;
@@ -73,7 +74,7 @@ struct methodinfo {                 /* method structure                       */
 #endif
 
        methoddesc   *parseddesc;       /* parsed descriptor                      */
-                            
+
        classinfo    *clazz;            /* class, the method belongs to           */
        s4            vftblindex;       /* index of method in virtual function    */
                                        /* table (if it is a virtual method)      */
@@ -91,6 +92,11 @@ struct methodinfo {                 /* method structure                       */
        u2            linenumbercount;  /* number of linenumber attributes        */
        lineinfo     *linenumbers;      /* array of lineinfo items                */
 
+#if defined(ENABLE_JAVASE) && defined(ENABLE_JVMTI)
+       uint16_t      localvarcount;    /* number of local variable attributes    */
+       localvarinfo* localvars;        /* array of localvarinfo items            */
+#endif
+
        u1           *stubroutine;      /* stub for compiling or calling natives  */
        codeinfo     *code;             /* current code of this method            */
 
@@ -160,6 +166,17 @@ struct lineinfo {
 };
 
 
+/* localvarinfo ***************************************************************/
+
+struct localvarinfo {
+       uint16_t start_pc;
+       uint16_t length;
+       utf*     name;
+       utf*     descriptor;
+       uint16_t index;
+};
+
+
 /* global variables ***********************************************************/
 
 extern methodinfo *method_java_lang_reflect_Method_invoke;
index 5a6f5c29f89afa645dff5dcab7b1016e15b1cebc..2fc95f3468d08440c75d96479688a756c91a0720 100644 (file)
@@ -207,9 +207,13 @@ int      opt_TraceHPI                     = 0;
 int      opt_TraceInlining                = 0;
 #endif
 int      opt_TraceJavaCalls               = 0;
+bool     opt_TraceJMMCalls                = false;
 int      opt_TraceJNICalls                = 0;
 int      opt_TraceJVMCalls                = 0;
 int      opt_TraceJVMCallsVerbose         = 0;
+#if defined(ENABLE_JVMTI)
+int      opt_TraceJVMTICalls              = 0;
+#endif
 int      opt_TraceLinkClass               = 0;
 #if defined(ENABLE_REPLACEMENT)
 int      opt_TraceReplacement             = 0;
@@ -271,9 +275,11 @@ enum {
        OPT_TraceHPI,
        OPT_TraceInlining,
        OPT_TraceJavaCalls,
+       OPT_TraceJMMCalls,
        OPT_TraceJNICalls,
        OPT_TraceJVMCalls,
        OPT_TraceJVMCallsVerbose,
+       OPT_TraceJVMTICalls,
        OPT_TraceLinkClass,
        OPT_TraceReplacement,
        OPT_TraceSubsystemInitialization,
@@ -348,9 +354,13 @@ option_t options_XX[] = {
 #if !defined(ENABLE_VMLOG)
        { "TraceJavaCalls",               OPT_TraceJavaCalls,               OPT_TYPE_BOOLEAN, "trace Java method calls" },
 #endif
+       { "TraceJMMCalls",                OPT_TraceJMMCalls,                OPT_TYPE_BOOLEAN, "trace JMM method calls" },
        { "TraceJNICalls",                OPT_TraceJNICalls,                OPT_TYPE_BOOLEAN, "trace JNI method calls" },
        { "TraceJVMCalls",                OPT_TraceJVMCalls,                OPT_TYPE_BOOLEAN, "trace JVM method calls but omit very frequent ones" },
        { "TraceJVMCallsVerbose",         OPT_TraceJVMCallsVerbose,         OPT_TYPE_BOOLEAN, "trace all JVM method calls" },
+#if defined(ENABLE_JVMTI)
+       { "TraceJVMTICalls",              OPT_TraceJVMTICalls,              OPT_TYPE_BOOLEAN, "trace JVMTI method calls" },
+#endif
        { "TraceLinkClass",               OPT_TraceLinkClass,               OPT_TYPE_BOOLEAN, "trace class linking" },
 #if defined(ENABLE_REPLACEMENT)
        { "TraceReplacement",             OPT_TraceReplacement,             OPT_TYPE_VALUE,   "trace on-stack replacement with the given verbosity level (default: 1)" },
@@ -831,6 +841,10 @@ void options_xx(JavaVMInitArgs *vm_args)
                        opt_TraceJavaCalls = enable;
                        break;
 
+               case OPT_TraceJMMCalls:
+                       opt_TraceJMMCalls = enable;
+                       break;
+
                case OPT_TraceJNICalls:
                        opt_TraceJNICalls = enable;
                        break;
@@ -843,6 +857,12 @@ void options_xx(JavaVMInitArgs *vm_args)
                        opt_TraceJVMCallsVerbose = enable;
                        break;
 
+#if defined(ENABLE_JVMTI)
+               case OPT_TraceJVMTICalls:
+                       opt_TraceJVMTICalls = enable;
+                       break;
+#endif
+
                case OPT_TraceLinkClass:
                        opt_TraceLinkClass = enable;
                        break;
index 0aa9ed3d8c7c6cd7109799067687159e17b26f03..cdd2bd1940f2aa0b648aca586e6700a5a68df011 100644 (file)
@@ -229,9 +229,13 @@ extern int      opt_TraceHPI;
 extern int      opt_TraceInlining;
 #endif
 extern int      opt_TraceJavaCalls;
+extern bool     opt_TraceJMMCalls;
 extern int      opt_TraceJNICalls;
 extern int      opt_TraceJVMCalls;
 extern int      opt_TraceJVMCallsVerbose;
+#if defined(ENABLE_JVMTI)
+extern int      opt_TraceJVMTICalls;
+#endif
 extern int      opt_TraceLinkClass;
 #if defined(ENABLE_REPLACEMENT)
 extern int      opt_TraceReplacement;
index dcfc08e8f3b20f817b9879c2cd32b82143b0ab3c..b0becaafb5838ac1e512b1479a370a2a9fae4788 100644 (file)
 
 #include "config.h"
 
-/* NOTE: In this file we check for all system headers, because we wrap
-   all system calls into functions for better portability. */
-
-#if defined(HAVE_ERRNO_H)
-# include <errno.h>
-#endif
-
-#if defined(HAVE_STDINT_H)
-# include <stdint.h>
-#endif
-
-#if defined(HAVE_STRING_H)
-# include <string.h>
-#endif
-
-#if defined(HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined(HAVE_SYS_MMAN_H)
-# include <sys/mman.h>
-#endif
-
 #if defined(__DARWIN__)
 # include <mach/mach.h>
 # include <mach/mach_host.h>
@@ -58,6 +35,9 @@
 /* this should work on BSD */
 /* #include <sys/sysctl.h> */
 
+#include "mm/memory.hpp"
+
+#include "vm/os.hpp"
 #include "vm/vm.hpp"
 
 
@@ -141,6 +121,40 @@ void os::abort_errno(const char* text, ...)
 }
 
 
+/**
+ * Return the current working directory.
+ *
+ * @return Pointer to a char array allocated by MNEW, or
+ *         NULL if memory could not be allocated.
+ */
+char* os::getcwd(void)
+{
+       int32_t size = 1024;
+
+       char* buf = MNEW(char, size);
+
+       while (buf != NULL) {
+               if (getcwd(buf, size) != NULL)
+                       return buf;
+
+               MFREE(buf, char, size);
+
+               /* too small buffer or a more serious problem */
+
+               if (errno != ERANGE)
+                       abort_errno("os::getcwd: getcwd failed");
+
+               /* double the buffer size */
+
+               size *= 2;
+
+               buf = MNEW(char, size);
+       }
+
+       return NULL;
+}
+
+
 /**
  * Maps anonymous memory, even on systems not defining
  * MAP_ANON(YMOUS).
@@ -266,27 +280,10 @@ int os::processors_online(void)
 extern "C" {
        void*  os_mmap_anonymous(void *addr, size_t len, int prot, int flags) { return os::mmap_anonymous(addr, len, prot, flags); }
 
-       void   os_abort(void) { os::abort(); }
-       int    os_access(const char* pathname, int mode) { return os::access(pathname, mode); }
        int    os_atoi(const char* nptr) { return os::atoi(nptr); }
-       void*  os_calloc(size_t nmemb, size_t size) { return os::calloc(nmemb, size); }
-#if defined(ENABLE_JRE_LAYOUT)
-       char*  os_dirname(char* path) { return os::dirname(path); }
-#endif
-       char*  os_dlerror(void) { return os::dlerror(); }
-       void*  os_dlsym(void* handle, const char* symbol) { return os::dlsym(handle, symbol); }
-       int    os_fclose(FILE* fp) { return os::fclose(fp); }
-       FILE*  os_fopen(const char* path, const char* mode) { return os::fopen(path, mode); }
-       size_t os_fread(void* ptr, size_t size, size_t nmemb, FILE* stream) { return os::fread(ptr, size, nmemb, stream); }
-       void   os_free(void* ptr) { os::free(ptr); }
        int    os_getpagesize(void) { return os::getpagesize(); }
        void*  os_memcpy(void* dest, const void* src, size_t n) { return os::memcpy(dest, src, n); }
        void*  os_memset(void* s, int c, size_t n) { return os::memset(s, c, n); }
-       int    os_mprotect(void* addr, size_t len, int prot) { return os::mprotect(addr, len, prot); }
-       int    os_scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*)) { return os::scandir(dir, namelist, filter, compar); }
-       int    os_stat(const char* path, struct stat* buf) { return os::stat(path, buf); }
-       char*  os_strcat(char* dest, const char* src) { return os::strcat(dest, src); }
-       char*  os_strcpy(char* dest, const char* src) { return os::strcpy(dest, src); }
        char*  os_strdup(const char* s) { return os::strdup(s); }
        int    os_strlen(const char* s) { return os::strlen(s); }
 
index 10da1fe9023e7e5bf3fa0a3ce4203121be69a9b7..5e895d56c897f5fce5f835f849a69d6685f0c6ce 100644 (file)
 # include <unistd.h>
 #endif
 
+#if defined(__DARWIN__)
+# if defined(HAVE_MACH_MACH_H)
+#  include <mach/mach.h>
+# endif
+#endif
+
+#if defined(HAVE_SYS_LOADAVG_H)
+# include <sys/loadavg.h>
+#endif
+
 #if defined(HAVE_SYS_MMAN_H)
 # include <sys/mman.h>
 #endif
 # include <sys/types.h>
 #endif
 
+#if defined(HAVE_SYS_UTSNAME_H)
+# include <sys/utsname.h>
+#endif
+
 
 #ifdef __cplusplus
 
@@ -133,9 +147,12 @@ public:
        static inline int     fprintf(FILE* stream, const char* format, ...);
        static inline size_t  fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
        static inline void    free(void* ptr);
+       static inline char*   getcwd(char* buf, size_t size);
        static inline char*   getenv(const char* name);
        static inline int     gethostname(char* name, size_t len);
+       static inline int     getloadavg(double loadavg[], int nelem);
        static inline int     getpagesize(void);
+       static inline pid_t   getpid(void);
        static inline int     getsockname(int s, struct sockaddr* name, socklen_t* namelen);
        static inline int     getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen);
        static inline int     listen(int sockfd, int backlog);
@@ -164,6 +181,7 @@ public:
        static void  abort(const char* text, ...);
        static void  abort_errnum(int errnum, const char* text, ...);
        static void  abort_errno(const char* text, ...);
+       static char* getcwd(void);
        static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
        static void  print_backtrace();
        static int   processors_online();
@@ -373,6 +391,15 @@ inline static int system_ftruncate(int fd, off_t length)
 #endif
 }
 
+inline char* os::getcwd(char* buf, size_t size)
+{
+#if defined(HAVE_GETCWD)
+       return ::getcwd(buf, size);
+#else
+# error getcwd not available
+#endif
+}
+
 inline char* os::getenv(const char* name)
 {
 #if defined(HAVE_GETENV)
@@ -391,6 +418,15 @@ inline int os::gethostname(char* name, size_t len)
 #endif
 }
 
+inline int os::getloadavg(double loadavg[], int nelem)
+{
+#if defined(HAVE_GETLOADAVG)
+       return ::getloadavg(loadavg, nelem);
+#else
+# error getloadavg not available
+#endif
+}
+
 inline int os::getpagesize(void)
 {
 #if defined(HAVE_GETPAGESIZE)
@@ -400,6 +436,15 @@ inline int os::getpagesize(void)
 #endif
 }
 
+inline pid_t os::getpid(void)
+{
+#if defined(HAVE_GETPID)
+       return ::getpid();
+#else
+# error getpid not available
+#endif
+}
+
 inline int os::getsockname(int s, struct sockaddr* name, socklen_t* namelen)
 {
 #if defined(HAVE_GETSOCKNAME)
@@ -647,25 +692,10 @@ inline static ssize_t system_write(int fd, const void *buf, size_t count)
 
 void*  os_mmap_anonymous(void *addr, size_t len, int prot, int flags);
 
-void   os_abort(void);
-int    os_access(const char* pathname, int mode);
 int    os_atoi(const char* nptr);
-void*  os_calloc(size_t nmemb, size_t size);
-char*  os_dirname(char* path);
-char*  os_dlerror(void);
-void*  os_dlsym(void* handle, const char* symbol);
-int    os_fclose(FILE* fp);
-FILE*  os_fopen(const char* path, const char* mode);
-size_t os_fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
-void   os_free(void* ptr);
 int    os_getpagesize(void);
 void*  os_memcpy(void* dest, const void* src, size_t n);
 void*  os_memset(void* s, int c, size_t n);
-int    os_mprotect(void* addr, size_t len, int prot);
-int    os_scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
-int    os_stat(const char* path, struct stat* buf);
-char*  os_strcat(char* dest, const char* src);
-char*  os_strcpy(char* dest, const char* src);
 char*  os_strdup(const char* s);
 int    os_strlen(const char* s);
 
index 9d6b79200e7ea2bcb753cbc69a915dee1869a12f..59c97eb205c0be159669b7a6bf40c952ae17abc2 100644 (file)
@@ -369,6 +369,27 @@ int Primitive::get_type_by_wrapperclass(classinfo *c)
 }
 
 
+/**
+ * Returns the primitive type of the given primitive-class.
+ *
+ * @param c Class structure.
+ *
+ * @return Integer type of the class.
+ */
+int Primitive::get_type_by_primitiveclass(classinfo *c)
+{
+       /* Search primitive table. */
+
+       for (int i = 0; i < PRIMITIVETYPE_COUNT; i++)
+               if (primitivetype_table[i].class_primitive == c)
+                       return i;
+       
+       /* Invalid primitive class. */
+
+       return -1;
+}
+
+
 /**
  * Box a primitive of the given type.  If the type is an object,
  * simply return it.
index 2016786f00b27cbe57d204f22a02916ca984250a..c650521039b15acec2407f1e5ff1ff41e73cc289 100644 (file)
@@ -50,6 +50,7 @@ public:
        static classinfo*     get_arrayclass_by_type(int type);
 
        static int            get_type_by_wrapperclass(classinfo *c);
+       static int            get_type_by_primitiveclass(classinfo *c);
 
        static java_handle_t* box(int type, imm_union value);
 
index e2f3858388d5e1cb33a64280c60d52102efe0ce4..a13b8b6dd2479777412dfdbd0694d71d0f660518 100644 (file)
 #include <string.h>
 #include <time.h>
 #include <unistd.h>
-#include <sys/utsname.h>
 
 #include "mm/memory.hpp"
 
 #include "native/llni.h"
 
-#include "toolbox/util.h"
-
 #include "vm/class.hpp"
 #include "vm/global.h"
 #include "vm/method.hpp"
@@ -339,7 +336,7 @@ Properties::Properties()
 
        /* Get properties from system. */
 
-       char* cwd      = _Jv_getcwd();
+       char* cwd      = os::getcwd();
 
        char* env_user = os::getenv("USER");
        char* env_home = os::getenv("HOME");
index 9bfe3da3de9a83abfa6f80b206bd960e0a2adc39..a34cfd54c57f119b5fb42ce7b794c36fcd48af7a 100644 (file)
 #include <stdint.h>
 #include <stdlib.h>
 
-#if defined(__DARWIN__)
-/* If we compile with -ansi on darwin, <sys/types.h> is not
- included. So let's do it here. */
-# include <sys/types.h>
-# include <sys/utsname.h>
-#endif
-
 #include "arch.h"
 
 #if defined(ENABLE_GC_BOEHM)
@@ -62,6 +55,7 @@
 /* function prototypes ********************************************************/
 
 void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p);
+void signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p);
 
 
 /* signal_init *****************************************************************
@@ -195,10 +189,10 @@ bool signal_init(void)
        signal_register_signal(Signal_INTERRUPT_SYSTEM_CALL, (functionptr) signal_handler_sighup, 0);
 #endif
 
-#if defined(ENABLE_THREADS) && defined(ENABLE_GC_CACAO)
-       /* SIGUSR1 handler for the exact GC to suspend threads */
+#if defined(ENABLE_THREADS)
+       /* SIGUSR1 handler for thread suspension */
 
-       signal_register_signal(SIGUSR1, (functionptr) md_signal_handler_sigusr1,
+       signal_register_signal(SIGUSR1, (functionptr) signal_handler_sigusr1,
                                                   SA_SIGINFO);
 #endif
 
@@ -388,6 +382,21 @@ void signal_handler_sighup(int sig, siginfo_t *siginfo, void *_p)
 #endif
 
 
+/* signal_handler_sigusr1 ******************************************************
+
+   Signal handler for suspending threads.
+
+*******************************************************************************/
+
+#if defined(ENABLE_THREADS)
+void signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p)
+{
+       // Really suspend ourselves by acknowledging the suspension.
+       threads_suspend_ack();
+}
+#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
index 94d1727cc3872913eda662260964f4678bdba88f..29a75cf4b9aadd36038d05d84d8e7e2e17911d3d 100644 (file)
@@ -74,8 +74,6 @@ void md_signal_handler_sigill(int sig, siginfo_t *siginfo, void *_p);
 void md_signal_handler_sigtrap(int sig, siginfo_t *siginfo, void *_p);
 #endif
 
-void md_signal_handler_sigusr1(int sig, siginfo_t *siginfo, void *_p);
-
 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p);
 
 #ifdef __cplusplus
index ecf0a70c3ee5ed2927469e430692661fe3d54b0e..ef43e92ff114f11e17c22fb075bc3a0bcaf2a335 100644 (file)
@@ -38,7 +38,6 @@
 
 #include "toolbox/list.hpp"
 #include "toolbox/logging.hpp"
-#include "toolbox/util.h"
 
 #include "vm/exceptions.hpp"
 #include "vm/loader.hpp"
@@ -115,7 +114,7 @@ void SuckClasspath::add(char *classpath)
                        cwdlen = 0;
 
                        if (*start != '/') {                      /* XXX fix me for win32 */
-                               cwd = _Jv_getcwd();
+                               cwd = os::getcwd();
                                cwdlen = strlen(cwd) + strlen("/");
                        }
 
index 8282b082ebcf17fae0f82ccf1535ce20d867a836..3a775bfe09f6c526ef77334d65f4d9525f3f6c90 100644 (file)
@@ -1,9 +1,7 @@
 /* src/vm/types.h - type definitions for CACAO's internal types
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
-   C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
-   E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
-   J. Wenninger, Institut f. Computersprachen - TU Wien
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Reinhard Grafl
-            Andreas  Krall
-
-   Changes: Christian Thalinger
-
 */
 
 
 
 #include "config.h"
 
+#include <stdint.h>
+
 
 /* In this file we check for unknown pointersizes, so we don't have to
    do this somewhere else. */
 
 /* Define the sizes of the integer types used internally by CACAO. ************/
 
-typedef signed char             s1;
-typedef unsigned char           u1;
-typedef signed short int        s2;
-typedef unsigned short int      u2;
+typedef int8_t            s1;
+typedef uint8_t           u1;
+
+typedef int16_t           s2;
+typedef uint16_t          u2;
 
-typedef signed int              s4;
-typedef unsigned int            u4;
+typedef int32_t           s4;
+typedef uint32_t          u4;
 
-#if SIZEOF_VOID_P == 8
-typedef signed long int         s8;
-typedef unsigned long int       u8;
-#elif SIZEOF_VOID_P == 4
-typedef signed long long int    s8;
-typedef unsigned long long int  u8;
-#else
-#error unknown pointer size
-#endif
+typedef int64_t           s8;
+typedef uint64_t          u8;
 
 
 /* Define the size of a function pointer used in function pointer casts. ******/
 
-#if SIZEOF_VOID_P == 8
-typedef u8                      ptrint;
-#else
-typedef u4                      ptrint;
-#endif
+typedef uintptr_t                      ptrint;
 
 #endif /* _CACAO_TYPES_H */
 
index ccc5e0f745e407d7aa730363b51527ce12adbd2a..7afcb2ce14d540538f992ffd5cea05ba62934c18 100644 (file)
@@ -152,13 +152,17 @@ utf *utf_EnclosingMethod;
 utf *utf_Signature;
 utf *utf_StackMapTable;
 
-#if defined(ENABLE_ANNOTATIONS)
+# if defined(ENABLE_JVMTI)
+utf *utf_LocalVariableTable;
+# endif
+
+# if defined(ENABLE_ANNOTATIONS)
 utf *utf_RuntimeVisibleAnnotations;            /* RuntimeVisibleAnnotations            */
 utf *utf_RuntimeInvisibleAnnotations;          /* RuntimeInvisibleAnnotations          */
 utf *utf_RuntimeVisibleParameterAnnotations;   /* RuntimeVisibleParameterAnnotations   */
 utf *utf_RuntimeInvisibleParameterAnnotations; /* RuntimeInvisibleParameterAnnotations */
 utf *utf_AnnotationDefault;                    /* AnnotationDefault                    */
-#endif
+# endif
 #endif
 
 utf *utf_init;                          /* <init>                             */
@@ -414,6 +418,10 @@ void utf8_init(void)
        utf_Signature                  = utf_new_char("Signature");
        utf_StackMapTable              = utf_new_char("StackMapTable");
 
+# if defined(ENABLE_JVMTI)
+       utf_LocalVariableTable         = utf_new_char("LocalVariableTable");
+# endif
+
 # if defined(ENABLE_ANNOTATIONS)
        utf_RuntimeVisibleAnnotations            = utf_new_char("RuntimeVisibleAnnotations");
        utf_RuntimeInvisibleAnnotations          = utf_new_char("RuntimeInvisibleAnnotations");
index 8a1197ebf619715b50361bf5c851cea3a950dc17..b60111dc4ed9885b1bb27f4e080d006bd30f0e68 100644 (file)
@@ -149,13 +149,17 @@ extern utf *utf_EnclosingMethod;
 extern utf *utf_Signature;
 extern utf *utf_StackMapTable;
 
-#if defined(ENABLE_ANNOTATIONS)
+# if defined(ENABLE_JVMTI)
+extern utf *utf_LocalVariableTable;
+# endif
+
+# if defined(ENABLE_ANNOTATIONS)
 extern utf *utf_RuntimeVisibleAnnotations;
 extern utf *utf_RuntimeInvisibleAnnotations;
 extern utf *utf_RuntimeVisibleParameterAnnotations;
 extern utf *utf_RuntimeInvisibleParameterAnnotations;
 extern utf *utf_AnnotationDefault;
-#endif
+# endif
 #endif
 
 extern utf *utf_init;
index 7aff240f09e7f86f220e1acd67f94741a119a4f5..70c0ae53c8f896e79e5872fdbe74bbccd4f1af4d 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/vm.cpp - VM startup and shutdown functions
 
-   Copyright (C) 1996-2005, 2006, 2007, 2008
+   Copyright (C) 1996-2005, 2006, 2007, 2008, 2009
    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
 
    This file is part of CACAO.
@@ -69,6 +69,7 @@
 #include "vm/finalizer.hpp"
 #include "vm/global.h"
 #include "vm/globals.hpp"
+#include "vm/hook.hpp"
 #include "vm/initialize.hpp"
 #include "vm/options.h"
 #include "vm/os.hpp"
@@ -389,7 +390,7 @@ opt_struct opts[] = {
 
 *******************************************************************************/
 
-void usage(void)
+static void usage(void)
 {
        puts("Usage: cacao [-options] classname [arguments]");
        puts("               (to run a class file)");
@@ -541,7 +542,7 @@ static void version(bool opt_exit)
        puts("java version \""JAVA_VERSION"\"");
        puts("CACAO version "VERSION"\n");
 
-       puts("Copyright (C) 1996-2005, 2006, 2007, 2008");
+       puts("Copyright (C) 1996-2005, 2006, 2007, 2008, 2009");
        puts("CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO");
        puts("This is free software; see the source for copying conditions.  There is NO");
        puts("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
@@ -1283,6 +1284,9 @@ VM::VM(JavaVMInitArgs* vm_args)
 
        utf8_init();
 
+       // Hook point before the VM is initialized.
+       Hook::vm_preinit();
+
 #if defined(ENABLE_JVMTI)
        // AFTER: utf8_init
        if (!_nativeagents.load_agents())
@@ -1444,11 +1448,21 @@ VM::VM(JavaVMInitArgs* vm_args)
        // Initialization is done, VM is created.
        _created      = true;
        _initializing = false;
-       
+
+       // Set the VM inittime.
+       _inittime = builtin_currenttimemillis();
+
+       // Hook point after the VM is initialized.
+       Hook::vm_init();
+
        // Print the run-time VM configuration after all stuff is set and
        // the VM is initialized.
        if (opt_PrintConfig)
                print_run_time_config();
+
+       // Start runtime agents after the VM is created.
+       if (!start_runtime_agents())
+               os::abort("vm_create: start_runtime_agents failed");
 }
 
 
@@ -1517,6 +1531,60 @@ void VM::print_run_time_config()
 }
 
 
+/**
+ * Start runtime agents which are provided by the JRE but need to be
+ * started explicitly by the VM.
+ */
+bool VM::start_runtime_agents()
+{
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+       // Nothing to do.
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+       // Check whether the management agent should be loaded.
+       if ((_properties.get("com.sun.management.jmxremote") != NULL) ||
+               (_properties.get("com.sun.management.snmp") != NULL))
+       {
+
+               // Load the management agent class.
+               classinfo* class_sun_management_Agent;
+               if (!(class_sun_management_Agent = load_class_from_sysloader(utf_new_char("sun/management/Agent"))))
+                       return false;
+
+               // Link the management agent class.
+               if (!link_class(class_sun_management_Agent))
+                       return false;
+
+               // Actually start the management agent.
+               methodinfo* m = class_resolveclassmethod(class_sun_management_Agent,
+                                                                                                utf_new_char("startAgent"),
+                                                                                                utf_void__void,
+                                                                                                class_java_lang_Object,
+                                                                                                false);
+
+               if (m == NULL)
+                       return false;
+
+               (void) vm_call_method(m, NULL);
+
+               if (exceptions_get_exception() != NULL)
+                       return false;
+       }
+
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+       // Nothing to do.
+
+#else
+# error unknown classpath configuration
+#endif
+
+       return true;
+}
+
+
 /* vm_run **********************************************************************
 
    Runs the main-method of the passed class.
@@ -1667,17 +1735,6 @@ void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args)
        typeinfo_test();
 #endif
 
-       /* set ThreadMXBean variables */
-
-//     _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount++;
-//     _Jv_jvm->java_lang_management_ThreadMXBean_TotalStartedThreadCount++;
-
-//     if (_Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount >
-//             _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount)
-//             _Jv_jvm->java_lang_management_ThreadMXBean_PeakThreadCount =
-//                     _Jv_jvm->java_lang_management_ThreadMXBean_ThreadCount;
-#warning Move to C++
-
        /* start the main thread */
 
        (void) vm_call_method(m, NULL, oa.get_handle());
@@ -1732,6 +1789,9 @@ int vm_destroy(JavaVM *vm)
        threads_join_all_threads();
 #endif
 
+       // Hook point before the VM is actually destroyed.
+       Hook::vm_shutdown();
+
        /* VM is gone. */
 
 //     _created = false;
@@ -2454,11 +2514,7 @@ java_handle_t *vm_call_method_objectarray(methodinfo *m, java_handle_t *o,
 
 extern "C" {
 
-JavaVM* VM_get_javavm()      { return VM::get_current()->get_javavm(); }
 JNIEnv* VM_get_jnienv()      { return VM::get_current()->get_jnienv(); }
-bool    VM_is_initializing() { return VM::get_current()->is_initializing(); }
-bool    VM_is_created()      { return VM::get_current()->is_created(); }
-int64_t VM_get_starttime()   { return VM::get_current()->get_starttime(); }
 
 void vm_abort(const char* text, ...)
 {
index e57c1b958054cb535c55b124c168451ddc70f5ef..0430fa4d6a30be141f7a43469bd9cd9352ecca36 100644 (file)
@@ -65,6 +65,7 @@ private:
        bool    _created;
        bool    _exiting;
        int64_t _starttime;
+       int64_t _inittime;
 
        // Subsystems.
        Properties      _properties;      ///< Commandline properties.
@@ -101,6 +102,7 @@ public:
        bool    is_created()      { return _created; }
        bool    is_exiting()      { return _exiting; }
        int64_t get_starttime()   { return _starttime; }
+       int64_t get_inittime()    { return _inittime; }
 
        Properties&      get_properties     () { return _properties; }
        Recompiler&      get_recompiler     () { return _recompiler; } // REMOVEME
@@ -111,15 +113,15 @@ public:
        NativeLibraries& get_nativelibraries() { return _nativelibraries; }
        NativeMethods&   get_nativemethods  () { return _nativemethods; }
        SuckClasspath&   get_suckclasspath  () { return _suckclasspath; }
+
+private:
+       // Internal helper methods.
+       bool start_runtime_agents();
 };
 
 #else
 
-JavaVM* VM_get_javavm();
 JNIEnv* VM_get_jnienv();
-bool    VM_is_initializing();
-bool    VM_is_created();
-int64_t VM_get_starttime();
 
 #endif
 
@@ -155,9 +157,6 @@ extern uint8_t* intrp_main_stack;
 extern "C" {
 #endif
 
-void usage(void);
-
-bool vm_create(JavaVMInitArgs *vm_args);
 void vm_run(JavaVM *vm, JavaVMInitArgs *vm_args);
 int32_t   vm_destroy(JavaVM *vm);
 void vm_exit(int32_t status);
index 601e31d08c7564996f3d67cdc1510b6e571c8cd6..6eb7f621b9ce36661a19d1d201e345553708d592 100644 (file)
 
 #include <assert.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <unistd.h>
 #include <zlib.h>
-#include <sys/mman.h>
 
 #include "vm/types.h"
 
@@ -40,6 +38,7 @@
 #include "mm/memory.hpp"
 
 #include "vm/global.h"
+#include "vm/os.hpp"
 #include "vm/suck.hpp"
 #include "vm/utf8.h"
 #include "vm/vm.hpp"
index 4f421c76388ad1dd2570d309334927c8959a9b58..7754f78e24dd9994d8e59e8e20115fc439f2b9af 100644 (file)
@@ -29,6 +29,7 @@ import org.junit.runners.Suite;
 @RunWith(Suite.class)
 
 @Suite.SuiteClasses({
+TestAbstractMethodError.class,
 TestArrayClasses.class,
 TestCloning.class,
 TestExceptionInStaticClassInitializer.class,
diff --git a/tests/regression/base/TestAbstractMethodError.java b/tests/regression/base/TestAbstractMethodError.java
new file mode 100644 (file)
index 0000000..62f766b
--- /dev/null
@@ -0,0 +1,87 @@
+/* tests/regression/base/TestAbstractMethodError.java
+
+   Copyright (C) 2009
+   CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+   This file is part of CACAO.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2, or (at
+   your option) any later version.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public 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 TestAbstractMethodError extends ClassLoader {
+    @Test
+    public void test() throws InstantiationException, IllegalAccessException {
+        Class cls = super.defineClass(null, bytecode, 0, bytecode.length);
+        Base obj = (Base) cls.newInstance();
+        try {
+            obj.foo();
+            fail();
+        } catch (AbstractMethodError e) {
+            StackTraceElement[] st = e.getStackTrace();
+            assertNotNull("stack trace available", st);
+            assertTrue("stack trace size", st.length > 1);
+            assertEquals("stack trace element",
+                         "TestAbstractMethodError.test(TestAbstractMethodError.java:35)",
+                         st[0].toString());
+        }
+    }
+
+    public static abstract class Base {
+        abstract void foo();
+    };
+
+    /*
+     * The following Bytecode was derived from a class like this:
+     *    public class Foo extends TestAbstractMethodError.Base {
+     *        // empty.
+     *    }
+     *
+     * This class is not abstract but it misses to implement the
+     * abstract method "void foo()" of the base class.
+     */
+    static byte[] bytecode = {
+       (byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x2e, 
+       (byte)0x00, (byte)0x0e, (byte)0x07, (byte)0x00, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x03, 
+       (byte)0x46, (byte)0x6f, (byte)0x6f, (byte)0x07, (byte)0x00, (byte)0x04, (byte)0x01, (byte)0x00, 
+       (byte)0x1c, (byte)0x54, (byte)0x65, (byte)0x73, (byte)0x74, (byte)0x41, (byte)0x62, (byte)0x73, 
+       (byte)0x74, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x74, (byte)0x4d, (byte)0x65, (byte)0x74, 
+       (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x45, (byte)0x72, (byte)0x72, (byte)0x6f, (byte)0x72, 
+       (byte)0x24, (byte)0x42, (byte)0x61, (byte)0x73, (byte)0x65, (byte)0x01, (byte)0x00, (byte)0x06, 
+       (byte)0x3c, (byte)0x69, (byte)0x6e, (byte)0x69, (byte)0x74, (byte)0x3e, (byte)0x01, (byte)0x00, 
+       (byte)0x03, (byte)0x28, (byte)0x29, (byte)0x56, (byte)0x01, (byte)0x00, (byte)0x04, (byte)0x43, 
+       (byte)0x6f, (byte)0x64, (byte)0x65, (byte)0x0a, (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x09, 
+       (byte)0x0c, (byte)0x00, (byte)0x05, (byte)0x00, (byte)0x06, (byte)0x01, (byte)0x00, (byte)0x0c, 
+       (byte)0x49, (byte)0x6e, (byte)0x6e, (byte)0x65, (byte)0x72, (byte)0x43, (byte)0x6c, (byte)0x61, 
+       (byte)0x73, (byte)0x73, (byte)0x65, (byte)0x73, (byte)0x07, (byte)0x00, (byte)0x0c, (byte)0x01, 
+       (byte)0x00, (byte)0x17, (byte)0x54, (byte)0x65, (byte)0x73, (byte)0x74, (byte)0x41, (byte)0x62, 
+       (byte)0x73, (byte)0x74, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x74, (byte)0x4d, (byte)0x65, 
+       (byte)0x74, (byte)0x68, (byte)0x6f, (byte)0x64, (byte)0x45, (byte)0x72, (byte)0x72, (byte)0x6f, 
+       (byte)0x72, (byte)0x01, (byte)0x00, (byte)0x04, (byte)0x42, (byte)0x61, (byte)0x73, (byte)0x65, 
+       (byte)0x00, (byte)0x21, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x00, 
+       (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x05, 
+       (byte)0x00, (byte)0x06, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x07, (byte)0x00, (byte)0x00, 
+       (byte)0x00, (byte)0x11, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, 
+       (byte)0x00, (byte)0x05, (byte)0x2a, (byte)0xb7, (byte)0x00, (byte)0x08, (byte)0xb1, (byte)0x00, 
+       (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x0a, (byte)0x00, 
+       (byte)0x00, (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x03, (byte)0x00, 
+       (byte)0x0b, (byte)0x00, (byte)0x0d, (byte)0x04, (byte)0x09, 
+    };
+}