[src/vm/jit/x86_64/freebsd/Makefile]
[src/vm/jit/x86_64/linux/Makefile]
[src/vm/jit/x86_64/solaris/Makefile]
- [src/vmcore/Makefile]
[tests/Makefile]
[tests/regression/Makefile]
[tests/regression/assertion/Makefile]
scripts \
threads \
toolbox \
- vm \
- vmcore
+ vm
# DON'T CHANGE THIS ORDER!!!
fdlibm \
toolbox \
mm \
- vmcore \
vm \
threads \
native \
$(top_builddir)/src/threads/libthreads.la \
$(top_builddir)/src/toolbox/libtoolbox.la \
$(top_builddir)/src/vm/libvm.la \
- $(top_builddir)/src/vmcore/libvmcore.la \
$(GC_LIB)
bin_PROGRAMS = \
# include "native/jvmti/cacaodbg.h"
#endif
-#include "vmcore/os.hpp"
-
+#include "vm/os.hpp"
#include "vm/vm.hpp"
/* mm/cacao-gc/final.c - GC module for finalization and weak references
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
/* mm/cacao-gc/final.h - GC header for finalization and weak references
- Copyright (C) 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#ifndef _FINAL_H
#define _FINAL_H
+#include "config.h"
#include "vm/types.h"
#include "toolbox/list.h"
-#include "vmcore/method.h"
+#include "vm/method.h"
/* Global Variables ***********************************************************/
#include "rootset.h"
#include "mm/memory.h"
#include "toolbox/logging.h"
+
#include "vm/finalizer.h"
+#include "vm/rt-timing.h"
#include "vm/vm.hpp"
-#include "vmcore/rt-timing.h"
/* Global Variables ***********************************************************/
#if !defined(NDEBUG) && defined(GC_DEBUGGING)
# include <assert.h>
-# include "vmcore/options.h"
+# include "vm/options.h"
# define GC_LOG(code) if (opt_verbosegc) { code; }
# define GC_ASSERT(assertion) assert(assertion)
#else
#include "native/include/java_lang_String.h"
#include "native/llni.h"
#include "toolbox/logging.h"
+
#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/rt-timing.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
/* Global Variables ***********************************************************/
#include "rootset.h"
#include "mm/memory.h"
#include "toolbox/logging.h"
+
#include "vm/global.h"
+#include "vm/linker.h"
#include "vm/vm.hpp"
-#include "vmcore/linker.h"
/* Helper Macros **************************************************************/
#include "threads/thread.hpp"
+#include "vm/method.h"
+
#include "vm/jit/replace.h"
-#include "vmcore/method.h"
/* Structures *****************************************************************/
#include "mm/codememory.h"
#include "mm/memory.h"
-#include "vmcore/options.h"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/os.hpp"
-
-#include "vm/global.h"
-
/* global code memory variables ***********************************************/
#include "threads/thread.hpp"
-#include "vmcore/options.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/os.hpp"
-
#include "vm/vm.hpp"
#include "vm/exceptions.hpp"
#include "vm/finalizer.h"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/rt-timing.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-
/* global variables ***********************************************************/
#include "vm/builtin.h"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/* global stuff ***************************************************************/
#endif
#include "vm/global.h"
-
-#include "vmcore/method.h"
+#include "vm/method.h"
/* reference types ************************************************************/
#include "vm/string.hpp"
#include "vm/vm.hpp"
-#include "vmcore/options.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/os.hpp"
-
/* memory_mprotect *************************************************************
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
+#include "vm/statistics.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/jit/jit.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* debug **********************************************************************/
#include "vm/types.h"
#include "vm/global.h"
-
-#include "vmcore/method.h"
+#include "vm/method.h"
#if 0
#include "toolbox/logging.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/argument.h"
-#include "vmcore/options.h"
-
/* debug **********************************************************************/
#include "vm/types.h"
#include "vm/global.h"
-
-#include "vmcore/method.h"
+#include "vm/method.h"
/* localref_table **************************************************************
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/resolve.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
-
#if defined(ENABLE_JVMTI)
#include "native/jvmti/cacaodbg.h"
#endif
#include "native/jni.h"
+#include "vm/class.h"
#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/os.hpp"
-#include "vmcore/utf8.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/os.hpp"
+#include "vm/utf8.h"
/* defines ********************************************************************/
#include "threads/lock-common.h"
-#include "vm/types.h"
#include "vm/builtin.h"
-#include "vm/vm.hpp" /* REMOVE ME: temporarily */
#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/string.hpp"
-
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/zip.h"
+#include "vm/types.h"
+#include "vm/vm.hpp" /* REMOVE ME: temporarily */
+#include "vm/zip.h"
static java_handle_t* zip_read_resource(list_classpath_entry *lce, utf *name)
# include "native/include/java_lang_Runtime.h"
#endif
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/utf8.h"
-
// Native functions are exported as C functions.
extern "C" {
# include "native/include/java_lang_String.h"
#endif
+#include "vm/javaobjects.hpp"
#include "vm/string.hpp"
-#include "vmcore/javaobjects.hpp"
-
// Native functions are exported as C functions.
extern "C" {
#include "toolbox/logging.h"
#include "vm/builtin.h"
-
-#include "vmcore/javaobjects.hpp"
+#include "vm/javaobjects.hpp"
// Native functions are exported as C functions.
#endif
#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/javaobjects.hpp"
-
// Native functions are exported as C functions.
extern "C" {
# include "native/vm/include/gnu_classpath_VMStackWalker.h"
#endif
+#include "vm/class.h"
#include "vm/global.h"
+#include "vm/utf8.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/class.h"
-#include "vmcore/utf8.h"
-
// Native functions are exported as C functions.
extern "C" {
#include "native/llni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/gnu_java_lang_VMCPStringBuilder.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/gnu_java_lang_VMCPStringBuilder.h"
+#endif
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
-
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
/*
#include "toolbox/logging.h"
+#include "vm/classcache.h"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/classcache.h"
-#include "vmcore/utf8.h"
-
// Native functions are exported as C functions.
extern "C" {
#endif
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/global.h"
+#include "vm/loader.h" /* XXX only for load_class_bootstrap */
+#include "vm/options.h"
#include "vm/vm.hpp"
-#include "vmcore/class.h"
-#include "vmcore/loader.h" /* XXX only for load_class_bootstrap */
-#include "vmcore/options.h"
-
// Native functions are exported as C functions.
extern "C" {
#include "vm/builtin.h"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/globals.hpp"
-#include "vmcore/utf8.h"
-
// Native functions are exported as C functions.
extern "C" {
#include "toolbox/logging.h"
+#include "vm/classcache.h"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/classcache.h"
-#include "vmcore/utf8.h"
-
// Native functions are exported as C functions.
extern "C" {
#include "native/llni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/java_lang_VMClass.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMClass.h"
+#endif
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
#include "vm/string.hpp"
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-
#if defined(ENABLE_ANNOTATIONS)
+#include "vm/annotation.h"
#include "vm/vm.hpp"
-
-#include "vmcore/annotation.h"
#endif
#include "native/llni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/java_lang_VMClassLoader.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMClassLoader.h"
+#endif
#include "toolbox/logging.h"
#include "toolbox/list.h"
#endif
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/classcache.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
+#include "vm/statistics.h"
#include "vm/string.hpp"
+#include "vm/suck.h"
#include "vm/vm.hpp"
+#include "vm/zip.h"
#include "vm/jit/asmpart.h"
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vmcore/suck.h"
-#include "vmcore/zip.h"
-
#if defined(ENABLE_JVMTI)
#include "native/jvmti/cacaodbg.h"
#endif
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
-
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
// Native functions are exported as C functions.
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
+#include "vm/os.hpp"
#include "vm/string.hpp"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/os.hpp"
-#include "vmcore/utf8.h"
-
static bool finalizeOnExit = false;
#include "threads/thread.hpp"
#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/string.hpp"
-
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
// Native functions are exported as C functions.
#include "native/llni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/java_lang_VMThrowable.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_VMThrowable.h"
+#endif
#include "vm/array.h"
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
#include "vm/string.hpp"
#include "vm/jit/code.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/loader.h"
// Native functions are exported as C functions.
#include "native/jni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/java_lang_management_VMManagementFactory.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_management_VMManagementFactory.h"
+#endif
#include "toolbox/logging.h"
#include "vm/builtin.h"
-
-#include "vmcore/globals.hpp"
+#include "vm/globals.hpp"
/*
#include "native/llni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/java_lang_reflect_VMConstructor.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_reflect_VMConstructor.h"
+#endif
#include "native/vm/reflection.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/string.hpp"
-
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
// Native functions are exported as C functions.
#include "native/llni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/java_lang_reflect_VMField.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_reflect_VMField.h"
+#endif
#if defined(ENABLE_ANNOTATIONS)
// REMOVEME
#include "vm/exceptions.hpp"
#include "vm/global.h"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/string.hpp"
-
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
/* _field_access_check *********************************************************
#include "native/llni.h"
#include "native/native.h"
-// FIXME
-//#include "native/include/java_lang_reflect_VMMethod.h"
+#if defined(ENABLE_JNI_HEADERS)
+# include "native/vm/include/java_lang_reflect_VMMethod.h"
+#endif
#include "native/vm/reflection.hpp"
#include "vm/access.h"
-#include "vm/global.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/method.h"
#include "vm/resolve.h"
#include "vm/string.hpp"
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/method.h"
-
// Native functions are exported as C functions.
extern "C" {
#endif
#include "vm/global.h"
+#include "vm/utf8.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/utf8.h"
-
// Native functions are exported as C functions.
extern "C" {
# include "native/include/java_util_concurrent_atomic_AtomicLong.h"
#endif
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
// Native functions are exported as C functions.
#include "toolbox/logging.h"
-#include "vm/vm.hpp"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/resolve.h"
#include "vm/string.hpp"
-
-#include "vmcore/class.h"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+// Native functions are exported as C functions.
extern "C" {
/*
#include "native/vm/nativevm.h"
+#include "vm/class.h"
#include "vm/initialize.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
# include "mm/memory.h"
# include "native/vm/openjdk/hpi.h"
+# include "vm/globals.hpp"
# include "vm/properties.h"
+# include "vm/utf8.h"
# include "vm/vm.hpp"
-
-# include "vmcore/globals.hpp"
-# include "vmcore/utf8.h"
#endif
#include "native/vm/openjdk/hpi.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/properties.h"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
-#include "vmcore/utf8.h"
-
/* VM callback functions ******************************************************/
#endif
#include "vm/builtin.h"
+#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/package.hpp"
#include "vm/primitive.hpp"
#include "vm/properties.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/classcache.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
-
/* debugging macros ***********************************************************/
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/method.h"
#include "vm/string.hpp"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/method.h"
-
/**
* Invoke a method on the given object with the given arguments.
#include "native/jni.h"
#include "native/native.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
+#include "vm/field.h"
+#include "vm/method.h"
class Reflection {
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+#include "vm/os.hpp"
#include "vm/string.hpp"
-
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/os.hpp"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
// Native functions are exported as C functions.
#include "toolbox/list.h"
-#include "vm/global.h"
#include "vm/exceptions.hpp"
#include "vm/finalizer.h"
+#include "vm/global.h"
+#include "vm/options.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
-#include "vmcore/options.h"
-
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
#if defined(ENABLE_VMLOG)
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
#include "vm/signallocal.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
-#include "vm/jit/asmpart.h"
-
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/options.h"
-
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
+#include "vm/jit/asmpart.h"
+
#if !defined(__DARWIN__)
# include <semaphore.h>
#endif
#include "threads/thread.hpp"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
#include "vm/string.hpp"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vm/jit/stacktrace.hpp"
-
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
-#include "vmcore/utf8.h"
+#include "vm/jit/stacktrace.hpp"
// FIXME
extern "C" {
#endif
-#include "vmcore/os.hpp"
-
-#include "threads/mutex.hpp"
+#include "vm/types.h"
+// Include early to get threadobject.
#if defined(ENABLE_THREADS)
# include "threads/posix/thread-posix.hpp"
#else
# include "threads/none/thread-none.h"
#endif
-#include "vm/types.h"
-
-#include "vm/global.h"
+#include "vm/os.hpp"
#include "native/jni.h"
#include "native/llni.h"
-#include "vmcore/utf8.h"
+#include "threads/mutex.hpp"
+
+#include "vm/global.h"
+#include "vm/utf8.h"
/* only define the following stuff with thread enabled ************************/
#include "toolbox/list.h"
-#include "vmcore/options.h"
+#include "vm/options.h"
/* global variables ***********************************************************/
/* src/toolbox/hashtable.h - functions for internal hashtables
- Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Contact: cacao@cacaojvm.org
-
- Authors: Reinhard Grafl
- Christian Thalinger
-
*/
#include "vm/types.h"
#include "vm/global.h"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
/* data structures for hashtables ********************************************
#include "vm/global.h"
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
#include <stdio.h>
#include <stdarg.h>
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/utf8.h"
+#include "vm/class.h"
+#include "vm/method.h"
+#include "vm/utf8.h"
/*500 is to small for eclipse traces, (builtin_trace_args, perhaps the
cycles-stats.h
endif
+if ENABLE_JAVASE
+if ENABLE_ANNOTATIONS
+ANNOTATION_SOURCES = \
+ annotation.c \
+ annotation.h
+endif
+
+STACKMAP_SOURCES = \
+ stackmap.c \
+ stackmap.h
+endif
+
+if ENABLE_RT_TIMING
+RT_TIMING_SOURCES = \
+ rt-timing.c \
+ rt-timing.h
+endif
+
+if ENABLE_STATISTICS
+STATISTICS_SOURCES = \
+ statistics.c \
+ statistics.h
+endif
+
+if ENABLE_ZLIB
+ZLIB_SOURCES = \
+ zip.c \
+ zip.h
+endif
+
noinst_HEADERS = \
global.h \
types.h
libvm.la
libvm_la_SOURCES = \
- $(ASSERTION_SOURCES) \
access.c \
access.h \
+ $(ANNOTATION_SOURCES) \
array.c \
array.h \
+ $(ASSERTION_SOURCES) \
builtin.c \
builtin.h \
builtintable.inc \
+ class.c \
+ class.h \
+ classcache.c \
+ classcache.h \
$(CYCLES_STATS_SOURCES) \
+ descriptor.c \
+ descriptor.h \
exceptions.cpp \
exceptions.hpp \
+ field.c \
+ field.h \
finalizer.c \
finalizer.h \
+ globals.cpp \
+ globals.hpp \
initialize.c \
initialize.h \
+ javaobjects.cpp \
+ javaobjects.hpp \
jit_interface.h \
+ linker.c \
+ linker.h \
+ loader.c \
+ loader.h \
+ method.c \
+ method.h \
+ options.c \
+ options.h \
+ os.cpp \
+ os.hpp \
package.cpp \
package.hpp \
primitive.cpp \
primitive.hpp \
+ primitivecore.c \
properties.c \
properties.h \
+ references.h \
resolve.c \
resolve.h \
+ $(RT_TIMING_SOURCES) \
signal.c \
signallocal.h \
+ $(STACKMAP_SOURCES) \
+ $(STATISTICS_SOURCES) \
string.cpp \
string.hpp \
+ suck.c \
+ suck.h \
+ utf8.c \
+ utf8.h \
vm.cpp \
- vm.hpp
+ vm.hpp \
+ $(ZLIB_SOURCES)
libvm_la_LIBADD = \
jit/libjit.la
#include "vm/access.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/field.h"
+#include "vm/globals.hpp"
+#include "vm/method.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/method.h"
-
/* access_is_accessible_class **************************************************
extern "C" {
#endif
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
+#include "vm/method.h"
/* macros *********************************************************************/
--- /dev/null
+/* src/vm/annotation.c - class annotations
+
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "native/llni.h"
+
+#include "mm/memory.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/annotation.h"
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/loader.h"
+#include "vm/primitive.hpp"
+#include "vm/suck.h"
+#include "vm/types.h"
+
+#if !defined(ENABLE_ANNOTATIONS)
+# error annotation support has to be enabled when compling this file!
+#endif
+
+
+/* annotation_bytearrays_resize ***********************************************
+
+ Resize an array of bytearrays.
+
+ IN:
+ bytearrays.....array of bytearrays
+ size...........new size of the refered array
+
+ RETURN VALUE:
+ The new array if a resize was neccessarry, the old if the given size
+ equals the current size or NULL if an error occured.
+
+*******************************************************************************/
+
+static java_handle_objectarray_t *annotation_bytearrays_resize(
+ java_handle_objectarray_t *bytearrays, uint32_t size)
+{
+ java_handle_objectarray_t *newbas = NULL; /* new array */
+ uint32_t minsize = 0; /* count of object refs to copy */
+ uint32_t oldsize = 0; /* size of old array */
+
+ if (bytearrays != NULL) {
+ oldsize = array_length_get((java_handle_t*)bytearrays);
+
+ /* if the size already fits do nothing */
+ if (size == oldsize) {
+ return bytearrays;
+ }
+ }
+
+ newbas = builtin_anewarray(size,
+ Primitive_get_arrayclass_by_type(PRIMITIVETYPE_BYTE));
+
+ /* is there a old byte array array? */
+ if (newbas != NULL && bytearrays != NULL) {
+ minsize = size < oldsize ? size : oldsize;
+
+ LLNI_CRITICAL_START;
+ MCOPY(
+ LLNI_array_data(newbas), LLNI_array_data(bytearrays),
+ java_object_t*, minsize);
+ LLNI_CRITICAL_END;
+ }
+
+ return newbas;
+}
+
+
+/* annotation_bytearrays_insert ***********************************************
+
+ Insert a bytearray into an array of bytearrays.
+
+ IN:
+ bytearrays........array of bytearrays where 'bytearray' has to be
+ inserted at position 'index'.
+ index.............position where 'ba' has to be inserted into
+ 'bytearrays'.
+ bytearray.........byte array which has to be inserted into
+ 'bytearrays'.
+
+ RETURN VALUE:
+ The new array if a resize was neccessarry, the old if the given size
+ equals the current size or NULL if an error occured.
+
+*******************************************************************************/
+
+static java_handle_t *annotation_bytearrays_insert(
+ java_handle_t *bytearrays, uint32_t index,
+ java_handle_bytearray_t *bytearray)
+{
+ java_handle_objectarray_t *bas; /* bytearrays */
+ uint32_t size = 0; /* current size of the array */
+
+ /* do nothing if NULL is inserted but no array exists */
+ if (bytearray == NULL && bytearrays == NULL) {
+ return NULL;
+ }
+
+ /* get lengths if array exists */
+ if (bytearrays != NULL) {
+ size = array_length_get(bytearrays);
+ }
+
+ bas = (java_handle_objectarray_t*)bytearrays;
+
+ if (bytearray == NULL) {
+ /* insert NULL only if array is big enough */
+ if (size > index) {
+ array_objectarray_element_set(bas, index, NULL);
+ }
+ }
+ else {
+ /* resize array if it's not enough for inserted value */
+ if (size <= index) {
+ bas = annotation_bytearrays_resize(bas, index + 1);
+
+ if (bas == NULL) {
+ /* out of memory */
+ return NULL;
+ }
+ }
+
+ array_objectarray_element_set(bas, index, (java_handle_t*)bytearray);
+ }
+
+ return (java_handle_t*)bas;
+}
+
+
+/* annotation_load_attribute_body *********************************************
+
+ This function loads the body of a generic attribute.
+
+ XXX: Maybe this function should be called loader_load_attribute_body and
+ located in vm/loader.c?
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ errormsg_prefix....prefix for error messages (if any).
+
+ OUT:
+ attribute..........bytearray-pointer which will be set to the read data.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+static bool annotation_load_attribute_body(classbuffer *cb,
+ java_handle_bytearray_t **attribute, const char *errormsg_prefix)
+{
+ uint32_t size = 0; /* size of the attribute */
+ java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */
+
+ assert(cb != NULL);
+ assert(attribute != NULL);
+
+ if (!suck_check_classbuffer_size(cb, 4)) {
+ log_println("%s: size missing", errormsg_prefix);
+ return false;
+ }
+
+ /* load attribute_length */
+ size = suck_u4(cb);
+
+ if (!suck_check_classbuffer_size(cb, size)) {
+ log_println("%s: invalid size", errormsg_prefix);
+ return false;
+ }
+
+ /* if attribute_length == 0 then NULL is
+ * the right value for this attribute */
+ if (size > 0) {
+ ba = builtin_newarray_byte(size);
+
+ if (ba == NULL) {
+ /* out of memory */
+ return false;
+ }
+
+ /* load data */
+ LLNI_CRITICAL_START;
+
+ suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size);
+
+ LLNI_CRITICAL_END;
+
+ /* return data */
+ *attribute = ba;
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_annotationdefault *************************
+
+ Load annotation default value.
+
+ AnnotationDefault_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ element_value default_value;
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the annotation
+ default value is read and into which the value is
+ stored into.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_annotationdefault(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ /* the slot of the method */
+ java_handle_bytearray_t *annotationdefault = NULL;
+ /* unparsed annotation defalut value */
+ java_handle_t *annotationdefaults = NULL;
+ /* array of unparsed annotation default values */
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ LLNI_classinfo_field_get(
+ m->clazz, method_annotationdefaults, annotationdefaults);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotationdefault,
+ "invalid annotation default method attribute")) {
+ return false;
+ }
+
+ if (annotationdefault != NULL) {
+ slot = m - m->clazz->methods;
+ annotationdefaults = annotation_bytearrays_insert(
+ annotationdefaults, slot, annotationdefault);
+
+ if (annotationdefaults == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ m->clazz, method_annotationdefaults, annotationdefaults);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_runtimevisibleparameterannotations ********
+
+ Load runtime visible parameter annotations.
+
+ RuntimeVisibleParameterAnnotations_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 num_parameters;
+ {
+ u2 num_annotations;
+ annotation annotations[num_annotations];
+ } parameter_annotations[num_parameters];
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the parameter
+ annotations are read and into which the parameter
+ annotations are stored into.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimevisibleparameterannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ /* the slot of the method */
+ java_handle_bytearray_t *annotations = NULL;
+ /* unparsed parameter annotations */
+ java_handle_t *parameterannotations = NULL;
+ /* array of unparsed parameter annotations */
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ LLNI_classinfo_field_get(
+ m->clazz, method_parameterannotations, parameterannotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible parameter annotations method attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = m - m->clazz->methods;
+ parameterannotations = annotation_bytearrays_insert(
+ parameterannotations, slot, annotations);
+
+ if (parameterannotations == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ m->clazz, method_parameterannotations, parameterannotations);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
+
+ Load runtime invisible parameter annotations.
+
+ <quote cite="http://jcp.org/en/jsr/detail?id=202">
+ The RuntimeInvisibleParameterAnnotations attribute is similar to the
+ RuntimeVisibleParameterAnnotations attribute, except that the annotations
+ represented by a RuntimeInvisibleParameterAnnotations attribute must not be
+ made available for return by reflective APIs, unless the the JVM has
+ specifically been instructed to retain these annotations via some
+ implementation-specific mechanism such as a command line flag. In the
+ absence of such instructions, the JVM ignores this attribute.
+ </quote>
+
+ Hotspot loads them into the same bytearray as the runtime visible parameter
+ annotations (after the runtime visible parameter annotations). But in J2SE
+ the bytearray will only be parsed as if there is only one annotation
+ structure in it, so the runtime invisible parameter annotatios will be
+ ignored.
+
+ Therefore I do not even bother to read them.
+
+ RuntimeInvisibleParameterAnnotations_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 num_parameters;
+ {
+ u2 num_annotations;
+ annotation annotations[num_annotations];
+ } parameter_annotations[num_parameters];
+ }
+
+ IN:
+ cb.................classbuffer from which to read the data.
+ m..................methodinfo for the method of which the parameter
+ annotations are read and into which the parameter
+ annotations are stored into.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_class_attribute_runtimevisibleannotations ******************
+
+ Load runtime visible annotations of a class.
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_class_attribute_runtimevisibleannotations(
+ classbuffer *cb)
+{
+ java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations class attribute")) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations);
+
+ return true;
+}
+
+
+/* annotation_load_class_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a class (just skip them).
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_class_attribute_runtimeinvisibleannotations(
+ classbuffer *cb)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_method_attribute_runtimevisibleannotations *****************
+
+ Load runtime visible annotations of a method.
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ m.........the method of which the runtime visible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimevisibleannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ int slot = 0;
+ /* slot of the method */
+ java_handle_bytearray_t *annotations = NULL;
+ /* unparsed annotations */
+ java_handle_t *method_annotations = NULL;
+ /* array of unparsed method annotations */
+
+ assert(cb != NULL);
+ assert(m != NULL);
+
+ LLNI_classinfo_field_get(
+ m->clazz, method_annotations, method_annotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations method attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = m - m->clazz->methods;
+ method_annotations = annotation_bytearrays_insert(
+ method_annotations, slot, annotations);
+
+ if (method_annotations == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ m->clazz, method_annotations, method_annotations);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_method_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a method (just skip them).
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ m.........the method of which the runtime invisible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_method_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, methodinfo *m)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/* annotation_load_field_attribute_runtimevisibleannotations ******************
+
+ Load runtime visible annotations of a field.
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ f.........the field of which the runtime visible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_field_attribute_runtimevisibleannotations(
+ classbuffer *cb, fieldinfo *f)
+{
+ int slot = 0;
+ /* slot of the field */
+ java_handle_bytearray_t *annotations = NULL;
+ /* unparsed annotations */
+ java_handle_t *field_annotations = NULL;
+ /* array of unparsed field annotations */
+
+ assert(cb != NULL);
+ assert(f != NULL);
+
+ LLNI_classinfo_field_get(
+ f->clazz, field_annotations, field_annotations);
+
+ if (!annotation_load_attribute_body(
+ cb, &annotations,
+ "invalid runtime visible annotations field attribute")) {
+ return false;
+ }
+
+ if (annotations != NULL) {
+ slot = f - f->clazz->fields;
+ field_annotations = annotation_bytearrays_insert(
+ field_annotations, slot, annotations);
+
+ if (field_annotations == NULL) {
+ return false;
+ }
+
+ LLNI_classinfo_field_set(
+ f->clazz, field_annotations, field_annotations);
+ }
+
+ return true;
+}
+
+
+/* annotation_load_field_attribute_runtimeinvisibleannotations ****************
+
+ Load runtime invisible annotations of a field (just skip them).
+
+ IN:
+ cb........the classbuffer from which the attribute has to be loaded.
+ f.........the field of which the runtime invisible annotations have
+ to be loaded.
+
+ RETURN VALUE:
+ true if all went good. false otherwhise.
+
+*******************************************************************************/
+
+bool annotation_load_field_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, fieldinfo *f)
+{
+ return loader_skip_attribute_body(cb);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/annotation.h - class annotations
+
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _ANNOTATION_H
+#define _ANNOTATION_H
+
+
+#include "config.h"
+
+#include "vm/types.h"
+
+#include "vm/class.h"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+
+
+/* function prototypes ********************************************************/
+
+bool annotation_load_class_attribute_runtimevisibleannotations(
+ classbuffer *cb);
+
+bool annotation_load_class_attribute_runtimeinvisibleannotations(
+ classbuffer *cb);
+
+bool annotation_load_method_attribute_runtimevisibleannotations(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_method_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_field_attribute_runtimevisibleannotations(
+ classbuffer *cb, fieldinfo *f);
+
+bool annotation_load_field_attribute_runtimeinvisibleannotations(
+ classbuffer *cb, fieldinfo *f);
+
+bool annotation_load_method_attribute_annotationdefault(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_method_attribute_runtimevisibleparameterannotations(
+ classbuffer *cb, methodinfo *m);
+
+bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
+ classbuffer *cb, methodinfo *m);
+
+#endif /* _ANNOTATION_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "vm/assertion.h"
#include "vm/global.h"
+#include "vm/os.hpp"
#include "vm/vm.hpp"
-#include "vmcore/os.hpp"
-
/* -ea/-da options ************************************************************/
#include "vm/array.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/cycles-stats.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
+#include "vm/rt-timing.h"
#include "vm/string.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/trace.hpp"
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
#endif
#include "toolbox/logging.h"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
/* define infinity for floating point numbers */
--- /dev/null
+/* src/vm/class.c - class related functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/suck.h"
+#include "vm/utf8.h"
+
+#include "vm/jit/asmpart.h"
+
+
+/* class_set_packagename *******************************************************
+
+ Derive the package name from the class name and store it in the
+ struct.
+
+ An internal package name consists of the package name plus the
+ trailing '/', e.g. "java/lang/".
+
+ For classes in the unnamed package, the package name is set to
+ NULL.
+
+*******************************************************************************/
+
+void class_set_packagename(classinfo *c)
+{
+ char *p;
+ char *start;
+
+ p = UTF_END(c->name) - 1;
+ start = c->name->text;
+
+ if (c->name->text[0] == '[') {
+ /* Set packagename of arrays to the element's package. */
+
+ for (; *start == '['; start++);
+
+ /* Skip the 'L' in arrays of references. */
+
+ if (*start == 'L')
+ start++;
+ }
+
+ /* Search for last '/'. */
+
+ for (; (p > start) && (*p != '/'); --p);
+
+ /* If we found a '/' we set the package name plus the trailing
+ '/'. Otherwise we set the packagename to NULL. */
+
+ if (p > start)
+ c->packagename = utf_new(start, p - start + 1);
+ else
+ c->packagename = NULL;
+}
+
+
+/* class_create_classinfo ******************************************************
+
+ Create a new classinfo struct. The class name is set to the given utf *,
+ most other fields are initialized to zero.
+
+ Note: classname may be NULL. In this case a not-yet-named classinfo is
+ created. The name must be filled in later and class_set_packagename
+ must be called after that.
+
+*******************************************************************************/
+
+classinfo *class_create_classinfo(utf *classname)
+{
+ classinfo *c;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_classinfo += sizeof(classinfo);
+#endif
+
+ /* we use a safe name for temporarily unnamed classes */
+
+ if (classname == NULL)
+ classname = utf_not_named_yet;
+
+#if !defined(NDEBUG)
+ if (initverbose)
+ log_message_utf("Creating class: ", classname);
+#endif
+
+#if !defined(ENABLE_GC_BOEHM)
+ c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
+ /*c = NEW(classinfo);
+ MZERO(c, classinfo, 1);*/
+#else
+ c = GCNEW_UNCOLLECTABLE(classinfo, 1);
+ /* GCNEW_UNCOLLECTABLE clears the allocated memory */
+#endif
+
+ c->name = classname;
+
+ /* Set the header.vftbl of all loaded classes to the one of
+ java.lang.Class, so Java code can use a class as object. */
+
+ if (class_java_lang_Class != NULL)
+ if (class_java_lang_Class->vftbl != NULL)
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+
+#if defined(ENABLE_JAVASE)
+ /* check if the class is a reference class and flag it */
+
+ if (classname == utf_java_lang_ref_SoftReference) {
+ c->flags |= ACC_CLASS_REFERENCE_SOFT;
+ }
+ else if (classname == utf_java_lang_ref_WeakReference) {
+ c->flags |= ACC_CLASS_REFERENCE_WEAK;
+ }
+ else if (classname == utf_java_lang_ref_PhantomReference) {
+ c->flags |= ACC_CLASS_REFERENCE_PHANTOM;
+ }
+#endif
+
+ if (classname != utf_not_named_yet)
+ class_set_packagename(c);
+
+ LOCK_INIT_OBJECT_LOCK(&c->object.header);
+
+ return c;
+}
+
+
+/* class_postset_header_vftbl **************************************************
+
+ Set the header.vftbl of all classes created before java.lang.Class
+ was linked. This is necessary that Java code can use a class as
+ object.
+
+*******************************************************************************/
+
+void class_postset_header_vftbl(void)
+{
+ classinfo *c;
+ u4 slot;
+ classcache_name_entry *nmen;
+ classcache_class_entry *clsen;
+
+ assert(class_java_lang_Class);
+
+ for (slot = 0; slot < hashtable_classcache.size; slot++) {
+ nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+ for (; nmen; nmen = nmen->hashlink) {
+ /* iterate over all class entries */
+
+ for (clsen = nmen->classes; clsen; clsen = clsen->next) {
+ c = clsen->classobj;
+
+ /* now set the the vftbl */
+
+ if (c->object.header.vftbl == NULL)
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+ }
+ }
+ }
+}
+
+/* class_define ****************************************************************
+
+ Calls the loader and defines a class in the VM.
+
+*******************************************************************************/
+
+classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
+{
+ classinfo *c;
+ classinfo *r;
+ classbuffer *cb;
+
+ if (name != NULL) {
+ /* check if this class has already been defined */
+
+ c = classcache_lookup_defined_or_initiated(cl, name);
+
+ if (c != NULL) {
+ exceptions_throw_linkageerror("duplicate class definition: ", c);
+ return NULL;
+ }
+ }
+
+ /* create a new classinfo struct */
+
+ c = class_create_classinfo(name);
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_start();
+#endif
+
+ /* build a classbuffer with the given data */
+
+ cb = NEW(classbuffer);
+
+ cb->clazz = c;
+ cb->size = length;
+ cb->data = data;
+ cb->pos = cb->data;
+
+ /* preset the defining classloader */
+
+ c->classloader = cl;
+
+ /* load the class from this buffer */
+
+ r = load_class_from_classbuffer(cb);
+
+ /* free memory */
+
+ FREE(cb, classbuffer);
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_stop();
+#endif
+
+ if (r == NULL) {
+ /* If return value is NULL, we had a problem and the class is
+ not loaded. Now free the allocated memory, otherwise we
+ could run into a DOS. */
+
+ class_free(c);
+
+ return NULL;
+ }
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* Store the protection domain. */
+
+ c->protectiondomain = pd;
+# endif
+#endif
+
+ /* Store the newly defined class in the class cache. This call
+ also checks whether a class of the same name has already been
+ defined by the same defining loader, and if so, replaces the
+ newly created class by the one defined earlier. */
+
+ /* Important: The classinfo given to classcache_store must be
+ fully prepared because another thread may return
+ this pointer after the lookup at to top of this
+ function directly after the class cache lock has
+ been released. */
+
+ c = classcache_store(cl, c, true);
+
+ return c;
+}
+
+
+/* class_load_attribute_sourcefile *********************************************
+
+ SourceFile_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 sourcefile_index;
+ }
+
+*******************************************************************************/
+
+static bool class_load_attribute_sourcefile(classbuffer *cb)
+{
+ classinfo *c;
+ u4 attribute_length;
+ u2 sourcefile_index;
+ utf *sourcefile;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* check attribute length */
+
+ attribute_length = suck_u4(cb);
+
+ if (attribute_length != 2) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* there can be no more than one SourceFile attribute */
+
+ if (c->sourcefile != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
+ return false;
+ }
+
+ /* get sourcefile */
+
+ sourcefile_index = suck_u2(cb);
+ sourcefile = class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
+
+ if (sourcefile == NULL)
+ return false;
+
+ /* store sourcefile */
+
+ c->sourcefile = sourcefile;
+
+ return true;
+}
+
+
+/* class_load_attribute_enclosingmethod ****************************************
+
+ EnclosingMethod_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 class_index;
+ u2 method_index;
+ }
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+static bool class_load_attribute_enclosingmethod(classbuffer *cb)
+{
+ classinfo *c;
+ u4 attribute_length;
+ u2 class_index;
+ u2 method_index;
+ classref_or_classinfo cr;
+ constant_nameandtype *cn;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
+ /* check attribute length */
+
+ attribute_length = suck_u4(cb);
+
+ if (attribute_length != 4) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* there can be no more than one EnclosingMethod attribute */
+
+ if (c->enclosingmethod != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
+ return false;
+ }
+
+ /* get class index */
+
+ class_index = suck_u2(cb);
+ cr.ref = innerclass_getconstant(c, class_index, CONSTANT_Class);
+
+ /* get method index */
+
+ method_index = suck_u2(cb);
+ cn = innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
+
+ /* store info in classinfo */
+
+ c->enclosingclass.any = cr.any;
+ c->enclosingmethod = cn;
+
+ return true;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
+/* class_load_attributes *******************************************************
+
+ Read attributes from ClassFile.
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+ InnerClasses_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ }
+
+*******************************************************************************/
+
+bool class_load_attributes(classbuffer *cb)
+{
+ classinfo *c;
+ uint16_t attributes_count;
+ uint16_t attribute_name_index;
+ utf *attribute_name;
+ innerclassinfo *info;
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *name;
+ uint16_t flags;
+ int i, j;
+
+ c = cb->clazz;
+
+ /* get attributes count */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attributes_count = suck_u2(cb);
+
+ for (i = 0; i < attributes_count; i++) {
+ /* get attribute name */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attribute_name_index = suck_u2(cb);
+ attribute_name =
+ class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
+
+ if (attribute_name == NULL)
+ return false;
+
+ if (attribute_name == utf_InnerClasses) {
+ /* InnerClasses */
+
+ if (c->innerclass != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* skip attribute length */
+ suck_u4(cb);
+
+ /* number of records */
+ c->innerclasscount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
+ return false;
+
+ /* allocate memory for innerclass structure */
+ c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
+
+ for (j = 0; j < c->innerclasscount; j++) {
+ /* The innerclass structure contains a class with an encoded
+ name, its defining scope, its simple name and a bitmask of
+ the access flags. */
+
+ info = c->innerclass + j;
+
+ inner.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ outer.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
+ name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
+ flags = suck_u2(cb);
+
+ /* If the current inner-class is the currently loaded
+ class check for some special flags. */
+
+ if (inner.ref->name == c->name) {
+ /* If an inner-class is not a member, its
+ outer-class is NULL. */
+
+ if (outer.ref != NULL) {
+ c->flags |= ACC_CLASS_MEMBER;
+
+ /* A member class doesn't have an
+ EnclosingMethod attribute, so set the
+ enclosing-class to be the same as the
+ declaring-class. */
+
+ c->declaringclass = outer;
+ c->enclosingclass = outer;
+ }
+
+ /* If an inner-class is anonymous, its name is
+ NULL. */
+
+ if (name == NULL)
+ c->flags |= ACC_CLASS_ANONYMOUS;
+ }
+
+ info->inner_class = inner;
+ info->outer_class = outer;
+ info->name = name;
+ info->flags = flags;
+ }
+ }
+ else if (attribute_name == utf_SourceFile) {
+ /* SourceFile */
+
+ if (!class_load_attribute_sourcefile(cb))
+ return false;
+ }
+#if defined(ENABLE_JAVASE)
+ else if (attribute_name == utf_EnclosingMethod) {
+ /* EnclosingMethod */
+
+ if (!class_load_attribute_enclosingmethod(cb))
+ return false;
+ }
+ else if (attribute_name == utf_Signature) {
+ /* Signature */
+
+ if (!loader_load_attribute_signature(cb, &(c->signature)))
+ return false;
+ }
+#endif
+
+#if defined(ENABLE_ANNOTATIONS)
+ else if (attribute_name == utf_RuntimeVisibleAnnotations) {
+ /* RuntimeVisibleAnnotations */
+ if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
+ return false;
+ }
+#endif
+
+ else {
+ /* unknown attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+/* class_freepool **************************************************************
+
+ Frees all resources used by this classes Constant Pool.
+
+*******************************************************************************/
+
+static void class_freecpool(classinfo *c)
+{
+ u4 idx;
+ u4 tag;
+ void* info;
+
+ if (c->cptags && c->cpinfos) {
+ for (idx = 0; idx < c->cpcount; idx++) {
+ tag = c->cptags[idx];
+ info = c->cpinfos[idx];
+
+ if (info != NULL) {
+ switch (tag) {
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ FREE(info, constant_FMIref);
+ break;
+ case CONSTANT_Integer:
+ FREE(info, constant_integer);
+ break;
+ case CONSTANT_Float:
+ FREE(info, constant_float);
+ break;
+ case CONSTANT_Long:
+ FREE(info, constant_long);
+ break;
+ case CONSTANT_Double:
+ FREE(info, constant_double);
+ break;
+ case CONSTANT_NameAndType:
+ FREE(info, constant_nameandtype);
+ break;
+ }
+ }
+ }
+ }
+
+ if (c->cptags)
+ MFREE(c->cptags, u1, c->cpcount);
+
+ if (c->cpinfos)
+ MFREE(c->cpinfos, void*, c->cpcount);
+}
+
+
+/* class_getconstant ***********************************************************
+
+ Retrieves the value at position 'pos' of the constantpool of a
+ class. If the type of the value is other than 'ctype', an error is
+ thrown.
+
+*******************************************************************************/
+
+void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
+{
+ /* check index and type of constantpool entry */
+ /* (pos == 0 is caught by type comparison) */
+
+ if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ return c->cpinfos[pos];
+}
+
+
+/* innerclass_getconstant ******************************************************
+
+ Like class_getconstant, but if cptags is ZERO, null is returned.
+
+*******************************************************************************/
+
+void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
+{
+ /* invalid position in constantpool */
+
+ if (pos >= c->cpcount) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ /* constantpool entry of type 0 */
+
+ if (c->cptags[pos] == 0)
+ return NULL;
+
+ /* check type of constantpool entry */
+
+ if (c->cptags[pos] != ctype) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool index");
+ return NULL;
+ }
+
+ return c->cpinfos[pos];
+}
+
+
+/* class_free ******************************************************************
+
+ Frees all resources used by the class.
+
+*******************************************************************************/
+
+void class_free(classinfo *c)
+{
+ s4 i;
+ vftbl_t *v;
+
+ class_freecpool(c);
+
+ if (c->interfaces != NULL)
+ MFREE(c->interfaces, classinfo*, c->interfacescount);
+
+ if (c->fields) {
+ for (i = 0; i < c->fieldscount; i++)
+ field_free(&(c->fields[i]));
+ MFREE(c->fields, fieldinfo, c->fieldscount);
+ }
+
+ if (c->methods) {
+ for (i = 0; i < c->methodscount; i++)
+ method_free(&(c->methods[i]));
+ MFREE(c->methods, methodinfo, c->methodscount);
+ }
+
+ if ((v = c->vftbl) != NULL) {
+ if (v->arraydesc)
+ mem_free(v->arraydesc,sizeof(arraydescriptor));
+
+ for (i = 0; i < v->interfacetablelength; i++) {
+ MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
+ }
+ MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
+
+ i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
+ sizeof(methodptr*) * (v->interfacetablelength -
+ (v->interfacetablelength > 0));
+ v = (vftbl_t*) (((methodptr*) v) -
+ (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
+ mem_free(v, i);
+ }
+
+ if (c->innerclass)
+ MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
+
+ /* if (c->classvftbl)
+ mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
+
+/* GCFREE(c); */
+}
+
+
+/* get_array_class *************************************************************
+
+ Returns the array class with the given name for the given
+ classloader, or NULL if an exception occurred.
+
+ Note: This function does eager loading.
+
+*******************************************************************************/
+
+static classinfo *get_array_class(utf *name,classloader_t *initloader,
+ classloader_t *defloader,bool link)
+{
+ classinfo *c;
+
+ /* lookup this class in the classcache */
+ c = classcache_lookup(initloader,name);
+ if (!c)
+ c = classcache_lookup_defined(defloader,name);
+
+ if (!c) {
+ /* we have to create it */
+ c = class_create_classinfo(name);
+ c = load_newly_created_array(c,initloader);
+ if (c == NULL)
+ return NULL;
+ }
+
+ assert(c);
+ assert(c->state & CLASS_LOADED);
+ assert(c->classloader == defloader);
+
+ if (link && !(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ assert(!link || (c->state & CLASS_LINKED));
+
+ return c;
+}
+
+
+/* class_array_of **************************************************************
+
+ Returns an array class with the given component class. The array
+ class is dynamically created if neccessary.
+
+*******************************************************************************/
+
+classinfo *class_array_of(classinfo *component, bool link)
+{
+ classloader_t *cl;
+ s4 namelen;
+ char *namebuf;
+ utf *u;
+ classinfo *c;
+ int32_t dumpmarker;
+
+ cl = component->classloader;
+
+ DMARKER;
+
+ /* Assemble the array class name */
+ namelen = component->name->blength;
+
+ if (component->name->text[0] == '[') {
+ /* the component is itself an array */
+ namebuf = DMNEW(char, namelen + 1);
+ namebuf[0] = '[';
+ MCOPY(namebuf + 1, component->name->text, char, namelen);
+ namelen++;
+ }
+ else {
+ /* the component is a non-array class */
+ namebuf = DMNEW(char, namelen + 3);
+ namebuf[0] = '[';
+ namebuf[1] = 'L';
+ MCOPY(namebuf + 2, component->name->text, char, namelen);
+ namebuf[2 + namelen] = ';';
+ namelen += 3;
+ }
+
+ u = utf_new(namebuf, namelen);
+
+ c = get_array_class(u, cl, cl, link);
+
+ DRELEASE;
+
+ return c;
+}
+
+
+/* class_multiarray_of *********************************************************
+
+ Returns an array class with the given dimension and element class.
+ The array class is dynamically created if neccessary.
+
+*******************************************************************************/
+
+classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
+{
+ s4 namelen;
+ char *namebuf;
+ classinfo *c;
+ int32_t dumpmarker;
+
+ DMARKER;
+
+ if (dim < 1) {
+ log_text("Invalid array dimension requested");
+ assert(0);
+ }
+
+ /* Assemble the array class name */
+ namelen = element->name->blength;
+
+ if (element->name->text[0] == '[') {
+ /* the element is itself an array */
+ namebuf = DMNEW(char, namelen + dim);
+ memcpy(namebuf + dim, element->name->text, namelen);
+ namelen += dim;
+ }
+ else {
+ /* the element is a non-array class */
+ namebuf = DMNEW(char, namelen + 2 + dim);
+ namebuf[dim] = 'L';
+ memcpy(namebuf + dim + 1, element->name->text, namelen);
+ namelen += (2 + dim);
+ namebuf[namelen - 1] = ';';
+ }
+ memset(namebuf, '[', dim);
+
+ c = get_array_class(utf_new(namebuf, namelen),
+ element->classloader,
+ element->classloader,
+ link);
+
+ DRELEASE;
+
+ return c;
+}
+
+
+/* class_lookup_classref *******************************************************
+
+ Looks up the constant_classref for a given classname in the classref
+ tables of a class.
+
+ IN:
+ cls..............the class containing the reference
+ name.............the name of the class refered to
+
+ RETURN VALUE:
+ a pointer to a constant_classref, or
+ NULL if the reference was not found
+
+*******************************************************************************/
+
+constant_classref *class_lookup_classref(classinfo *cls, utf *name)
+{
+ constant_classref *ref;
+ extra_classref *xref;
+ int count;
+
+ assert(cls);
+ assert(name);
+ assert(!cls->classrefcount || cls->classrefs);
+
+ /* first search the main classref table */
+ count = cls->classrefcount;
+ ref = cls->classrefs;
+ for (; count; --count, ++ref)
+ if (ref->name == name)
+ return ref;
+
+ /* next try the list of extra classrefs */
+ for (xref = cls->extclassrefs; xref; xref = xref->next) {
+ if (xref->classref.name == name)
+ return &(xref->classref);
+ }
+
+ /* not found */
+ return NULL;
+}
+
+
+/* class_get_classref **********************************************************
+
+ Returns the constant_classref for a given classname.
+
+ IN:
+ cls..............the class containing the reference
+ name.............the name of the class refered to
+
+ RETURN VALUE:
+ a pointer to a constant_classref (never NULL)
+
+ NOTE:
+ The given name is not checked for validity!
+
+*******************************************************************************/
+
+constant_classref *class_get_classref(classinfo *cls, utf *name)
+{
+ constant_classref *ref;
+ extra_classref *xref;
+
+ assert(cls);
+ assert(name);
+
+ ref = class_lookup_classref(cls,name);
+ if (ref)
+ return ref;
+
+ xref = NEW(extra_classref);
+ CLASSREF_INIT(xref->classref,cls,name);
+
+ xref->next = cls->extclassrefs;
+ cls->extclassrefs = xref;
+
+ return &(xref->classref);
+}
+
+
+/* class_get_self_classref *****************************************************
+
+ Returns the constant_classref to the class itself.
+
+ IN:
+ cls..............the class containing the reference
+
+ RETURN VALUE:
+ a pointer to a constant_classref (never NULL)
+
+*******************************************************************************/
+
+constant_classref *class_get_self_classref(classinfo *cls)
+{
+ /* XXX this should be done in a faster way. Maybe always make */
+ /* the classref of index 0 a self reference. */
+ return class_get_classref(cls,cls->name);
+}
+
+/* class_get_classref_multiarray_of ********************************************
+
+ Returns an array type reference with the given dimension and element class
+ reference.
+
+ IN:
+ dim..............the requested dimension
+ dim must be in [1;255]. This is NOT checked!
+ ref..............the component class reference
+
+ RETURN VALUE:
+ a pointer to the class reference for the array type
+
+ NOTE:
+ The referer of `ref` is used as the referer for the new classref.
+
+*******************************************************************************/
+
+constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
+{
+ s4 namelen;
+ char *namebuf;
+ constant_classref *cr;
+ int32_t dumpmarker;
+
+ assert(ref);
+ assert(dim >= 1 && dim <= 255);
+
+ DMARKER;
+
+ /* Assemble the array class name */
+ namelen = ref->name->blength;
+
+ if (ref->name->text[0] == '[') {
+ /* the element is itself an array */
+ namebuf = DMNEW(char, namelen + dim);
+ memcpy(namebuf + dim, ref->name->text, namelen);
+ namelen += dim;
+ }
+ else {
+ /* the element is a non-array class */
+ namebuf = DMNEW(char, namelen + 2 + dim);
+ namebuf[dim] = 'L';
+ memcpy(namebuf + dim + 1, ref->name->text, namelen);
+ namelen += (2 + dim);
+ namebuf[namelen - 1] = ';';
+ }
+ memset(namebuf, '[', dim);
+
+ cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
+
+ DRELEASE;
+
+ return cr;
+}
+
+
+/* class_get_classref_component_of *********************************************
+
+ Returns the component classref of a given array type reference
+
+ IN:
+ ref..............the array type reference
+
+ RETURN VALUE:
+ a reference to the component class, or
+ NULL if `ref` is not an object array type reference
+
+ NOTE:
+ The referer of `ref` is used as the referer for the new classref.
+
+*******************************************************************************/
+
+constant_classref *class_get_classref_component_of(constant_classref *ref)
+{
+ s4 namelen;
+ char *name;
+
+ assert(ref);
+
+ name = ref->name->text;
+ if (*name++ != '[')
+ return NULL;
+
+ namelen = ref->name->blength - 1;
+ if (*name == 'L') {
+ name++;
+ namelen -= 2;
+ }
+ else if (*name != '[') {
+ return NULL;
+ }
+
+ return class_get_classref(ref->referer, utf_new(name, namelen));
+}
+
+
+/* class_findmethod ************************************************************
+
+ Searches a 'classinfo' structure for a method having the given name
+ and descriptor. If descriptor is NULL, it is ignored.
+
+*******************************************************************************/
+
+methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
+{
+ methodinfo *m;
+ s4 i;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
+ return m;
+ }
+
+ return NULL;
+}
+
+
+/* class_resolvemethod *********************************************************
+
+ Searches a class and it's super classes for a method.
+
+ Superinterfaces are *not* searched.
+
+*******************************************************************************/
+
+methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
+{
+ methodinfo *m;
+
+ while (c) {
+ m = class_findmethod(c, name, desc);
+
+ if (m)
+ return m;
+
+ /* JVM Specification bug:
+
+ It is important NOT to resolve special <init> and <clinit>
+ methods to super classes or interfaces; yet, this is not
+ explicited in the specification. Section 5.4.3.3 should be
+ updated appropriately. */
+
+ if (name == utf_init || name == utf_clinit)
+ return NULL;
+
+ c = c->super;
+ }
+
+ return NULL;
+}
+
+
+/* class_resolveinterfacemethod_intern *****************************************
+
+ Internally used helper function. Do not use this directly.
+
+*******************************************************************************/
+
+static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
+ utf *name, utf *desc)
+{
+ methodinfo *m;
+ s4 i;
+
+ /* try to find the method in the class */
+
+ m = class_findmethod(c, name, desc);
+
+ if (m != NULL)
+ return m;
+
+ /* No method found? Try the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+
+ if (m != NULL)
+ return m;
+ }
+
+ /* no method found */
+
+ return NULL;
+}
+
+
+/* class_resolveclassmethod ****************************************************
+
+ Resolves a reference from REFERER to a method with NAME and DESC in
+ class C.
+
+ If the method cannot be resolved the return value is NULL. If
+ EXCEPT is true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
+ classinfo *referer, bool throwexception)
+{
+ classinfo *cls;
+ methodinfo *m;
+ s4 i;
+
+/* if (c->flags & ACC_INTERFACE) { */
+/* if (throwexception) */
+/* *exceptionptr = */
+/* new_exception(string_java_lang_IncompatibleClassChangeError); */
+/* return NULL; */
+/* } */
+
+ /* try class c and its superclasses */
+
+ cls = c;
+
+ m = class_resolvemethod(cls, name, desc);
+
+ if (m != NULL)
+ goto found;
+
+ /* Try the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
+
+ if (m != NULL)
+ goto found;
+ }
+
+ if (throwexception)
+ exceptions_throw_nosuchmethoderror(c, name, desc);
+
+ return NULL;
+
+ found:
+ if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
+ if (throwexception)
+ exceptions_throw_abstractmethoderror();
+
+ return NULL;
+ }
+
+ /* XXX check access rights */
+
+ return m;
+}
+
+
+/* class_resolveinterfacemethod ************************************************
+
+ Resolves a reference from REFERER to a method with NAME and DESC in
+ interface C.
+
+ If the method cannot be resolved the return value is NULL. If
+ EXCEPT is true *exceptionptr is set, too.
+
+*******************************************************************************/
+
+methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
+ classinfo *referer, bool throwexception)
+{
+ methodinfo *mi;
+
+ if (!(c->flags & ACC_INTERFACE)) {
+ if (throwexception)
+ exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
+
+ return NULL;
+ }
+
+ mi = class_resolveinterfacemethod_intern(c, name, desc);
+
+ if (mi != NULL)
+ return mi;
+
+ /* try class java.lang.Object */
+
+ mi = class_findmethod(class_java_lang_Object, name, desc);
+
+ if (mi != NULL)
+ return mi;
+
+ if (throwexception)
+ exceptions_throw_nosuchmethoderror(c, name, desc);
+
+ return NULL;
+}
+
+
+/* class_findfield *************************************************************
+
+ Searches for field with specified name and type in a classinfo
+ structure. If no such field is found NULL is returned.
+
+*******************************************************************************/
+
+fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
+{
+ s4 i;
+
+ for (i = 0; i < c->fieldscount; i++)
+ if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
+ return &(c->fields[i]);
+
+ if (c->super != NULL)
+ return class_findfield(c->super, name, desc);
+
+ return NULL;
+}
+
+
+/* class_findfield_approx ******************************************************
+
+ Searches in 'classinfo'-structure for a field with the specified
+ name.
+
+*******************************************************************************/
+
+fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
+{
+ for (int32_t i = 0; i < c->fieldscount; i++) {
+ fieldinfo* f = &(c->fields[i]);
+
+ if (f->name == name)
+ return f;
+ }
+
+ // Field not found.
+ exceptions_throw_nosuchfielderror(c, name);
+ return NULL;
+}
+
+
+/****************** Function: class_resolvefield_int ***************************
+
+ This is an internally used helper function. Do not use this directly.
+
+ Tries to resolve a field having the given name and type.
+ If the field cannot be resolved, NULL is returned.
+
+*******************************************************************************/
+
+static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
+{
+ fieldinfo *fi;
+ s4 i;
+
+ /* search for field in class c */
+
+ for (i = 0; i < c->fieldscount; i++) {
+ if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
+ return &(c->fields[i]);
+ }
+ }
+
+ /* Try super interfaces recursively. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ fi = class_resolvefield_int(c->interfaces[i], name, desc);
+
+ if (fi != NULL)
+ return fi;
+ }
+
+ /* Try super class. */
+
+ if (c->super != NULL)
+ return class_resolvefield_int(c->super, name, desc);
+
+ /* not found */
+
+ return NULL;
+}
+
+
+/********************* Function: class_resolvefield ***************************
+
+ Resolves a reference from REFERER to a field with NAME and DESC in class C.
+
+ If the field cannot be resolved, an exception is thrown and the
+ return value is NULL.
+
+*******************************************************************************/
+
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer)
+{
+ fieldinfo *fi;
+
+ fi = class_resolvefield_int(c, name, desc);
+
+ if (!fi) {
+ exceptions_throw_nosuchfielderror(c, name);
+ return NULL;
+ }
+
+ /* XXX check access rights */
+
+ return fi;
+}
+
+
+/* class_issubclass ************************************************************
+
+ Checks if sub is a descendant of super.
+
+*******************************************************************************/
+
+bool class_issubclass(classinfo *sub, classinfo *super)
+{
+ classinfo *c;
+
+ c = sub;
+
+ for (;;) {
+ /* We reached java/lang/Object and did not find the requested
+ super class. */
+
+ if (c == NULL)
+ return false;
+
+ /* We found the requested super class. */
+
+ if (c == super)
+ return true;
+
+ c = c->super;
+ }
+}
+
+
+/* class_isanysubclass *********************************************************
+
+ Checks a subclass relation between two classes. Implemented
+ interfaces are interpreted as super classes.
+
+ Return value: 1 ... sub is subclass of super
+ 0 ... otherwise
+
+*******************************************************************************/
+
+bool class_isanysubclass(classinfo *sub, classinfo *super)
+{
+ uint32_t diffval;
+ bool result;
+
+ /* This is the trivial case. */
+
+ if (sub == super)
+ return true;
+
+ /* Primitive classes are only subclasses of themselves. */
+
+ if (class_is_primitive(sub) || class_is_primitive(super))
+ return false;
+
+ /* Check for interfaces. */
+
+ if (super->flags & ACC_INTERFACE) {
+ result = (sub->vftbl->interfacetablelength > super->index) &&
+ (sub->vftbl->interfacetable[-super->index] != NULL);
+ }
+ else {
+ /* java.lang.Object is the only super class of any
+ interface. */
+
+ if (sub->flags & ACC_INTERFACE)
+ return (super == class_java_lang_Object);
+
+ LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+ diffval = sub->vftbl->baseval - super->vftbl->baseval;
+ result = diffval <= (uint32_t) super->vftbl->diffval;
+
+ LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+ }
+
+ return result;
+}
+
+
+/* class_is_assignable_from ****************************************************
+
+ Return whether an instance of the "from" class parameter would be
+ an instance of this class "to" as well.
+
+ ARGUMENTS:
+ to ..... class
+ from ... class
+
+ RETURN:
+ true .... is assignable
+ false ... is not assignable
+
+*******************************************************************************/
+
+bool class_is_assignable_from(classinfo *to, classinfo *from)
+{
+ if (!(to->state & CLASS_LINKED))
+ if (!link_class(to))
+ return false;
+
+ if (!(from->state & CLASS_LINKED))
+ if (!link_class(from))
+ return false;
+
+ return class_isanysubclass(from, to);
+}
+
+
+/* class_is_instance ***********************************************************
+
+ Return if the given Java object is an instance of the given class.
+
+ ARGUMENTS:
+ c ... class
+ h ... Java object
+
+ RETURN:
+ true .... is instance
+ false ... is not instance
+
+*******************************************************************************/
+
+bool class_is_instance(classinfo *c, java_handle_t *h)
+{
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+ return builtin_instanceof(h, c);
+}
+
+
+/* class_get_componenttype *****************************************************
+
+ Return the component class of the given class. If the given class
+ is not an array, return NULL.
+
+*******************************************************************************/
+
+classinfo *class_get_componenttype(classinfo *c)
+{
+ classinfo *component;
+ arraydescriptor *ad;
+
+ /* XXX maybe we could find a way to do this without linking. */
+ /* This way should be safe and easy, however. */
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ ad = c->vftbl->arraydesc;
+
+ if (ad == NULL)
+ return NULL;
+
+ if (ad->arraytype == ARRAYTYPE_OBJECT)
+ component = ad->componentvftbl->clazz;
+ else
+ component = Primitive_get_class_by_type(ad->arraytype);
+
+ return component;
+}
+
+
+/* class_get_declaredclasses ***************************************************
+
+ Return an array of declared classes of the given class.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
+{
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *outername;
+ int declaredclasscount; /* number of declared classes */
+ int pos; /* current declared class */
+ java_handle_objectarray_t *oa; /* array of declared classes */
+ int i;
+ classinfo *ic;
+
+ declaredclasscount = 0;
+
+ if (!class_is_primitive(c) && !class_is_array(c)) {
+ /* Determine number of declared classes. */
+
+ for (i = 0; i < c->innerclasscount; i++) {
+ /* Get outer-class. If the inner-class is not a member
+ class, the outer-class is NULL. */
+
+ outer = c->innerclass[i].outer_class;
+
+ if (outer.any == NULL)
+ continue;
+
+ /* Check if outer-class is a classref or a real class and
+ get the class name from the structure. */
+
+ outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+ /* Outer class is this class. */
+
+ if ((outername == c->name) &&
+ ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
+ declaredclasscount++;
+ }
+ }
+
+ /* Allocate Class[] and check for OOM. */
+
+ oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ for (i = 0, pos = 0; i < c->innerclasscount; i++) {
+ inner = c->innerclass[i].inner_class;
+ outer = c->innerclass[i].outer_class;
+
+ /* Get outer-class. If the inner-class is not a member class,
+ the outer-class is NULL. */
+
+ if (outer.any == NULL)
+ continue;
+
+ /* Check if outer_class is a classref or a real class and get
+ the class name from the structure. */
+
+ outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
+
+ /* Outer class is this class. */
+
+ if ((outername == c->name) &&
+ ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
+
+ ic = resolve_classref_or_classinfo_eager(inner, false);
+
+ if (ic == NULL)
+ return NULL;
+
+ if (!(ic->state & CLASS_LINKED))
+ if (!link_class(ic))
+ return NULL;
+
+ LLNI_array_direct(oa, pos++) = (java_object_t *) ic;
+ }
+ }
+
+ return oa;
+}
+
+
+/**
+ * Return an array of declared constructors of the given class.
+ *
+ * @param c class to get the constructors of
+ * @param publicOnly show only public fields
+ *
+ * @return array of java.lang.reflect.Constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
+{
+ methodinfo* m;
+ java_handle_objectarray_t* oa;
+ java_handle_t* rc;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of constructors. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init))
+ count++;
+ }
+
+ /* Create array of constructors. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the constructors and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
+ (m->name == utf_init)) {
+ // Create a java.lang.reflect.Constructor object.
+
+ rc = java_lang_reflect_Constructor_create(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, rc);
+ index++;
+ }
+ }
+
+ return oa;
+}
+#endif
+
+
+/* class_get_declaredfields ****************************************************
+
+ Return an array of declared fields of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the fields of
+ publicOnly ... show only public fields
+
+ RETURN:
+ array of java.lang.reflect.Field
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
+{
+ java_handle_objectarray_t *oa;
+ fieldinfo *f;
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* Determine number of fields. */
+
+ count = 0;
+
+ for (i = 0; i < c->fieldscount; i++)
+ if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
+ count++;
+
+ /* Create array of fields. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Field);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the fields and store them in the array. */
+
+ for (i = 0, index = 0; i < c->fieldscount; i++) {
+ f = &(c->fields[i]);
+
+ if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
+ // Create a java.lang.reflect.Field object.
+
+ h = java_lang_reflect_Field_create(f);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+}
+#endif
+
+
+/* class_get_declaredmethods ***************************************************
+
+ Return an array of declared methods of the given class.
+
+ ARGUMENTS:
+ c ............ class to get the methods of
+ publicOnly ... show only public methods
+
+ RETURN:
+ array of java.lang.reflect.Method
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
+{
+ java_handle_objectarray_t *oa; /* result: array of Method-objects */
+ methodinfo *m; /* the current method to be represented */
+ java_handle_t *h;
+ int count;
+ int index;
+ int i;
+
+ /* JOWENN: array classes do not declare methods according to mauve
+ test. It should be considered, if we should return to my old
+ clone method overriding instead of declaring it as a member
+ function. */
+
+ if (class_is_array(c))
+ return builtin_anewarray(0, class_java_lang_reflect_Method);
+
+ /* Determine number of methods. */
+
+ count = 0;
+
+ for (i = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA))
+ count++;
+ }
+
+ /* Create array of methods. */
+
+ oa = builtin_anewarray(count, class_java_lang_reflect_Method);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* Get the methods and store them in the array. */
+
+ for (i = 0, index = 0; i < c->methodscount; i++) {
+ m = &(c->methods[i]);
+
+ if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
+ ((m->name != utf_init) && (m->name != utf_clinit)) &&
+ !(m->flags & ACC_MIRANDA)) {
+ // Create java.lang.reflect.Method object.
+
+ h = java_lang_reflect_Method_create(m);
+
+ /* Store object into array. */
+
+ array_objectarray_element_set(oa, index, h);
+ index++;
+ }
+ }
+
+ return oa;
+}
+#endif
+
+
+/* class_get_declaringclass ****************************************************
+
+ If the class or interface given is a member of another class,
+ return the declaring class. For array and primitive classes return
+ NULL.
+
+*******************************************************************************/
+
+classinfo *class_get_declaringclass(classinfo *c)
+{
+ classref_or_classinfo cr;
+ classinfo *dc;
+
+ /* Get declaring class. */
+
+ cr = c->declaringclass;
+
+ if (cr.any == NULL)
+ return NULL;
+
+ /* Resolve the class if necessary. */
+
+ if (IS_CLASSREF(cr)) {
+/* dc = resolve_classref_eager(cr.ref); */
+ dc = resolve_classref_or_classinfo_eager(cr, true);
+
+ if (dc == NULL)
+ return NULL;
+
+ /* Store the resolved class in the class structure. */
+
+ cr.cls = dc;
+ }
+
+ dc = cr.cls;
+
+ return dc;
+}
+
+
+/* class_get_enclosingclass ****************************************************
+
+ Return the enclosing class for the given class.
+
+*******************************************************************************/
+
+classinfo *class_get_enclosingclass(classinfo *c)
+{
+ classref_or_classinfo cr;
+ classinfo *ec;
+
+ /* Get enclosing class. */
+
+ cr = c->enclosingclass;
+
+ if (cr.any == NULL)
+ return NULL;
+
+ /* Resolve the class if necessary. */
+
+ if (IS_CLASSREF(cr)) {
+/* ec = resolve_classref_eager(cr.ref); */
+ ec = resolve_classref_or_classinfo_eager(cr, true);
+
+ if (ec == NULL)
+ return NULL;
+
+ /* Store the resolved class in the class structure. */
+
+ cr.cls = ec;
+ }
+
+ ec = cr.cls;
+
+ return ec;
+}
+
+
+/**
+ * Return the enclosing constructor as java.lang.reflect.Constructor
+ * object for the given class.
+ *
+ * @param c class to return the enclosing constructor for
+ *
+ * @return java.lang.reflect.Constructor object of the enclosing
+ * constructor
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingconstructor(classinfo *c)
+{
+ methodinfo* m;
+ java_handle_t* rc;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* Check for <init>. */
+
+ if (m->name != utf_init)
+ return NULL;
+
+ // Create a java.lang.reflect.Constructor object.
+
+ rc = java_lang_reflect_Constructor_create(m);
+
+ return rc;
+}
+#endif
+
+
+/* class_get_enclosingmethod ***************************************************
+
+ Return the enclosing method for the given class.
+
+ IN:
+ c ... class to return the enclosing method for
+
+ RETURN:
+ methodinfo of the enclosing method
+
+*******************************************************************************/
+
+methodinfo *class_get_enclosingmethod_raw(classinfo *c)
+{
+ constant_nameandtype *cn;
+ classinfo *ec;
+ methodinfo *m;
+
+ /* get enclosing class and method */
+
+ ec = class_get_enclosingclass(c);
+ cn = c->enclosingmethod;
+
+ /* check for enclosing class and method */
+
+ if (ec == NULL)
+ return NULL;
+
+ if (cn == NULL)
+ return NULL;
+
+ /* find method in enclosing class */
+
+ m = class_findmethod(ec, cn->name, cn->descriptor);
+
+ if (m == NULL) {
+ exceptions_throw_internalerror("Enclosing method doesn't exist");
+ return NULL;
+ }
+
+ return m;
+}
+
+
+/**
+ * Return the enclosing method as java.lang.reflect.Method object for
+ * the given class.
+ *
+ * @param c class to return the enclosing method for
+ *
+ * @return java.lang.reflect.Method object of the enclosing method
+ */
+#if defined(ENABLE_JAVASE)
+java_handle_t* class_get_enclosingmethod(classinfo *c)
+{
+ methodinfo* m;
+ java_handle_t* rm;
+
+ m = class_get_enclosingmethod_raw(c);
+
+ if (m == NULL)
+ return NULL;
+
+ /* check for <init> */
+
+ if (m->name == utf_init)
+ return NULL;
+
+ // Create a java.lang.reflect.Method object.
+
+ rm = java_lang_reflect_Method_create(m);
+
+ return rm;
+}
+#endif
+
+
+/* class_get_interfaces ********************************************************
+
+ Return an array of interfaces of the given class.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *class_get_interfaces(classinfo *c)
+{
+ classinfo *ic;
+ java_handle_objectarray_t *oa;
+ u4 i;
+
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return NULL;
+
+ oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ for (i = 0; i < c->interfacescount; i++) {
+ ic = c->interfaces[i];
+
+ LLNI_array_direct(oa, i) = (java_object_t *) ic;
+ }
+
+ return oa;
+}
+
+
+/* class_get_annotations *******************************************************
+
+ Get the unparsed declared annotations in a byte array
+ of the given class.
+
+ IN:
+ c........the class of which the annotations should be returned
+
+ RETURN VALUE:
+ The unparsed declared annotations in a byte array
+ (or NULL if there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *class_get_annotations(classinfo *c)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ java_handle_t *annotations; /* unparsed annotations */
+
+ LLNI_classinfo_field_get(c, annotations, annotations);
+
+ return (java_handle_bytearray_t*)annotations;
+#else
+ return NULL;
+#endif
+}
+
+
+/* class_get_modifiers *********************************************************
+
+ Get the modifier flags of the given class.
+
+ IN:
+ c....the class of which the modifier flags should be returned
+ ignoreInnerClassesAttrib
+ RETURN VALUE:
+ modifier flags
+
+*******************************************************************************/
+
+int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
+{
+ classref_or_classinfo inner;
+ classref_or_classinfo outer;
+ utf *innername;
+ int i;
+
+ if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
+ /* search for passed class as inner class */
+
+ for (i = 0; i < c->innerclasscount; i++) {
+ inner = c->innerclass[i].inner_class;
+ outer = c->innerclass[i].outer_class;
+
+ /* Check if inner is a classref or a real class and get
+ the name of the structure */
+
+ innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
+
+ /* innerclass is this class */
+
+ if (innername == c->name) {
+ /* has the class actually an outer class? */
+
+ if (outer.any)
+ /* return flags got from the outer class file */
+ return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
+ else
+ return c->flags & ACC_CLASS_REFLECT_MASK;
+ }
+ }
+ }
+
+ /* passed class is no inner class or it was not requested */
+
+ return c->flags & ACC_CLASS_REFLECT_MASK;
+}
+
+
+/* class_get_signature *********************************************************
+
+ Return the signature of the given class. For array and primitive
+ classes return NULL.
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+utf *class_get_signature(classinfo *c)
+{
+ /* For array and primitive classes return NULL. */
+
+ if (class_is_array(c) || class_is_primitive(c))
+ return NULL;
+
+ return c->signature;
+}
+#endif
+
+
+/* class_printflags ************************************************************
+
+ Prints flags of a class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_printflags(classinfo *c)
+{
+ if (c == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (c->flags & ACC_PUBLIC) printf(" PUBLIC");
+ if (c->flags & ACC_PRIVATE) printf(" PRIVATE");
+ if (c->flags & ACC_PROTECTED) printf(" PROTECTED");
+ if (c->flags & ACC_STATIC) printf(" STATIC");
+ if (c->flags & ACC_FINAL) printf(" FINAL");
+ if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (c->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (c->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (c->flags & ACC_NATIVE) printf(" NATIVE");
+ if (c->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (c->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+}
+#endif
+
+
+/* class_print *****************************************************************
+
+ Prints classname plus flags.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_print(classinfo *c)
+{
+ if (c == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ utf_display_printable_ascii(c->name);
+ class_printflags(c);
+}
+#endif
+
+
+/* class_classref_print ********************************************************
+
+ Prints classname plus referer class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_print(constant_classref *cr)
+{
+ if (cr == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ utf_display_printable_ascii(cr->name);
+ printf("(ref.by ");
+ if (cr->referer)
+ class_print(cr->referer);
+ else
+ printf("NULL");
+ printf(")");
+}
+#endif
+
+
+/* class_println ***************************************************************
+
+ Prints classname plus flags and new line.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_println(classinfo *c)
+{
+ class_print(c);
+ printf("\n");
+}
+#endif
+
+
+/* class_classref_println ******************************************************
+
+ Prints classname plus referer class and new line.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_println(constant_classref *cr)
+{
+ class_classref_print(cr);
+ printf("\n");
+}
+#endif
+
+
+/* class_classref_or_classinfo_print *******************************************
+
+ Prints classname plus referer class.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_or_classinfo_print(classref_or_classinfo c)
+{
+ if (c.any == NULL) {
+ printf("(classref_or_classinfo) NULL");
+ return;
+ }
+ if (IS_CLASSREF(c))
+ class_classref_print(c.ref);
+ else
+ class_print(c.cls);
+}
+#endif
+
+
+/* class_classref_or_classinfo_println *****************************************
+
+ Prints classname plus referer class and a newline.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_classref_or_classinfo_println(classref_or_classinfo c)
+{
+ class_classref_or_classinfo_print(c);
+ printf("\n");
+}
+#endif
+
+
+/* class_showconstantpool ******************************************************
+
+ Dump the constant pool of the given class to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_showconstantpool (classinfo *c)
+{
+ u4 i;
+ void* e;
+
+ printf ("---- dump of constant pool ----\n");
+
+ for (i=0; i<c->cpcount; i++) {
+ printf ("#%d: ", (int) i);
+
+ e = c -> cpinfos [i];
+ if (e) {
+
+ switch (c -> cptags [i]) {
+ case CONSTANT_Class:
+ printf ("Classreference -> ");
+ utf_display_printable_ascii ( ((constant_classref*)e) -> name );
+ break;
+ case CONSTANT_Fieldref:
+ printf ("Fieldref -> ");
+ field_fieldref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_Methodref:
+ printf ("Methodref -> ");
+ method_methodref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_InterfaceMethodref:
+ printf ("InterfaceMethod -> ");
+ method_methodref_print((constant_FMIref *) e);
+ break;
+ case CONSTANT_String:
+ printf ("String -> ");
+ utf_display_printable_ascii (e);
+ break;
+ case CONSTANT_Integer:
+ printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
+ break;
+ case CONSTANT_Float:
+ printf ("Float -> %f", ((constant_float*)e) -> value);
+ break;
+ case CONSTANT_Double:
+ printf ("Double -> %f", ((constant_double*)e) -> value);
+ break;
+ case CONSTANT_Long:
+ {
+ u8 v = ((constant_long*)e) -> value;
+#if U8_AVAILABLE
+ printf ("Long -> %ld", (long int) v);
+#else
+ printf ("Long -> HI: %ld, LO: %ld\n",
+ (long int) v.high, (long int) v.low);
+#endif
+ }
+ break;
+ case CONSTANT_NameAndType:
+ {
+ constant_nameandtype *cnt = e;
+ printf ("NameAndType: ");
+ utf_display_printable_ascii (cnt->name);
+ printf (" ");
+ utf_display_printable_ascii (cnt->descriptor);
+ }
+ break;
+ case CONSTANT_Utf8:
+ printf ("Utf8 -> ");
+ utf_display_printable_ascii (e);
+ break;
+ default:
+ log_text("Invalid type of ConstantPool-Entry");
+ assert(0);
+ }
+ }
+
+ printf ("\n");
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* class_showmethods ***********************************************************
+
+ Dump info about the fields and methods of the given class to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void class_showmethods (classinfo *c)
+{
+ s4 i;
+
+ printf("--------- Fields and Methods ----------------\n");
+ printf("Flags: ");
+ class_printflags(c);
+ printf("\n");
+
+ printf("This: ");
+ utf_display_printable_ascii(c->name);
+ printf("\n");
+
+ if (c->super) {
+ printf("Super: ");
+ utf_display_printable_ascii(c->super->name);
+ printf ("\n");
+ }
+
+ printf("Index: %d\n", c->index);
+
+ printf("Interfaces:\n");
+ for (i = 0; i < c->interfacescount; i++) {
+ printf(" ");
+ utf_display_printable_ascii(c->interfaces[i]->name);
+ printf (" (%d)\n", c->interfaces[i]->index);
+ }
+
+ printf("Fields:\n");
+ for (i = 0; i < c->fieldscount; i++)
+ field_println(&(c->fields[i]));
+
+ printf("Methods:\n");
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ if (!(m->flags & ACC_STATIC))
+ printf("vftblindex: %d ", m->vftblindex);
+
+ method_println(m);
+ }
+
+ printf ("Virtual function table:\n");
+ for (i = 0; i < c->vftbl->vftbllength; i++)
+ printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]));
+}
+#endif /* !defined(NDEBUG) */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/class.h - class related functions header
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _CLASS_H
+#define _CLASS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* forward typedefs ***********************************************************/
+
+typedef struct classinfo classinfo;
+typedef struct innerclassinfo innerclassinfo;
+typedef struct extra_classref extra_classref;
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "toolbox/list.h"
+
+#if defined(ENABLE_JAVASE)
+# include "vm/annotation.h"
+#endif
+
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/string.hpp"
+#include "vm/utf8.h"
+
+
+/* class state defines ********************************************************/
+
+#define CLASS_LOADING 0x0001
+#define CLASS_LOADED 0x0002
+#define CLASS_LINKING 0x0004
+#define CLASS_LINKED 0x0008
+#define CLASS_INITIALIZING 0x0010
+#define CLASS_INITIALIZED 0x0020
+#define CLASS_ERROR 0x0040
+
+
+/* some macros ****************************************************************/
+
+#define CLASS_IS_OR_ALMOST_INITIALIZED(c) \
+ (((c)->state & CLASS_INITIALIZING) || ((c)->state & CLASS_INITIALIZED))
+
+
+/* classinfo ******************************************************************/
+
+/* We define this dummy structure of java_lang_Class so we can
+ bootstrap cacaoh without needing a java_lang_Class.h file. Whether
+ the size of the dummy structure is big enough is checked during
+ runtime in vm_create. */
+
+typedef struct {
+ java_object_t header;
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ intptr_t padding[4];
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ intptr_t padding[19];
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+ intptr_t padding[3];
+#else
+# error unknown classpath configuration
+#endif
+} dummy_java_lang_Class;
+
+struct classinfo { /* class structure */
+ dummy_java_lang_Class object;
+
+ s4 flags; /* ACC flags */
+ utf *name; /* class name */
+
+ s4 cpcount; /* number of entries in constant pool */
+ u1 *cptags; /* constant pool tags */
+ void* *cpinfos; /* pointer to constant pool info structures */
+
+ s4 classrefcount; /* number of symbolic class references */
+ constant_classref *classrefs; /* table of symbolic class references */
+ extra_classref *extclassrefs; /* additional classrefs */
+ s4 parseddescsize; /* size of the parsed descriptors block */
+ u1 *parseddescs; /* parsed descriptors */
+
+ classinfo *super; /* super class */
+ classinfo *sub; /* sub class pointer */
+ classinfo *nextsub; /* pointer to next class in sub class list */
+
+ int32_t interfacescount; /* number of interfaces */
+ classinfo **interfaces; /* super interfaces */
+
+ int32_t fieldscount; /* number of fields */
+ fieldinfo *fields; /* field table */
+
+ int32_t methodscount; /* number of methods */
+ methodinfo *methods; /* method table */
+
+ s4 state; /* current class state */
+ s4 index; /* hierarchy depth (classes) or index */
+ /* (interfaces) */
+ s4 instancesize; /* size of an instance of this class */
+
+ vftbl_t *vftbl; /* pointer to virtual function table */
+
+ methodinfo *finalizer; /* finalizer method */
+
+ u2 innerclasscount; /* number of inner classes */
+ innerclassinfo *innerclass;
+
+ classref_or_classinfo declaringclass;
+ classref_or_classinfo enclosingclass; /* enclosing class */
+ constant_nameandtype *enclosingmethod; /* enclosing method */
+
+ utf *packagename; /* full name of the package */
+ utf *sourcefile; /* SourceFile attribute */
+#if defined(ENABLE_JAVASE)
+ utf *signature; /* Signature attribute */
+#if defined(ENABLE_ANNOTATIONS)
+ /* All the annotation attributes are NULL (and not a zero length array) */
+ /* if there is nothing. */
+ java_object_t *annotations; /* annotations of this class */
+
+ java_object_t *method_annotations; /* array of annotations of the methods */
+ java_object_t *method_parameterannotations; /* array of parameter */
+ /* annotations of the methods */
+ java_object_t *method_annotationdefaults; /* array of annotation default */
+ /* values of the methods */
+
+ java_object_t *field_annotations; /* array of annotations of the fields */
+
+#endif
+#endif
+ classloader_t *classloader; /* NULL for bootstrap classloader */
+
+#if defined(ENABLE_JAVASE)
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ java_object_t *protectiondomain;
+ java_objectarray_t *signers;
+# endif
+#endif
+};
+
+
+/* innerclassinfo *************************************************************/
+
+struct innerclassinfo {
+ classref_or_classinfo inner_class; /* inner class pointer */
+ classref_or_classinfo outer_class; /* outer class pointer */
+ utf *name; /* innerclass name */
+ s4 flags; /* ACC flags */
+};
+
+
+/* extra_classref **************************************************************
+
+ for classrefs not occurring within descriptors
+
+*******************************************************************************/
+
+struct extra_classref {
+ extra_classref *next;
+ constant_classref classref;
+};
+
+
+/* inline functions ***********************************************************/
+
+/**
+ * Returns the classname of the class, where slashes ('/') are
+ * replaced by dots ('.').
+ *
+ * @param c class to get name of
+ * @return classname
+ */
+inline static java_handle_t* class_get_classname(classinfo* c)
+{
+ java_handle_t *s;
+
+ /* Create a java string. */
+
+ s = javastring_new_slash_to_dot(c->name);
+
+ return s;
+}
+
+
+/* class_is_primitive **********************************************************
+
+ Checks if the given class is a primitive class.
+
+*******************************************************************************/
+
+static inline bool class_is_primitive(classinfo *c)
+{
+ if (c->flags & ACC_CLASS_PRIMITIVE)
+ return true;
+
+ return false;
+}
+
+
+/* class_is_anonymousclass *****************************************************
+
+ Checks if the given class is an anonymous class.
+
+*******************************************************************************/
+
+static inline bool class_is_anonymousclass(classinfo *c)
+{
+ if (c->flags & ACC_CLASS_ANONYMOUS)
+ return true;
+
+ return false;
+}
+
+
+/* class_is_array **************************************************************
+
+ Checks if the given class is an array class.
+
+*******************************************************************************/
+
+static inline bool class_is_array(classinfo *c)
+{
+ if (!(c->state & CLASS_LINKED))
+ if (!link_class(c))
+ return false;
+
+ return (c->vftbl->arraydesc != NULL);
+}
+
+
+/* class_is_interface **********************************************************
+
+ Checks if the given class is an interface.
+
+*******************************************************************************/
+
+static inline bool class_is_interface(classinfo *c)
+{
+ if (c->flags & ACC_INTERFACE)
+ return true;
+
+ return false;
+}
+
+
+/* class_is_localclass *********************************************************
+
+ Checks if the given class is a local class.
+
+*******************************************************************************/
+
+static inline bool class_is_localclass(classinfo *c)
+{
+ if ((c->enclosingmethod != NULL) && !class_is_anonymousclass(c))
+ return true;
+
+ return false;
+}
+
+
+/* class_is_memberclass ********************************************************
+
+ Checks if the given class is a member class.
+
+*******************************************************************************/
+
+static inline bool class_is_memberclass(classinfo *c)
+{
+ if (c->flags & ACC_CLASS_MEMBER)
+ return true;
+
+ return false;
+}
+
+
+/* class_get_classloader *******************************************************
+
+ Return the classloader of the given class.
+
+*******************************************************************************/
+
+static inline classloader_t *class_get_classloader(classinfo *c)
+{
+ classloader_t *cl;
+
+ cl = c->classloader;
+
+ /* The classloader may be NULL. */
+
+ return cl;
+}
+
+
+/* class_get_superclass ********************************************************
+
+ Return the super class of the given class.
+
+*******************************************************************************/
+
+static inline classinfo *class_get_superclass(classinfo *c)
+{
+ /* For interfaces we return NULL. */
+
+ if (c->flags & ACC_INTERFACE)
+ return NULL;
+
+ /* For java/lang/Object, primitive-type and Void classes c->super
+ is NULL and we return NULL. */
+
+ return c->super;
+}
+
+
+/* function prototypes ********************************************************/
+
+classinfo *class_create_classinfo(utf *u);
+void class_postset_header_vftbl(void);
+classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd);
+void class_set_packagename(classinfo *c);
+
+bool class_load_attributes(classbuffer *cb);
+
+/* retrieve constantpool element */
+void* class_getconstant(classinfo *c, u4 pos, u4 ctype);
+void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype);
+
+/* frees all resources used by the class */
+void class_free(classinfo *);
+
+/* return an array class with the given component class */
+classinfo *class_array_of(classinfo *component,bool link);
+
+/* return an array class with the given dimension and element class */
+classinfo *class_multiarray_of(s4 dim, classinfo *element,bool link);
+
+/* return a classref for the given class name */
+/* (does a linear search!) */
+constant_classref *class_lookup_classref(classinfo *cls,utf *name);
+
+/* return a classref for the given class name */
+/* (does a linear search!) */
+constant_classref *class_get_classref(classinfo *cls,utf *name);
+
+/* return a classref to the class itself */
+/* (does a linear search!) */
+constant_classref *class_get_self_classref(classinfo *cls);
+
+/* return a classref for an array with the given dimension of with the */
+/* given component type */
+constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref);
+
+/* return a classref for the component type of the given array type */
+constant_classref *class_get_classref_component_of(constant_classref *ref);
+
+/* get a class' field by name and descriptor */
+fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc);
+
+/* search 'classinfo'-structure for a field with the specified name */
+fieldinfo *class_findfield_by_name(classinfo *c, utf *name);
+
+/* search class for a field */
+fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer);
+
+/* search for a method with a specified name and descriptor */
+methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc);
+methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *dest);
+methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
+
+bool class_issubclass(classinfo *sub, classinfo *super);
+bool class_isanysubclass(classinfo *sub, classinfo *super);
+bool class_is_assignable_from(classinfo *to, classinfo *from);
+bool class_is_instance(classinfo *c, java_handle_t *h);
+
+classloader_t *class_get_classloader(classinfo *c);
+classinfo *class_get_superclass(classinfo *c);
+classinfo *class_get_componenttype(classinfo *c);
+java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly);
+java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly);
+java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly);
+java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly);
+classinfo *class_get_declaringclass(classinfo *c);
+classinfo *class_get_enclosingclass(classinfo *c);
+java_handle_t* class_get_enclosingconstructor(classinfo *c);
+methodinfo* class_get_enclosingmethod_raw(classinfo *c);
+java_handle_t* class_get_enclosingmethod(classinfo *c);
+java_handle_objectarray_t *class_get_interfaces(classinfo *c);
+java_handle_bytearray_t *class_get_annotations(classinfo *c);
+int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib);
+java_handle_t *class_get_name(classinfo *c);
+
+#if defined(ENABLE_JAVASE)
+utf *class_get_signature(classinfo *c);
+#endif
+
+/* some debugging functions */
+
+#if !defined(NDEBUG)
+void class_printflags(classinfo *c);
+void class_print(classinfo *c);
+void class_println(classinfo *c);
+void class_classref_print(constant_classref *cr);
+void class_classref_println(constant_classref *cr);
+void class_classref_or_classinfo_print(classref_or_classinfo c);
+void class_classref_or_classinfo_println(classref_or_classinfo c);
+#endif
+
+/* debug purposes */
+void class_showmethods(classinfo *c);
+void class_showconstantpool(classinfo *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CLASS_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/vm/classcache.c - loaded class cache and loading constraints
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/logging.h"
+
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/utf8.h"
+
+
+/*************************************************************************
+
+ Class Cache
+
+ The classcache has two functions:
+
+ 1) caching the resolution of class references
+ 2) storing and checking loading constraints
+
+ We will use the following terms in this description:
+
+ N a class name: a utf string
+ (N,L) a class reference with initiating loader L and class name N
+ C a class (object): the result of resolving a reference (N,L)
+ We will write resultion as
+ C = *(N,L)
+ (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
+ resolve to the same class C. So (N,L1,L2) means
+ *(N,L1) = *(N,L2)
+
+ The functions of the classcache require:
+
+ 1) a mapping (N,L) |--> C for looking up prior resolution results.
+ 2) storing the current set of loading constraints { (N,L1,L2) }
+
+ These functions can be rearranged like that:
+
+ a mapping N |--> (a mapping L |--> C or NULL,
+ a set of constraints {(L1,L2)})
+
+ Thus we can treat the mapping and constraints for each name N
+ separately. The implementation does this by keeping a hash table
+ mapping a name N to a `classcache_name_entry` which contains all
+ info with respect to N.
+
+ For a class name N we can define an equivalence relation ~N~ on
+ class loaders:
+
+ L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
+
+ A loading constraint (N,L1,L2) implies L1 ~N~ L2.
+
+ Also, if two references (N,L1) and (N,L2) resolve to the same class C
+ we have L1 ~N~ L2 because class loaders are required to return
+ consistent resolutions for a name N [XXX].
+
+ A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
+ where
+ Cx...is a class C or NULL
+ IL...is the set of initiating loaders
+ CL...is the set of constrained loaders
+
+ Such a tuple is called `classcache_class_entry` in the source code.
+
+ The following holds for each tuple (Cx,IL,CL):
+
+ . (Cx is NULL) implies IL = {}.
+
+ . If Cx is a class, IL is the set of loaders that have been
+ recorded as initiating loaders for Cx. IL may be the
+ empty set {} in case Cx has already been defined but no
+ initiating loader has been recorded, yet.
+
+ . (IL u CL) is a subset of an equivalence class of ~N~.
+
+ (This means that all loaders in IL and CL must resolve
+ the name N to the same class.)
+
+ The following holds for the set of tuples { (Cx,IL,CL) }:
+
+ . For a given class C there is at most one tuple with Cx = C
+ in the set. (There may be an arbitrary number of tuples
+ with Cx = NULL, however.)
+
+ . For a given loader L there is at most one tuple with
+ L in (IL u CL).
+
+ The implementation stores sets of loaders as linked lists of
+ `classcache_loader_entry`s.
+
+ Comments about manipulating the classcache can be found in the
+ individual functions below.
+
+*************************************************************************/
+
+
+/* initial number of slots in the classcache hash table */
+#define CLASSCACHE_INIT_SIZE 2048
+
+/*============================================================================*/
+/* DEBUG HELPERS */
+/*============================================================================*/
+
+/* #define CLASSCACHE_VERBOSE */
+
+/*============================================================================*/
+/* STATISTICS */
+/*============================================================================*/
+
+/*#define CLASSCACHE_STATS*/
+
+#ifdef CLASSCACHE_STATS
+static int stat_classnames_stored = 0;
+static int stat_classes_stored = 0;
+static int stat_trivial_constraints = 0;
+static int stat_nontriv_constraints = 0;
+static int stat_nontriv_constraints_both = 0;
+static int stat_nontriv_constraints_merged = 0;
+static int stat_nontriv_constraints_one = 0;
+static int stat_nontriv_constraints_none = 0;
+static int stat_new_loader_entry = 0;
+static int stat_merge_class_entries = 0;
+static int stat_merge_loader_entries = 0;
+static int stat_lookup = 0;
+static int stat_lookup_class_entry_checked = 0;
+static int stat_lookup_loader_checked = 0;
+static int stat_lookup_name = 0;
+static int stat_lookup_name_entry = 0;
+static int stat_lookup_name_notfound = 0;
+static int stat_lookup_new_name = 0;
+static int stat_lookup_new_name_entry = 0;
+static int stat_lookup_new_name_collisions = 0;
+static int stat_rehash_names = 0;
+static int stat_rehash_names_collisions = 0;
+
+#define CLASSCACHE_COUNT(cnt) (cnt)++
+#define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
+
+void classcache_print_statistics(FILE *file) {
+ fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
+ fprintf(file,"classes stored : %8d\n",stat_classes_stored);
+ fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
+ fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
+ fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
+ fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
+ fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
+ fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
+ fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
+ fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
+ fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
+ fprintf(file,"lookups : %8d\n",stat_lookup);
+ fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
+ fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
+ fprintf(file,"lookup name : %8d\n",stat_lookup_name);
+ fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
+ fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
+ fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
+ fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
+ fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
+ fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
+ fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
+}
+#else
+#define CLASSCACHE_COUNT(cnt)
+#define CLASSCACHE_COUNTIF(cond,cnt)
+#endif
+
+/*============================================================================*/
+/* THREAD-SAFE LOCKING */
+/*============================================================================*/
+
+ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+ /* CAUTION: The static functions below are */
+ /* NOT synchronized! */
+ /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+#if defined(ENABLE_THREADS)
+# define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
+# define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
+#else
+# define CLASSCACHE_LOCK()
+# define CLASSCACHE_UNLOCK()
+#endif
+
+/*============================================================================*/
+/* GLOBAL VARIABLES */
+/*============================================================================*/
+
+hashtable hashtable_classcache;
+
+#if defined(ENABLE_THREADS)
+static java_object_t *lock_hashtable_classcache;
+#endif
+
+
+/*============================================================================*/
+/* */
+/*============================================================================*/
+
+/* prototypes */
+
+static void classcache_free_class_entry(classcache_class_entry *clsen);
+static void classcache_remove_class_entry(classcache_name_entry *en,
+ classcache_class_entry *clsen);
+
+/* hash function to use */
+
+#define CLASSCACHE_HASH utf_full_hashkey
+
+/* classcache_init *************************************************************
+
+ Initialize the class cache
+
+ Note: NOT synchronized!
+
+*******************************************************************************/
+
+bool classcache_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("classcache_init");
+
+ /* create the hashtable */
+
+ hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
+
+#if defined(ENABLE_THREADS)
+ /* create utf hashtable lock object */
+
+ lock_hashtable_classcache = NEW(java_object_t);
+
+ LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
+#endif
+
+ /* everything's ok */
+
+ return true;
+}
+
+/* classcache_new_loader_entry *************************************************
+
+ Create a new classcache_loader_entry struct
+ (internally used helper function)
+
+ IN:
+ loader...........the ClassLoader object
+ next.............the next classcache_loader_entry
+
+ RETURN VALUE:
+ the new classcache_loader_entry
+
+*******************************************************************************/
+
+static classcache_loader_entry * classcache_new_loader_entry(
+ classloader_t * loader,
+ classcache_loader_entry * next)
+{
+ classcache_loader_entry *lden;
+
+ lden = NEW(classcache_loader_entry);
+ lden->loader = loader;
+ lden->next = next;
+ CLASSCACHE_COUNT(stat_new_loader_entry);
+
+ return lden;
+}
+
+/* classcache_merge_loaders ****************************************************
+
+ Merge two lists of loaders into one
+ (internally used helper function)
+
+ IN:
+ lista............first list (may be NULL)
+ listb............second list (may be NULL)
+
+ RETURN VALUE:
+ the merged list (may be NULL)
+
+ NOTE:
+ The lists given as arguments are destroyed!
+
+*******************************************************************************/
+
+static classcache_loader_entry * classcache_merge_loaders(
+ classcache_loader_entry * lista,
+ classcache_loader_entry * listb)
+{
+ classcache_loader_entry *result;
+ classcache_loader_entry *ldenA;
+ classcache_loader_entry *ldenB;
+ classcache_loader_entry **chain;
+
+ CLASSCACHE_COUNT(stat_merge_loader_entries);
+
+ /* XXX This is a quadratic algorithm. If this ever
+ * becomes a problem, the loader lists should be
+ * stored as sorted lists and merged in linear time. */
+
+ result = NULL;
+ chain = &result;
+
+ for (ldenA = lista; ldenA; ldenA = ldenA->next) {
+
+ for (ldenB = listb; ldenB; ldenB = ldenB->next) {
+ if (ldenB->loader == ldenA->loader)
+ goto common_element;
+ }
+
+ /* this loader is only in lista */
+ *chain = ldenA;
+ chain = &(ldenA->next);
+
+ common_element:
+ /* XXX free the duplicated element */
+ ;
+ }
+
+ /* concat listb to the result */
+ *chain = listb;
+
+ return result;
+}
+
+/* classcache_merge_class_entries **********************************************
+
+ Merge two `classcache_class_entry`s into one.
+ (internally used helper function)
+
+ IN:
+ en...............the classcache_name_entry containing both class entries
+ clsenA...........first class entry, will receive the result
+ clsenB...........second class entry
+
+ PRE-CONDITION:
+ Either both entries must have the same classobj, or one of them has
+ classobj == NULL.
+
+ NOTE:
+ clsenB is freed by this function!
+
+*******************************************************************************/
+
+static void classcache_merge_class_entries(classcache_name_entry *en,
+ classcache_class_entry *clsenA,
+ classcache_class_entry *clsenB)
+{
+#ifdef CLASSCACHE_VERBOSE
+ char logbuffer[1024];
+#endif
+
+ assert(en);
+ assert(clsenA);
+ assert(clsenB);
+ assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
+
+#ifdef CLASSCACHE_VERBOSE
+ sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
+ (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
+ if (clsenA->classobj)
+ utf_cat_classname(logbuffer, clsenA->classobj->name);
+ if (clsenB->classobj)
+ utf_cat_classname(logbuffer, clsenB->classobj->name);
+ log_println(logbuffer);
+#endif
+
+ CLASSCACHE_COUNT(stat_merge_class_entries);
+
+ /* clsenB will be merged into clsenA */
+ clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
+ clsenB->loaders = NULL; /* these have been freed or reused */
+
+ clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
+ clsenB->constraints);
+ clsenB->constraints = NULL; /* these have been freed or reused */
+
+ if (!clsenA->classobj)
+ clsenA->classobj = clsenB->classobj;
+
+ /* remove clsenB from the list of class entries */
+ classcache_remove_class_entry(en, clsenB);
+}
+
+
+/* classcache_lookup_name ******************************************************
+
+ Lookup a name in the first level of the cache
+ (internally used helper function)
+
+ IN:
+ name.............the name to look up
+
+ RETURN VALUE:
+ a pointer to the classcache_name_entry for this name, or
+ null if no entry was found.
+
+*******************************************************************************/
+
+static classcache_name_entry *classcache_lookup_name(utf *name)
+{
+ classcache_name_entry *c; /* hash table element */
+ u4 key; /* hashkey computed from classname */
+ u4 slot; /* slot in hashtable */
+
+ CLASSCACHE_COUNT(stat_lookup_name);
+
+ key = CLASSCACHE_HASH(name->text, (u4) name->blength);
+ slot = key & (hashtable_classcache.size - 1);
+ c = hashtable_classcache.ptr[slot];
+
+ /* search external hash chain for the entry */
+
+ while (c) {
+ /* entry found in hashtable */
+ CLASSCACHE_COUNT(stat_lookup_name_entry);
+
+ if (c->name == name)
+ return c;
+
+ c = c->hashlink; /* next element in external chain */
+ }
+
+ /* not found */
+
+ CLASSCACHE_COUNT(stat_lookup_name_notfound);
+ return NULL;
+}
+
+
+/* classcache_new_name *********************************************************
+
+ Return a classcache_name_entry for the given name. The entry is created
+ if it is not already in the cache.
+ (internally used helper function)
+
+ IN:
+ name.............the name to look up / create an entry for
+
+ RETURN VALUE:
+ a pointer to the classcache_name_entry for this name
+
+*******************************************************************************/
+
+static classcache_name_entry *classcache_new_name(utf *name)
+{
+ classcache_name_entry *c; /* hash table element */
+ u4 key; /* hashkey computed from classname */
+ u4 slot; /* slot in hashtable */
+ u4 i;
+
+ CLASSCACHE_COUNT(stat_lookup_new_name);
+
+ key = CLASSCACHE_HASH(name->text, (u4) name->blength);
+ slot = key & (hashtable_classcache.size - 1);
+ c = hashtable_classcache.ptr[slot];
+
+ /* search external hash chain for the entry */
+
+ while (c) {
+ /* entry found in hashtable */
+ CLASSCACHE_COUNT(stat_lookup_new_name_entry);
+
+ if (c->name == name)
+ return c;
+
+ c = c->hashlink; /* next element in external chain */
+ }
+
+ /* location in hashtable found, create new entry */
+
+ c = NEW(classcache_name_entry);
+
+ c->name = name;
+ c->classes = NULL;
+
+ /* insert entry into hashtable */
+ c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+ CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
+ hashtable_classcache.ptr[slot] = c;
+
+ /* update number of hashtable-entries */
+ hashtable_classcache.entries++;
+ CLASSCACHE_COUNT(stat_classnames_stored);
+
+ if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
+ /* reorganization of hashtable */
+
+ classcache_name_entry *c2;
+ hashtable newhash; /* the new hashtable */
+
+ CLASSCACHE_COUNT(stat_rehash_names);
+
+ /* create new hashtable, double the size */
+
+ hashtable_create(&newhash, hashtable_classcache.size * 2);
+ newhash.entries = hashtable_classcache.entries;
+
+ /* transfer elements to new hashtable */
+
+ for (i = 0; i < hashtable_classcache.size; i++) {
+ c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
+ while (c2) {
+ classcache_name_entry *nextc = c2->hashlink;
+ u4 newslot =
+ (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
+
+ c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
+ CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
+ newhash.ptr[newslot] = c2;
+
+ c2 = nextc;
+ }
+ }
+
+ /* dispose old table */
+
+ MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
+ hashtable_classcache = newhash;
+ }
+
+ return c;
+}
+
+
+/* classcache_lookup ***********************************************************
+
+ Lookup a possibly loaded class
+
+ IN:
+ initloader.......initiating loader for resolving the class name
+ classname........class name to look up
+
+ RETURN VALUE:
+ The return value is a pointer to the cached class object,
+ or NULL, if the class is not in the cache.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+classinfo *classcache_lookup(classloader_t *initloader, utf *classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+ classinfo *cls = NULL;
+
+ CLASSCACHE_LOCK();
+
+ CLASSCACHE_COUNT(stat_lookup);
+ en = classcache_lookup_name(classname);
+
+ if (en) {
+ /* iterate over all class entries */
+
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+ CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
+ /* check if this entry has been loaded by initloader */
+
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ CLASSCACHE_COUNT(stat_lookup_loader_checked);
+ if (lden->loader == initloader) {
+ /* found the loaded class entry */
+
+ assert(clsen->classobj);
+ cls = clsen->classobj;
+ goto found;
+ }
+ }
+ }
+ }
+
+ found:
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+
+/* classcache_lookup_defined ***************************************************
+
+ Lookup a class with the given name and defining loader
+
+ IN:
+ defloader........defining loader
+ classname........class name
+
+ RETURN VALUE:
+ The return value is a pointer to the cached class object,
+ or NULL, if the class is not in the cache.
+
+*******************************************************************************/
+
+classinfo *classcache_lookup_defined(classloader_t *defloader, utf *classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classinfo *cls = NULL;
+
+ CLASSCACHE_LOCK();
+
+ en = classcache_lookup_name(classname);
+
+ if (en) {
+ /* iterate over all class entries */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+ if (!clsen->classobj)
+ continue;
+
+ /* check if this entry has been defined by defloader */
+ if (clsen->classobj->classloader == defloader) {
+ cls = clsen->classobj;
+ goto found;
+ }
+ }
+ }
+
+ found:
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+
+/* classcache_lookup_defined_or_initiated **************************************
+
+ Lookup a class that has been defined or initiated by the given loader
+
+ IN:
+ loader...........defining or initiating loader
+ classname........class name to look up
+
+ RETURN VALUE:
+ The return value is a pointer to the cached class object,
+ or NULL, if the class is not in the cache.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+classinfo *classcache_lookup_defined_or_initiated(classloader_t *loader,
+ utf *classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+ classinfo *cls = NULL;
+
+ CLASSCACHE_LOCK();
+
+ en = classcache_lookup_name(classname);
+
+ if (en) {
+ /* iterate over all class entries */
+
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+
+ /* check if this entry has been defined by loader */
+ if (clsen->classobj && clsen->classobj->classloader == loader) {
+ cls = clsen->classobj;
+ goto found;
+ }
+
+ /* check if this entry has been initiated by loader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == loader) {
+ /* found the loaded class entry */
+
+ assert(clsen->classobj);
+ cls = clsen->classobj;
+ goto found;
+ }
+ }
+ }
+ }
+
+ found:
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+
+/* classcache_store ************************************************************
+
+ Store a loaded class. If a class of the same name has already been stored
+ with the same initiating loader, then the given class CLS is freed (if
+ possible) and the previously stored class is returned.
+
+ IN:
+ initloader.......initiating loader used to load the class
+ (may be NULL indicating the bootstrap loader)
+ cls..............class object to cache
+ mayfree..........true if CLS may be freed in case another class is
+ returned
+
+ RETURN VALUE:
+ cls..............everything ok, the class was stored in the cache,
+ other classinfo..another class with the same (initloader,name) has been
+ stored earlier. CLS has been freed[1] and the earlier
+ stored class is returned.
+ NULL.............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+ [1]...in case MAYFREE is true
+
+*******************************************************************************/
+
+classinfo *classcache_store(classloader_t *initloader, classinfo *cls,
+ bool mayfree)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ classcache_class_entry *clsenB;
+ classcache_loader_entry *lden;
+#ifdef CLASSCACHE_VERBOSE
+ char logbuffer[1024];
+#endif
+
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
+
+ CLASSCACHE_LOCK();
+
+#ifdef CLASSCACHE_VERBOSE
+ sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
+ utf_cat_classname(logbuffer, cls->name);
+ strcat(logbuffer,")");
+ log_println(logbuffer);
+#endif
+
+ en = classcache_new_name(cls->name);
+
+ assert(en);
+
+ /* iterate over all class entries */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+
+ /* check if this entry has already been loaded by initloader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == initloader) {
+ if (clsen->classobj != cls) {
+ /* A class with the same (initloader,name) pair has been stored already. */
+ /* We free the given class and return the earlier one. */
+#ifdef CLASSCACHE_VERBOSE
+ log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
+#endif
+ assert(clsen->classobj);
+ if (mayfree)
+ class_free(cls);
+ cls = clsen->classobj;
+ }
+ goto return_success;
+ }
+ }
+
+ /* {This entry has not been resolved with initloader} */
+
+ /* check if initloader is constrained to this entry */
+ for (lden = clsen->constraints; lden; lden = lden->next) {
+ if (lden->loader == initloader) {
+ /* we have to use this entry. check if it has been resolved */
+ if (clsen->classobj) {
+ /* check if is has already been resolved to another class */
+ if (clsen->classobj != cls) {
+ /* a loading constraint is violated */
+ exceptions_throw_linkageerror("loading constraint violated: ", cls);
+ goto return_exception;
+ }
+
+ /* record initloader as initiating loader */
+ clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
+ goto return_success;
+ }
+
+ /* {this is the first resolution for this entry} */
+ /* record initloader as initiating loader */
+ clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
+
+ /* maybe we can merge this entry with another one */
+ for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
+ /* we dont want the entry that we have already */
+ if (clsenB->classobj == cls) {
+ /* this entry has the same classobj. let's merge them */
+ classcache_merge_class_entries(en,clsen,clsenB);
+ goto return_success;
+ }
+ }
+
+ /* record the loaded class object */
+ clsen->classobj = cls;
+ CLASSCACHE_COUNT(stat_classes_stored);
+
+ /* done */
+ goto return_success;
+ }
+ }
+
+ }
+
+ /* {There is no class entry containing initloader as initiating
+ * or constrained loader.} */
+
+ /* we look for a class entry with the same classobj we want to store */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+ if (clsen->classobj == cls) {
+ /* this entry is about the same classobj. let's use it */
+ /* check if this entry has already been loaded by initloader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == initloader)
+ goto return_success;
+ }
+ clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
+ goto return_success;
+ }
+ }
+
+ /* create a new class entry for this class object with */
+ /* initiating loader initloader */
+
+ clsen = NEW(classcache_class_entry);
+ clsen->classobj = cls;
+ clsen->loaders = classcache_new_loader_entry(initloader, NULL);
+ clsen->constraints = NULL;
+
+ clsen->next = en->classes;
+ en->classes = clsen;
+ CLASSCACHE_COUNT(stat_classes_stored);
+
+ return_success:
+#ifdef CLASSCACHE_VERBOSE
+ classcache_debug_dump(stdout,cls->name);
+#endif
+ CLASSCACHE_UNLOCK();
+ return cls;
+
+ return_exception:
+ CLASSCACHE_UNLOCK();
+ return NULL; /* exception */
+}
+
+/* classcache_store_unique *****************************************************
+
+ Store a loaded class as loaded by the bootstrap loader. This is a wrapper
+ aroung classcache_store that throws an exception if a class with the same
+ name has already been loaded by the bootstrap loader.
+
+ This function is used to register a few special classes during startup.
+ It should not be used otherwise.
+
+ IN:
+ cls..............class object to cache
+
+ RETURN VALUE:
+ true.............everything ok, the class was stored.
+ false............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+bool classcache_store_unique(classinfo *cls)
+{
+ classinfo *result;
+
+ result = classcache_store(NULL,cls,false);
+ if (result == NULL)
+ return false;
+
+ if (result != cls) {
+ exceptions_throw_internalerror("class already stored in the class cache");
+ return false;
+ }
+
+ return true;
+}
+
+/* classcache_store_defined ****************************************************
+
+ Store a loaded class after it has been defined. If the class has already
+ been defined by the same defining loader in another thread, free the given
+ class and returned the one which has been defined earlier.
+
+ IN:
+ cls..............class object to store. classloader must be set
+ (classloader may be NULL, for bootloader)
+
+ RETURN VALUE:
+ cls..............everything ok, the class was stored the cache,
+ other classinfo..the class had already been defined, CLS was freed, the
+ class which was defined earlier is returned,
+ NULL.............an exception has been thrown.
+
+*******************************************************************************/
+
+classinfo *classcache_store_defined(classinfo *cls)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+#ifdef CLASSCACHE_VERBOSE
+ char logbuffer[1024];
+#endif
+
+ assert(cls);
+ assert(cls->state & CLASS_LOADED);
+
+ CLASSCACHE_LOCK();
+
+#ifdef CLASSCACHE_VERBOSE
+ sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
+ utf_cat_classname(logbuffer, cls->name);
+ strcat(logbuffer,")");
+ log_println(logbuffer);
+#endif
+
+ en = classcache_new_name(cls->name);
+
+ assert(en);
+
+ /* iterate over all class entries */
+ for (clsen = en->classes; clsen; clsen = clsen->next) {
+
+ /* check if this class has been defined by the same classloader */
+ if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
+ /* we found an earlier definition, delete the newer one */
+ /* (if it is a different classinfo) */
+ if (clsen->classobj != cls) {
+#ifdef CLASSCACHE_VERBOSE
+ log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
+#endif
+ class_free(cls);
+ cls = clsen->classobj;
+ }
+ goto return_success;
+ }
+ }
+
+ /* create a new class entry for this class object */
+ /* the list of initiating loaders is empty at this point */
+
+ clsen = NEW(classcache_class_entry);
+ clsen->classobj = cls;
+ clsen->loaders = NULL;
+ clsen->constraints = NULL;
+
+ clsen->next = en->classes;
+ en->classes = clsen;
+ CLASSCACHE_COUNT(stat_classes_stored);
+
+return_success:
+#ifdef CLASSCACHE_VERBOSE
+ classcache_debug_dump(stdout,cls->name);
+#endif
+ CLASSCACHE_UNLOCK();
+ return cls;
+}
+
+/* classcache_find_loader ******************************************************
+
+ Find the class entry loaded by or constrained to a given loader
+ (internally used helper function)
+
+ IN:
+ entry............the classcache_name_entry
+ loader...........the loader to look for
+
+ RETURN VALUE:
+ the classcache_class_entry for the given loader, or
+ NULL if no entry was found
+
+*******************************************************************************/
+
+static classcache_class_entry * classcache_find_loader(
+ classcache_name_entry * entry,
+ classloader_t * loader)
+{
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+
+ assert(entry);
+
+ /* iterate over all class entries */
+ for (clsen = entry->classes; clsen; clsen = clsen->next) {
+
+ /* check if this entry has already been loaded by initloader */
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ if (lden->loader == loader)
+ return clsen; /* found */
+ }
+
+ /* check if loader is constrained to this entry */
+ for (lden = clsen->constraints; lden; lden = lden->next) {
+ if (lden->loader == loader)
+ return clsen; /* found */
+ }
+ }
+
+ /* not found */
+ return NULL;
+}
+
+/* classcache_free_class_entry *************************************************
+
+ Free the memory used by a class entry
+
+ IN:
+ clsen............the classcache_class_entry to free
+
+*******************************************************************************/
+
+static void classcache_free_class_entry(classcache_class_entry * clsen)
+{
+ classcache_loader_entry *lden;
+ classcache_loader_entry *next;
+
+ assert(clsen);
+
+ for (lden = clsen->loaders; lden; lden = next) {
+ next = lden->next;
+ FREE(lden, classcache_loader_entry);
+ }
+ for (lden = clsen->constraints; lden; lden = next) {
+ next = lden->next;
+ FREE(lden, classcache_loader_entry);
+ }
+
+ FREE(clsen, classcache_class_entry);
+}
+
+/* classcache_remove_class_entry ***********************************************
+
+ Remove a classcache_class_entry from the list of possible resolution of
+ a name entry
+ (internally used helper function)
+
+ IN:
+ entry............the classcache_name_entry
+ clsen............the classcache_class_entry to remove
+
+*******************************************************************************/
+
+static void classcache_remove_class_entry(classcache_name_entry * entry,
+ classcache_class_entry * clsen)
+{
+ classcache_class_entry **chain;
+
+ assert(entry);
+ assert(clsen);
+
+ chain = &(entry->classes);
+ while (*chain) {
+ if (*chain == clsen) {
+ *chain = clsen->next;
+ classcache_free_class_entry(clsen);
+ return;
+ }
+ chain = &((*chain)->next);
+ }
+}
+
+/* classcache_free_name_entry **************************************************
+
+ Free the memory used by a name entry
+
+ IN:
+ entry............the classcache_name_entry to free
+
+*******************************************************************************/
+
+static void classcache_free_name_entry(classcache_name_entry * entry)
+{
+ classcache_class_entry *clsen;
+ classcache_class_entry *next;
+
+ assert(entry);
+
+ for (clsen = entry->classes; clsen; clsen = next) {
+ next = clsen->next;
+ classcache_free_class_entry(clsen);
+ }
+
+ FREE(entry, classcache_name_entry);
+}
+
+/* classcache_free *************************************************************
+
+ Free the memory used by the class cache
+
+ NOTE:
+ The class cache may not be used any more after this call, except
+ when it is reinitialized with classcache_init.
+
+ Note: NOT synchronized!
+
+*******************************************************************************/
+
+void classcache_free(void)
+{
+ u4 slot;
+ classcache_name_entry *entry;
+ classcache_name_entry *next;
+
+ for (slot = 0; slot < hashtable_classcache.size; ++slot) {
+ for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
+ next = entry->hashlink;
+ classcache_free_name_entry(entry);
+ }
+ }
+
+ MFREE(hashtable_classcache.ptr, void*, hashtable_classcache.size);
+ hashtable_classcache.size = 0;
+ hashtable_classcache.entries = 0;
+ hashtable_classcache.ptr = NULL;
+}
+
+/* classcache_add_constraint ***************************************************
+
+ Add a loading constraint
+
+ IN:
+ a................first initiating loader
+ b................second initiating loader
+ classname........class name
+
+ RETURN VALUE:
+ true.............everything ok, the constraint has been added,
+ false............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool classcache_add_constraint(classloader_t * a,
+ classloader_t * b,
+ utf * classname)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsenA;
+ classcache_class_entry *clsenB;
+
+ assert(classname);
+
+#ifdef CLASSCACHE_VERBOSE
+ log_start();
+ log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
+ utf_fprint_printable_ascii_classname(stdout, classname);
+ log_print(")\n");
+ log_finish();
+#endif
+
+ /* a constraint with a == b is trivially satisfied */
+ if (a == b) {
+ CLASSCACHE_COUNT(stat_trivial_constraints);
+ return true;
+ }
+
+ CLASSCACHE_LOCK();
+
+ en = classcache_new_name(classname);
+
+ assert(en);
+ CLASSCACHE_COUNT(stat_nontriv_constraints);
+
+ /* find the entry loaded by / constrained to each loader */
+ clsenA = classcache_find_loader(en, a);
+ clsenB = classcache_find_loader(en, b);
+
+ if (clsenA && clsenB) {
+ /* { both loaders have corresponding entries } */
+ CLASSCACHE_COUNT(stat_nontriv_constraints_both);
+
+ /* if the entries are the same, the constraint is already recorded */
+ if (clsenA == clsenB)
+ goto return_success;
+
+ /* check if the entries can be merged */
+ if (clsenA->classobj && clsenB->classobj
+ && clsenA->classobj != clsenB->classobj) {
+ /* no, the constraint is violated */
+ exceptions_throw_linkageerror("loading constraint violated: ",
+ clsenA->classobj);
+ goto return_exception;
+ }
+
+ /* yes, merge the entries */
+ classcache_merge_class_entries(en,clsenA,clsenB);
+ CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
+ }
+ else {
+ /* { at most one of the loaders has a corresponding entry } */
+
+ /* set clsenA to the single class entry we have */
+ if (!clsenA)
+ clsenA = clsenB;
+
+ if (!clsenA) {
+ /* { no loader has a corresponding entry } */
+ CLASSCACHE_COUNT(stat_nontriv_constraints_none);
+
+ /* create a new class entry with the constraint (a,b,en->name) */
+ clsenA = NEW(classcache_class_entry);
+ clsenA->classobj = NULL;
+ clsenA->loaders = NULL;
+ clsenA->constraints = classcache_new_loader_entry(b, NULL);
+ clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
+
+ clsenA->next = en->classes;
+ en->classes = clsenA;
+ }
+ else {
+ CLASSCACHE_COUNT(stat_nontriv_constraints_one);
+
+ /* make b the loader that has no corresponding entry */
+ if (clsenB)
+ b = a;
+
+ /* loader b must be added to entry clsenA */
+ clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
+ }
+ }
+
+ return_success:
+ CLASSCACHE_UNLOCK();
+ return true;
+
+ return_exception:
+ CLASSCACHE_UNLOCK();
+ return false; /* exception */
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+/* classcache_add_constraints_for_params ***************************************
+
+ Add loading constraints for the parameters and return type of
+ the given method.
+
+ IN:
+ a................first initiating loader
+ b................second initiating loader
+ m................methodinfo
+
+ RETURN VALUE:
+ true.............everything ok, the constraints have been added,
+ false............an exception has been thrown.
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+#if defined(ENABLE_VERIFIER)
+bool classcache_add_constraints_for_params(classloader_t * a,
+ classloader_t * b,
+ methodinfo *m)
+{
+ methoddesc *md;
+ typedesc *td;
+ s4 i;
+
+ /* a constraint with a == b is trivially satisfied */
+
+ if (a == b) {
+ return true;
+ }
+
+ /* get the parsed descriptor */
+
+ assert(m);
+ md = m->parseddesc;
+ assert(md);
+
+ /* constrain the return type */
+
+ if (md->returntype.type == TYPE_ADR) {
+ if (!classcache_add_constraint(a, b, md->returntype.classref->name))
+ return false; /* exception */
+ }
+
+ /* constrain each reference type used in the parameters */
+
+ td = md->paramtypes;
+ i = md->paramcount;
+ for (; i--; td++) {
+ if (td->type != TYPE_ADR)
+ continue;
+
+ if (!classcache_add_constraint(a, b, td->classref->name))
+ return false; /* exception */
+ }
+
+ /* everything ok */
+ return true;
+}
+#endif /* defined(ENABLE_VERIFIER) */
+
+
+/* classcache_number_of_loaded_classes *****************************************
+
+ Counts the number of loaded classes and returns it.
+
+ Note: This function assumes that the CLASSCACHE_LOCK is held by the
+ caller!
+
+*******************************************************************************/
+
+static s4 classcache_number_of_loaded_classes(void)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ s4 number;
+ s4 i;
+
+ /* initialize class counter */
+
+ number = 0;
+
+ for (i = 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)
+ number++;
+ }
+ }
+ }
+
+ return number;
+}
+
+
+/* classcache_get_loaded_class_count *******************************************
+
+ Counts the number of loaded classes and returns it.
+
+*******************************************************************************/
+
+s4 classcache_get_loaded_class_count(void)
+{
+ s4 count;
+
+ CLASSCACHE_LOCK();
+
+ count = classcache_number_of_loaded_classes();
+
+ CLASSCACHE_UNLOCK();
+
+ return count;
+}
+
+
+/* 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.
+
+*******************************************************************************/
+
+void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
+ void *data)
+{
+ classcache_name_entry *en;
+ classcache_class_entry *clsen;
+ s4 i;
+
+ CLASSCACHE_LOCK();
+
+ /* look in every slot of the hashtable */
+
+ for (i = 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) {
+ (*func)(clsen->classobj, data);
+ }
+ }
+ }
+ }
+
+ CLASSCACHE_UNLOCK();
+}
+
+
+/*============================================================================*/
+/* DEBUG DUMPS */
+/*============================================================================*/
+
+/* classcache_debug_dump *******************************************************
+
+ Print the contents of the loaded class cache to a stream
+
+ IN:
+ file.............output stream
+ only.............if != NULL, only print entries for this name
+ (Currently we print also the rest of the hash chain to
+ get a feel for the average length of hash chains.)
+
+ Note: synchronized with global tablelock
+
+*******************************************************************************/
+
+#ifndef NDEBUG
+void classcache_debug_dump(FILE * file,utf *only)
+{
+ classcache_name_entry *c;
+ classcache_class_entry *clsen;
+ classcache_loader_entry *lden;
+ u4 slot;
+
+ CLASSCACHE_LOCK();
+
+ log_println("=== [loaded class cache] =====================================");
+ log_println("hash size : %d", (int) hashtable_classcache.size);
+ log_println("hash entries: %d", (int) hashtable_classcache.entries);
+ log_println("");
+
+ if (only) {
+ c = classcache_lookup_name(only);
+ slot = 0; /* avoid compiler warning */
+ goto dump_it;
+ }
+
+ for (slot = 0; slot < hashtable_classcache.size; ++slot) {
+ c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
+
+dump_it:
+ for (; c; c = c->hashlink) {
+ utf_fprint_printable_ascii_classname(file, c->name);
+ fprintf(file, "\n");
+
+ /* iterate over all class entries */
+ for (clsen = c->classes; clsen; clsen = clsen->next) {
+ if (clsen->classobj) {
+ log_println(" loaded %p", (void *) clsen->classobj);
+ }
+ else {
+ log_println(" unresolved");
+ }
+
+ log_start();
+ log_print(" loaders: ");
+ for (lden = clsen->loaders; lden; lden = lden->next) {
+ log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
+ }
+ log_finish();
+
+ log_start();
+ log_print(" constraints: ");
+ for (lden = clsen->constraints; lden; lden = lden->next) {
+ log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
+ }
+ log_finish();
+ }
+ }
+
+ if (only)
+ break;
+ }
+ fprintf(file, "\n==============================================================\n\n");
+
+ CLASSCACHE_UNLOCK();
+}
+#endif /* NDEBUG */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/classcache.h - loaded class cache and loading constraints
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _CLASSCACHE_H
+#define _CLASSCACHE_H
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/types.h"
+
+#include <stdio.h> /* for FILE */
+
+#if defined(ENABLE_JVMTI)
+# include "native/jni.h"
+#endif
+
+#include "toolbox/hashtable.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/references.h"
+
+
+/* forward declarations *******************************************************/
+
+typedef struct classcache_name_entry classcache_name_entry;
+typedef struct classcache_class_entry classcache_class_entry;
+typedef struct classcache_loader_entry classcache_loader_entry;
+
+/* global variables ***********************************************************/
+
+extern hashtable hashtable_classcache;
+
+
+/* structs ********************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* The Loaded Class Cache */
+/* */
+/* The loaded class cache is implemented as a two-level data structure. */
+/* */
+/* The first level is a hash table indexed by class names. For each class */
+/* name in the cache there is a classcache_name_entry, which collects all */
+/* information about classes with this class name. */
+/* */
+/* Second level: For each classcache_name_entry there is a list of */
+/* classcache_class_entry:s representing the possible different resolutions */
+/* of the class name. */
+/* */
+/* A classcache_class_entry records the following: */
+/* */
+/* - the loaded class object, if this entry has been resolved, otherwise NULL */
+/* - the list of initiating loaders which have resolved the class name to */
+/* this class object */
+/* - the list of initiating loaders which are constrained to resolve this */
+/* class name to this class object in the future */
+/* */
+/* The classcache_class_entry:s approximate the equivalence classes created */
+/* by the loading constraints and the equivalence of loaded classes. */
+/* */
+/* When a loading constraint (loaderA,loaderB,NAME) is added, then the */
+/* classcache_class_entry:s for NAME containing loaderA and loaderB resp. */
+/* must be merged into one entry. If this is impossible, because the entries */
+/* have already been resolved to different class objects, then the constraint */
+/* is violated and an expception must be thrown. */
+/*----------------------------------------------------------------------------*/
+
+
+/* classcache_name_entry
+ *
+ * For each classname a classcache_name_entry struct is created.
+ */
+
+struct classcache_name_entry
+{
+ utf *name; /* class name */
+ classcache_name_entry *hashlink; /* link for external chaining */
+ classcache_class_entry *classes; /* equivalence classes for this name*/
+};
+
+struct classcache_class_entry
+{
+ classinfo *classobj; /* the loaded class object, or NULL */
+ classcache_loader_entry *loaders;
+ classcache_loader_entry *constraints;
+ classcache_class_entry *next; /* next class entry for same name */
+};
+
+struct classcache_loader_entry
+{
+ classloader_t *loader; /* class loader object */
+ classcache_loader_entry *next; /* next loader entry in the list */
+};
+
+
+/* callback function type for classcache_foreach_loaded_class */
+
+typedef void (*classcache_foreach_functionptr_t)(classinfo *, void *);
+
+
+/* function prototypes ********************************************************/
+
+/* initialize the loaded class cache */
+bool classcache_init(void);
+void classcache_free(void);
+
+classinfo * classcache_lookup(classloader_t *initloader,utf *classname);
+classinfo * classcache_lookup_defined(classloader_t *defloader,utf *classname);
+classinfo * classcache_lookup_defined_or_initiated(classloader_t *loader,utf *classname);
+
+bool classcache_store_unique(classinfo *cls);
+classinfo * classcache_store(classloader_t *initloader,classinfo *cls,bool mayfree);
+classinfo * classcache_store_defined(classinfo *cls);
+
+#if defined(ENABLE_VERIFIER)
+bool classcache_add_constraint(classloader_t *a,classloader_t *b,utf *classname);
+bool classcache_add_constraints_for_params(classloader_t *a,classloader_t *b,
+ methodinfo *m);
+#endif
+
+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
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CLASSCACHE_H */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+
--- /dev/null
+/* src/vm/descriptor.c - checking and parsing of field / method descriptors
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "md-abi.h"
+
+#include "mm/memory.h"
+
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/abi.h"
+
+
+/* constants (private to descriptor.c) ****************************************/
+
+/* initial number of entries for the classrefhash of a descriptor_pool */
+/* (currently the hash is never grown!) */
+#define CLASSREFHASH_INIT_SIZE 64
+
+/* initial number of entries for the descriptorhash of a descriptor_pool */
+/* (currently the hash is never grown!) */
+#define DESCRIPTORHASH_INIT_SIZE 128
+
+/* data structures (private to descriptor.c) **********************************/
+
+typedef struct classref_hash_entry classref_hash_entry;
+typedef struct descriptor_hash_entry descriptor_hash_entry;
+
+/* entry struct for the classrefhash of descriptor_pool */
+struct classref_hash_entry {
+ classref_hash_entry *hashlink; /* for hash chaining */
+ utf *name; /* name of the class refered to */
+ u2 index; /* index into classref table */
+};
+
+/* entry struct for the descriptorhash of descriptor_pool */
+struct descriptor_hash_entry {
+ descriptor_hash_entry *hashlink;
+ utf *desc;
+ parseddesc_t parseddesc;
+ s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
+};
+
+
+/****************************************************************************/
+/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
+/****************************************************************************/
+
+/* SKIP_FIELDDESCRIPTOR:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * CAUTION: This macro does not check for an unexpected end of the
+ * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
+ */
+#define SKIP_FIELDDESCRIPTOR(utf_ptr) \
+ do { while (*(utf_ptr)=='[') (utf_ptr)++; \
+ if (*(utf_ptr)++=='L') \
+ while(*(utf_ptr)++ != ';') /* skip */; } while(0)
+
+/* SKIP_FIELDDESCRIPTOR_SAFE:
+ * utf_ptr must point to the first character of a field descriptor.
+ * After the macro call utf_ptr points to the first character after
+ * the field descriptor.
+ *
+ * Input:
+ * utf_ptr....points to first char of descriptor
+ * end_ptr....points to first char after the end of the string
+ * errorflag..must be initialized (to false) by the caller!
+ * Output:
+ * utf_ptr....points to first char after the descriptor
+ * errorflag..set to true if the string ended unexpectedly
+ */
+#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
+ do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
+ if ((utf_ptr) == (end_ptr)) \
+ (errorflag) = true; \
+ else \
+ if (*(utf_ptr)++=='L') { \
+ while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
+ /* skip */; \
+ if ((utf_ptr)[-1] != ';') \
+ (errorflag) = true; }} while(0)
+
+
+/****************************************************************************/
+/* DEBUG HELPERS */
+/****************************************************************************/
+
+/*#define DESCRIPTOR_VERBOSE*/
+
+/****************************************************************************/
+/* FUNCTIONS */
+/****************************************************************************/
+
+/* descriptor_to_basic_type ****************************************************
+
+ Return the basic type to use for a value with this descriptor.
+
+ IN:
+ utf..............descriptor utf string
+
+ OUT:
+ A TYPE_* constant.
+
+ PRECONDITIONS:
+ This function assumes that the descriptor has passed
+ descriptor_pool_add checks and that it does not start with '('.
+
+*******************************************************************************/
+
+int descriptor_to_basic_type(utf *descriptor)
+{
+ assert(descriptor->blength >= 1);
+
+ switch (descriptor->text[0]) {
+ case 'Z':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'I':
+ return TYPE_INT;
+
+ case 'J':
+ return TYPE_LNG;
+
+ case 'F':
+ return TYPE_FLT;
+
+ case 'D':
+ return TYPE_DBL;
+
+ case 'L':
+ case '[':
+ return TYPE_ADR;
+
+ default:
+ vm_abort("descriptor_to_basic_type: invalid type %c",
+ descriptor->text[0]);
+ }
+
+ /* keep the compiler happy */
+
+ return 0;
+}
+
+
+/* descriptor_typesize *********************************************************
+
+ Return the size in bytes needed for the given type.
+
+ IN:
+ td..............typedesc describing the type
+
+ OUT:
+ The number of bytes
+
+*******************************************************************************/
+
+int descriptor_typesize(typedesc *td)
+{
+ assert(td);
+
+ switch (td->type) {
+ case TYPE_INT:
+ case TYPE_FLT:
+ return 4;
+
+ case TYPE_LNG:
+ case TYPE_DBL:
+ return 8;
+
+ case TYPE_ADR:
+ return SIZEOF_VOID_P;
+
+ default:
+ vm_abort("descriptor_typesize: invalid type %d", td->type);
+ }
+
+ /* keep the compiler happy */
+
+ return 0;
+}
+
+
+/* name_from_descriptor ********************************************************
+
+ Return the class name indicated by the given descriptor
+ (Internally used helper function)
+
+ IN:
+ c................class containing the descriptor
+ utf_ptr..........first character of descriptor
+ end_ptr..........first character after the end of the string
+ mode.............a combination (binary or) of the following flags:
+
+ (Flags marked with * are the default settings.)
+
+ How to handle "V" descriptors:
+
+ * DESCRIPTOR_VOID.....handle it like other primitive types
+ DESCRIPTOR_NOVOID...treat it as an error
+
+ How to deal with extra characters after the end of the
+ descriptor:
+
+ * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
+ DESCRIPTOR_CHECKEND.....treat them as an error
+
+ OUT:
+ *next............if non-NULL, *next is set to the first character after
+ the descriptor. (Undefined if an error occurs.)
+ *name............set to the utf name of the class
+
+ RETURN VALUE:
+ true.............descriptor parsed successfully
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+#define DESCRIPTOR_VOID 0 /* default */
+#define DESCRIPTOR_NOVOID 0x0040
+#define DESCRIPTOR_NOCHECKEND 0 /* default */
+#define DESCRIPTOR_CHECKEND 0x1000
+
+static bool
+name_from_descriptor(classinfo *c,
+ char *utf_ptr, char *end_ptr,
+ char **next, int mode, utf **name)
+{
+ char *start = utf_ptr;
+ bool error = false;
+
+ assert(c);
+ assert(utf_ptr);
+ assert(end_ptr);
+ assert(name);
+
+ *name = NULL;
+ SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
+
+ if (mode & DESCRIPTOR_CHECKEND)
+ error |= (utf_ptr != end_ptr);
+
+ if (!error) {
+ if (next) *next = utf_ptr;
+
+ switch (*start) {
+ case 'V':
+ if (mode & DESCRIPTOR_NOVOID)
+ break;
+ /* FALLTHROUGH! */
+ case 'I':
+ case 'J':
+ case 'F':
+ case 'D':
+ case 'B':
+ case 'C':
+ case 'S':
+ case 'Z':
+ return true;
+
+ case 'L':
+ start++;
+ utf_ptr--;
+ /* FALLTHROUGH! */
+ case '[':
+ *name = utf_new(start, utf_ptr - start);
+ return true;
+ }
+ }
+
+ exceptions_throw_classformaterror(c, "Invalid descriptor");
+ return false;
+}
+
+
+/* descriptor_to_typedesc ******************************************************
+
+ Parse the given type descriptor and fill a typedesc struct
+ (Internally used helper function)
+
+ IN:
+ pool.............the descriptor pool
+ utf_ptr..........points to first character of type descriptor
+ end_pos..........points after last character of the whole descriptor
+
+ OUT:
+ *next............set to next character after type descriptor
+ *d...............filled with parsed information
+
+ RETURN VALUE:
+ true.............parsing succeeded
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+static bool
+descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
+ char **next, typedesc *td)
+{
+ utf *name;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
+ return false;
+
+ if (name) {
+ /* a reference type */
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
+ td->arraydim++;
+ td->classref = descriptor_pool_lookup_classref(pool, name);
+
+ } else {
+ /* a primitive type */
+ switch (*utf_ptr) {
+ case 'B':
+ td->primitivetype = PRIMITIVETYPE_BYTE;
+ td->type = TYPE_INT;
+ break;
+ case 'C':
+ td->primitivetype = PRIMITIVETYPE_CHAR;
+ td->type = TYPE_INT;
+ break;
+ case 'S':
+ td->primitivetype = PRIMITIVETYPE_SHORT;
+ td->type = TYPE_INT;
+ break;
+ case 'Z':
+ td->primitivetype = PRIMITIVETYPE_BOOLEAN;
+ td->type = TYPE_INT;
+ break;
+ case 'I':
+ td->primitivetype = PRIMITIVETYPE_INT;
+ td->type = TYPE_INT;
+ break;
+ case 'D':
+ td->primitivetype = PRIMITIVETYPE_DOUBLE;
+ td->type = TYPE_DBL;
+ break;
+ case 'F':
+ td->primitivetype = PRIMITIVETYPE_FLOAT;
+ td->type = TYPE_FLT;
+ break;
+ case 'J':
+ td->primitivetype = PRIMITIVETYPE_LONG;
+ td->type = TYPE_LNG;
+ break;
+ case 'V':
+ td->primitivetype = PRIMITIVETYPE_VOID;
+ td->type = TYPE_VOID;
+ break;
+ default:
+ assert(false);
+ }
+
+ td->arraydim = 0;
+ td->classref = NULL;
+ }
+
+ return true;
+}
+
+
+/* descriptor_pool_new *********************************************************
+
+ Allocate a new descriptor_pool
+
+ IN:
+ referer..........class for which to create the pool
+
+ RETURN VALUE:
+ a pointer to the new descriptor_pool
+
+*******************************************************************************/
+
+descriptor_pool *
+descriptor_pool_new(classinfo *referer)
+{
+ descriptor_pool *pool;
+ u4 hashsize;
+ u4 slot;
+
+ pool = DNEW(descriptor_pool);
+ assert(pool);
+
+ pool->referer = referer;
+ pool->fieldcount = 0;
+ pool->methodcount = 0;
+ pool->paramcount = 0;
+ pool->descriptorsize = 0;
+ pool->descriptors = NULL;
+ pool->descriptors_next = NULL;
+ pool->classrefs = NULL;
+ pool->descriptor_kind = NULL;
+ pool->descriptor_kind_next = NULL;
+
+ hashsize = CLASSREFHASH_INIT_SIZE;
+ pool->classrefhash.size = hashsize;
+ pool->classrefhash.entries = 0;
+ pool->classrefhash.ptr = DMNEW(void*, hashsize);
+ for (slot=0; slot<hashsize; ++slot)
+ pool->classrefhash.ptr[slot] = NULL;
+
+ hashsize = DESCRIPTORHASH_INIT_SIZE;
+ pool->descriptorhash.size = hashsize;
+ pool->descriptorhash.entries = 0;
+ pool->descriptorhash.ptr = DMNEW(void*, hashsize);
+ for (slot=0; slot<hashsize; ++slot)
+ pool->descriptorhash.ptr[slot] = NULL;
+
+ return pool;
+}
+
+
+/* descriptor_pool_add_class ***************************************************
+
+ Add the given class reference to the pool
+
+ IN:
+ pool.............the descriptor_pool
+ name.............the class reference to add
+
+ RETURN VALUE:
+ true.............reference has been added
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
+descriptor_pool_add_class(descriptor_pool *pool, utf *name)
+{
+ u4 key,slot;
+ classref_hash_entry *c;
+
+ assert(pool);
+ assert(name);
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
+ utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
+#endif
+
+ /* find a place in the hashtable */
+
+ key = utf_hashkey(name->text, name->blength);
+ slot = key & (pool->classrefhash.size - 1);
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
+ while (c) {
+ if (c->name == name)
+ return true; /* already stored */
+ c = c->hashlink;
+ }
+
+ /* check if the name is a valid classname */
+
+ if (!is_valid_name(name->text,UTF_END(name))) {
+ exceptions_throw_classformaterror(pool->referer, "Invalid class name");
+ return false; /* exception */
+ }
+
+ /* XXX check maximum array dimension */
+
+ c = DNEW(classref_hash_entry);
+ c->name = name;
+ c->index = pool->classrefhash.entries++;
+ c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ pool->classrefhash.ptr[slot] = c;
+
+ return true;
+}
+
+
+/* descriptor_pool_add *********************************************************
+
+ Check the given descriptor and add it to the pool
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the descriptor to add. Maybe a field or method desc.
+
+ OUT:
+ *paramslots......if non-NULL, set to the number of parameters.
+ LONG and DOUBLE are counted twice
+
+ RETURN VALUE:
+ true.............descriptor has been added
+ false............an exception has been thrown
+
+*******************************************************************************/
+
+bool
+descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
+{
+ u4 key,slot;
+ descriptor_hash_entry *d;
+ char *utf_ptr;
+ char *end_pos;
+ utf *name;
+ s4 argcount = 0;
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
+ utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
+#endif
+
+ assert(pool);
+ assert(desc);
+
+ /* find a place in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ /* Save all method descriptors in the hashtable, since the parsed */
+ /* descriptor may vary between differenf methods (static vs. non-static). */
+
+ utf_ptr = desc->text;
+
+ if (*utf_ptr != '(') {
+ while (d) {
+ if (d->desc == desc) {
+ if (paramslots)
+ *paramslots = d->paramslots;
+ return true; /* already stored */
+ }
+ d = d->hashlink;
+ }
+ }
+
+ /* add the descriptor to the pool */
+
+ d = DNEW(descriptor_hash_entry);
+ d->desc = desc;
+ d->parseddesc.any = NULL;
+ d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+ pool->descriptorhash.ptr[slot] = d;
+
+ /* now check the descriptor */
+
+ end_pos = UTF_END(desc);
+
+ if (*utf_ptr == '(') {
+ /* a method descriptor */
+
+ pool->methodcount++;
+ utf_ptr++;
+
+ /* check arguments */
+
+ while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
+ pool->paramcount++;
+
+ /* We cannot count the `this' argument here because
+ * we don't know if the method is static. */
+
+ if (*utf_ptr == 'J' || *utf_ptr == 'D')
+ argcount += 2;
+ else
+ argcount++;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
+ DESCRIPTOR_NOVOID, &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool, name))
+ return false;
+ }
+
+ if (utf_ptr == end_pos) {
+ exceptions_throw_classformaterror(pool->referer,
+ "Missing ')' in method descriptor");
+ return false;
+ }
+
+ utf_ptr++; /* skip ')' */
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+ DESCRIPTOR_CHECKEND, &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
+
+ if (argcount > 255) {
+ exceptions_throw_classformaterror(pool->referer,
+ "Too many arguments in signature");
+ return false;
+ }
+
+ } else {
+ /* a field descriptor */
+
+ pool->fieldcount++;
+
+ if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
+ DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
+ &name))
+ return false;
+
+ if (name)
+ if (!descriptor_pool_add_class(pool,name))
+ return false;
+ }
+
+ d->paramslots = argcount;
+
+ if (paramslots)
+ *paramslots = argcount;
+
+ return true;
+}
+
+
+/* descriptor_pool_create_classrefs ********************************************
+
+ Create a table containing all the classrefs which were added to the pool
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *count...........if count is non-NULL, this is set to the number
+ of classrefs in the table
+
+ RETURN VALUE:
+ a pointer to the constant_classref table
+
+*******************************************************************************/
+
+constant_classref *
+descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
+{
+ u4 nclasses;
+ u4 slot;
+ classref_hash_entry *c;
+ constant_classref *ref;
+
+ assert(pool);
+
+ nclasses = pool->classrefhash.entries;
+ pool->classrefs = MNEW(constant_classref,nclasses);
+
+ /* fill the constant_classref structs */
+
+ for (slot = 0; slot < pool->classrefhash.size; ++slot) {
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ while (c) {
+ ref = pool->classrefs + c->index;
+ CLASSREF_INIT(*ref, pool->referer, c->name);
+ c = c->hashlink;
+ }
+ }
+
+ if (count)
+ *count = nclasses;
+
+ return pool->classrefs;
+}
+
+
+/* descriptor_pool_lookup_classref *********************************************
+
+ Return the constant_classref for the given class name
+
+ IN:
+ pool.............the descriptor_pool
+ classname........name of the class to look up
+
+ RETURN VALUE:
+ a pointer to the constant_classref, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+constant_classref *
+descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
+{
+ u4 key,slot;
+ classref_hash_entry *c;
+
+ assert(pool);
+ assert(pool->classrefs);
+ assert(classname);
+
+ key = utf_hashkey(classname->text, classname->blength);
+ slot = key & (pool->classrefhash.size - 1);
+ c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+
+ while (c) {
+ if (c->name == classname)
+ return pool->classrefs + c->index;
+ c = c->hashlink;
+ }
+
+ exceptions_throw_internalerror("Class reference not found in descriptor pool");
+ return NULL;
+}
+
+
+/* descriptor_pool_alloc_parsed_descriptors ************************************
+
+ Allocate space for the parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ NOTE:
+ This function must be called after all descriptors have been added
+ with descriptor_pool_add.
+
+*******************************************************************************/
+
+void
+descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
+{
+ u4 size;
+
+ assert(pool);
+
+ /* TWISTI: paramcount + 1: we don't know if the method is static or */
+ /* not, i have no better solution yet. */
+
+ size =
+ pool->fieldcount * sizeof(typedesc) +
+ pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
+ pool->paramcount * sizeof(typedesc) +
+ pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
+
+ pool->descriptorsize = size;
+ if (size) {
+ pool->descriptors = MNEW(u1, size);
+ pool->descriptors_next = pool->descriptors;
+ }
+
+ size = pool->fieldcount + pool->methodcount;
+ if (size) {
+ pool->descriptor_kind = DMNEW(u1, size);
+ pool->descriptor_kind_next = pool->descriptor_kind;
+ }
+}
+
+
+/* descriptor_pool_parse_field_descriptor **************************************
+
+ Parse the given field descriptor
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the field descriptor
+
+ RETURN VALUE:
+ a pointer to the parsed field descriptor, or
+ NULL if an exception has been thrown
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called (once)
+ before this function is used.
+
+*******************************************************************************/
+
+typedesc *
+descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
+{
+ u4 key,slot;
+ descriptor_hash_entry *d;
+ typedesc *td;
+
+ assert(pool);
+ assert(pool->descriptors);
+ assert(pool->descriptors_next);
+
+ /* lookup the descriptor in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ while (d) {
+ if (d->desc == desc) {
+ /* found */
+ if (d->parseddesc.fd)
+ return d->parseddesc.fd;
+ break;
+ }
+ d = d->hashlink;
+ }
+
+ assert(d);
+
+ if (desc->text[0] == '(') {
+ exceptions_throw_classformaterror(pool->referer,
+ "Method descriptor used in field reference");
+ return NULL;
+ }
+
+ td = (typedesc *) pool->descriptors_next;
+ pool->descriptors_next += sizeof(typedesc);
+
+ if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
+ return NULL;
+
+ *(pool->descriptor_kind_next++) = 'f';
+
+ d->parseddesc.fd = td;
+
+ return td;
+}
+
+
+/* descriptor_pool_parse_method_descriptor *************************************
+
+ Parse the given method descriptor
+
+ IN:
+ pool.............the descriptor_pool
+ desc.............the method descriptor
+ mflags...........the method flags
+ thisclass........classref to the class containing the method.
+ This is ignored if mflags contains ACC_STATIC.
+ The classref is stored for inserting the 'this' argument.
+
+ RETURN VALUE:
+ a pointer to the parsed method descriptor, or
+ NULL if an exception has been thrown
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called
+ (once) before this function is used.
+
+*******************************************************************************/
+
+methoddesc *
+descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
+ s4 mflags,constant_classref *thisclass)
+{
+ u4 key, slot;
+ descriptor_hash_entry *d;
+ methoddesc *md;
+ typedesc *td;
+ char *utf_ptr;
+ char *end_pos;
+ s2 paramcount = 0;
+ s2 paramslots = 0;
+
+#ifdef DESCRIPTOR_VERBOSE
+ fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
+ (void*)pool,(int)mflags,(void*)thisclass);
+ utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
+#endif
+
+ assert(pool);
+ assert(pool->descriptors);
+ assert(pool->descriptors_next);
+
+ /* check that it is a method descriptor */
+
+ if (desc->text[0] != '(') {
+ exceptions_throw_classformaterror(pool->referer,
+ "Field descriptor used in method reference");
+ return NULL;
+ }
+
+ /* lookup the descriptor in the hashtable */
+
+ key = utf_hashkey(desc->text, desc->blength);
+ slot = key & (pool->descriptorhash.size - 1);
+ d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+
+ /* find an un-parsed descriptor */
+
+ while (d) {
+ if (d->desc == desc)
+ if (!d->parseddesc.md)
+ break;
+ d = d->hashlink;
+ }
+
+ assert(d);
+
+ md = (methoddesc *) pool->descriptors_next;
+ pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
+
+ utf_ptr = desc->text + 1; /* skip '(' */
+ end_pos = UTF_END(desc);
+
+ td = md->paramtypes;
+
+ /* count the `this' pointer */
+
+ if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ td->classref = thisclass;
+
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ paramcount++;
+ paramslots++;
+ }
+
+ while (*utf_ptr != ')') {
+ /* parse a parameter type */
+
+ if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
+ return NULL;
+
+ if (IS_2_WORD_TYPE(td->type))
+ paramslots++;
+
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ paramcount++;
+ paramslots++;
+ }
+ utf_ptr++; /* skip ')' */
+
+ /* Skip possible `this' pointer in paramtypes array to allow a possible */
+ /* memory move later in parse. */
+ /* We store the thisclass reference, so we can later correctly fill in */
+ /* the parameter slot of the 'this' argument. */
+
+ if (mflags == ACC_UNDEF) {
+ td->classref = thisclass;
+ td++;
+ pool->descriptors_next += sizeof(typedesc);
+ }
+
+ /* parse return type */
+
+ if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
+ &(md->returntype)))
+ return NULL;
+
+ md->paramcount = paramcount;
+ md->paramslots = paramslots;
+
+ /* If mflags != ACC_UNDEF we parse a real loaded method, so do
+ param prealloc. Otherwise we do this in stack analysis. */
+
+ if (mflags != ACC_UNDEF) {
+ if (md->paramcount > 0) {
+ /* allocate memory for params */
+
+ md->params = MNEW(paramdesc, md->paramcount);
+ }
+ else {
+ md->params = METHODDESC_NOPARAMS;
+ }
+
+ /* fill the paramdesc */
+ /* md_param_alloc has to be called if md->paramcount == 0,
+ too, so it can make the reservation for the Linkage Area,
+ Return Register... */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ {
+ /* As builtin-functions are native functions, we have
+ to pre-allocate for the native ABI. */
+
+ if (mflags & ACC_METHOD_BUILTIN)
+ md_param_alloc_native(md);
+ else
+ md_param_alloc(md);
+ }
+#endif
+ }
+ else {
+ /* params will be allocated later by
+ descriptor_params_from_paramtypes if necessary */
+
+ md->params = NULL;
+ }
+
+ *(pool->descriptor_kind_next++) = 'm';
+
+ d->parseddesc.md = md;
+
+ return md;
+}
+
+/* descriptor_params_from_paramtypes *******************************************
+
+ Create the paramdescs for a method descriptor. This function is called
+ when we know whether the method is static or not. This function may only
+ be called once for each methoddesc, and only if md->params == NULL.
+
+ IN:
+ md...............the parsed method descriptor
+ md->params MUST be NULL.
+ mflags...........the ACC_* access flags of the method. Only the
+ ACC_STATIC bit is checked.
+ The value ACC_UNDEF is NOT allowed.
+
+ RETURN VALUE:
+ true.............the paramdescs were created successfully
+ false............an exception has been thrown
+
+ POSTCONDITION:
+ md->parms != NULL
+
+*******************************************************************************/
+
+bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
+{
+ typedesc *td;
+
+ assert(md);
+ assert(md->params == NULL);
+ assert(mflags != ACC_UNDEF);
+
+ td = md->paramtypes;
+
+ /* check for `this' pointer */
+
+ if (!(mflags & ACC_STATIC)) {
+ constant_classref *thisclass;
+
+ /* fetch class reference from reserved param slot */
+ thisclass = td[md->paramcount].classref;
+ assert(thisclass);
+
+ if (md->paramcount > 0) {
+ /* shift param types by 1 argument */
+ MMOVE(td + 1, td, typedesc, md->paramcount);
+ }
+
+ /* fill in first argument `this' */
+
+ td->type = TYPE_ADR;
+ td->primitivetype = TYPE_ADR;
+ td->arraydim = 0;
+ td->classref = thisclass;
+
+ md->paramcount++;
+ md->paramslots++;
+ }
+
+ /* if the method has params, process them */
+
+ if (md->paramcount > 0) {
+ /* allocate memory for params */
+
+ md->params = MNEW(paramdesc, md->paramcount);
+
+ } else {
+ md->params = METHODDESC_NOPARAMS;
+ }
+
+ /* fill the paramdesc */
+ /* md_param_alloc has to be called if md->paramcount == 0, too, so
+ it can make the reservation for the Linkage Area, Return
+ Register.. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (!opt_intrp)
+# endif
+ {
+ /* As builtin-functions are native functions, we have to
+ pre-allocate for the native ABI. */
+
+ if (mflags & ACC_METHOD_BUILTIN)
+ md_param_alloc_native(md);
+ else
+ md_param_alloc(md);
+ }
+#endif
+
+ return true;
+}
+
+
+/* descriptor_pool_get_parsed_descriptors **************************************
+
+ Return a pointer to the block of parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *size............if size is non-NULL, this is set to the size of the
+ parsed descriptor block (in u1)
+
+ RETURN VALUE:
+ a pointer to the block of parsed descriptors
+
+ NOTE:
+ descriptor_pool_alloc_parsed_descriptors must be called (once)
+ before this function is used.
+
+*******************************************************************************/
+
+void *
+descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
+{
+ assert(pool);
+ assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+
+ if (size)
+ *size = pool->descriptorsize;
+
+ return pool->descriptors;
+}
+
+
+/* descriptor_pool_get_sizes ***************************************************
+
+ Get the sizes of the class reference table and the parsed descriptors
+
+ IN:
+ pool.............the descriptor_pool
+
+ OUT:
+ *classrefsize....set to size of the class reference table
+ *descsize........set to size of the parsed descriptors
+
+ NOTE:
+ This function may only be called after both
+ descriptor_pool_create_classrefs, and
+ descriptor_pool_alloc_parsed_descriptors
+ have been called.
+
+*******************************************************************************/
+
+void
+descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
+{
+ assert(pool);
+ assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
+ assert(pool->classrefs);
+ assert(classrefsize);
+ assert(descsize);
+
+ *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
+ *descsize = pool->descriptorsize;
+}
+
+
+/****************************************************************************/
+/* DEBUG HELPERS */
+/****************************************************************************/
+
+#ifndef NDEBUG
+/* descriptor_debug_print_typedesc *********************************************
+
+ Print the given typedesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parsed descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_typedesc(FILE *file,typedesc *d)
+{
+ int ch;
+
+ if (!d) {
+ fprintf(file,"(typedesc *)NULL");
+ return;
+ }
+
+ if (d->type == TYPE_ADR) {
+ if (d->classref)
+ utf_fprint_printable_ascii(file,d->classref->name);
+ else
+ fprintf(file,"<class=NULL>");
+ }
+ else {
+ switch (d->primitivetype) {
+ case PRIMITIVETYPE_INT : ch='I'; break;
+ case PRIMITIVETYPE_CHAR : ch='C'; break;
+ case PRIMITIVETYPE_BYTE : ch='B'; break;
+ case PRIMITIVETYPE_SHORT : ch='S'; break;
+ case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
+ case PRIMITIVETYPE_LONG : ch='J'; break;
+ case PRIMITIVETYPE_FLOAT : ch='F'; break;
+ case PRIMITIVETYPE_DOUBLE : ch='D'; break;
+ case PRIMITIVETYPE_VOID : ch='V'; break;
+ default : ch='!';
+ }
+ fputc(ch,file);
+ }
+ if (d->arraydim)
+ fprintf(file,"[%d]",d->arraydim);
+}
+
+/* descriptor_debug_print_paramdesc ********************************************
+
+ Print the given paramdesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parameter descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
+{
+ if (!d) {
+ fprintf(file,"(paramdesc *)NULL");
+ return;
+ }
+
+ if (d->inmemory) {
+ fprintf(file,"<m%d>",d->regoff);
+ }
+ else {
+ fprintf(file,"<r%d>",d->regoff);
+ }
+}
+
+/* descriptor_debug_print_methoddesc *******************************************
+
+ Print the given methoddesc to the given stream
+
+ IN:
+ file.............stream to print to
+ d................the parsed descriptor
+
+*******************************************************************************/
+
+void
+descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
+{
+ int i;
+
+ if (!d) {
+ fprintf(file,"(methoddesc *)NULL");
+ return;
+ }
+
+ fputc('(',file);
+ for (i=0; i<d->paramcount; ++i) {
+ if (i)
+ fputc(',',file);
+ descriptor_debug_print_typedesc(file,d->paramtypes + i);
+ if (d->params) {
+ descriptor_debug_print_paramdesc(file,d->params + i);
+ }
+ }
+ if (d->params == METHODDESC_NOPARAMS)
+ fputs("<NOPARAMS>",file);
+ fputc(')',file);
+ descriptor_debug_print_typedesc(file,&(d->returntype));
+}
+
+/* descriptor_pool_debug_dump **************************************************
+
+ Print the state of the descriptor_pool to the given stream
+
+ IN:
+ pool.............the descriptor_pool
+ file.............stream to print to
+
+*******************************************************************************/
+
+void
+descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
+{
+ u4 slot;
+ u1 *pos;
+ u1 *kind;
+ u4 size;
+
+ fprintf(file,"======[descriptor_pool for ");
+ utf_fprint_printable_ascii(file,pool->referer->name);
+ fprintf(file,"]======\n");
+
+ fprintf(file,"fieldcount: %d\n",pool->fieldcount);
+ fprintf(file,"methodcount: %d\n",pool->methodcount);
+ fprintf(file,"paramcount: %d\n",pool->paramcount);
+ fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
+ fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
+ fprintf(file,"classrefsize: %d bytes\n",
+ (int)(pool->classrefhash.entries * sizeof(constant_classref)));
+
+ fprintf(file,"class references:\n");
+ for (slot=0; slot<pool->classrefhash.size; ++slot) {
+ classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
+ while (c) {
+ fprintf(file," %4d: ",c->index);
+ utf_fprint_printable_ascii(file,c->name);
+ fprintf(file,"\n");
+ c = c->hashlink;
+ }
+ }
+
+ fprintf(file,"hashed descriptors:\n");
+ for (slot=0; slot<pool->descriptorhash.size; ++slot) {
+ descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
+ while (c) {
+ fprintf(file," %p: ",c->parseddesc.any);
+ utf_fprint_printable_ascii(file,c->desc);
+ fprintf(file,"\n");
+ c = c->hashlink;
+ }
+ }
+
+ fprintf(file,"descriptors:\n");
+ if (pool->descriptors) {
+ pos = pool->descriptors;
+ size = pool->descriptors_next - pool->descriptors;
+ fprintf(file," size: %d bytes\n",size);
+
+ if (pool->descriptor_kind) {
+ kind = pool->descriptor_kind;
+
+ while (pos < (pool->descriptors + size)) {
+ fprintf(file," %p: ",pos);
+ switch (*kind++) {
+ case 'f':
+ descriptor_debug_print_typedesc(file,(typedesc*)pos);
+ pos += sizeof(typedesc);
+ break;
+ case 'm':
+ descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
+ pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
+ pos += sizeof(methoddesc) - sizeof(typedesc);
+ break;
+ default:
+ fprintf(file,"INVALID KIND");
+ }
+ fputc('\n',file);
+ }
+ }
+ else {
+ while (size >= sizeof(void*)) {
+ fprintf(file," %p\n",*((void**)pos));
+ pos += sizeof(void*);
+ size -= sizeof(void*);
+ }
+ }
+ }
+
+ fprintf(file,"==========================================================\n");
+}
+#endif /* !defined(NDEBUG) */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+
--- /dev/null
+/* src/vm/descriptor.h - checking and parsing of field / method descriptors
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _DESCRIPTOR_H
+#define _DESCRIPTOR_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct descriptor_pool descriptor_pool;
+typedef struct typedesc typedesc;
+typedef struct paramdesc paramdesc;
+typedef struct methoddesc methoddesc;
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/utf8.h"
+
+#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */
+
+
+/* data structures ************************************************************/
+
+/*----------------------------------------------------------------------------*/
+/* Descriptor Pools */
+/* */
+/* A descriptor_pool is a temporary data structure used during loading of */
+/* a class. The descriptor_pool is used to allocate the table of */
+/* constant_classrefs the class uses, and for parsing the field and method */
+/* descriptors which occurr within the class. The inner workings of */
+/* descriptor_pool are not important for outside code. */
+/* */
+/* You use a descriptor_pool as follows: */
+/* */
+/* 1. create one with descriptor_pool_new */
+/* 2. add all explicit class references with descriptor_pool_add_class */
+/* 3. add all field/method descriptors with descriptor_pool_add */
+/* 4. call descriptor_pool_create_classrefs */
+/* You can now lookup classrefs with descriptor_pool_lookup_classref */
+/* 5. call descriptor_pool_alloc_parsed_descriptors */
+/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */
+/* for each method descriptor call descriptor_pool_parse_method_descriptor */
+/* 7. call descriptor_pool_get_parsed_descriptors */
+/* */
+/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */
+/* memory which can be thrown away when the steps above have been */
+/* done. */
+/*----------------------------------------------------------------------------*/
+
+struct descriptor_pool {
+ classinfo *referer;
+ u4 fieldcount;
+ u4 methodcount;
+ u4 paramcount;
+ u4 descriptorsize;
+ u1 *descriptors;
+ u1 *descriptors_next;
+ hashtable descriptorhash;
+ constant_classref *classrefs;
+ hashtable classrefhash;
+ u1 *descriptor_kind; /* useful for debugging */
+ u1 *descriptor_kind_next; /* useful for debugging */
+};
+
+
+/* data structures for parsed field/method descriptors ************************/
+
+struct typedesc {
+ constant_classref *classref; /* class reference for TYPE_ADR types */
+ u1 type; /* TYPE_??? constant [1] */
+ u1 primitivetype; /* (PRIMITIVE)TYPE_??? constant [2] */
+ u1 arraydim; /* array dimension (0 if no array) */
+};
+
+/* [1]...the type field contains the basic type used within the VM. So ints, */
+/* shorts, chars, bytes, booleans all have TYPE_INT. */
+/* [2]...the primitivetype field contains the declared type. */
+/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */
+/* For non-primitive types primitivetype is TYPE_ADR. */
+
+struct paramdesc {
+#if defined(__MIPS__)
+ u1 type; /* TYPE_??? of the register allocated */
+#endif
+ bool inmemory; /* argument in register or on stack */
+ uint32_t index; /* index into argument register array */
+ uint32_t regoff; /* register index or stack offset */
+};
+
+struct methoddesc {
+ s2 paramcount; /* number of parameters */
+ s2 paramslots; /* like above but LONG,DOUBLE count twice */
+ s4 argintreguse; /* number of used integer argument registers */
+ s4 argfltreguse; /* number of used float argument registers */
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+ s4 argadrreguse; /* number of used address registers */
+#endif
+ s4 memuse; /* number of stack slots used */
+ paramdesc *params; /* allocated parameter descriptions [3] */
+ typedesc returntype; /* parsed descriptor of the return type */
+ typedesc paramtypes[1]; /* parameter types, variable length! */
+};
+
+/* [3]...If params is NULL, the parameter descriptions have not yet been */
+/* allocated. In this case ___the possible 'this' pointer of the method */
+/* is NOT counted in paramcount/paramslots and it is NOT included in */
+/* the paramtypes array___. */
+/* If params != NULL, the parameter descriptions have been */
+/* allocated, and the 'this' pointer of the method, if any, IS included.*/
+/* In case the method has no parameters at all, the special value */
+/* METHODDESC_NO_PARAMS is used (see below). */
+
+/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */
+/* indicating that the method is a static method without any parameters. */
+/* This special value must be != NULL and it may only be set if */
+/* md->paramcount == 0. */
+
+#define METHODDESC_NOPARAMS ((paramdesc*)1)
+
+/* function prototypes ********************************************************/
+
+descriptor_pool * descriptor_pool_new(classinfo *referer);
+
+bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
+bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots);
+
+int descriptor_to_basic_type(utf *desc);
+int descriptor_typesize(typedesc *td);
+
+constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool,
+ s4 *count);
+constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname);
+
+void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool);
+
+typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc);
+methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags,
+ constant_classref *thisclass);
+
+bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags);
+
+void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size);
+void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize,
+ u4 *descsize);
+
+#ifndef NDEBUG
+void descriptor_debug_print_typedesc(FILE *file,typedesc *d);
+void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d);
+void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d);
+void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
+#endif /* !defined(NDEBUG) */
+
+#endif /* _DESCRIPTOR_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "toolbox/util.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trace.hpp"
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
-
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
#endif
#include "vm/types.h"
#include "vm/global.h"
-
-#include "vmcore/references.h"
-#include "vmcore/method.h"
+#include "vm/references.h"
+#include "vm/method.h"
/* function prototypes ********************************************************/
--- /dev/null
+/* src/vm/field.c - field functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "vm/types.h"
+
+#include "vm/annotation.h"
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/descriptor.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/references.h"
+#include "vm/string.hpp"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/* field_load ******************************************************************
+
+ Load everything about a class field from the class file and fill a
+ fieldinfo structure.
+
+*******************************************************************************/
+
+#define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
+
+bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
+{
+ classinfo *c;
+ u4 attrnum, i;
+ u4 pindex = field_load_NOVALUE; /* constantvalue_index */
+ utf *u;
+
+ /* Get class. */
+
+ c = cb->clazz;
+
+ f->clazz = c;
+
+ /* Get access flags. */
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
+ return false;
+
+ f->flags = suck_u2(cb);
+
+ /* Get name. */
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ f->name = u;
+
+ /* Get descriptor. */
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ f->descriptor = u;
+ f->parseddesc = NULL;
+
+ if (!descriptor_pool_add(descpool, u, NULL))
+ return false;
+
+ /* descriptor_pool_add accepts method descriptors, so we have to
+ check against them here before the call of
+ descriptor_to_basic_type below. */
+
+ if (u->text[0] == '(') {
+ exceptions_throw_classformaterror(c, "Method descriptor used for field");
+ return false;
+ }
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ /* check name */
+ if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
+ exceptions_throw_classformaterror(c,
+ "Illegal Field name \"%s\"",
+ f->name->text);
+ return false;
+ }
+
+ /* check flag consistency */
+ i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
+
+ if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
+ ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
+ exceptions_throw_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
+ return false;
+ }
+
+ if (c->flags & ACC_INTERFACE) {
+ if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
+ != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
+ f->flags & ACC_TRANSIENT) {
+ exceptions_throw_classformaterror(c,
+ "Illegal field modifiers: 0x%X",
+ f->flags);
+ return false;
+ }
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* data type */
+
+ f->type = descriptor_to_basic_type(f->descriptor);
+
+ /* For static-fields allocate memory for the value and set the
+ value to 0. */
+
+ if (f->flags & ACC_STATIC) {
+ switch (f->type) {
+ case TYPE_INT:
+ case TYPE_LNG:
+ case TYPE_FLT:
+ case TYPE_DBL:
+ f->value = NEW(imm_union);
+ break;
+
+ case TYPE_ADR:
+#if !defined(ENABLE_GC_BOEHM)
+ f->value = NEW(imm_union);
+#else
+ f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
+#endif
+ break;
+
+ default:
+ vm_abort("field_load: invalid field type %d", f->type);
+ }
+
+ /* Set the field to zero, for float and double fields set the
+ correct 0.0 value. */
+
+ switch (f->type) {
+ case TYPE_INT:
+ case TYPE_LNG:
+ case TYPE_ADR:
+ f->value->l = 0;
+ break;
+
+ case TYPE_FLT:
+ f->value->f = 0.0;
+ break;
+
+ case TYPE_DBL:
+ f->value->d = 0.0;
+ break;
+ }
+ }
+ else {
+ /* For instance-fields set the offset to 0. */
+
+ f->offset = 0;
+
+ /* For final fields, which are not static, we need a value
+ structure. */
+
+ if (f->flags & ACC_FINAL) {
+ f->value = NEW(imm_union);
+ /* XXX hack */
+ f->value->l = 0;
+ }
+
+ switch (f->type) {
+ case TYPE_ADR:
+ c->flags |= ACC_CLASS_HAS_POINTERS;
+ break;
+ }
+ }
+
+ /* read attributes */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ attrnum = suck_u2(cb);
+
+ for (i = 0; i < attrnum; i++) {
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
+ return false;
+
+ if (u == utf_ConstantValue) {
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* check attribute length */
+
+ if (suck_u4(cb) != 2) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ /* constant value attribute */
+
+ if (pindex != field_load_NOVALUE) {
+ exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
+ return false;
+ }
+
+ /* index of value in constantpool */
+
+ pindex = suck_u2(cb);
+
+ /* initialize field with value from constantpool */
+
+ switch (f->type) {
+ case TYPE_INT: {
+ constant_integer *ci;
+
+ if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
+ return false;
+
+ f->value->i = ci->value;
+ }
+ break;
+
+ case TYPE_LNG: {
+ constant_long *cl;
+
+ if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
+ return false;
+
+ f->value->l = cl->value;
+ }
+ break;
+
+ case TYPE_FLT: {
+ constant_float *cf;
+
+ if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
+ return false;
+
+ f->value->f = cf->value;
+ }
+ break;
+
+ case TYPE_DBL: {
+ constant_double *cd;
+
+ if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
+ return false;
+
+ f->value->d = cd->value;
+ }
+ break;
+
+ case TYPE_ADR:
+ if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
+ return false;
+
+ /* Create Java-string from compressed UTF8-string. */
+
+ f->value->a = literalstring_new(u);
+ break;
+
+ default:
+ vm_abort("field_load: invalid field type %d", f->type);
+ }
+ }
+#if defined(ENABLE_JAVASE)
+ else if (u == utf_Signature) {
+ /* Signature */
+
+ if (!loader_load_attribute_signature(cb, &(f->signature)))
+ return false;
+ }
+
+#if defined(ENABLE_ANNOTATIONS)
+ else if (u == utf_RuntimeVisibleAnnotations) {
+ /* RuntimeVisibleAnnotations */
+ if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
+ return false;
+ }
+ else if (u == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
+ return false;
+ }
+#endif
+#endif
+ else {
+ /* unknown attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+
+ /* everything was ok */
+
+ return true;
+}
+
+
+/* field_get_type **************************************************************
+
+ Returns the type of the field as class.
+
+*******************************************************************************/
+
+classinfo *field_get_type(fieldinfo *f)
+{
+ typedesc *td;
+ utf *u;
+ classinfo *c;
+
+ td = f->parseddesc;
+
+ if (td->type == TYPE_ADR) {
+ assert(td->classref);
+
+ u = td->classref->name;
+
+ /* load the class of the field-type with the field's
+ classloader */
+
+ c = load_class_from_classloader(u, f->clazz->classloader);
+ }
+ else {
+ c = Primitive_get_class_by_type(td->primitivetype);
+ }
+
+ return c;
+}
+
+
+/* field_free ******************************************************************
+
+ Frees a fields' resources.
+
+*******************************************************************************/
+
+void field_free(fieldinfo *f)
+{
+ /* free memory for fields which have a value */
+
+ if (f->value)
+#if defined(ENABLE_GC_BOEHM)
+ if (f->type != TYPE_ADR)
+#endif
+ FREE(f->value, imm_union);
+}
+
+
+/* field_get_annotations ******************************************************
+
+ Get a fields' unparsed annotations in a byte array.
+
+ IN:
+ f........the field of which the annotations should be returned
+
+ RETURN VALUE:
+ The unparsed annotations in a byte array (or NULL if there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* declaring class */
+ int slot; /* slot of this field */
+ java_handle_bytearray_t *annotations; /* unparsed annotations */
+ java_handle_t *field_annotations; /* array of unparsed */
+ /* annotations of all fields of the declaring class */
+
+ c = f->clazz;
+ slot = f - c->fields;
+ annotations = NULL;
+
+ LLNI_classinfo_field_get(c, field_annotations, field_annotations);
+
+ /* the field_annotations array might be shorter then the field
+ * count if the fields above a certain index have no annotations.
+ */
+ if (field_annotations != NULL &&
+ array_length_get(field_annotations) > slot) {
+ annotations = (java_handle_bytearray_t*)array_objectarray_element_get(
+ (java_handle_objectarray_t*)field_annotations, slot);
+ }
+
+ return annotations;
+#else
+ return NULL;
+#endif
+}
+
+
+/* field_printflags ************************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_printflags(fieldinfo *f)
+{
+ if (f == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
+ if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
+ if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
+ if (f->flags & ACC_STATIC) printf(" STATIC");
+ if (f->flags & ACC_FINAL) printf(" FINAL");
+ if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (f->flags & ACC_NATIVE) printf(" NATIVE");
+ if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (f->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+}
+#endif
+
+
+/* field_print *****************************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_print(fieldinfo *f)
+{
+ if (f == NULL) {
+ printf("(fieldinfo*)NULL");
+ return;
+ }
+
+ utf_display_printable_ascii_classname(f->clazz->name);
+ printf(".");
+ utf_display_printable_ascii(f->name);
+ printf(" ");
+ utf_display_printable_ascii(f->descriptor);
+
+ field_printflags(f);
+
+ if (!(f->flags & ACC_STATIC)) {
+ printf(", offset: %d", f->offset);
+ }
+}
+#endif
+
+
+/* field_println ***************************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_println(fieldinfo *f)
+{
+ field_print(f);
+ printf("\n");
+}
+#endif
+
+/* field_fieldref_print ********************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_fieldref_print(constant_FMIref *fr)
+{
+ if (fr == NULL) {
+ printf("(constant_FMIref *)NULL");
+ return;
+ }
+
+ if (IS_FMIREF_RESOLVED(fr)) {
+ printf("<field> ");
+ field_print(fr->p.field);
+ }
+ else {
+ printf("<fieldref> ");
+ utf_display_printable_ascii_classname(fr->p.classref->name);
+ printf(".");
+ utf_display_printable_ascii(fr->name);
+ printf(" ");
+ utf_display_printable_ascii(fr->descriptor);
+ }
+}
+#endif
+
+/* field_fieldref_println ******************************************************
+
+ (debugging only)
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void field_fieldref_println(constant_FMIref *fr)
+{
+ field_fieldref_print(fr);
+ printf("\n");
+}
+#endif
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/field.h - field functions header
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _FIELD_H
+#define _FIELD_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct fieldinfo fieldinfo;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/descriptor.h"
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/references.h"
+#include "vm/utf8.h"
+
+
+/* fieldinfo ******************************************************************/
+
+struct fieldinfo { /* field of a class */
+
+ /* CAUTION: The first field must be a pointer that is never the same */
+ /* value as CLASSREF_PSEUDO_VFTBL! This is used to check whether */
+ /* a constant_FMIref has been resolved. */
+
+ classinfo *clazz; /* needed by typechecker. Could be optimized */
+ /* away by using constant_FMIref instead of */
+ /* fieldinfo throughout the compiler. */
+
+ s4 flags; /* ACC flags */
+ s4 type; /* basic data type */
+ utf *name; /* name of field */
+ utf *descriptor;/* JavaVM descriptor string of field */
+ utf *signature; /* Signature attribute string */
+ typedesc *parseddesc;/* parsed descriptor */
+
+ int32_t offset; /* offset from start of object (instance variables) */
+ imm_union *value; /* storage for static values (class variables) */
+};
+
+
+/* function prototypes ********************************************************/
+
+bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool);
+classinfo *field_get_type(fieldinfo *f);
+void field_free(fieldinfo *f);
+
+java_handle_bytearray_t *field_get_annotations(fieldinfo *f);
+
+#if !defined(NDEBUG)
+void field_printflags(fieldinfo *f);
+void field_print(fieldinfo *f);
+void field_println(fieldinfo *f);
+void field_fieldref_print(constant_FMIref *fr);
+void field_fieldref_println(constant_FMIref *fr);
+#endif
+
+#endif /* _FIELD_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vmcore/options.h"
-
/* global variables ***********************************************************/
--- /dev/null
+/* src/vm/globals.cpp - global variables
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/class.h"
+
+
+// Classes.
+
+/* Important system classes. */
+
+classinfo *class_java_lang_Object;
+classinfo *class_java_lang_Class;
+classinfo *class_java_lang_ClassLoader;
+classinfo *class_java_lang_Cloneable;
+classinfo *class_java_lang_SecurityManager;
+classinfo *class_java_lang_String;
+classinfo *class_java_lang_System;
+classinfo *class_java_lang_Thread;
+classinfo *class_java_lang_ThreadGroup;
+classinfo *class_java_lang_Throwable;
+classinfo *class_java_io_Serializable;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_java_lang_VMSystem;
+classinfo *class_java_lang_VMThread;
+classinfo *class_java_lang_VMThrowable;
+#endif
+
+/* Important system exceptions. */
+
+classinfo *class_java_lang_Exception;
+classinfo *class_java_lang_ClassNotFoundException;
+classinfo *class_java_lang_RuntimeException;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+classinfo *class_sun_misc_Signal;
+classinfo *class_sun_reflect_MagicAccessorImpl;
+#endif
+
+#if defined(ENABLE_JAVASE)
+classinfo *class_java_lang_Void;
+#endif
+classinfo *class_java_lang_Boolean;
+classinfo *class_java_lang_Byte;
+classinfo *class_java_lang_Character;
+classinfo *class_java_lang_Short;
+classinfo *class_java_lang_Integer;
+classinfo *class_java_lang_Long;
+classinfo *class_java_lang_Float;
+classinfo *class_java_lang_Double;
+
+/* some classes which may be used more often */
+
+#if defined(ENABLE_JAVASE)
+classinfo *class_java_lang_StackTraceElement;
+classinfo *class_java_lang_reflect_Constructor;
+classinfo *class_java_lang_reflect_Field;
+classinfo *class_java_lang_reflect_Method;
+classinfo *class_java_security_PrivilegedAction;
+classinfo *class_java_util_Vector;
+classinfo *class_java_util_HashMap;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_java_lang_reflect_VMConstructor;
+classinfo *class_java_lang_reflect_VMField;
+classinfo *class_java_lang_reflect_VMMethod;
+# endif
+
+classinfo *arrayclass_java_lang_Object;
+
+# if defined(ENABLE_ANNOTATIONS)
+classinfo *class_sun_reflect_ConstantPool;
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+classinfo *class_sun_reflect_annotation_AnnotationParser;
+# endif
+# endif
+#endif
+
+/* pseudo classes for the typechecker */
+
+classinfo *pseudo_class_Arraystub;
+classinfo *pseudo_class_Null;
+classinfo *pseudo_class_New;
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/globals.hpp - global variables
+
+ Copyright (C) 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _GLOBALS_HPP
+#define _GLOBALS_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/class.h"
+
+
+// FIXME For now we export them a C symbols.
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Classes.
+
+/* Important system classes. */
+
+extern classinfo *class_java_lang_Object;
+extern classinfo *class_java_lang_Class;
+extern classinfo *class_java_lang_ClassLoader;
+extern classinfo *class_java_lang_Cloneable;
+extern classinfo *class_java_lang_SecurityManager;
+extern classinfo *class_java_lang_String;
+extern classinfo *class_java_lang_System;
+extern classinfo *class_java_lang_Thread;
+extern classinfo *class_java_lang_ThreadGroup;
+extern classinfo *class_java_lang_Throwable;
+extern classinfo *class_java_io_Serializable;
+
+/* Important system exceptions. */
+
+extern classinfo *class_java_lang_Exception;
+extern classinfo *class_java_lang_ClassNotFoundException;
+extern classinfo *class_java_lang_RuntimeException;
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern classinfo *class_java_lang_VMSystem;
+extern classinfo *class_java_lang_VMThread;
+extern classinfo *class_java_lang_VMThrowable;
+#endif
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+extern classinfo *class_sun_misc_Signal;
+extern classinfo *class_sun_reflect_MagicAccessorImpl;
+#endif
+
+#if defined(ENABLE_JAVASE)
+extern classinfo *class_java_lang_Void;
+#endif
+
+extern classinfo *class_java_lang_Boolean;
+extern classinfo *class_java_lang_Byte;
+extern classinfo *class_java_lang_Character;
+extern classinfo *class_java_lang_Short;
+extern classinfo *class_java_lang_Integer;
+extern classinfo *class_java_lang_Long;
+extern classinfo *class_java_lang_Float;
+extern classinfo *class_java_lang_Double;
+
+/* some classes which may be used more often */
+
+#if defined(ENABLE_JAVASE)
+extern classinfo *class_java_lang_StackTraceElement;
+extern classinfo *class_java_lang_reflect_Constructor;
+extern classinfo *class_java_lang_reflect_Field;
+extern classinfo *class_java_lang_reflect_Method;
+extern classinfo *class_java_security_PrivilegedAction;
+extern classinfo *class_java_util_Vector;
+extern classinfo *class_java_util_HashMap;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern classinfo *class_java_lang_reflect_VMConstructor;
+extern classinfo *class_java_lang_reflect_VMField;
+extern classinfo *class_java_lang_reflect_VMMethod;
+# endif
+
+extern classinfo *arrayclass_java_lang_Object;
+
+# if defined(ENABLE_ANNOTATIONS)
+extern classinfo *class_sun_reflect_ConstantPool;
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern classinfo *class_sun_reflect_annotation_AnnotationParser;
+# endif
+# endif
+#endif
+
+
+/* pseudo classes for the type checker ****************************************/
+
+/*
+ * pseudo_class_Arraystub
+ * (extends Object implements Cloneable, java.io.Serializable)
+ *
+ * If two arrays of incompatible component types are merged,
+ * the resulting reference has no accessible components.
+ * The result does, however, implement the interfaces Cloneable
+ * and java.io.Serializable. This pseudo class is used internally
+ * to represent such results. (They are *not* considered arrays!)
+ *
+ * pseudo_class_Null
+ *
+ * This pseudo class is used internally to represent the
+ * null type.
+ *
+ * pseudo_class_New
+ *
+ * This pseudo class is used internally to represent the
+ * the 'uninitialized object' type.
+ */
+
+extern classinfo *pseudo_class_Arraystub;
+extern classinfo *pseudo_class_Null;
+extern classinfo *pseudo_class_New;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _CLASS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
#include "threads/lock-common.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
-#include "vm/jit/asmpart.h"
-
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
+#include "vm/jit/asmpart.h"
+
/* private functions **********************************************************/
extern "C" {
#endif
+#include "vm/class.h"
#include "vm/global.h"
-#include "vmcore/class.h"
-
/* function prototypes ********************************************************/
--- /dev/null
+/* src/vm/javaobjects.cpp - functions to create and access Java objects
+
+ Copyright (C) 2008 Theobroma Systems Ltd.
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "native/vm/reflection.hpp"
+
+#include "vm/access.h"
+#include "vm/builtin.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/initialize.h"
+#include "vm/javaobjects.hpp"
+
+
+#if defined(ENABLE_JAVASE)
+
+/**
+ * Constructs a Java object with the given
+ * java.lang.reflect.Constructor.
+ *
+ * @param args Constructor arguments.
+ *
+ * @return Handle to Java object.
+ */
+java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarray_t* args)
+{
+ methodinfo* m = get_method();
+
+ // Should we bypass security the checks (AccessibleObject)?
+ if (get_override() == false) {
+ /* This method is always called like this:
+ [0] java.lang.reflect.Constructor.constructNative (Native Method)
+ [1] java.lang.reflect.Constructor.newInstance
+ [2] <caller>
+ */
+
+ if (!access_check_method(m, 2))
+ return NULL;
+ }
+
+ // Create a Java object.
+ java_handle_t* h = builtin_new(m->clazz);
+
+ if (h == NULL)
+ return NULL;
+
+ // Call initializer.
+ (void) Reflection::invoke(m, h, args);
+
+ return h;
+}
+
+
+/**
+ * Invokes the given method.
+ *
+ * @param args Method arguments.
+ *
+ * @return return value of the method
+ */
+java_handle_t* java_lang_reflect_Method::invoke(java_handle_t* o, java_handle_objectarray_t* args)
+{
+ methodinfo* m = get_method();
+
+ // Should we bypass security the checks (AccessibleObject)?
+ if (get_override() == false) {
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ /* This method is always called like this:
+ [0] java.lang.reflect.Method.invokeNative (Native Method)
+ [1] java.lang.reflect.Method.invoke (Method.java:329)
+ [2] <caller>
+ */
+
+ if (!access_check_method(m, 2))
+ return NULL;
+#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* We only pass 1 here as stacktrace_get_caller_class, which
+ is called from access_check_method, skips
+ java.lang.reflect.Method.invoke(). */
+
+ if (!access_check_method(m, 1))
+ return NULL;
+#else
+# error unknown classpath configuration
+#endif
+ }
+
+ // Check if method class is initialized.
+ if (!(m->clazz->state & CLASS_INITIALIZED))
+ if (!initialize_class(m->clazz))
+ return NULL;
+
+ // Call the Java method.
+ java_handle_t* result = Reflection::invoke(m, o, args);
+
+ return result;
+}
+
+
+// Legacy C interface.
+
+extern "C" {
+ java_handle_t* java_lang_reflect_Constructor_create(methodinfo* m) { return java_lang_reflect_Constructor(m).get_handle(); }
+ java_handle_t* java_lang_reflect_Field_create(fieldinfo* f) { return java_lang_reflect_Field(f).get_handle(); }
+ java_handle_t* java_lang_reflect_Method_create(methodinfo* m) { return java_lang_reflect_Method(m).get_handle(); }
+}
+
+#endif // ENABLE_JAVASE
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/vm/javaobjects.hpp - functions to create and access Java objects
+
+ Copyright (C) 2008 Theobroma Systems Ltd.
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _JAVAOBJECTS_HPP
+#define _JAVAOBJECTS_HPP
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "vm/class.h"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/method.h"
+
+
+#ifdef __cplusplus
+
+/**
+ * This class provides low-level functions to access Java object
+ * instance fields.
+ *
+ * These functions do NOT take care about the GC critical section!
+ * Please use FieldAccess wherever possible.
+ */
+class RawFieldAccess {
+protected:
+ template<class T> static inline T raw_get(void* address, const off_t offset);
+ template<class T> static inline void raw_set(void* address, const off_t offset, T value);
+};
+
+
+template<class T> inline T RawFieldAccess::raw_get(void* address, const off_t offset)
+{
+ T* p = (T*) (((uintptr_t) address) + offset);
+ return *p;
+}
+
+
+template<class T> inline void RawFieldAccess::raw_set(void* address, const off_t offset, T value)
+{
+ T* p = (T*) (((uintptr_t) address) + offset);
+ *p = value;
+}
+
+
+/**
+ * This classes provides functions to access Java object instance
+ * fields. These functions enter a critical GC section before
+ * accessing the Java object throught the handle and leave it
+ * afterwards.
+ */
+class FieldAccess : private RawFieldAccess {
+protected:
+ template<class T> static inline T get(java_handle_t* h, const off_t offset);
+ template<class T> static inline void set(java_handle_t* h, const off_t offset, T value);
+};
+
+template<class T> inline T FieldAccess::get(java_handle_t* h, const off_t offset)
+{
+ java_object_t* o;
+ T result;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be _handle->get_object();
+ o = LLNI_UNWRAP(h);
+
+ result = raw_get<T>(o, offset);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+
+ return result;
+}
+
+template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
+{
+ java_object_t* o;
+ java_object_t* result;
+ java_handle_t* hresult;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be _handle->get_object();
+ o = LLNI_UNWRAP(h);
+
+ result = raw_get<java_object_t*>(o, offset);
+
+ hresult = LLNI_WRAP(result);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+
+ return result;
+}
+
+
+template<class T> inline void FieldAccess::set(java_handle_t* h, const off_t offset, T value)
+{
+ java_object_t* o;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be h->get_object();
+ o = LLNI_UNWRAP(h);
+
+ raw_set(o, offset, value);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+}
+
+template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
+{
+ java_object_t* o;
+ java_object_t* ovalue;
+
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be h->get_object();
+ o = LLNI_UNWRAP(h);
+ ovalue = LLNI_UNWRAP(value);
+
+ raw_set(o, offset, ovalue);
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+}
+
+
+/**
+ * java/lang/Object
+ *
+ * Object layout:
+ *
+ * 0. object header
+ */
+class java_lang_Object {
+protected:
+ // Handle of Java object.
+ java_handle_t* _handle;
+
+protected:
+ java_lang_Object() : _handle(NULL) {}
+ java_lang_Object(java_handle_t* h) : _handle(h) {}
+ java_lang_Object(jobject h) : _handle((java_handle_t*) h) {}
+
+public:
+ // Getters.
+ virtual inline java_handle_t* get_handle() const { return _handle; }
+ inline vftbl_t* get_vftbl () const;
+ inline classinfo* get_Class () const;
+
+ inline bool is_null () const;
+ inline bool is_non_null() const;
+};
+
+
+inline vftbl_t* java_lang_Object::get_vftbl() const
+{
+ // XXX Move this to a GC inline function, e.g.
+ // gc->enter_critical();
+ LLNI_CRITICAL_START;
+
+ // XXX This should be h->get_object();
+ java_object_t* o = LLNI_UNWRAP(_handle);
+ vftbl_t* vftbl = o->vftbl;
+
+ // XXX Move this to a GC inline function.
+ // gc->leave_critical();
+ LLNI_CRITICAL_END;
+
+ return vftbl;
+}
+
+inline classinfo* java_lang_Object::get_Class() const
+{
+ return get_vftbl()->clazz;
+}
+
+
+inline bool java_lang_Object::is_null() const
+{
+ return (_handle == NULL);
+}
+
+inline bool java_lang_Object::is_non_null() const
+{
+ return (_handle != NULL);
+}
+
+
+/**
+ * java/lang/Boolean
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean value;
+ */
+class java_lang_Boolean : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Boolean(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline uint8_t get_value();
+ inline void set_value(uint8_t value);
+};
+
+inline uint8_t java_lang_Boolean::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Boolean::set_value(uint8_t value)
+{
+ set(_handle, offset_value, (uint32_t) value);
+}
+
+
+/**
+ * java/lang/Byte
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. byte value;
+ */
+class java_lang_Byte : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Byte(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int8_t get_value();
+ inline void set_value(int8_t value);
+};
+
+inline int8_t java_lang_Byte::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Byte::set_value(int8_t value)
+{
+ set(_handle, offset_value, (int32_t) value);
+}
+
+
+/**
+ * java/lang/Character
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char value;
+ */
+class java_lang_Character : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Character(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline uint16_t get_value();
+ inline void set_value(uint16_t value);
+};
+
+inline uint16_t java_lang_Character::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Character::set_value(uint16_t value)
+{
+ set(_handle, offset_value, (uint32_t) value);
+}
+
+
+/**
+ * java/lang/Short
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. short value;
+ */
+class java_lang_Short : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Short(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int16_t get_value();
+ inline void set_value(int16_t value);
+};
+
+inline int16_t java_lang_Short::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Short::set_value(int16_t value)
+{
+ set(_handle, offset_value, (int32_t) value);
+}
+
+
+/**
+ * java/lang/Integer
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int value;
+ */
+class java_lang_Integer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+
+public:
+ java_lang_Integer(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int32_t get_value();
+ inline void set_value(int32_t value);
+};
+
+inline int32_t java_lang_Integer::get_value()
+{
+ return get<int32_t>(_handle, offset_value);
+}
+
+inline void java_lang_Integer::set_value(int32_t value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+/**
+ * java/lang/Long
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. long value;
+ */
+class java_lang_Long : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int64_t));
+
+public:
+ java_lang_Long(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline int64_t get_value();
+ inline void set_value(int64_t value);
+};
+
+inline int64_t java_lang_Long::get_value()
+{
+ return get<int64_t>(_handle, offset_value);
+}
+
+inline void java_lang_Long::set_value(int64_t value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+/**
+ * java/lang/Float
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. float value;
+ */
+class java_lang_Float : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(float));
+
+public:
+ java_lang_Float(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline float get_value();
+ inline void set_value(float value);
+};
+
+inline float java_lang_Float::get_value()
+{
+ return get<float>(_handle, offset_value);
+}
+
+inline void java_lang_Float::set_value(float value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+/**
+ * java/lang/Double
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. double value;
+ */
+class java_lang_Double : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(double));
+
+public:
+ java_lang_Double(java_handle_t* h) : java_lang_Object(h) {}
+
+ inline double get_value();
+ inline void set_value(double value);
+};
+
+inline double java_lang_Double::get_value()
+{
+ return get<double>(_handle, offset_value);
+}
+
+inline void java_lang_Double::set_value(double value)
+{
+ set(_handle, offset_value, value);
+}
+
+
+#if defined(ENABLE_JAVASE)
+
+# if defined(ENABLE_ANNOTATIONS)
+/**
+ * OpenJDK sun/reflect/ConstantPool
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object constantPoolOop;
+ */
+class sun_reflect_ConstantPool : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_constantPoolOop = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+
+public:
+ sun_reflect_ConstantPool(java_handle_t* h) : java_lang_Object(h) {}
+ sun_reflect_ConstantPool(java_handle_t* h, jclass constantPoolOop);
+
+ // Setters.
+ inline void set_constantPoolOop(classinfo* value);
+ inline void set_constantPoolOop(jclass value);
+};
+
+
+inline sun_reflect_ConstantPool::sun_reflect_ConstantPool(java_handle_t* h, jclass constantPoolOop) : java_lang_Object(h)
+{
+ set_constantPoolOop(constantPoolOop);
+}
+
+
+inline void sun_reflect_ConstantPool::set_constantPoolOop(classinfo* value)
+{
+ set(_handle, offset_constantPoolOop, value);
+}
+
+inline void sun_reflect_ConstantPool::set_constantPoolOop(jclass value)
+{
+ // XXX jclass is a boxed object.
+ set_constantPoolOop(LLNI_classinfo_unwrap(value));
+}
+# endif // ENABLE_ANNOTATIONS
+
+#endif // ENABLE_JAVASE
+
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+
+/**
+ * GNU Classpath java/lang/Class
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object[] signers;
+ * 2. java.security.ProtectionDomain pd;
+ * 3. java.lang.Object vmdata;
+ * 4. java.lang.reflect.Constructor constructor;
+ */
+class java_lang_Class : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_signers = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_pd = MEMORY_ALIGN(offset_signers + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_vmdata = MEMORY_ALIGN(offset_pd + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_constructor = MEMORY_ALIGN(offset_vmdata + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Class(java_handle_t* h) : java_lang_Object(h) {}
+
+ // Setters.
+ inline void set_pd(java_handle_t* value);
+ inline void set_pd(jobject value);
+};
+
+inline void java_lang_Class::set_pd(java_handle_t* value)
+{
+ set(_handle, offset_pd, value);
+}
+
+inline void java_lang_Class::set_pd(jobject value)
+{
+ set_pd((java_handle_t*) value);
+}
+
+
+/**
+ * GNU Classpath java/lang/StackTraceElement
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String fileName;
+ * 2. int lineNumber;
+ * 3. java.lang.String declaringClass;
+ * 4. java.lang.String methodName;
+ * 5. boolean isNative;
+ */
+class java_lang_StackTraceElement : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_fileName = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_lineNumber = MEMORY_ALIGN(offset_fileName + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_declaringClass = MEMORY_ALIGN(offset_lineNumber + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_methodName = MEMORY_ALIGN(offset_declaringClass + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_isNative = MEMORY_ALIGN(offset_methodName + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_StackTraceElement(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_StackTraceElement(java_handle_t* h, java_handle_t* fileName, int32_t lineNumber, java_handle_t* declaringClass, java_handle_t* methodName, uint8_t isNative);
+};
+
+inline java_lang_StackTraceElement::java_lang_StackTraceElement(java_handle_t* h, java_handle_t* fileName, int32_t lineNumber, java_handle_t* declaringClass, java_handle_t* methodName, uint8_t isNative) : java_lang_Object(h)
+{
+ java_lang_StackTraceElement((java_handle_t*) h);
+
+ set(_handle, offset_fileName, fileName);
+ set(_handle, offset_lineNumber, lineNumber);
+ set(_handle, offset_declaringClass, declaringClass);
+ set(_handle, offset_methodName, methodName);
+ set(_handle, offset_isNative, isNative);
+}
+
+
+/**
+ * GNU Classpath java/lang/String
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] value;
+ * 2. int count;
+ * 3. int cachedHashCode;
+ * 4. int offset;
+ */
+class java_lang_String : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_count = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_cachedHashCode = MEMORY_ALIGN(offset_count + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_offset = MEMORY_ALIGN(offset_cachedHashCode + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_String(jstring h);
+ java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
+
+ // Getters.
+ inline java_handle_chararray_t* get_value () const;
+ inline int32_t get_count () const;
+ inline int32_t get_offset() const;
+
+ // Setters.
+ inline void set_value (java_handle_chararray_t* value);
+ inline void set_count (int32_t value);
+ inline void set_offset(int32_t value);
+};
+
+inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
+{
+ java_lang_String((java_handle_t*) h);
+}
+
+inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
+{
+ set_value(value);
+ set_count(count);
+ set_offset(offset);
+}
+
+inline java_handle_chararray_t* java_lang_String::get_value() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_value);
+}
+
+inline int32_t java_lang_String::get_count() const
+{
+ return get<int32_t>(_handle, offset_count);
+}
+
+inline int32_t java_lang_String::get_offset() const
+{
+ return get<int32_t>(_handle, offset_offset);
+}
+
+inline void java_lang_String::set_value(java_handle_chararray_t* value)
+{
+ set(_handle, offset_value, value);
+}
+
+inline void java_lang_String::set_count(int32_t value)
+{
+ set(_handle, offset_count, value);
+}
+
+inline void java_lang_String::set_offset(int32_t value)
+{
+ set(_handle, offset_offset, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/Thread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.VMThread vmThread;
+ * 2. java.lang.ThreadGroup group;
+ * 3. java.lang.Runnable runnable;
+ * 4. java.lang.String name;
+ * 5. boolean daemon;
+ * 6. int priority;
+ * 7. long stacksize;
+ * 8. java.lang.Throwable stillborn;
+ * 9. java.lang.ClassLoader contextClassLoader;
+ * 10. boolean contextClassLoaderIsSystemClassLoader;
+ * 11. long threadId;
+ * 12. java.lang.Object parkBlocker;
+ * 13. gnu.java.util.WeakIdentityHashMap locals;
+ * 14. java_lang_Thread_UncaughtExceptionHandler exceptionHandler;
+ */
+class java_lang_Thread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_vmThread = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_group = MEMORY_ALIGN(offset_vmThread + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_runnable = MEMORY_ALIGN(offset_group + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_name = MEMORY_ALIGN(offset_runnable + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_daemon = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_priority = MEMORY_ALIGN(offset_daemon + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_stacksize = MEMORY_ALIGN(offset_priority + sizeof(int32_t), sizeof(int64_t));
+ static const off_t offset_stillborn = MEMORY_ALIGN(offset_stacksize + sizeof(int64_t), SIZEOF_VOID_P);
+ static const off_t offset_contextClassLoader = MEMORY_ALIGN(offset_stillborn + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_contextClassLoaderIsSystemClassLoader = MEMORY_ALIGN(offset_contextClassLoader + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_threadId = MEMORY_ALIGN(offset_contextClassLoaderIsSystemClassLoader + sizeof(int32_t), sizeof(int64_t));
+ static const off_t offset_parkBlocker = MEMORY_ALIGN(offset_threadId + sizeof(int64_t), SIZEOF_VOID_P);
+ static const off_t offset_locals = MEMORY_ALIGN(offset_parkBlocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_exceptionHandler = MEMORY_ALIGN(offset_locals + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
+// java_lang_Thread(threadobject* t);
+
+ // Getters.
+ inline java_handle_t* get_vmThread () const;
+ inline java_handle_t* get_group () const;
+ inline java_handle_t* get_name () const;
+ inline int32_t get_daemon () const;
+ inline int32_t get_priority () const;
+ inline java_handle_t* get_exceptionHandler() const;
+
+ // Setters.
+ inline void set_group(java_handle_t* value);
+};
+
+
+// inline java_lang_Thread::java_lang_Thread(threadobject* t) : java_lang_Object(h)
+// {
+// java_lang_Thread(thread_get_object(t));
+// }
+
+
+inline java_handle_t* java_lang_Thread::get_vmThread() const
+{
+ return get<java_handle_t*>(_handle, offset_vmThread);
+}
+
+inline java_handle_t* java_lang_Thread::get_group() const
+{
+ return get<java_handle_t*>(_handle, offset_group);
+}
+
+inline java_handle_t* java_lang_Thread::get_name() const
+{
+ return get<java_handle_t*>(_handle, offset_name);
+}
+
+inline int32_t java_lang_Thread::get_daemon() const
+{
+ return get<int32_t>(_handle, offset_daemon);
+}
+
+inline int32_t java_lang_Thread::get_priority() const
+{
+ return get<int32_t>(_handle, offset_priority);
+}
+
+inline java_handle_t* java_lang_Thread::get_exceptionHandler() const
+{
+ return get<java_handle_t*>(_handle, offset_exceptionHandler);
+}
+
+
+inline void java_lang_Thread::set_group(java_handle_t* value)
+{
+ set(_handle, offset_group, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/VMThread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Thread thread;
+ * 2. boolean running;
+ * 3. java.lang.VMThread vmdata;
+ */
+class java_lang_VMThread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_thread = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_running = MEMORY_ALIGN(offset_thread + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_vmdata = MEMORY_ALIGN(offset_running + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_lang_VMThread(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_VMThread(jobject h);
+ java_lang_VMThread(java_handle_t* h, java_handle_t* thread, threadobject* vmdata);
+
+ // Getters.
+ inline java_handle_t* get_thread() const;
+ inline threadobject* get_vmdata() const;
+
+ // Setters.
+ inline void set_thread(java_handle_t* value);
+ inline void set_vmdata(threadobject* value);
+};
+
+
+inline java_lang_VMThread::java_lang_VMThread(jobject h) : java_lang_Object(h)
+{
+ java_lang_VMThread((java_handle_t*) h);
+}
+
+inline java_lang_VMThread::java_lang_VMThread(java_handle_t* h, java_handle_t* thread, threadobject* vmdata) : java_lang_Object(h)
+{
+ set_thread(thread);
+ set_vmdata(vmdata);
+}
+
+
+inline java_handle_t* java_lang_VMThread::get_thread() const
+{
+ return get<java_handle_t*>(_handle, offset_thread);
+}
+
+inline threadobject* java_lang_VMThread::get_vmdata() const
+{
+ return get<threadobject*>(_handle, offset_vmdata);
+}
+
+
+inline void java_lang_VMThread::set_thread(java_handle_t* value)
+{
+ set(_handle, offset_thread, value);
+}
+
+inline void java_lang_VMThread::set_vmdata(threadobject* value)
+{
+ set(_handle, offset_vmdata, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/Throwable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String detailMessage;
+ * 2. java.lang.Throwable cause;
+ * 3. java.lang.StackTraceElement[] stackTrace;
+ * 4. java.lang.VMThrowable vmState;
+ */
+class java_lang_Throwable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_detailMessage = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_cause = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stackTrace = MEMORY_ALIGN(offset_cause + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_vmState = MEMORY_ALIGN(offset_stackTrace + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
+
+ // Getters.
+ inline java_handle_t* get_detailMessage() const;
+ inline java_handle_t* get_cause () const;
+ inline java_handle_t* get_vmState () const;
+};
+
+
+inline java_handle_t* java_lang_Throwable::get_detailMessage() const
+{
+ return get<java_handle_t*>(_handle, offset_detailMessage);
+}
+
+inline java_handle_t* java_lang_Throwable::get_cause() const
+{
+ return get<java_handle_t*>(_handle, offset_cause);
+}
+
+inline java_handle_t* java_lang_Throwable::get_vmState() const
+{
+ return get<java_handle_t*>(_handle, offset_vmState);
+}
+
+
+/**
+ * GNU Classpath java/lang/VMThrowable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object vmdata;
+ */
+class java_lang_VMThrowable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_vmdata = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+
+public:
+ java_lang_VMThrowable(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_VMThrowable(jobject h);
+
+ inline java_handle_bytearray_t* get_vmdata() const;
+ inline void set_vmdata(java_handle_bytearray_t* value);
+};
+
+inline java_lang_VMThrowable::java_lang_VMThrowable(jobject h) : java_lang_Object(h)
+{
+ java_lang_VMThrowable((java_handle_t*) h);
+}
+
+inline java_handle_bytearray_t* java_lang_VMThrowable::get_vmdata() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_vmdata);
+}
+
+inline void java_lang_VMThrowable::set_vmdata(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_vmdata, value);
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/VMConstructor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Class clazz;
+ * 2. int slot;
+ * 3. byte[] annotations;
+ * 4. byte[] parameterAnnotations;
+ * 5. java.util.Map declaredAnnotations;
+ * 6. java.lang.reflect.Constructor cons;
+ */
+class java_lang_reflect_VMConstructor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_cons = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_VMConstructor(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_VMConstructor(jobject h);
+ java_lang_reflect_VMConstructor(methodinfo* m);
+
+ // Getters.
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_bytearray_t* get_parameterAnnotations() const;
+ inline java_handle_t* get_declaredAnnotations () const;
+ inline java_handle_t* get_cons () const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_slot (int32_t value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_parameterAnnotations(java_handle_bytearray_t* value);
+ inline void set_declaredAnnotations (java_handle_t* value);
+ inline void set_cons (java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method();
+};
+
+
+inline java_lang_reflect_VMConstructor::java_lang_reflect_VMConstructor(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_VMConstructor((java_handle_t*) h);
+}
+
+inline java_lang_reflect_VMConstructor::java_lang_reflect_VMConstructor(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_VMConstructor);
+
+ if (is_null())
+ return;
+
+ int slot = m - m->clazz->methods;
+ java_handle_bytearray_t* annotations = method_get_annotations(m);
+ java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
+
+ set_clazz(m->clazz);
+ set_slot(slot);
+ set_annotations(annotations);
+ set_parameterAnnotations(parameterAnnotations);
+}
+
+
+inline classinfo* java_lang_reflect_VMConstructor::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_VMConstructor::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMConstructor::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMConstructor::get_parameterAnnotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMConstructor::get_declaredAnnotations() const
+{
+ return get<java_handle_t*>(_handle, offset_declaredAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMConstructor::get_cons() const
+{
+ return get<java_handle_t*>(_handle, offset_cons);
+}
+
+inline void java_lang_reflect_VMConstructor::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_parameterAnnotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_parameterAnnotations, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_declaredAnnotations(java_handle_t* value)
+{
+ set(_handle, offset_declaredAnnotations, value);
+}
+
+inline void java_lang_reflect_VMConstructor::set_cons(java_handle_t* value)
+{
+ set(_handle, offset_cons, value);
+}
+
+inline methodinfo* java_lang_reflect_VMConstructor::get_method()
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/Constructor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean flag;
+ * 2. gnu.java.lang.reflect.MethodSignatureParser p;
+ * 3. java.lang.reflect.VMConstructor cons;
+ */
+class java_lang_reflect_Constructor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_cons = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Constructor(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Constructor(jobject h);
+ java_lang_reflect_Constructor(methodinfo* m);
+
+ java_handle_t* new_instance(java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_flag() const;
+ inline java_handle_t* get_cons() const;
+
+ // Setters.
+ inline void set_cons(java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method () const;
+ inline int32_t get_override() const;
+};
+
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Constructor((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(methodinfo* m)
+{
+ java_lang_reflect_VMConstructor jlrvmc(m);
+
+ if (jlrvmc.is_null())
+ return;
+
+ _handle = builtin_new(class_java_lang_reflect_Constructor);
+
+ if (is_null())
+ return;
+
+ // Link the two Java objects.
+ set_cons(jlrvmc.get_handle());
+ jlrvmc.set_cons(get_handle());
+}
+
+
+inline int32_t java_lang_reflect_Constructor::get_flag() const
+{
+ return get<int32_t>(_handle, offset_flag);
+}
+
+inline java_handle_t* java_lang_reflect_Constructor::get_cons() const
+{
+ return get<java_handle_t*>(_handle, offset_cons);
+}
+
+
+inline void java_lang_reflect_Constructor::set_cons(java_handle_t* value)
+{
+ set(_handle, offset_cons, value);
+}
+
+
+inline methodinfo* java_lang_reflect_Constructor::get_method() const
+{
+ java_lang_reflect_VMConstructor jlrvmc(get_cons());
+ return jlrvmc.get_method();
+}
+
+inline int32_t java_lang_reflect_Constructor::get_override() const
+{
+ return get_flag();
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/VMField
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Class clazz;
+ * 2. java.lang.String name;
+ * 3. int slot;
+ * 4. byte[] annotations;
+ * 5. java.lang.Map declaredAnnotations;
+ * 6. java.lang.reflect.Field f;
+ */
+class java_lang_reflect_VMField : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_name = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_f = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_VMField(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_VMField(jobject h);
+ java_lang_reflect_VMField(fieldinfo* f);
+
+ // Getters.
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_t* get_declaredAnnotations() const;
+ inline java_handle_t* get_f () const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_name (java_handle_t* value);
+ inline void set_slot (int32_t value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_declaredAnnotations(java_handle_t* value);
+ inline void set_f (java_handle_t* value);
+
+ // Convenience functions.
+ inline fieldinfo* get_field() const;
+};
+
+
+inline java_lang_reflect_VMField::java_lang_reflect_VMField(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_VMField((java_handle_t*) h);
+}
+
+inline java_lang_reflect_VMField::java_lang_reflect_VMField(fieldinfo* f)
+{
+ _handle = builtin_new(class_java_lang_reflect_VMField);
+
+ if (is_null())
+ return;
+
+ java_handle_t* name = javastring_intern(javastring_new(f->name));
+ int slot = f - f->clazz->fields;
+ java_handle_bytearray_t* annotations = field_get_annotations(f);
+
+ set_clazz(f->clazz);
+ set_name(name);
+ set_slot(slot);
+ set_annotations(annotations);
+}
+
+
+inline classinfo* java_lang_reflect_VMField::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_VMField::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMField::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMField::get_declaredAnnotations() const
+{
+ return get<java_handle_t*>(_handle, offset_declaredAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMField::get_f() const
+{
+ return get<java_handle_t*>(_handle, offset_f);
+}
+
+
+inline void java_lang_reflect_VMField::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_VMField::set_name(java_handle_t* value)
+{
+ set(_handle, offset_name, value);
+}
+
+inline void java_lang_reflect_VMField::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_VMField::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_VMField::set_declaredAnnotations(java_handle_t* value)
+{
+ set(_handle, offset_declaredAnnotations, value);
+}
+
+inline void java_lang_reflect_VMField::set_f(java_handle_t* value)
+{
+ set(_handle, offset_f, value);
+}
+
+inline fieldinfo* java_lang_reflect_VMField::get_field() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ fieldinfo* f = &(c->fields[slot]);
+ return f;
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/Field
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean flag;
+ * 2. gnu.java.lang.reflect.FieldSignatureParser p;
+ * 3. java.lang.reflect.VMField f;
+ */
+class java_lang_reflect_Field : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_f = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Field(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Field(jobject h);
+ java_lang_reflect_Field(fieldinfo* f);
+
+ // Getters.
+ inline int32_t get_flag() const;
+ inline java_handle_t* get_f() const;
+
+ // Setters.
+ inline void set_f(java_handle_t* value);
+
+ // Convenience functions.
+ inline fieldinfo* get_field() const;
+};
+
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Field((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(fieldinfo* f)
+{
+ java_lang_reflect_VMField jlrvmf(f);
+
+ if (jlrvmf.is_null())
+ return;
+
+ _handle = builtin_new(class_java_lang_reflect_Field);
+
+ if (is_null())
+ return;
+
+ // Link the two Java objects.
+ set_f(jlrvmf.get_handle());
+ jlrvmf.set_f(get_handle());
+}
+
+
+inline int32_t java_lang_reflect_Field::get_flag() const
+{
+ return get<int32_t>(_handle, offset_flag);
+}
+
+inline java_handle_t* java_lang_reflect_Field::get_f() const
+{
+ return get<java_handle_t*>(_handle, offset_f);
+}
+
+
+inline void java_lang_reflect_Field::set_f(java_handle_t* value)
+{
+ set(_handle, offset_f, value);
+}
+
+
+inline fieldinfo* java_lang_reflect_Field::get_field() const
+{
+ java_lang_reflect_VMField jlrvmf(get_f());
+ return jlrvmf.get_field();
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/VMMethod
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Class clazz;
+ * 2. java.lang.String name;
+ * 3. int slot;
+ * 4. byte[] annotations;
+ * 5. byte[] parameterAnnotations;
+ * 6. byte[] annotationDefault;
+ * 7. java.lang.Map declaredAnnotations;
+ * 8. java.lang.reflect.Method m;
+ */
+class java_lang_reflect_VMMethod : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_name = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotationDefault = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_annotationDefault + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_m = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_VMMethod(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_VMMethod(jobject h);
+ java_lang_reflect_VMMethod(methodinfo* m);
+
+ // Getters.
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_bytearray_t* get_parameterAnnotations() const;
+ inline java_handle_bytearray_t* get_annotationDefault () const;
+ inline java_handle_t* get_declaredAnnotations () const;
+ inline java_handle_t* get_m () const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_name (java_handle_t* value);
+ inline void set_slot (int32_t value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_parameterAnnotations(java_handle_bytearray_t* value);
+ inline void set_annotationDefault (java_handle_bytearray_t* value);
+ inline void set_declaredAnnotations (java_handle_t* value);
+ inline void set_m (java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method() const;
+};
+
+inline java_lang_reflect_VMMethod::java_lang_reflect_VMMethod(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_VMMethod((java_handle_t*) h);
+}
+
+inline java_lang_reflect_VMMethod::java_lang_reflect_VMMethod(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_VMMethod);
+
+ if (is_null())
+ return;
+
+ java_handle_t* name = javastring_intern(javastring_new(m->name));
+ int slot = m - m->clazz->methods;
+ java_handle_bytearray_t* annotations = method_get_annotations(m);
+ java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
+ java_handle_bytearray_t* annotationDefault = method_get_annotationdefault(m);
+
+ set_clazz(m->clazz);
+ set_name(name);
+ set_slot(slot);
+ set_annotations(annotations);
+ set_parameterAnnotations(parameterAnnotations);
+ set_annotationDefault(annotationDefault);
+}
+
+inline classinfo* java_lang_reflect_VMMethod::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_VMMethod::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_parameterAnnotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_annotationDefault() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotationDefault);
+}
+
+inline java_handle_t* java_lang_reflect_VMMethod::get_declaredAnnotations() const
+{
+ return get<java_handle_t*>(_handle, offset_declaredAnnotations);
+}
+
+inline java_handle_t* java_lang_reflect_VMMethod::get_m() const
+{
+ return get<java_handle_t*>(_handle, offset_m);
+}
+
+inline void java_lang_reflect_VMMethod::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_name(java_handle_t* value)
+{
+ set(_handle, offset_name, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_parameterAnnotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_parameterAnnotations, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_annotationDefault(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotationDefault, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_declaredAnnotations(java_handle_t* value)
+{
+ set(_handle, offset_declaredAnnotations, value);
+}
+
+inline void java_lang_reflect_VMMethod::set_m(java_handle_t* value)
+{
+ set(_handle, offset_m, value);
+}
+
+inline methodinfo* java_lang_reflect_VMMethod::get_method() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * GNU Classpath java/lang/reflect/Method
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean flag;
+ * 2. gnu.java.lang.reflect.MethodSignatureParser p;
+ * 3. java.lang.reflect.VMMethod m;
+ */
+class java_lang_reflect_Method : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_m = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Method(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Method(jobject h);
+ java_lang_reflect_Method(methodinfo* m);
+
+ java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_flag() const;
+ inline java_handle_t* get_m() const;
+
+ // Setters.
+ inline void set_m(java_handle_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method () const;
+ inline int32_t get_override() const;
+};
+
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Method((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(methodinfo* m)
+{
+ java_lang_reflect_VMMethod jlrvmm(m);
+
+ if (jlrvmm.is_null())
+ return;
+
+ _handle = builtin_new(class_java_lang_reflect_Method);
+
+ if (is_null())
+ return;
+
+ // Link the two Java objects.
+ set_m(jlrvmm.get_handle());
+ jlrvmm.set_m(get_handle());
+}
+
+
+inline int32_t java_lang_reflect_Method::get_flag() const
+{
+ return get<int32_t>(_handle, offset_flag);
+}
+
+inline java_handle_t* java_lang_reflect_Method::get_m() const
+{
+ return get<java_handle_t*>(_handle, offset_m);
+}
+
+
+inline void java_lang_reflect_Method::set_m(java_handle_t* value)
+{
+ set(_handle, offset_m, value);
+}
+
+
+inline methodinfo* java_lang_reflect_Method::get_method() const
+{
+ java_lang_reflect_VMMethod jlrvmm(get_m());
+ return jlrvmm.get_method();
+}
+
+inline int32_t java_lang_reflect_Method::get_override() const
+{
+ return get_flag();
+}
+
+
+/**
+ * GNU Classpath java/nio/Buffer
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int cap;
+ * 2. int limit;
+ * 3. int pos;
+ * 4. int mark;
+ * 5. gnu.classpath.Pointer address;
+ */
+class java_nio_Buffer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_cap = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_limit = MEMORY_ALIGN(offset_cap + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_pos = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_mark = MEMORY_ALIGN(offset_pos + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_address = MEMORY_ALIGN(offset_mark + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
+
+ // Getters.
+ inline int32_t get_cap() const;
+};
+
+inline int32_t java_nio_Buffer::get_cap() const
+{
+ return get<int32_t>(_handle, offset_cap);
+}
+
+
+/**
+ * GNU Classpath java/nio/DirectByteBufferImpl
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int cap;
+ * 2. int limit;
+ * 3. int pos;
+ * 4. int mark;
+ * 5. gnu.classpath.Pointer address;
+ * 6. java.nio.ByteOrder endian;
+ * 7. byte[] backing_buffer;
+ * 8. int array_offset;
+ * 9. java.lang.Object owner;
+ */
+class java_nio_DirectByteBufferImpl : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_cap = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_limit = MEMORY_ALIGN(offset_cap + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_pos = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_mark = MEMORY_ALIGN(offset_pos + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_address = MEMORY_ALIGN(offset_mark + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_endian = MEMORY_ALIGN(offset_address + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_backing_buffer = MEMORY_ALIGN(offset_endian + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_array_offset = MEMORY_ALIGN(offset_backing_buffer + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_owner = MEMORY_ALIGN(offset_array_offset + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_nio_DirectByteBufferImpl(java_handle_t* h) : java_lang_Object(h) {}
+ java_nio_DirectByteBufferImpl(jobject h);
+
+ // Getters.
+ inline java_handle_t* get_address() const;
+};
+
+inline java_nio_DirectByteBufferImpl::java_nio_DirectByteBufferImpl(jobject h) : java_lang_Object(h)
+{
+ java_nio_DirectByteBufferImpl((java_handle_t*) h);
+}
+
+inline java_handle_t* java_nio_DirectByteBufferImpl::get_address() const
+{
+ return get<java_handle_t*>(_handle, offset_address);
+}
+
+
+/**
+ * GNU Classpath gnu/classpath/Pointer
+ *
+ * Actually there are two classes, gnu.classpath.Pointer32 and
+ * gnu.classpath.Pointer64, but we only define the abstract super
+ * class and use the int/long field as void* type.
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int/long data;
+ */
+class gnu_classpath_Pointer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_data = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+
+public:
+ gnu_classpath_Pointer(java_handle_t* h) : java_lang_Object(h) {}
+ gnu_classpath_Pointer(java_handle_t* h, void* data);
+
+ // Setters.
+ inline void* get_data() const;
+
+ // Setters.
+ inline void set_data(void* value);
+};
+
+inline gnu_classpath_Pointer::gnu_classpath_Pointer(java_handle_t* h, void* data) : java_lang_Object(h)
+{
+ set_data(data);
+}
+
+inline void* gnu_classpath_Pointer::get_data() const
+{
+ return get<void*>(_handle, offset_data);
+}
+
+inline void gnu_classpath_Pointer::set_data(void* value)
+{
+ set(_handle, offset_data, value);
+}
+
+#endif // WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH
+
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+
+/**
+ * OpenJDK java/lang/AssertionStatusDirectives
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String[] classes;
+ * 2. boolean[] classEnabled;
+ * 3. java.lang.String[] packages;
+ * 4. boolean[] packageEnabled;
+ * 5. boolean deflt;
+ */
+class java_lang_AssertionStatusDirectives : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_classes = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_classEnabled = MEMORY_ALIGN(offset_classes + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_packages = MEMORY_ALIGN(offset_classEnabled + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_packageEnabled = MEMORY_ALIGN(offset_packages + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_deflt = MEMORY_ALIGN(offset_packageEnabled + SIZEOF_VOID_P, sizeof(int32_t));
+
+public:
+ java_lang_AssertionStatusDirectives(java_handle_objectarray_t* classes, java_handle_booleanarray_t* classEnabled, java_handle_objectarray_t* packages, java_handle_booleanarray_t* packageEnabled);
+};
+
+inline java_lang_AssertionStatusDirectives::java_lang_AssertionStatusDirectives(java_handle_objectarray_t* classes, java_handle_booleanarray_t* classEnabled, java_handle_objectarray_t* packages, java_handle_booleanarray_t* packageEnabled)
+{
+ classinfo* c = load_class_bootstrap(utf_new_char("java/lang/AssertionStatusDirectives"));
+
+ // FIXME Load the class at VM startup.
+ if (c == NULL)
+ return;
+
+ _handle = builtin_new(c);
+
+ if (is_null())
+ return;
+
+ set(_handle, offset_classes, classes);
+ set(_handle, offset_classEnabled, classEnabled);
+ set(_handle, offset_packages, packages);
+ set(_handle, offset_packageEnabled, packageEnabled);
+}
+
+
+/**
+ * OpenJDK java/lang/StackTraceElement
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String declaringClass;
+ * 2. java.lang.String methodName;
+ * 3. java.lang.String fileName;
+ * 4. int lineNumber;
+ */
+class java_lang_StackTraceElement : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_declaringClass = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_methodName = MEMORY_ALIGN(offset_declaringClass + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_fileName = MEMORY_ALIGN(offset_methodName + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_lineNumber = MEMORY_ALIGN(offset_fileName + SIZEOF_VOID_P, sizeof(int32_t));
+
+public:
+ java_lang_StackTraceElement(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_StackTraceElement(java_handle_t* declaringClass, java_handle_t* methodName, java_handle_t* fileName, int32_t lineNumber);
+};
+
+inline java_lang_StackTraceElement::java_lang_StackTraceElement(java_handle_t* declaringClass, java_handle_t* methodName, java_handle_t* fileName, int32_t lineNumber)
+{
+ _handle = builtin_new(class_java_lang_StackTraceElement);
+
+ if (is_null())
+ return;
+
+ set(_handle, offset_declaringClass, declaringClass);
+ set(_handle, offset_methodName, methodName);
+ set(_handle, offset_fileName, fileName);
+ set(_handle, offset_lineNumber, lineNumber);
+}
+
+
+/**
+ * OpenJDK java/lang/String
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] value;
+ * 2. int offset;
+ * 3. int count;
+ * 4. int hash;
+ */
+class java_lang_String : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_offset = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_count = MEMORY_ALIGN(offset_offset + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_hash = MEMORY_ALIGN(offset_count + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_String(jstring h);
+ java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
+
+ // Getters.
+ inline java_handle_chararray_t* get_value () const;
+ inline int32_t get_offset() const;
+ inline int32_t get_count () const;
+
+ // Setters.
+ inline void set_value (java_handle_chararray_t* value);
+ inline void set_offset(int32_t value);
+ inline void set_count (int32_t value);
+};
+
+inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
+{
+ java_lang_String((java_handle_t*) h);
+}
+
+inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
+{
+ set_value(value);
+ set_offset(offset);
+ set_count(count);
+}
+
+inline java_handle_chararray_t* java_lang_String::get_value() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_value);
+}
+
+inline int32_t java_lang_String::get_offset() const
+{
+ return get<int32_t>(_handle, offset_offset);
+}
+
+inline int32_t java_lang_String::get_count() const
+{
+ return get<int32_t>(_handle, offset_count);
+}
+
+inline void java_lang_String::set_value(java_handle_chararray_t* value)
+{
+ set(_handle, offset_value, value);
+}
+
+inline void java_lang_String::set_offset(int32_t value)
+{
+ set(_handle, offset_offset, value);
+}
+
+inline void java_lang_String::set_count(int32_t value)
+{
+ set(_handle, offset_count, value);
+}
+
+
+/**
+ * OpenJDK java/lang/Thread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] name;
+ * 2. int priority;
+ * 3. java_lang_Thread threadQ;
+ * 4. long eetop;
+ * 5. boolean single_step;
+ * 6. boolean daemon;
+ * 7. boolean stillborn;
+ * 8. java_lang_Runnable target;
+ * 9. java_lang_ThreadGroup group;
+ * 10. java_lang_ClassLoader contextClassLoader;
+ * 11. java_security_AccessControlContext inheritedAccessControlContext;
+ * 12. java_lang_ThreadLocal_ThreadLocalMap threadLocals;
+ * 13. java_lang_ThreadLocal_ThreadLocalMap inheritableThreadLocals;
+ * 14. long stackSize;
+ * 15. long nativeParkEventPointer;
+ * 16. long tid;
+ * 17. int threadStatus;
+ * 18. java_lang_Object parkBlocker;
+ * 19. sun_nio_ch_Interruptible blocker;
+ * 20. java_lang_Object blockerLock;
+ * 21. boolean stopBeforeStart;
+ * 22. java_lang_Throwable throwableFromStop;
+ * 23. java.lang.Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
+ */
+class java_lang_Thread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_name = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_priority = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_threadQ = MEMORY_ALIGN(offset_priority + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_eetop = MEMORY_ALIGN(offset_threadQ + SIZEOF_VOID_P, sizeof(int64_t));
+ static const off_t offset_single_step = MEMORY_ALIGN(offset_eetop + sizeof(int64_t), sizeof(int32_t));
+ static const off_t offset_daemon = MEMORY_ALIGN(offset_single_step + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_stillborn = MEMORY_ALIGN(offset_daemon + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_target = MEMORY_ALIGN(offset_stillborn + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_group = MEMORY_ALIGN(offset_target + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_contextClassLoader = MEMORY_ALIGN(offset_group + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_inheritedAccessControlContext = MEMORY_ALIGN(offset_contextClassLoader + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_threadLocals = MEMORY_ALIGN(offset_inheritedAccessControlContext + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_inheritableThreadLocals = MEMORY_ALIGN(offset_threadLocals + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stackSize = MEMORY_ALIGN(offset_inheritableThreadLocals + SIZEOF_VOID_P, sizeof(int64_t));
+ static const off_t offset_nativeParkEventPointer = MEMORY_ALIGN(offset_stackSize + sizeof(int64_t), sizeof(int64_t));
+ static const off_t offset_tid = MEMORY_ALIGN(offset_nativeParkEventPointer + sizeof(int64_t), sizeof(int64_t));
+ static const off_t offset_threadStatus = MEMORY_ALIGN(offset_tid + sizeof(int64_t), sizeof(int32_t));
+ static const off_t offset_parkBlocker = MEMORY_ALIGN(offset_threadStatus + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_blocker = MEMORY_ALIGN(offset_parkBlocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_blockerLock = MEMORY_ALIGN(offset_blocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stopBeforeStart = MEMORY_ALIGN(offset_blockerLock + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_throwableFromStop = MEMORY_ALIGN(offset_stopBeforeStart + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_uncaughtExceptionHandler = MEMORY_ALIGN(offset_throwableFromStop + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
+// java_lang_Thread(threadobject* t);
+
+ // Getters.
+ inline int32_t get_priority () const;
+ inline int32_t get_daemon () const;
+ inline java_handle_t* get_group () const;
+ inline java_handle_t* get_uncaughtExceptionHandler() const;
+
+ // Setters.
+ inline void set_priority(int32_t value);
+ inline void set_group (java_handle_t* value);
+};
+
+
+inline int32_t java_lang_Thread::get_priority() const
+{
+ return get<int32_t>(_handle, offset_priority);
+}
+
+inline int32_t java_lang_Thread::get_daemon() const
+{
+ return get<int32_t>(_handle, offset_daemon);
+}
+
+inline java_handle_t* java_lang_Thread::get_group() const
+{
+ return get<java_handle_t*>(_handle, offset_group);
+}
+
+inline java_handle_t* java_lang_Thread::get_uncaughtExceptionHandler() const
+{
+ return get<java_handle_t*>(_handle, offset_uncaughtExceptionHandler);
+}
+
+
+inline void java_lang_Thread::set_priority(int32_t value)
+{
+ set(_handle, offset_priority, value);
+}
+
+inline void java_lang_Thread::set_group(java_handle_t* value)
+{
+ set(_handle, offset_group, value);
+}
+
+
+
+/**
+ * OpenJDK java/lang/Throwable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.Object backtrace;
+ * 2. java.lang.String detailMessage;
+ * 3. java.lang.Throwable cause;
+ * 4. java.lang.StackTraceElement[] stackTrace;
+ */
+class java_lang_Throwable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_backtrace = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_detailMessage = MEMORY_ALIGN(offset_backtrace + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_cause = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_stackTrace = MEMORY_ALIGN(offset_cause + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_Throwable(jobject h);
+ java_lang_Throwable(jobject h, java_handle_bytearray_t* backtrace);
+
+ // Getters.
+ inline java_handle_bytearray_t* get_backtrace () const;
+ inline java_handle_t* get_detailMessage() const;
+ inline java_handle_t* get_cause () const;
+
+ // Setters.
+ inline void set_backtrace(java_handle_bytearray_t* value);
+};
+
+
+inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
+{
+ java_lang_Throwable((java_handle_t*) h);
+}
+
+inline java_lang_Throwable::java_lang_Throwable(jobject h, java_handle_bytearray_t* backtrace) : java_lang_Object(h)
+{
+ java_lang_Throwable((java_handle_t*) h);
+ set_backtrace(backtrace);
+}
+
+
+inline java_handle_bytearray_t* java_lang_Throwable::get_backtrace() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_backtrace);
+}
+
+inline java_handle_t* java_lang_Throwable::get_detailMessage() const
+{
+ return get<java_handle_t*>(_handle, offset_detailMessage);
+}
+
+inline java_handle_t* java_lang_Throwable::get_cause() const
+{
+ return get<java_handle_t*>(_handle, offset_cause);
+}
+
+
+inline void java_lang_Throwable::set_backtrace(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_backtrace, value);
+}
+
+
+/**
+ * OpenJDK java/lang/reflect/Constructor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean override;
+ * 2. java.lang.Class clazz;
+ * 3. int slot;
+ * 4. java.lang.Class[] parameterTypes;
+ * 5. java.lang.Class[] exceptionTypes;
+ * 6. int modifiers;
+ * 7. java.lang.String signature;
+ * 8. sun.reflect.generics.repository.ConstructorRepository genericInfo;
+ * 9. byte[] annotations;
+ * 10. byte[] parameterAnnotations;
+ * 11. java.lang.Class securityCheckCache;
+ * 12. sun.reflect.ConstructorAccessor constructorAccessor;
+ * 13. java.lang.reflect.Constructor root;
+ * 14. java.util.Map declaredAnnotations;
+ */
+class java_lang_reflect_Constructor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_parameterTypes = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_exceptionTypes = MEMORY_ALIGN(offset_parameterTypes + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_modifiers = MEMORY_ALIGN(offset_exceptionTypes + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_constructorAccessor = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_root = MEMORY_ALIGN(offset_constructorAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Constructor(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Constructor(jobject h);
+ java_lang_reflect_Constructor(methodinfo* m);
+
+ java_handle_t* new_instance(java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_override () const;
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations() const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_slot (int32_t value);
+ inline void set_parameterTypes (java_handle_objectarray_t* value);
+ inline void set_exceptionTypes (java_handle_objectarray_t* value);
+ inline void set_modifiers (int32_t value);
+ inline void set_signature (java_handle_t* value);
+ inline void set_annotations (java_handle_bytearray_t* value);
+ inline void set_parameterAnnotations(java_handle_bytearray_t* value);
+
+ // Convenience functions.
+ inline methodinfo* get_method();
+};
+
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Constructor((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_Constructor);
+
+ if (is_null())
+ return;
+
+ int slot = m - m->clazz->methods;
+ java_handle_objectarray_t* parameterTypes = method_get_parametertypearray(m);
+ java_handle_objectarray_t* exceptionTypes = method_get_exceptionarray(m);
+ java_handle_bytearray_t* annotations = method_get_annotations(m);
+ java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
+
+ set_clazz(m->clazz);
+ set_slot(slot);
+ set_parameterTypes(parameterTypes);
+ set_exceptionTypes(exceptionTypes);
+ set_modifiers(m->flags & ACC_CLASS_REFLECT_MASK);
+ set_signature(m->signature ? javastring_new(m->signature) : NULL);
+ set_annotations(annotations);
+ set_parameterAnnotations(parameterAnnotations);
+}
+
+
+inline int32_t java_lang_reflect_Constructor::get_override() const
+{
+ return get<int32_t>(_handle, offset_override);
+}
+
+inline classinfo* java_lang_reflect_Constructor::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_Constructor::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Constructor::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+
+inline void java_lang_reflect_Constructor::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_Constructor::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_Constructor::set_parameterTypes(java_handle_objectarray_t* value)
+{
+ set(_handle, offset_parameterTypes, value);
+}
+
+inline void java_lang_reflect_Constructor::set_exceptionTypes(java_handle_objectarray_t* value)
+{
+ set(_handle, offset_exceptionTypes, value);
+}
+
+inline void java_lang_reflect_Constructor::set_modifiers(int32_t value)
+{
+ set(_handle, offset_modifiers, value);
+}
+
+inline void java_lang_reflect_Constructor::set_signature(java_handle_t* value)
+{
+ set(_handle, offset_signature, value);
+}
+
+inline void java_lang_reflect_Constructor::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+inline void java_lang_reflect_Constructor::set_parameterAnnotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_parameterAnnotations, value);
+}
+
+
+inline methodinfo* java_lang_reflect_Constructor::get_method()
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * OpenJDK java/lang/reflect/Field
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean override;
+ * 2. java.lang.Class clazz;
+ * 3. int slot;
+ * 4. java.lang.String name;
+ * 5. java.lang.Class type;
+ * 6. int modifiers;
+ * 7. java.lang.String signature;
+ * 8. sun.reflect.generics.repository.FieldRepository genericInfo;
+ * 9. byte[] annotations;
+ * 10. sun.reflect.FieldAccessor fieldAccessor;
+ * 11. sun.reflect.FieldAccessor overrideFieldAccessor;
+ * 12. java.lang.reflect.Field root;
+ * 13. java.lang.Class securityCheckCache;
+ * 14. java.lang.Class securityCheckTargetClassCache;
+ * 15. java.util.Map declaredAnnotations;
+ */
+class java_lang_reflect_Field : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_name = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_type = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_modifiers = MEMORY_ALIGN(offset_type + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_fieldAccessor = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_overrideFieldAccessor = MEMORY_ALIGN(offset_fieldAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_root = MEMORY_ALIGN(offset_overrideFieldAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckTargetClassCache = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_securityCheckTargetClassCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Field(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Field(jobject h);
+ java_lang_reflect_Field(fieldinfo* f);
+
+ // Getters.
+ inline int32_t get_override () const;
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations() const;
+
+ // Setters.
+ inline void set_clazz (classinfo* value);
+ inline void set_slot (int32_t value);
+ inline void set_name (java_handle_t* value);
+ inline void set_type (classinfo* value);
+ inline void set_modifiers (int32_t value);
+ inline void set_signature (java_handle_t* value);
+ inline void set_annotations(java_handle_bytearray_t* value);
+
+ // Convenience functions.
+ inline fieldinfo* get_field() const;
+};
+
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Field((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Field::java_lang_reflect_Field(fieldinfo* f)
+{
+ _handle = builtin_new(class_java_lang_reflect_Field);
+
+ // OOME.
+ if (is_null())
+ return;
+
+ set_clazz(f->clazz);
+ set_slot(f - f->clazz->fields);
+ set_name(javastring_intern(javastring_new(f->name)));
+ set_type(field_get_type(f));
+ set_modifiers(f->flags);
+ set_signature(f->signature ? javastring_new(f->signature) : NULL);
+ set_annotations(field_get_annotations(f));
+}
+
+
+inline int32_t java_lang_reflect_Field::get_override() const
+{
+ return get<int32_t>(_handle, offset_override);
+}
+
+inline classinfo* java_lang_reflect_Field::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_Field::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Field::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+
+inline void java_lang_reflect_Field::set_clazz(classinfo* value)
+{
+ set(_handle, offset_clazz, value);
+}
+
+inline void java_lang_reflect_Field::set_slot(int32_t value)
+{
+ set(_handle, offset_slot, value);
+}
+
+inline void java_lang_reflect_Field::set_name(java_handle_t* value)
+{
+ set(_handle, offset_name, value);
+}
+
+inline void java_lang_reflect_Field::set_type(classinfo* value)
+{
+ set(_handle, offset_type, value);
+}
+
+inline void java_lang_reflect_Field::set_modifiers(int32_t value)
+{
+ set(_handle, offset_modifiers, value);
+}
+
+inline void java_lang_reflect_Field::set_signature(java_handle_t* value)
+{
+ set(_handle, offset_signature, value);
+}
+
+inline void java_lang_reflect_Field::set_annotations(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_annotations, value);
+}
+
+
+inline fieldinfo* java_lang_reflect_Field::get_field() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ fieldinfo* f = &(c->fields[slot]);
+ return f;
+}
+
+
+/**
+ * OpenJDK java/lang/reflect/Method
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. boolean override;
+ * 2. java.lang.Class clazz;
+ * 3. int slot;
+ * 4. java.lang.String name;
+ * 5. java.lang.Class returnType;
+ * 6. java.lang.Class[] parameterTypes;
+ * 7. java.lang.Class[] exceptionTypes;
+ * 8. int modifiers;
+ * 9. java.lang.String signature;
+ * 10 sun.reflect.generics.repository.ConstructorRepository genericInfo;
+ * 11. byte[] annotations;
+ * 12. byte[] parameterAnnotations;
+ * 13. byte[] annotationDefault;
+ * 14. sun.reflect.MethodAccessor methodAccessor;
+ * 15. java.lang.reflect.Method root;
+ * 16. java.lang.Class securityCheckCache;
+ * 17. java.lang.Class securityCheckTargetClassCache;
+ * 18. java.util.Map declaredAnnotations;
+ */
+class java_lang_reflect_Method : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_name = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_returnType = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_parameterTypes = MEMORY_ALIGN(offset_returnType + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_exceptionTypes = MEMORY_ALIGN(offset_parameterTypes + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_modifiers = MEMORY_ALIGN(offset_exceptionTypes + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_annotationDefault = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_methodAccessor = MEMORY_ALIGN(offset_annotationDefault + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_root = MEMORY_ALIGN(offset_methodAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_securityCheckTargetClassCache = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_securityCheckTargetClassCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_reflect_Method(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_reflect_Method(jobject h);
+ java_lang_reflect_Method(methodinfo* m);
+
+ java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
+
+ // Getters.
+ inline int32_t get_override () const;
+ inline classinfo* get_clazz () const;
+ inline int32_t get_slot () const;
+ inline java_handle_bytearray_t* get_annotations () const;
+ inline java_handle_bytearray_t* get_parameterAnnotations() const;
+ inline java_handle_bytearray_t* get_annotationDefault () const;
+
+ // Setters.
+
+ // Convenience functions.
+ inline methodinfo* get_method() const;
+};
+
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(jobject h) : java_lang_Object(h)
+{
+ java_lang_reflect_Method((java_handle_t*) h);
+}
+
+inline java_lang_reflect_Method::java_lang_reflect_Method(methodinfo* m)
+{
+ _handle = builtin_new(class_java_lang_reflect_Method);
+
+ if (is_null())
+ return;
+
+ set(_handle, offset_clazz, m->clazz);
+ set(_handle, offset_slot, m - m->clazz->methods);
+ set(_handle, offset_name, javastring_intern(javastring_new(m->name)));
+ set(_handle, offset_returnType, method_returntype_get(m));
+ set(_handle, offset_parameterTypes, method_get_parametertypearray(m));
+ set(_handle, offset_exceptionTypes, method_get_exceptionarray(m));
+ set(_handle, offset_modifiers, m->flags & ACC_CLASS_REFLECT_MASK);
+ set(_handle, offset_signature, m->signature ? javastring_new(m->signature) : NULL);
+ set(_handle, offset_annotations, method_get_annotations(m));
+ set(_handle, offset_parameterAnnotations, method_get_parameterannotations(m));
+ set(_handle, offset_annotationDefault, method_get_annotationdefault(m));
+}
+
+
+inline int32_t java_lang_reflect_Method::get_override() const
+{
+ return get<int32_t>(_handle, offset_override);
+}
+
+inline classinfo* java_lang_reflect_Method::get_clazz() const
+{
+ return get<classinfo*>(_handle, offset_clazz);
+}
+
+inline int32_t java_lang_reflect_Method::get_slot() const
+{
+ return get<int32_t>(_handle, offset_slot);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Method::get_annotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Method::get_parameterAnnotations() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
+}
+
+inline java_handle_bytearray_t* java_lang_reflect_Method::get_annotationDefault() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_annotationDefault);
+}
+
+
+inline methodinfo* java_lang_reflect_Method::get_method() const
+{
+ classinfo* c = get_clazz();
+ int32_t slot = get_slot();
+ methodinfo* m = &(c->methods[slot]);
+ return m;
+}
+
+
+/**
+ * OpenJDK java/nio/Buffer
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int mark;
+ * 2. int position;
+ * 3. int limit;
+ * 4. int capacity;
+ * 5. long address;
+ */
+class java_nio_Buffer : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_mark = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_position = MEMORY_ALIGN(offset_mark + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_limit = MEMORY_ALIGN(offset_position + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_capacity = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_address = MEMORY_ALIGN(offset_capacity + sizeof(int32_t), sizeof(int64_t));
+
+public:
+ java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
+ java_nio_Buffer(jobject h) : java_lang_Object(h) {}
+
+ // Getters.
+ inline void* get_address() const;
+};
+
+
+inline void* java_nio_Buffer::get_address() const
+{
+ return get<void*>(_handle, offset_address);
+}
+
+#endif // WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
+
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
+
+/**
+ * CLDC 1.1 com/sun/cldchi/jvm/FileDescriptor
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. long pointer;
+ * 2. int position;
+ * 3. int length;
+ */
+class com_sun_cldchi_jvm_FileDescriptor : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_pointer = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int64_t));
+ static const off_t offset_position = MEMORY_ALIGN(offset_pointer + sizeof(int64_t), sizeof(int32_t));
+ static const off_t offset_length = MEMORY_ALIGN(offset_position + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h) : java_lang_Object(h) {}
+ com_sun_cldchi_jvm_FileDescriptor(jobject h);
+ com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, int64_t pointer, int32_t position, int32_t length);
+ com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, com_sun_cldchi_jvm_FileDescriptor& fd);
+
+ // Getters.
+ inline int64_t get_pointer () const;
+ inline int32_t get_position() const;
+ inline int32_t get_length () const;
+
+ // Setters.
+ inline void set_pointer (int64_t value);
+ inline void set_position(int32_t value);
+ inline void set_length (int32_t value);
+};
+
+
+inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(jobject h) : java_lang_Object(h)
+{
+ com_sun_cldchi_jvm_FileDescriptor((java_handle_t*) h);
+}
+
+inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, int64_t pointer, int32_t position, int32_t length) : java_lang_Object(h)
+{
+ set_pointer(pointer);
+ set_position(position);
+ set_length(length);
+}
+
+inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, com_sun_cldchi_jvm_FileDescriptor& fd) : java_lang_Object(h)
+{
+ com_sun_cldchi_jvm_FileDescriptor(h, fd.get_pointer(), fd.get_position(), fd.get_length());
+}
+
+
+inline int64_t com_sun_cldchi_jvm_FileDescriptor::get_pointer() const
+{
+ return get<int64_t>(_handle, offset_pointer);
+}
+
+inline int32_t com_sun_cldchi_jvm_FileDescriptor::get_position() const
+{
+ return get<int32_t>(_handle, offset_position);
+}
+
+inline int32_t com_sun_cldchi_jvm_FileDescriptor::get_length() const
+{
+ return get<int32_t>(_handle, offset_length);
+}
+
+
+inline void com_sun_cldchi_jvm_FileDescriptor::set_pointer(int64_t value)
+{
+ set(_handle, offset_pointer, value);
+}
+
+inline void com_sun_cldchi_jvm_FileDescriptor::set_position(int32_t value)
+{
+ set(_handle, offset_position, value);
+}
+
+inline void com_sun_cldchi_jvm_FileDescriptor::set_length(int32_t value)
+{
+ set(_handle, offset_length, value);
+}
+
+
+/**
+ * CLDC 1.1 java/lang/String
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. char[] value;
+ * 2. int offset;
+ * 3. int count;
+ */
+class java_lang_String : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_offset = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_count = MEMORY_ALIGN(offset_offset + sizeof(int32_t), sizeof(int32_t));
+
+public:
+ java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_String(jstring h);
+ java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
+
+ // Getters.
+ inline java_handle_chararray_t* get_value () const;
+ inline int32_t get_offset() const;
+ inline int32_t get_count () const;
+
+ // Setters.
+ inline void set_value (java_handle_chararray_t* value);
+ inline void set_offset(int32_t value);
+ inline void set_count (int32_t value);
+};
+
+inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
+{
+ java_lang_String((java_handle_t*) h);
+}
+
+inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
+{
+ set_value(value);
+ set_offset(offset);
+ set_count(count);
+}
+
+inline java_handle_chararray_t* java_lang_String::get_value() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_value);
+}
+
+inline int32_t java_lang_String::get_offset() const
+{
+ return get<int32_t>(_handle, offset_offset);
+}
+
+inline int32_t java_lang_String::get_count() const
+{
+ return get<int32_t>(_handle, offset_count);
+}
+
+inline void java_lang_String::set_value(java_handle_chararray_t* value)
+{
+ set(_handle, offset_value, value);
+}
+
+inline void java_lang_String::set_offset(int32_t value)
+{
+ set(_handle, offset_offset, value);
+}
+
+inline void java_lang_String::set_count(int32_t value)
+{
+ set(_handle, offset_count, value);
+}
+
+
+/**
+ * CLDC 1.1 java/lang/Thread
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. int priority;
+ * 2. java.lang.Runnable runnable;
+ * 3. java.lang.Object vm_thread;
+ * 4. int is_terminated;
+ * 5. int is_stillborn;
+ * 6. char[] name;
+ */
+class java_lang_Thread : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_priority = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
+ static const off_t offset_runnable = MEMORY_ALIGN(offset_priority + sizeof(int32_t), SIZEOF_VOID_P);
+ static const off_t offset_vm_thread = MEMORY_ALIGN(offset_runnable + SIZEOF_VOID_P, SIZEOF_VOID_P);
+ static const off_t offset_is_terminated = MEMORY_ALIGN(offset_vm_thread + SIZEOF_VOID_P, sizeof(int32_t));
+ static const off_t offset_is_stillborn = MEMORY_ALIGN(offset_is_terminated + sizeof(int32_t), sizeof(int32_t));
+ static const off_t offset_name = MEMORY_ALIGN(offset_is_stillborn + sizeof(int32_t), SIZEOF_VOID_P);
+
+public:
+ java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_Thread(jobject h);
+// java_lang_Thread(threadobject* t);
+
+ // Getters.
+ inline int32_t get_priority () const;
+ inline threadobject* get_vm_thread() const;
+ inline java_handle_chararray_t* get_name () const;
+
+ // Setters.
+ inline void set_vm_thread(threadobject* value);
+};
+
+
+inline java_lang_Thread::java_lang_Thread(jobject h) : java_lang_Object(h)
+{
+ java_lang_Thread((java_handle_t*) h);
+}
+
+// inline java_lang_Thread::java_lang_Thread(threadobject* t) : java_lang_Object(h)
+// {
+// java_lang_Thread(thread_get_object(t));
+// }
+
+
+inline int32_t java_lang_Thread::get_priority() const
+{
+ return get<int32_t>(_handle, offset_priority);
+}
+
+inline threadobject* java_lang_Thread::get_vm_thread() const
+{
+ return get<threadobject*>(_handle, offset_vm_thread);
+}
+
+inline java_handle_chararray_t* java_lang_Thread::get_name() const
+{
+ return get<java_handle_chararray_t*>(_handle, offset_name);
+}
+
+
+inline void java_lang_Thread::set_vm_thread(threadobject* value)
+{
+ set(_handle, offset_vm_thread, value);
+}
+
+
+/**
+ * CLDC 1.1 java/lang/Throwable
+ *
+ * Object layout:
+ *
+ * 0. object header
+ * 1. java.lang.String detailMessage;
+ * 2. java.lang.Object backtrace;
+ */
+class java_lang_Throwable : public java_lang_Object, private FieldAccess {
+private:
+ // Static offsets of the object's instance fields.
+ // TODO These offsets need to be checked on VM startup.
+ static const off_t offset_detailMessage = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
+ static const off_t offset_backtrace = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
+
+public:
+ java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
+ java_lang_Throwable(jobject h);
+
+ // Getters.
+ inline java_handle_t* get_detailMessage() const;
+ inline java_handle_bytearray_t* get_backtrace () const;
+
+ // Setters.
+ inline void set_backtrace(java_handle_bytearray_t* value);
+};
+
+
+inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
+{
+ java_lang_Throwable((java_handle_t*) h);
+}
+
+
+inline java_handle_t* java_lang_Throwable::get_detailMessage() const
+{
+ return get<java_handle_t*>(_handle, offset_detailMessage);
+}
+
+inline java_handle_bytearray_t* java_lang_Throwable::get_backtrace() const
+{
+ return get<java_handle_bytearray_t*>(_handle, offset_backtrace);
+}
+
+
+inline void java_lang_Throwable::set_backtrace(java_handle_bytearray_t* value)
+{
+ set(_handle, offset_backtrace, value);
+}
+
+#endif // WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1
+
+#else
+
+// Legacy C interface.
+java_handle_t* java_lang_reflect_Constructor_create(methodinfo* m);
+java_handle_t* java_lang_reflect_Field_create(fieldinfo* f);
+java_handle_t* java_lang_reflect_Method_create(methodinfo* m);
+
+#endif
+
+#endif // _JAVAOBJECTS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
#include "vm/resolve.h"
#include "vm/string.hpp"
#include "vm/jit/show.h"
#include "vm/jit/allocator/simplereg.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
#if 0
# define LOG(args) printf args
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/* codegen_emit ****************************************************************
#include "threads/lock-common.h"
+#include "vm/options.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "vm/builtin.h"
#include "vm/signallocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
#include "vm/jit/trap.h"
-#include "vmcore/os.hpp"
-
/* md_signal_handler_sigsegv ***************************************************
#include "vm/jit/alpha/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
-#include "vmcore/descriptor.h"
-
/* register descripton array **************************************************/
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/methodheader.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
-
#define PATCH_BACK_ORIGINAL_MCODE \
*((u4 *) pr->mpc) = (u4) pr->mcode; \
#include "native/llni.h"
#include "vm/array.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
+#include "vm/method.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/vm.hpp"
#include "vm/jit/abi-asm.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/method.h"
-
/* argument_jitarray_load ******************************************************
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/* codegen_emit ****************************************************************
#include "threads/thread.hpp"
+#include "vm/os.hpp"
#include "vm/signallocal.h"
#include "vm/vm.hpp"
#include "vm/jit/executionstate.h"
#include "vm/jit/trap.h"
-#include "vmcore/os.hpp"
-
/* md_signal_handler_sigsegv ***************************************************
#include "vm/jit/arm/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
-#include "vmcore/descriptor.h"
-
/* register descripton array **************************************************/
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
-
#define PATCH_BACK_ORIGINAL_MCODE \
*((u4 *) pr->mpc) = (u4) pr->mcode; \
#include "vm/types.h"
#include "vm/global.h"
+#include "vm/linker.h"
#include "vm/vm.hpp"
-#include "vmcore/linker.h"
-
/* function prototypes ********************************************************/
#include "mm/memory.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/code.h"
#include "vm/jit/patcher-common.h"
#include "vm/jit/methodtree.h"
-#include "vmcore/options.h"
-
/* code_init *******************************************************************
#include "toolbox/list.h"
#include "vm/global.h"
+#include "vm/method.h"
#include "vm/jit/exceptiontable.h"
#include "vm/jit/linenumbertable.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/replace.h"
-#include "vmcore/method.h"
-
/* constants ******************************************************************/
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
#include "vm/string.hpp"
+# include "vm/statistics.h"
+
+
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/code.h"
#include "vm/jit/intrp/intrp.h"
#endif
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
-# include "vmcore/statistics.h"
-
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
#endif
#include "vm/types.h"
#include "vm/builtin.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
#include "vm/jit/dseg.h"
#include "vm/jit/jit.h"
#include "vm/jit/code.h"
#include "vm/jit/replace.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-
#define MCODEINITSIZE (1<<15) /* 32 Kbyte code area initialization size */
#define DSEGINITSIZE (1<<12) /* 4 Kbyte data area initialization size */
/* src/vm/jit/dseg.c - data segment handling stuff
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "mm/memory.h"
+#include "vm/options.h"
+
#include "vm/jit/codegen-common.h"
#include "vm/jit/methodheader.h"
-#include "vmcore/options.h"
-
/* dseg_finish *****************************************************************
/* src/vm/jit/dseg.c - data segment handling stuff
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "toolbox/list.h"
+#include "vm/references.h"
+
#include "vm/jit/jit.h"
#include "vm/jit/codegen-common.h"
-#include "vmcore/references.h"
-
/* convenience macros *********************************************************/
#include "arch.h"
#include "codegen.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* emit_load_s1 ****************************************************************
#include "md-abi.h"
+#include "vm/descriptor.h"
+#include "vm/os.hpp"
+
#include "vm/jit/abi.h"
#include "vm/jit/executionstate.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/os.hpp"
-
/* executionstate_sanity_check *************************************************
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
/* codegen_emit ****************************************************************
#include "threads/lock-common.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/dseg.h"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* emit_load ******************************************************************
#include "vm/jit/i386/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
-#include "vmcore/descriptor.h"
-
/* register descripton - array ************************************************/
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-#include "vmcore/references.h"
-
#define PATCH_BACK_ORIGINAL_MCODE *((u2 *) pr->mpc) = (u2) pr->mcode
#include "toolbox/logging.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/global.h"
#include "vm/initialize.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
#include "vm/jit/jit.h"
#include "vm/jit/parse.h"
#include "vm/jit/verify/typecheck.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* algorithm tuning constants *************************************************/
#include "threads/thread.hpp"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/intrp/intrp.h"
-#include "vmcore/class.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_VMLOG)
#include <vmlog_cacao.h>
#endif
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/stack.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/class.h"
-#include "vmcore/options.h"
-
#define gen_branch(_inst) { \
gen_##_inst(cd, 0); \
Copyright (C) 1995,1996,1997,1998,2000,2003,2004 Free Software Foundation, Inc.
Taken from Gforth.
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
+
*/
#include "toolbox/hashtable.h"
#include "toolbox/logging.h"
+#include "vm/options.h"
+
#include "vm/jit/disass.h"
#include "vm/jit/intrp/intrp.h"
-#include "vmcore/options.h"
-
s4 no_super=0; /* option: just use replication, but no dynamic superinsts */
#include "threads/thread.hpp"
#include "vm/builtin.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/patcher.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_THREADS)
# include "threads/atomic.hpp"
/* src/vm/jit/intrp/intrp.h - definitions for Interpreter
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
typedef s4 Cell;
#endif
+#include "vm/class.h"
#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/codegen-common.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
-#include "vmcore/linker.h"
-
typedef void *Label;
typedef void *Inst;
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-#include "vmcore/references.h"
-
/* patcher_get_putstatic *******************************************************
#include "vm/jit/intrp/intrp.h"
-#include "vmcore/options.h"
+#include "vm/options.h"
/* the numbers in this struct are primitive indices */
#include "threads/lock-common.h"
+#include "vm/class.h"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/rt-timing.h"
+#include "vm/statistics.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/verify/typecheck.h"
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-#include "vmcore/statistics.h"
-
/* debug macros ***************************************************************/
#include "toolbox/chain.h"
#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
#include "vm/resolve.h"
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
#include "vm/jit/codegen-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/replace.h"
#include "vm/jit/verify/typeinfo.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
/* common jit/codegen macros **************************************************/
#include "mm/memory.h"
+#if defined(ENABLE_STATISTICS)
+# include "vm/options.h"
+# include "vm/statistics.h"
+#endif
+
#include "vm/jit/code.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/linenumbertable.h"
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/options.h"
-# include "vmcore/statistics.h"
-#endif
#if defined(__S390__)
# define ADDR_MASK(type, x) ((type)((uintptr_t)(x) & 0x7FFFFFFF))
#include "toolbox/list.h"
+#include "vm/method.h"
+
#include "vm/jit/jit.h"
#include "vm/jit/code.h"
#include "vm/jit/codegen-common.h"
-#include "vmcore/method.h"
-
/* linenumbertable_t **********************************************************/
/* src/vm/jit/loop/graph.h - control flow graph header
Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "config.h"
#include "vm/types.h"
-#include "vm/jit/loop/loop.h"
+#include "vm/method.h"
-#include "vmcore/method.h"
+#include "vm/jit/loop/loop.h"
/* function prototypes ********************************************************/
/* src/vm/jit/loop/loop.h - array bound removal header
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/types.h"
#include "vm/global.h"
+#include "vm/method.h"
#include "vm/jit/jit.h"
-#include "vmcore/method.h"
-
/* Different types for struct Trace */
#define TRACE_UNKNOWN 0 /* unknown */
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
bool codegen_emit(jitdata *jd)
{
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-
#include "codegen.h"
#define PATCH_BACK_ORIGINAL_MCODE *((u4*)(pr->mpc)) = pr->mcode
#include "threads/lock-common.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/class.h"
-#include "vmcore/options.h"
-
/* codegen_emit ****************************************************************
#include "threads/lock-common.h"
#include "vm/builtin.h"
+#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/replace.h"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "mm/memory.h"
#include "vm/signallocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
#include "vm/jit/trap.h"
-#include "vmcore/os.hpp"
-
/* md_init *********************************************************************
#include "mm/memory.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
+#include "vm/method.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/method.h"
-
/* register descripton array **************************************************/
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-#include "vmcore/references.h"
-
#define PATCH_BACK_ORIGINAL_MCODE \
*((u4 *) pr->mpc) = (u4) pr->mcode; \
extern "C" {
#endif
-#include "vmcore/method.h"
+#include "vm/method.h"
#include <opagent.h>
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 "mm/dumpmemory.h"
#include "mm/memory.h"
#include "toolbox/bitvector.h"
+#include "vm/class.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
-#include "vm/jit/ir/bytecode.h"
-#include "vm/jit/optimizing/escape.h"
+#include "vm/references.h"
#include "vm/resolve.h"
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/references.h"
+#include "vm/jit/ir/bytecode.h"
+#include "vm/jit/optimizing/escape.h"
#include <assert.h>
#include <stdarg.h>
-/* src/vm/optimizing/e&scape.c
+/* src/vm/jit/optimizing/escape.c
Copyright (C) 2008
CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
+
*/
+
+#include "config.h"
+
+#include "vm/class.h"
+#include "vm/classcache.h"
+
#include "vm/jit/jit.h"
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
#include "vm/jit/optimizing/escape.h"
#include <stdarg.h>
#define _VM_JIT_OPTIMIZING_ESCAPE_H
#include "vm/jit/jit.h"
-#include "vmcore/method.h"
+#include "vm/method.h"
typedef enum {
ESCAPE_UNKNOWN,
/* src/vm/jit/optimizing/graph.c - CFG
- Copyright (C) 2005, 2006 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2005, 2006, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Christian Ullrich
-
- $Id: graph.c$
-
*/
#include <stdlib.h>
#include "vm/jit/optimizing/graph.h"
#ifdef GRAPH_DEBUG_VERBOSE
-#include "vmcore/options.h"
+#include "vm/options.h"
#endif
/* Helpers for graph_make_cfg */
#include "vm/types.h"
+#include "vm/method.h"
#include "vm/vm.hpp"
#include "vm/jit/codegen-common.h"
#include "vm/jit/reg.h"
#include "vm/jit/show.h"
-#include "vmcore/method.h"
-
/* patterns for a total number of 3 instructions ******************************/
/* src/vm/jit/optimizing/ifconv.h - if-conversion
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
#include "vm/jit/jit.h"
#include "vm/jit/reg.h"
-#include "vmcore/method.h"
-
/* function prototypes ********************************************************/
#include "vm/jit/optimizing/lifetimes.h"
#ifdef LT_DEBUG_VERBOSE
-#include "vmcore/options.h"
+#include "vm/options.h"
#endif
#include <time.h>
#include "toolbox/bitvector.h"
-#include "vmcore/statistics.h"
-#include "vmcore/options.h"
-#include "vmcore/method.h"
+#include "vm/statistics.h"
+#include "vm/options.h"
+#include "vm/method.h"
#include "vm/jit/abi.h"
#include "vm/jit/reg.h"
#include "threads/thread.hpp"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/classcache.h"
+#include "vm/method.h"
+#include "vm/options.h"
#include "vm/string.hpp"
#include "vm/jit/jit.h"
#include "vm/jit/optimizing/recompile.h"
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
/* profile_init ****************************************************************
#include "toolbox/list.h"
#include "vm/builtin.h"
+#include "vm/classcache.h"
#include "vm/exceptions.hpp"
+#include "vm/options.h"
#include "vm/string.hpp"
#include "vm/jit/code.h"
#include "vm/jit/optimizing/recompile.h"
-#include "vmcore/classcache.h"
-#include "vmcore/options.h"
-
/* global variables ***********************************************************/
#include "vm/jit/python.h"
#if defined(SSA_DEBUG_VERBOSE)
-#include "vmcore/options.h" /* compileverbose */
+#include "vm/options.h" /* compileverbose */
#endif
/* function prototypes */
-/* src/vm/optimizing/ssa3.c
+/* src/vm/jit/optimizing/ssa3.c
Copyright (C) 2008
CACAOVM - Verein zu Foerderung der freien virtuellen Machine CACAO
ssa->jd->localcount = ssa->original.localcount;
}
-#include "vmcore/rt-timing.h"
+#include "vm/rt-timing.h"
void yssa(jitdata *jd) {
basicblock *it;
/* src/vm/jit/optimizing/ssa.c - static single-assignment form
- Copyright (C) 2005 - 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
+ Copyright (C) 2005-2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
This file is part of CACAO.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Christian Ullrich
+*/
- $Id: $
-*/
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include "vm/jit/optimizing/ssa_phi.h"
#if defined(SSA_DEBUG_VERBOSE)
-#include "vmcore/options.h" /* compileverbose */
+#include "vm/options.h" /* compileverbose */
#endif
/* ssa_place_phi_functions *****************************************************
#include "vm/jit/optimizing/ssa_rename.h"
#if defined(SSA_DEBUG_VERBOSE)
-#include "vmcore/options.h" /* compileverbose */
+#include "vm/options.h" /* compileverbose */
#endif
/* function prototypes */
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
#include "vm/string.hpp"
+#include "vm/suck.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/jit.h"
#include "vm/jit/ir/bytecode.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/suck.h"
#define INSTRUCTIONS_INCREMENT 5 /* number of additional instructions to */
/* allocate if space runs out */
#include "vm/exceptions.hpp"
#include "vm/initialize.h"
+#include "vm/options.h"
#include "vm/resolve.h"
#include "vm/vm.hpp" /* for vm_abort */
#include "vm/jit/jit.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/options.h"
-
/* patcher_function_list *******************************************************
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/* codegen *********************************************************************
#include "vm/jit/powerpc/darwin/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* register descripton arrays *************************************************/
#include "threads/lock-common.h"
+#include "vm/options.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "vm/jit/powerpc/linux/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* register descripton arrays *************************************************/
#include "vm/builtin.h"
#include "vm/signallocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
#include "vm/jit/trap.h"
-#include "vmcore/os.hpp"
-
/* md_signal_handler_sigsegv ***************************************************
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-#include "vmcore/references.h"
-
#define PATCH_BACK_ORIGINAL_MCODE \
*((u4 *) pr->mpc) = (u4) pr->mcode; \
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/stacktrace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_LSRA)
# include "vm/jit/allocator/lsra.h"
#endif
#include "threads/lock-common.h"
+#include "vm/options.h"
#include "vm/vm.hpp"
#include "vm/jit/abi.h"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "vm/jit/powerpc64/linux/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
#define CACAO_ALIGN(a) do { if ((a) & 1) (a)++; } while (0)
#include "vm/builtin.h"
#include "vm/signallocal.h"
+#include "vm/os.hpp"
#include "vm/jit/asmpart.h"
#include "vm/jit/executionstate.h"
#include "vm/jit/trap.h"
-#include "vmcore/os.hpp"
-
/* md_signal_handler_sigsegv ***************************************************
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
-
/* patcher_patch_code **********************************************************
#include "toolbox/logging.h"
+#include "vm/classcache.h"
+#include "vm/globals.hpp"
+#include "vm/options.h"
#include "vm/string.hpp"
+#if defined(ENABLE_RT_TIMING)
+# include "vm/rt-timing.h"
+#endif
+
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/disass.h"
#include "vm/jit/show.h"
#include "vm/jit/stack.h"
-#include "vmcore/classcache.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/options.h"
-
-#if defined(ENABLE_RT_TIMING)
-# include "vmcore/rt-timing.h"
-#endif
#define REPLACE_PATCH_DYNAMIC_CALL
/*#define REPLACE_PATCH_ALL*/
#include "arch.h"
#include "md-abi.h"
+#include "vm/method.h"
+
#include "vm/jit/reg.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/method.h"
-
/*** structs *********************************************************/
#include "threads/lock-common.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
#include "vm/types.h"
#include "vm/vm.hpp"
#include "vm/builtin.h"
#include "vm/global.h"
#include "vm/types.h"
+#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "config.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/types.h"
#include "vm/jit/s390/md-abi.h"
-#include "vmcore/descriptor.h"
-
#include <assert.h>
#include "vm/jit/trap.h"
#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
-#include "vmcore/options.h" /* XXX debug */
+#include "vm/options.h" /* XXX debug */
#include "vm/jit/disass.h" /* XXX debug */
#endif
#include "mm/memory.h"
#include "native/native.h"
+
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
+#include "vm/types.h"
+
#include "vm/jit/patcher-common.h"
#include "vm/jit/s390/codegen.h"
#include "vm/jit/s390/md-abi.h"
-#include "vm/resolve.h"
-#include "vm/types.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
+
#define PATCH_BACK_ORIGINAL_MCODE \
*((u2 *) pr->mpc) = (u2) pr->mcode;
#include "vm/global.h"
#include "vm/builtin.h"
+#include "vm/options.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/jit/stack.h"
#include "vm/jit/parse.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_DEBUG_FILTER)
# include <sys/types.h>
# include <regex.h>
#include "native/jni.h"
#include "native/localref.h"
#include "native/native.h"
+
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/jit/abi.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#include "vm/jit/sparc64/solaris/macro_rename.h"
#define BUILTIN_FLOAT_ARGS 1
#include "mm/memory.h"
+#include "vm/builtin.h"
+#include "vm/options.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
-#include "vm/builtin.h"
#include "vm/jit/dseg.h"
#include "vm/jit/emit-common.h"
#include "vm/jit/jit.h"
#include "vm/jit/replace.h"
-#include "vmcore/options.h"
-
#include "vm/jit/sparc64/solaris/macro_rename.h"
/* how to leaf optimization in the emitted stubs?? */
#include "vm/jit/sparc64/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* temp */
#include "mm/memory.h"
#include <assert.h>
#include "vm/jit/sparc64/md-abi.h"
#include "native/native.h"
+
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/exceptions.hpp"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/patcher.h"
#include "vm/jit/methodheader.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
-
#include "vm/jit/sparc64/solaris/macro_rename.h"
#include "toolbox/logging.h"
-#include "vm/global.h"
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
#include "vm/string.hpp"
#include "vm/types.h"
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
#include "vm/jit/abi.h"
#include "vm/jit/cfg.h"
#include "vm/jit/codegen-common.h"
#endif
#endif
-#include "vmcore/options.h"
-#include "vm/resolve.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
/*#define STACK_VERBOSE*/
#include "vm/array.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/cycles-stats.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/jit/methodheader.h"
#include "vm/jit/methodtree.h"
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
// FIXME Use C-linkage for now.
extern "C" {
#include "threads/thread.hpp"
+#include "vm/class.h"
#include "vm/global.h"
#include "vm/jit/code.h"
-#include "vmcore/class.h"
-
/* stackframeinfo **************************************************************
#include "toolbox/logging.h"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
#include "vm/string.hpp"
+#include "vm/utf8.h"
+
#include "vm/jit/argument.h"
#include "vm/jit/codegen-common.h"
#include "vm/jit/trace.hpp"
#include "vm/jit/show.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
#if !defined(NDEBUG)
#include <stdint.h>
-#include "vmcore/method.h"
+#include "vm/method.h"
#if !defined(NDEBUG)
#include "toolbox/logging.h"
#include "vm/exceptions.hpp"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/vm.hpp"
#include "vm/jit/code.h"
#include "vm/jit/replace.h"
#include "vm/jit/stacktrace.hpp"
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
-
/**
* Mmap the first memory page to support hardware exceptions and check
#include <assert.h>
#include "vm/exceptions.hpp"
-#include "vm/jit/show.h"
+#include "vm/globals.hpp"
-#include "vmcore/globals.hpp"
+#include "vm/jit/show.h"
#include "typecheck-common.h"
#include "vm/array.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/primitive.hpp"
#include "vm/jit/parse.h"
#include "vm/jit/stack.h"
#include "vm/jit/verify/typecheck-common.h"
-#include "vmcore/globals.hpp"
-
/* this #if runs over the whole file: */
#if defined(ENABLE_VERIFIER)
#include "toolbox/logging.h"
-#include "vm/array.h"
#include "vm/access.h"
+#include "vm/array.h"
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/vm.hpp"
#include "vm/jit/verify/typecheck-typeinferer.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#define TYPECHECK_NO_STATISTICS
#include <typecheck-common.h>
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/jit/parse.h"
#include "vm/jit/show.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
#include <typecheck-common.h>
#include "toolbox/logging.h"
#include "vm/array.h"
+#include "vm/class.h"
+#include "vm/descriptor.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/jit/jit.h"
#include "vm/jit/verify/typeinfo.h"
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/loader.h"
-
/* check if a linked class is an array class. Only use for linked classes! */
#define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL)
#include "vm/types.h"
#include "vm/global.h"
-
-#include "vmcore/references.h"
+#include "vm/references.h"
/* configuration **************************************************************/
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
+#include "vm/statistics.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
# include "vm/jit/allocator/lsra.h"
#endif
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
/* codegen_emit ****************************************************************
#include "threads/lock-common.h"
+#include "vm/options.h"
+
#include "vm/jit/abi.h"
#include "vm/jit/abi-asm.h"
#include "vm/jit/asmpart.h"
#include "vm/jit/trace.hpp"
#include "vm/jit/trap.h"
-#include "vmcore/options.h"
-
/* emit_load *******************************************************************
#include "vm/jit/x86_64/md-abi.h"
+#include "vm/descriptor.h"
#include "vm/global.h"
#include "vm/jit/abi.h"
#include "vm/jit/jit.h" /* for REG_* (maybe can be removed) */
#include "vm/jit/stack.h"
-#include "vmcore/descriptor.h"
-
/* register descripton array **************************************************/
#include "native/native.h"
#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/references.h"
+#include "vm/resolve.h"
#include "vm/jit/patcher-common.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vm/resolve.h"
-
#define PATCH_BACK_ORIGINAL_MCODE \
do { \
+++ /dev/null
-/* src/vm/jit_interface.h - prototypes of jit functions used in vm/ code
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _JIT_INTERFACE
-#define _JIT_INTERFACE
-
-#include "config.h"
-#include "vm/types.h"
-
-
-/* These functions are used from vm/ but defined in vm/jit/ */
-
-void code_free_code_of_method(methodinfo *m);
-
-u1 *codegen_generate_stub_compiler(methodinfo *m);
-codeinfo *codegen_generate_stub_native(methodinfo *m, functionptr f);
-
-#if defined(ENABLE_INTRP)
-u1 *intrp_createcompilerstub(methodinfo *m);
-#endif
-
-void removecompilerstub(u1 *stub);
-void removenativestub(u1 *stub);
-
-void jit_invalidate_code(methodinfo *m);
-
-void md_param_alloc(methoddesc *md);
-void md_param_alloc_native(methoddesc *md);
-
-/* stub for throwing AbstractMethodError's */
-#if defined(ENABLE_JIT)
-void asm_abstractmethoderror(void);
-#endif
-
-#if defined(ENABLE_INTRP)
-void intrp_asm_abstractmethoderror(void);
-#endif
-
-#endif /* _JIT_INTERFACE */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
--- /dev/null
+/* src/vm/linker.c - class linker functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/native.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/logging.h"
+
+#include "vm/access.h"
+#include "vm/array.h"
+#include "vm/class.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/rt-timing.h"
+#include "vm/string.hpp"
+#include "vm/vm.hpp"
+
+#include "vm/jit/asmpart.h"
+
+
+/* debugging macros ***********************************************************/
+
+#if !defined(NDEBUG)
+# define TRACELINKCLASS(c) \
+ do { \
+ if (opt_TraceLinkClass) { \
+ log_start(); \
+ log_print("[Linking "); \
+ class_print((c)); \
+ log_print("]"); \
+ log_finish(); \
+ } \
+ } while (0)
+#else
+# define TRACELINKCLASS(c)
+#endif
+
+
+/* #include "vm/resolve.h" */
+/* copied prototype to avoid bootstrapping problem: */
+classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
+#else
+#define INLINELOG(code)
+#endif
+
+
+/* global variables ***********************************************************/
+
+static s4 interfaceindex; /* sequential numbering of interfaces */
+static s4 classvalue;
+
+java_object_t *linker_classrenumber_lock;
+
+
+/* private functions **********************************************************/
+
+static classinfo *link_class_intern(classinfo *c);
+static arraydescriptor *link_array(classinfo *c);
+static void linker_compute_class_values(classinfo *c);
+static void linker_compute_subclasses(classinfo *c);
+static bool linker_addinterface(classinfo *c, classinfo *ic);
+static s4 class_highestinterface(classinfo *c);
+
+
+/* linker_init *****************************************************************
+
+ Initializes the linker subsystem and links classes required for the
+ primitive table.
+
+*******************************************************************************/
+
+void linker_preinit(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("linker_preinit");
+
+ /* Reset interface index. */
+
+ interfaceindex = 0;
+
+#if defined(ENABLE_THREADS)
+ /* create the global lock object */
+
+ linker_classrenumber_lock = NEW(java_object_t);
+
+ LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
+#endif
+
+ /* Link the most basic classes. */
+
+ if (!link_class(class_java_lang_Object))
+ vm_abort("linker_preinit: linking java/lang/Object failed");
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_Cloneable))
+ vm_abort("linker_preinit: linking java/lang/Cloneable failed");
+
+ if (!link_class(class_java_io_Serializable))
+ vm_abort("linker_preinit: linking java/io/Serializable failed");
+#endif
+}
+
+
+/* linker_init *****************************************************************
+
+ Links all classes required in the VM.
+
+*******************************************************************************/
+
+void linker_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("linker_init");
+
+ /* Link java.lang.Class as first class of the system, because we
+ need it's vftbl for all other classes so we can use a class as
+ object. */
+
+ if (!link_class(class_java_lang_Class))
+ vm_abort("linker_init: linking java/lang/Class failed");
+
+ /* Now set the header.vftbl of all classes which were created
+ before java.lang.Class was linked. */
+
+ class_postset_header_vftbl();
+
+ /* Link primitive-type wrapping classes. */
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_Void))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ if (!link_class(class_java_lang_Boolean))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Byte))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Character))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Short))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Integer))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Long))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Float))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Double))
+ vm_abort("linker_init: linking failed");
+
+ /* Link important system classes. */
+
+ if (!link_class(class_java_lang_String))
+ vm_abort("linker_init: linking java/lang/String failed");
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_ClassLoader))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_SecurityManager))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ if (!link_class(class_java_lang_System))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_Thread))
+ vm_abort("linker_init: linking failed");
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_ThreadGroup))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ if (!link_class(class_java_lang_Throwable))
+ vm_abort("linker_init: linking failed");
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ if (!link_class(class_java_lang_VMSystem))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_VMThread))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_VMThrowable))
+ vm_abort("linker_init: linking failed");
+#endif
+
+ /* Important system exceptions. */
+
+ if (!link_class(class_java_lang_Exception))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_ClassNotFoundException))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_RuntimeException))
+ vm_abort("linker_init: linking failed");
+
+ /* some classes which may be used more often */
+
+#if defined(ENABLE_JAVASE)
+ if (!link_class(class_java_lang_StackTraceElement))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_Constructor))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_Field))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_Method))
+ vm_abort("linker_init: linking failed");
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ if (!link_class(class_java_lang_reflect_VMConstructor))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_VMField))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_lang_reflect_VMMethod))
+ vm_abort("linker_init: linking failed");
+# endif
+
+ if (!link_class(class_java_security_PrivilegedAction))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_util_Vector))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_java_util_HashMap))
+ vm_abort("linker_init: linking failed");
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ if (!link_class(class_sun_misc_Signal))
+ vm_abort("linker_init: linking failed");
+
+ if (!link_class(class_sun_reflect_MagicAccessorImpl))
+ vm_abort("linker_init: linking failed");
+# endif
+
+ if (!link_class(arrayclass_java_lang_Object))
+ vm_abort("linker_init: linking failed");
+#endif
+
+
+ /* create pseudo classes used by the typechecker */
+
+ /* pseudo class for Arraystubs (extends java.lang.Object) */
+
+ pseudo_class_Arraystub =
+ class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
+ pseudo_class_Arraystub->state |= CLASS_LOADED;
+ pseudo_class_Arraystub->super = class_java_lang_Object;
+
+#if defined(ENABLE_JAVASE)
+
+ pseudo_class_Arraystub->interfacescount = 2;
+ pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
+ pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
+ pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ pseudo_class_Arraystub->interfacescount = 0;
+ pseudo_class_Arraystub->interfaces = NULL;
+
+#else
+# error unknown Java configuration
+#endif
+
+ if (!classcache_store_unique(pseudo_class_Arraystub))
+ vm_abort("linker_init: could not cache pseudo_class_Arraystub");
+
+ if (!link_class(pseudo_class_Arraystub))
+ vm_abort("linker_init: linking pseudo_class_Arraystub failed");
+
+ /* pseudo class representing the null type */
+
+ pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
+ pseudo_class_Null->state |= CLASS_LOADED;
+ pseudo_class_Null->super = class_java_lang_Object;
+
+ if (!classcache_store_unique(pseudo_class_Null))
+ vm_abort("linker_init: could not cache pseudo_class_Null");
+
+ if (!link_class(pseudo_class_Null))
+ vm_abort("linker_init: linking failed");
+
+ /* pseudo class representing new uninitialized objects */
+
+ pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
+ pseudo_class_New->state |= CLASS_LOADED;
+ pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
+ pseudo_class_New->super = class_java_lang_Object;
+
+ if (!classcache_store_unique(pseudo_class_New))
+ vm_abort("linker_init: could not cache pseudo_class_New");
+
+ /* Correct vftbl-entries (retarded loading and linking of class
+ java/lang/String). */
+
+ stringtable_update();
+}
+
+
+/* link_class ******************************************************************
+
+ Wrapper function for link_class_intern to ease monitor enter/exit
+ and exception handling.
+
+*******************************************************************************/
+
+classinfo *link_class(classinfo *c)
+{
+ classinfo *r;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_end;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ if (c == NULL) {
+ exceptions_throw_nullpointerexception();
+ return NULL;
+ }
+
+ LOCK_MONITOR_ENTER(c);
+
+ /* Maybe the class is currently linking or is already linked.*/
+
+ if ((c->state & CLASS_LINKING) || (c->state & CLASS_LINKED)) {
+ LOCK_MONITOR_EXIT(c);
+
+ return c;
+ }
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ compilingtime_stop();
+
+ if (opt_getloadingtime)
+ loadingtime_start();
+#endif
+
+ /* call the internal function */
+
+ r = link_class_intern(c);
+
+ /* If return value is NULL, we had a problem and the class is not
+ linked. */
+
+ if (r == NULL)
+ c->state &= ~CLASS_LINKING;
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_stop();
+
+ if (opt_getcompilingtime)
+ compilingtime_start();
+#endif
+
+ LOCK_MONITOR_EXIT(c);
+
+ RT_TIMING_GET_TIME(time_end);
+
+ RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
+
+ return r;
+}
+
+
+/* linker_overwrite_method *****************************************************
+
+ Overwrite a method with another one, update method flags and check
+ assumptions.
+
+ IN:
+ mg................the general method being overwritten
+ ms................the overwriting (more specialized) method
+ wl................worklist where to add invalidated methods
+
+ RETURN VALUE:
+ true..............everything ok
+ false.............an exception has been thrown
+
+*******************************************************************************/
+
+static bool linker_overwrite_method(methodinfo *mg,
+ methodinfo *ms,
+ method_worklist **wl)
+{
+ classinfo *cg;
+ classinfo *cs;
+
+ cg = mg->clazz;
+ cs = ms->clazz;
+
+ /* overriding a final method is illegal */
+
+ if (mg->flags & ACC_FINAL) {
+ exceptions_throw_verifyerror(mg, "Overriding final method");
+ return false;
+ }
+
+ /* method ms overwrites method mg */
+
+#if defined(ENABLE_VERIFIER)
+ /* Add loading constraints (for the more general types of method mg). */
+ /* Not for <init>, as it is not invoked virtually. */
+
+ if ((ms->name != utf_init)
+ && !classcache_add_constraints_for_params(
+ cs->classloader, cg->classloader, mg))
+ {
+ return false;
+ }
+#endif
+
+ /* inherit the vftbl index, and record the overwriting */
+
+ ms->vftblindex = mg->vftblindex;
+ ms->overwrites = mg;
+
+ /* update flags and check assumptions */
+ /* <init> methods are a special case, as they are never dispatched dynamically */
+
+ if ((ms->flags & ACC_METHOD_IMPLEMENTED) && ms->name != utf_init) {
+ do {
+
+#if defined(ENABLE_TLH)
+ if (mg->flags & ACC_METHOD_MONOMORPHY_USED) {
+ printf("%s/%s is evil! the siner is %s/%s\n", mg->clazz->name->text, mg->name->text,
+ ms->clazz->name->text, ms->name->text);
+ ms->flags |= ACC_METHOD_PARENT_MONOMORPHY_USED;
+ }
+#endif
+
+ if (mg->flags & ACC_METHOD_IMPLEMENTED) {
+ /* this adds another implementation */
+
+ mg->flags &= ~ACC_METHOD_MONOMORPHIC;
+
+ INLINELOG( printf("becomes polymorphic: "); method_println(mg); );
+
+ method_break_assumption_monomorphic(mg, wl);
+ }
+ else {
+ /* this is the first implementation */
+
+ mg->flags |= ACC_METHOD_IMPLEMENTED;
+
+ INLINELOG( printf("becomes implemented: "); method_println(mg); );
+ }
+
+ ms = mg;
+ mg = mg->overwrites;
+ } while (mg != NULL);
+ }
+
+ return true;
+}
+
+
+/* link_class_intern ***********************************************************
+
+ Tries to link a class. The function calculates the length in bytes
+ that an instance of this class requires as well as the VTBL for
+ methods and interface methods.
+
+*******************************************************************************/
+
+static classinfo *link_class_intern(classinfo *c)
+{
+ classinfo *super; /* super class */
+ classinfo *tc; /* temporary class variable */
+ s4 supervftbllength; /* vftbllegnth of super class */
+ s4 vftbllength; /* vftbllength of current class */
+ s4 interfacetablelength; /* interface table length */
+ vftbl_t *v; /* vftbl of current class */
+ s4 i; /* interface/method/field counter */
+ arraydescriptor *arraydesc; /* descriptor for array classes */
+ method_worklist *worklist; /* worklist for recompilation */
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_resolving, time_compute_vftbl,
+ time_abstract, time_compute_iftbl, time_fill_vftbl,
+ time_offsets, time_fill_iftbl, time_finalizer,
+ time_subclasses;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ TRACELINKCLASS(c);
+
+ /* the class must be loaded */
+
+ /* XXX should this be a specific exception? */
+ assert(c->state & CLASS_LOADED);
+
+ /* This is check in link_class. */
+
+ assert(!(c->state & CLASS_LINKED));
+
+ /* cache the self-reference of this class */
+ /* we do this for cases where the defining loader of the class */
+ /* has not yet been recorded as an initiating loader for the class */
+ /* this is needed so subsequent code can assume that self-refs */
+ /* will always resolve lazily */
+ /* No need to do it for the bootloader - it is always registered */
+ /* as initiating loader for the classes it loads. */
+ if (c->classloader)
+ classcache_store(c->classloader,c,false);
+
+ /* this class is currently linking */
+
+ c->state |= CLASS_LINKING;
+
+ arraydesc = NULL;
+ worklist = NULL;
+
+ /* Link the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ tc = c->interfaces[i];
+
+ if (!(tc->state & CLASS_LINKED))
+ if (!link_class(tc))
+ return NULL;
+ }
+
+ /* check super class */
+
+ super = NULL;
+
+ /* Check for java/lang/Object. */
+
+ if (c->super == NULL) {
+ c->index = 0;
+ c->instancesize = sizeof(java_object_t);
+
+ vftbllength = supervftbllength = 0;
+
+ c->finalizer = NULL;
+ }
+ else {
+ /* Get super class. */
+
+ super = c->super;
+
+ /* Link the super class if necessary. */
+
+ if (!(super->state & CLASS_LINKED))
+ if (!link_class(super))
+ return NULL;
+
+ /* OR the ACC_CLASS_HAS_POINTERS and the ACC_CLASS_REFERENCE_*
+ flags. */
+
+ c->flags |= (super->flags &
+ (ACC_CLASS_HAS_POINTERS | ACC_CLASS_REFERENCE_MASK));
+
+ /* handle array classes */
+
+ if (c->name->text[0] == '[')
+ if (!(arraydesc = link_array(c)))
+ return NULL;
+
+ if (c->flags & ACC_INTERFACE)
+ c->index = interfaceindex++;
+ else
+ c->index = super->index + 1;
+
+ c->instancesize = super->instancesize;
+
+ vftbllength = supervftbllength = super->vftbl->vftbllength;
+
+ c->finalizer = super->finalizer;
+ }
+ RT_TIMING_GET_TIME(time_resolving);
+
+
+ /* compute vftbl length */
+
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ if (!(m->flags & ACC_STATIC)) { /* is instance method */
+ tc = super;
+
+ while (tc) {
+ s4 j;
+
+ for (j = 0; j < tc->methodscount; j++) {
+ if (method_canoverwrite(m, &(tc->methods[j]))) {
+ if (tc->methods[j].flags & ACC_PRIVATE)
+ goto notfoundvftblindex;
+
+ /* package-private methods in other packages */
+ /* must not be overridden */
+ /* (see Java Language Specification 8.4.8.1) */
+ if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
+ && !SAME_PACKAGE(c,tc) )
+ {
+ goto notfoundvftblindex;
+ }
+
+ if (!linker_overwrite_method(&(tc->methods[j]), m, &worklist))
+ return NULL;
+
+ goto foundvftblindex;
+ }
+ }
+
+ tc = tc->super;
+ }
+
+ notfoundvftblindex:
+ m->vftblindex = (vftbllength++);
+ foundvftblindex:
+ ;
+ }
+ }
+ RT_TIMING_GET_TIME(time_compute_vftbl);
+
+
+ /* Check all interfaces of an abstract class (maybe be an
+ interface too) for unimplemented methods. Such methods are
+ called miranda-methods and are marked with the ACC_MIRANDA
+ flag. VMClass.getDeclaredMethods does not return such
+ methods. */
+
+ if (c->flags & ACC_ABSTRACT) {
+ classinfo *ic;
+ methodinfo *im;
+ s4 abstractmethodscount;
+ s4 j;
+ s4 k;
+
+ abstractmethodscount = 0;
+
+ /* check all interfaces of the abstract class */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ ic = c->interfaces[i];
+
+ for (j = 0; j < ic->methodscount; j++) {
+ im = &(ic->methods[j]);
+
+ /* skip `<clinit>' and `<init>' */
+
+ if ((im->name == utf_clinit) || (im->name == utf_init))
+ continue;
+
+ for (tc = c; tc != NULL; tc = tc->super) {
+ for (k = 0; k < tc->methodscount; k++) {
+ if (method_canoverwrite(im, &(tc->methods[k])))
+ goto noabstractmethod;
+ }
+ }
+
+ abstractmethodscount++;
+
+ noabstractmethod:
+ ;
+ }
+ }
+
+ if (abstractmethodscount > 0) {
+ methodinfo *am;
+
+ /* reallocate methods memory */
+
+ c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
+ c->methodscount + abstractmethodscount);
+
+ for (i = 0; i < c->interfacescount; i++) {
+ ic = c->interfaces[i];
+
+ for (j = 0; j < ic->methodscount; j++) {
+ im = &(ic->methods[j]);
+
+ /* skip `<clinit>' and `<init>' */
+
+ if ((im->name == utf_clinit) || (im->name == utf_init))
+ continue;
+
+ for (tc = c; tc != NULL; tc = tc->super) {
+ for (k = 0; k < tc->methodscount; k++) {
+ if (method_canoverwrite(im, &(tc->methods[k])))
+ goto noabstractmethod2;
+ }
+ }
+
+ /* Copy the method found into the new c->methods
+ array and tag it as miranda-method. */
+
+ am = &(c->methods[c->methodscount]);
+ c->methodscount++;
+
+ MCOPY(am, im, methodinfo, 1);
+
+ am->vftblindex = (vftbllength++);
+ am->clazz = c;
+ am->flags |= ACC_MIRANDA;
+
+ noabstractmethod2:
+ ;
+ }
+ }
+ }
+ }
+ RT_TIMING_GET_TIME(time_abstract);
+
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_vftbl_len +=
+ sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
+#endif
+
+ /* compute interfacetable length */
+
+ interfacetablelength = 0;
+
+ for (tc = c; tc != NULL; tc = tc->super) {
+ for (i = 0; i < tc->interfacescount; i++) {
+ s4 h = class_highestinterface(tc->interfaces[i]) + 1;
+
+ if (h > interfacetablelength)
+ interfacetablelength = h;
+ }
+ }
+ RT_TIMING_GET_TIME(time_compute_iftbl);
+
+ /* allocate virtual function table */
+
+ v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
+ sizeof(methodptr) * (vftbllength - 1) +
+ sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
+ v = (vftbl_t *) (((methodptr *) v) +
+ (interfacetablelength - 1) * (interfacetablelength > 1));
+
+ c->vftbl = v;
+ v->clazz = c;
+ v->vftbllength = vftbllength;
+ v->interfacetablelength = interfacetablelength;
+ v->arraydesc = arraydesc;
+
+ /* store interface index in vftbl */
+
+ if (c->flags & ACC_INTERFACE)
+ v->baseval = -(c->index);
+
+ /* copy virtual function table of super class */
+
+ for (i = 0; i < supervftbllength; i++)
+ v->table[i] = super->vftbl->table[i];
+
+ /* Fill the remaining vftbl slots with the AbstractMethodError
+ stub (all after the super class slots, because they are already
+ initialized). */
+
+ for (; i < vftbllength; i++) {
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+ else
+# endif
+ v->table[i] = (methodptr) (ptrint) &asm_abstractmethoderror;
+#else
+ v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+#endif
+ }
+
+ /* add method stubs into virtual function table */
+
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &(c->methods[i]);
+
+ assert(m->stubroutine == NULL);
+
+ /* Don't create a compiler stub for abstract methods as they
+ throw an AbstractMethodError with the default stub in the
+ vftbl. This entry is simply copied by sub-classes. */
+
+ if (m->flags & ACC_ABSTRACT)
+ continue;
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ m->stubroutine = intrp_createcompilerstub(m);
+ else
+#endif
+ m->stubroutine = codegen_generate_stub_compiler(m);
+#else
+ m->stubroutine = intrp_createcompilerstub(m);
+#endif
+
+ /* static methods are not in the vftbl */
+
+ if (m->flags & ACC_STATIC)
+ continue;
+
+ /* insert the stubroutine into the vftbl */
+
+ v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
+ }
+ RT_TIMING_GET_TIME(time_fill_vftbl);
+
+ /* compute instance size and offset of each field */
+
+ for (i = 0; i < c->fieldscount; i++) {
+ s4 dsize;
+ fieldinfo *f = &(c->fields[i]);
+
+ if (!(f->flags & ACC_STATIC)) {
+ dsize = descriptor_typesize(f->parseddesc);
+ c->instancesize = MEMORY_ALIGN(c->instancesize, dsize);
+ f->offset = c->instancesize;
+ c->instancesize += dsize;
+ }
+ }
+ RT_TIMING_GET_TIME(time_offsets);
+
+ /* initialize interfacetable and interfacevftbllength */
+
+ v->interfacevftbllength = MNEW(s4, interfacetablelength);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
+#endif
+
+ for (i = 0; i < interfacetablelength; i++) {
+ v->interfacevftbllength[i] = 0;
+ v->interfacetable[-i] = NULL;
+ }
+
+ /* add interfaces */
+
+ for (tc = c; tc != NULL; tc = tc->super)
+ for (i = 0; i < tc->interfacescount; i++)
+ if (!linker_addinterface(c, tc->interfaces[i]))
+ return NULL;
+
+ RT_TIMING_GET_TIME(time_fill_iftbl);
+
+ /* add finalizer method (not for java.lang.Object) */
+
+ if (super) {
+ methodinfo *fi;
+
+ fi = class_findmethod(c, utf_finalize, utf_void__void);
+
+ if (fi)
+ if (!(fi->flags & ACC_STATIC))
+ c->finalizer = fi;
+ }
+ RT_TIMING_GET_TIME(time_finalizer);
+
+ /* final tasks */
+
+ linker_compute_subclasses(c);
+
+ RT_TIMING_GET_TIME(time_subclasses);
+
+ /* revert the linking state and class is linked */
+
+ c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
+
+ /* check worklist */
+
+ /* XXX must this also be done in case of exception? */
+
+ while (worklist != NULL) {
+ method_worklist *wi = worklist;
+
+ worklist = worklist->next;
+
+ INLINELOG( printf("MUST BE RECOMPILED: "); method_println(wi->m); );
+ jit_invalidate_code(wi->m);
+
+ /* XXX put worklist into dump memory? */
+ FREE(wi, method_worklist);
+ }
+
+ RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
+ RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
+ RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
+ RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
+ RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
+ RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
+ RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
+ RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
+ RT_TIMING_TIME_DIFF(time_finalizer ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
+
+ /* just return c to show that we didn't had a problem */
+
+ return c;
+}
+
+
+/* link_array ******************************************************************
+
+ This function is called by link_class to create the arraydescriptor
+ for an array class.
+
+ This function returns NULL if the array cannot be linked because
+ the component type has not been linked yet.
+
+*******************************************************************************/
+
+static arraydescriptor *link_array(classinfo *c)
+{
+ classinfo *comp;
+ s4 namelen;
+ arraydescriptor *desc;
+ vftbl_t *compvftbl;
+ utf *u;
+
+ comp = NULL;
+ namelen = c->name->blength;
+
+ /* Check the component type */
+
+ switch (c->name->text[1]) {
+ case '[':
+ /* c is an array of arrays. */
+ u = utf_new(c->name->text + 1, namelen - 1);
+ if (!(comp = load_class_from_classloader(u, c->classloader)))
+ return NULL;
+ break;
+
+ case 'L':
+ /* c is an array of objects. */
+ u = utf_new(c->name->text + 2, namelen - 3);
+ if (!(comp = load_class_from_classloader(u, c->classloader)))
+ return NULL;
+ break;
+ }
+
+ /* If the component type has not been linked, link it now */
+
+ assert(!comp || (comp->state & CLASS_LOADED));
+
+ if (comp && !(comp->state & CLASS_LINKED))
+ if (!link_class(comp))
+ return NULL;
+
+ /* Allocate the arraydescriptor */
+
+ desc = NEW(arraydescriptor);
+
+ if (comp) {
+ /* c is an array of references */
+ desc->arraytype = ARRAYTYPE_OBJECT;
+ desc->componentsize = sizeof(void*);
+ desc->dataoffset = OFFSET(java_objectarray_t, data);
+
+ compvftbl = comp->vftbl;
+
+ if (!compvftbl) {
+ log_text("Component class has no vftbl");
+ assert(0);
+ }
+
+ desc->componentvftbl = compvftbl;
+
+ if (compvftbl->arraydesc) {
+ desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
+
+ if (compvftbl->arraydesc->dimension >= 255) {
+ log_text("Creating array of dimension >255");
+ assert(0);
+ }
+
+ desc->dimension = compvftbl->arraydesc->dimension + 1;
+ desc->elementtype = compvftbl->arraydesc->elementtype;
+
+ } else {
+ desc->elementvftbl = compvftbl;
+ desc->dimension = 1;
+ desc->elementtype = ARRAYTYPE_OBJECT;
+ }
+
+ } else {
+ /* c is an array of a primitive type */
+ switch (c->name->text[1]) {
+ case 'Z':
+ desc->arraytype = ARRAYTYPE_BOOLEAN;
+ desc->dataoffset = OFFSET(java_booleanarray_t,data);
+ desc->componentsize = sizeof(u1);
+ break;
+
+ case 'B':
+ desc->arraytype = ARRAYTYPE_BYTE;
+ desc->dataoffset = OFFSET(java_bytearray_t,data);
+ desc->componentsize = sizeof(u1);
+ break;
+
+ case 'C':
+ desc->arraytype = ARRAYTYPE_CHAR;
+ desc->dataoffset = OFFSET(java_chararray_t,data);
+ desc->componentsize = sizeof(u2);
+ break;
+
+ case 'D':
+ desc->arraytype = ARRAYTYPE_DOUBLE;
+ desc->dataoffset = OFFSET(java_doublearray_t,data);
+ desc->componentsize = sizeof(double);
+ break;
+
+ case 'F':
+ desc->arraytype = ARRAYTYPE_FLOAT;
+ desc->dataoffset = OFFSET(java_floatarray_t,data);
+ desc->componentsize = sizeof(float);
+ break;
+
+ case 'I':
+ desc->arraytype = ARRAYTYPE_INT;
+ desc->dataoffset = OFFSET(java_intarray_t,data);
+ desc->componentsize = sizeof(s4);
+ break;
+
+ case 'J':
+ desc->arraytype = ARRAYTYPE_LONG;
+ desc->dataoffset = OFFSET(java_longarray_t,data);
+ desc->componentsize = sizeof(s8);
+ break;
+
+ case 'S':
+ desc->arraytype = ARRAYTYPE_SHORT;
+ desc->dataoffset = OFFSET(java_shortarray_t,data);
+ desc->componentsize = sizeof(s2);
+ break;
+
+ default:
+ exceptions_throw_noclassdeffounderror(c->name);
+ return NULL;
+ }
+
+ desc->componentvftbl = NULL;
+ desc->elementvftbl = NULL;
+ desc->dimension = 1;
+ desc->elementtype = desc->arraytype;
+ }
+
+ return desc;
+}
+
+
+/* linker_compute_subclasses ***************************************************
+
+ XXX
+
+ ATTENTION: DO NOT REMOVE ANY OF THE LOCKING MECHANISMS BELOW:
+ This function needs to take the class renumber lock and stop the
+ world during class renumbering. The lock is used in C code which
+ is not that performance critical. Whereas JIT code uses critical
+ sections to atomically access the class values.
+
+*******************************************************************************/
+
+static void linker_compute_subclasses(classinfo *c)
+{
+ LOCK_MONITOR_ENTER(linker_classrenumber_lock);
+
+ if (!(c->flags & ACC_INTERFACE)) {
+ c->nextsub = NULL;
+ c->sub = NULL;
+ }
+
+ if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
+ c->nextsub = c->super->sub;
+ c->super->sub = c;
+ }
+
+ classvalue = 0;
+
+ /* compute class values */
+
+ linker_compute_class_values(class_java_lang_Object);
+
+ LOCK_MONITOR_EXIT(linker_classrenumber_lock);
+}
+
+
+/* linker_compute_class_values *************************************************
+
+ XXX
+
+*******************************************************************************/
+
+static void linker_compute_class_values(classinfo *c)
+{
+ classinfo *subs;
+
+ c->vftbl->baseval = ++classvalue;
+
+ subs = c->sub;
+
+ while (subs) {
+ linker_compute_class_values(subs);
+
+ subs = subs->nextsub;
+ }
+
+ c->vftbl->diffval = classvalue - c->vftbl->baseval;
+}
+
+
+/* linker_addinterface *********************************************************
+
+ Is needed by link_class for adding a VTBL to a class. All
+ interfaces implemented by ic are added as well.
+
+ RETURN VALUE:
+ true.........everything ok
+ false........an exception has been thrown
+
+*******************************************************************************/
+
+static bool linker_addinterface(classinfo *c, classinfo *ic)
+{
+ s4 j, k;
+ vftbl_t *v;
+ s4 i;
+ classinfo *sc;
+ methodinfo *m;
+
+ v = c->vftbl;
+ i = ic->index;
+
+ if (i >= v->interfacetablelength)
+ vm_abort("Internal error: interfacetable overflow");
+
+ /* if this interface has already been added, return immediately */
+
+ if (v->interfacetable[-i] != NULL)
+ return true;
+
+ if (ic->methodscount == 0) { /* fake entry needed for subtype test */
+ v->interfacevftbllength[i] = 1;
+ v->interfacetable[-i] = MNEW(methodptr, 1);
+ v->interfacetable[-i][0] = NULL;
+ }
+ else {
+ v->interfacevftbllength[i] = ic->methodscount;
+ v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_vftbl_len += sizeof(methodptr) *
+ (ic->methodscount + (ic->methodscount == 0));
+#endif
+
+ for (j = 0; j < ic->methodscount; j++) {
+ for (sc = c; sc != NULL; sc = sc->super) {
+ for (k = 0; k < sc->methodscount; k++) {
+ m = &(sc->methods[k]);
+
+ if (method_canoverwrite(m, &(ic->methods[j]))) {
+ /* method m overwrites the (abstract) method */
+#if defined(ENABLE_VERIFIER)
+ /* Add loading constraints (for the more
+ general types of the method
+ ic->methods[j]). */
+ if (!classcache_add_constraints_for_params(
+ c->classloader, ic->classloader,
+ &(ic->methods[j])))
+ {
+ return false;
+ }
+#endif
+
+ /* XXX taken from gcj */
+ /* check for ACC_STATIC: IncompatibleClassChangeError */
+
+ /* check for !ACC_PUBLIC: IllegalAccessError */
+
+ /* check for ACC_ABSTRACT: AbstracMethodError,
+ not sure about that one */
+
+ v->interfacetable[-i][j] = v->table[m->vftblindex];
+ goto foundmethod;
+ }
+ }
+ }
+
+ /* If no method was found, insert the AbstractMethodError
+ stub. */
+
+#if defined(ENABLE_JIT)
+# if defined(ENABLE_INTRP)
+ if (opt_intrp)
+ v->interfacetable[-i][j] =
+ (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+ else
+# endif
+ v->interfacetable[-i][j] =
+ (methodptr) (ptrint) &asm_abstractmethoderror;
+#else
+ v->interfacetable[-i][j] =
+ (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
+#endif
+
+ foundmethod:
+ ;
+ }
+ }
+
+ /* add superinterfaces of this interface */
+
+ for (j = 0; j < ic->interfacescount; j++)
+ if (!linker_addinterface(c, ic->interfaces[j]))
+ return false;
+
+ /* everything ok */
+
+ return true;
+}
+
+
+/* class_highestinterface ******************************************************
+
+ Used by the function link_class to determine the amount of memory
+ needed for the interface table.
+
+*******************************************************************************/
+
+static s4 class_highestinterface(classinfo *c)
+{
+ s4 h;
+ s4 h2;
+ s4 i;
+
+ /* check for ACC_INTERFACE bit already done in link_class_intern */
+
+ h = c->index;
+
+ for (i = 0; i < c->interfacescount; i++) {
+ h2 = class_highestinterface(c->interfaces[i]);
+
+ if (h2 > h)
+ h = h2;
+ }
+
+ return h;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/linker.h - class linker header
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _LINKER_H
+#define _LINKER_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct _vftbl vftbl_t;
+typedef struct arraydescriptor arraydescriptor;
+typedef struct primitivetypeinfo primitivetypeinfo;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/class.h"
+#include "vm/references.h"
+
+
+/* virtual function table ******************************************************
+
+ The vtbl has a bidirectional layout with open ends at both sides.
+ interfacetablelength gives the number of entries of the interface
+ table at the start of the vftbl. The vftbl pointer points to
+ &interfacetable[0]. vftbllength gives the number of entries of
+ table at the end of the vftbl.
+
+ runtime type check (checkcast):
+
+ Different methods are used for runtime type check depending on the
+ argument of checkcast/instanceof.
+
+ A check against a class is implemented via relative numbering on
+ the class hierachy tree. The tree is numbered in a depth first
+ traversal setting the base field and the diff field. The diff field
+ gets the result of (high - base) so that a range check can be
+ implemented by an unsigned compare. A sub type test is done by
+ checking the inclusion of base of the sub class in the range of the
+ superclass.
+
+ A check against an interface is implemented via the
+ interfacevftbl. If the interfacevftbl contains a nonnull value a
+ class is a subclass of this interface.
+
+ interfacetable:
+
+ Like standard virtual methods interface methods are called using
+ virtual function tables. All interfaces are numbered sequentially
+ (starting with zero). For each class there exist an interface table
+ of virtual function tables for each implemented interface. The
+ length of the interface table is determined by the highest number
+ of an implemented interface.
+
+ The following example assumes a class which implements interface 0 and 3:
+
+ interfacetablelength = 4
+
+ | ... | +----------+
+ +-----------+ | method 2 |---> method z
+ | class | | method 1 |---> method y
+ +-----------+ | method 0 |---> method x
+ | ivftbl 0 |----------> +----------+
+ vftblptr ---> +-----------+
+ | ivftbl -1 |--> NULL +----------+
+ | ivftbl -2 |--> NULL | method 1 |---> method x
+ | ivftbl -3 |-----+ | method 0 |---> method a
+ +-----------+ +----> +----------+
+
+ +---------------+
+ | length 3 = 2 |
+ | length 2 = 0 |
+ | length 1 = 0 |
+ | length 0 = 3 |
+ interfacevftbllength ---> +---------------+
+
+*******************************************************************************/
+
+struct _vftbl {
+ methodptr *interfacetable[1]; /* interface table (access via macro) */
+ classinfo *clazz; /* class, the vtbl belongs to */
+ arraydescriptor *arraydesc; /* for array classes, otherwise NULL */
+ s4 vftbllength; /* virtual function table length */
+ s4 interfacetablelength; /* interface table length */
+ s4 baseval; /* base for runtime type check */
+ /* (-index for interfaces) */
+ s4 diffval; /* high - base for runtime type check */
+ s4 *interfacevftbllength; /* length of interface vftbls */
+ methodptr table[1]; /* class vftbl */
+};
+
+
+/* arraydescriptor *************************************************************
+
+ For every array class an arraydescriptor is allocated which
+ describes the array class. The arraydescriptor is referenced from
+ the vftbl of the array class.
+
+*******************************************************************************/
+
+struct arraydescriptor {
+ vftbl_t *componentvftbl; /* vftbl of the component type, NULL for primit. */
+ vftbl_t *elementvftbl; /* vftbl of the element type, NULL for primitive */
+ s2 arraytype; /* ARRAYTYPE_* constant */
+ s2 dimension; /* dimension of the array (always >= 1) */
+ s4 dataoffset; /* offset of the array data from object pointer */
+ s4 componentsize; /* size of a component in bytes */
+ s2 elementtype; /* ARRAYTYPE_* constant */
+};
+
+
+/* global variables ***********************************************************/
+
+/* This lock must be taken while renumbering classes or while atomically */
+/* accessing classes. */
+
+extern java_object_t *linker_classrenumber_lock;
+
+
+/* function prototypes ********************************************************/
+
+void linker_preinit(void);
+void linker_init(void);
+classinfo *link_class(classinfo *c);
+
+#endif /* _LINKER_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/vm/loader.c - class loader functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/logging.h"
+
+#include "vm/builtin.h"
+#include "vm/classcache.h"
+#include "vm/exceptions.hpp"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/package.hpp"
+#include "vm/primitive.hpp"
+#include "vm/resolve.h"
+#include "vm/rt-timing.h"
+#include "vm/string.hpp"
+#include "vm/suck.h"
+#include "vm/vm.hpp"
+
+
+#if defined(ENABLE_JAVASE)
+# include "vm/annotation.h"
+# include "vm/stackmap.h"
+#endif
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#if defined(ENABLE_ZLIB)
+# include "vm/zip.h"
+#endif
+
+#if defined(ENABLE_JVMTI)
+# include "native/jvmti/cacaodbg.h"
+#endif
+
+
+/* global variables ***********************************************************/
+
+static hashtable *hashtable_classloader;
+
+
+/* loader_preinit **************************************************************
+
+ Initializes the classpath list and loads classes required for the
+ primitive table.
+
+ NOTE: Exceptions thrown during VM initialization are caught in the
+ exception functions themselves.
+
+*******************************************************************************/
+
+void loader_preinit(void)
+{
+#if defined(ENABLE_THREADS)
+ list_classpath_entry *lce;
+#endif
+
+ TRACESUBSYSTEMINITIALIZATION("loader_preinit");
+
+#if defined(ENABLE_THREADS)
+ /* Initialize the monitor pointer for zip/jar file locking. */
+
+ for (lce = list_first(list_classpath_entries); lce != NULL;
+ lce = list_next(list_classpath_entries, lce)) {
+ if (lce->type == CLASSPATH_ARCHIVE)
+ LOCK_INIT_OBJECT_LOCK(lce);
+ }
+#endif
+
+ /* initialize classloader hashtable, 10 entries should be enough */
+
+ hashtable_classloader = NEW(hashtable);
+ hashtable_create(hashtable_classloader, 10);
+
+ /* Load the most basic classes. */
+
+ assert(VM_is_initializing() == true);
+
+ class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object);
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_Cloneable = load_class_bootstrap(utf_java_lang_Cloneable);
+ class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable);
+#endif
+}
+
+
+/* loader_init *****************************************************************
+
+ Loads all classes required in the VM.
+
+ NOTE: Exceptions thrown during VM initialization are caught in the
+ exception functions themselves.
+
+*******************************************************************************/
+
+void loader_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("loader_init");
+
+ /* Load primitive-type wrapping classes. */
+
+ assert(VM_is_initializing() == true);
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void);
+#endif
+
+ class_java_lang_Boolean = load_class_bootstrap(utf_java_lang_Boolean);
+ class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte);
+ class_java_lang_Character = load_class_bootstrap(utf_java_lang_Character);
+ class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short);
+ class_java_lang_Integer = load_class_bootstrap(utf_java_lang_Integer);
+ class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long);
+ class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float);
+ class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double);
+
+ /* Load important system classes. */
+
+ class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class);
+ class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_ClassLoader =
+ load_class_bootstrap(utf_java_lang_ClassLoader);
+
+ class_java_lang_SecurityManager =
+ load_class_bootstrap(utf_java_lang_SecurityManager);
+#endif
+
+ class_java_lang_System =
+ load_class_bootstrap(utf_new_char("java/lang/System"));
+
+ class_java_lang_Thread =
+ load_class_bootstrap(utf_new_char("java/lang/Thread"));
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_ThreadGroup =
+ load_class_bootstrap(utf_java_lang_ThreadGroup);
+#endif
+
+ class_java_lang_Throwable = load_class_bootstrap(utf_java_lang_Throwable);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ class_java_lang_VMSystem =
+ load_class_bootstrap(utf_new_char("java/lang/VMSystem"));
+
+ class_java_lang_VMThread =
+ load_class_bootstrap(utf_new_char("java/lang/VMThread"));
+
+ class_java_lang_VMThrowable =
+ load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
+#endif
+
+ /* Important system exceptions. */
+
+ class_java_lang_Exception = load_class_bootstrap(utf_java_lang_Exception);
+
+ class_java_lang_ClassNotFoundException =
+ load_class_bootstrap(utf_java_lang_ClassNotFoundException);
+
+ class_java_lang_RuntimeException =
+ load_class_bootstrap(utf_java_lang_RuntimeException);
+
+ /* Some classes which may be used often. */
+
+#if defined(ENABLE_JAVASE)
+ class_java_lang_StackTraceElement = load_class_bootstrap(utf_java_lang_StackTraceElement);
+
+ class_java_lang_reflect_Constructor = load_class_bootstrap(utf_java_lang_reflect_Constructor);
+ class_java_lang_reflect_Field = load_class_bootstrap(utf_java_lang_reflect_Field);
+ class_java_lang_reflect_Method = load_class_bootstrap(utf_java_lang_reflect_Method);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ class_java_lang_reflect_VMConstructor = load_class_bootstrap(utf_java_lang_reflect_VMConstructor);
+ class_java_lang_reflect_VMField = load_class_bootstrap(utf_java_lang_reflect_VMField);
+ class_java_lang_reflect_VMMethod = load_class_bootstrap(utf_java_lang_reflect_VMMethod);
+# endif
+
+ class_java_security_PrivilegedAction = load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
+
+ class_java_util_HashMap = load_class_bootstrap(utf_new_char("java/util/HashMap"));
+ class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ class_sun_misc_Signal = load_class_bootstrap(utf_new_char("sun/misc/Signal"));
+ class_sun_reflect_MagicAccessorImpl = load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
+# endif
+
+ arrayclass_java_lang_Object =
+ load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
+
+# if defined(ENABLE_ANNOTATIONS)
+ /* needed by annotation support */
+ class_sun_reflect_ConstantPool =
+ load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ /* needed by GNU Classpaths annotation support */
+ class_sun_reflect_annotation_AnnotationParser =
+ load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
+# endif
+# endif
+#endif
+}
+
+
+/* loader_hashtable_classloader_add ********************************************
+
+ Adds an entry to the classloader hashtable.
+
+ REMEMBER: Also use this to register native loaders!
+
+*******************************************************************************/
+
+classloader_t *loader_hashtable_classloader_add(java_handle_t *cl)
+{
+ hashtable_classloader_entry *cle;
+ u4 key;
+ u4 slot;
+
+ if (cl == NULL)
+ return NULL;
+
+ LOCK_MONITOR_ENTER(hashtable_classloader->header);
+
+ LLNI_CRITICAL_START;
+
+ /* key for entry is the hashcode of the classloader;
+ aligned to 16-byte boundaries */
+
+ key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
+ slot = key & (hashtable_classloader->size - 1);
+ cle = hashtable_classloader->ptr[slot];
+
+ /* search hashchain for existing entry */
+
+ while (cle) {
+ if (cle->object == LLNI_DIRECT(cl))
+ break;
+
+ cle = cle->hashlink;
+ }
+
+ LLNI_CRITICAL_END;
+
+ /* if no classloader was found, we create a new entry here */
+
+ if (cle == NULL) {
+ cle = NEW(hashtable_classloader_entry);
+
+#if defined(ENABLE_GC_CACAO)
+ /* register the classloader object with the GC */
+
+ gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
+#endif
+
+ LLNI_CRITICAL_START;
+
+ cle->object = LLNI_DIRECT(cl);
+
+ LLNI_CRITICAL_END;
+
+/*#define LOADER_DEBUG_CLASSLOADER*/
+#ifdef LOADER_DEBUG_CLASSLOADER
+ printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
+ class_print(LLNI_vftbl_direct(cl)->class);
+ printf("\n");
+ fflush(stdout);
+#endif
+
+ /* insert entry into hashtable */
+
+ cle->hashlink = hashtable_classloader->ptr[slot];
+ hashtable_classloader->ptr[slot] = cle;
+
+ /* update number of entries */
+
+ hashtable_classloader->entries++;
+ }
+
+
+ LOCK_MONITOR_EXIT(hashtable_classloader->header);
+
+#if defined(ENABLE_HANDLES)
+ return cle;
+#else
+ return cl;
+#endif
+}
+
+
+/* loader_hashtable_classloader_find *******************************************
+
+ Find an entry in the classloader hashtable.
+
+*******************************************************************************/
+
+classloader_t *loader_hashtable_classloader_find(java_handle_t *cl)
+{
+ hashtable_classloader_entry *cle;
+ u4 key;
+ u4 slot;
+
+ if (cl == NULL)
+ return NULL;
+
+ LLNI_CRITICAL_START;
+
+ /* key for entry is the hashcode of the classloader;
+ aligned to 16-byte boundaries */
+
+ key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
+ slot = key & (hashtable_classloader->size - 1);
+ cle = hashtable_classloader->ptr[slot];
+
+ /* search hashchain for existing entry */
+
+ while (cle) {
+ if (cle->object == LLNI_DIRECT(cl))
+ break;
+
+ cle = cle->hashlink;
+ }
+
+#ifdef LOADER_DEBUG_CLASSLOADER
+ if (cle == NULL) {
+ printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
+ class_print(LLNI_vftbl_direct(cl)->class);
+ printf("\n");
+ fflush(stdout);
+ }
+#endif
+
+ LLNI_CRITICAL_END;
+
+#if defined(ENABLE_HANDLES)
+ return cle;
+#else
+ return cl;
+#endif
+}
+
+
+/* loader_load_all_classes *****************************************************
+
+ Loads all classes specified in the BOOTCLASSPATH.
+
+*******************************************************************************/
+
+void loader_load_all_classes(void)
+{
+ list_classpath_entry *lce;
+#if defined(ENABLE_ZLIB)
+ hashtable *ht;
+ s4 slot;
+ hashtable_zipfile_entry *htzfe;
+ utf *u;
+#endif
+
+ for (lce = list_first(list_classpath_entries); lce != NULL;
+ lce = list_next(list_classpath_entries, lce)) {
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+ /* get the classes hashtable */
+
+ ht = lce->htclasses;
+
+ for (slot = 0; slot < ht->size; slot++) {
+ htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
+
+ for (; htzfe; htzfe = htzfe->hashlink) {
+ u = htzfe->filename;
+
+ /* skip all entries in META-INF and .properties,
+ .png files */
+
+ if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
+ strstr(u->text, ".properties") ||
+ strstr(u->text, ".png"))
+ continue;
+
+ /* load class from bootstrap classloader */
+
+ if (!load_class_bootstrap(u)) {
+ fprintf(stderr, "Error loading: ");
+ utf_fprint_printable_ascii_classname(stderr, u);
+ fprintf(stderr, "\n");
+
+#if !defined(NDEBUG)
+ /* print out exception and cause */
+
+ exceptions_print_current_exception();
+#endif
+ }
+ }
+ }
+
+ } else {
+#endif
+#if defined(ENABLE_ZLIB)
+ }
+#endif
+ }
+}
+
+
+/* loader_skip_attribute_body **************************************************
+
+ Skips an attribute the attribute_name_index has already been read.
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+*******************************************************************************/
+
+bool loader_skip_attribute_body(classbuffer *cb)
+{
+ u4 attribute_length;
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ attribute_length = suck_u4(cb);
+
+ if (!suck_check_classbuffer_size(cb, attribute_length))
+ return false;
+
+ suck_skip_nbytes(cb, attribute_length);
+
+ return true;
+}
+
+
+/* load_constantpool ***********************************************************
+
+ Loads the constantpool of a class, the entries are transformed into
+ a simpler format by resolving references (a detailed overview of
+ the compact structures can be found in global.h).
+
+*******************************************************************************/
+
+static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
+{
+
+ /* The following structures are used to save information which cannot be
+ processed during the first pass. After the complete constantpool has
+ been traversed the references can be resolved.
+ (only in specific order) */
+
+ /* CONSTANT_Class entries */
+ typedef struct forward_class {
+ struct forward_class *next;
+ u2 thisindex;
+ u2 name_index;
+ } forward_class;
+
+ /* CONSTANT_String */
+ typedef struct forward_string {
+ struct forward_string *next;
+ u2 thisindex;
+ u2 string_index;
+ } forward_string;
+
+ /* CONSTANT_NameAndType */
+ typedef struct forward_nameandtype {
+ struct forward_nameandtype *next;
+ u2 thisindex;
+ u2 name_index;
+ u2 sig_index;
+ } forward_nameandtype;
+
+ /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
+ typedef struct forward_fieldmethint {
+ struct forward_fieldmethint *next;
+ u2 thisindex;
+ u1 tag;
+ u2 class_index;
+ u2 nameandtype_index;
+ } forward_fieldmethint;
+
+
+ classinfo *c;
+ u4 idx;
+
+ forward_class *forward_classes = NULL;
+ forward_string *forward_strings = NULL;
+ forward_nameandtype *forward_nameandtypes = NULL;
+ forward_fieldmethint *forward_fieldmethints = NULL;
+
+ forward_class *nfc;
+ forward_string *nfs;
+ forward_nameandtype *nfn;
+ forward_fieldmethint *nff;
+
+ u4 cpcount;
+ u1 *cptags;
+ void** cpinfos;
+
+ c = cb->clazz;
+
+ /* number of entries in the constant_pool table plus one */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ cpcount = c->cpcount = suck_u2(cb);
+
+ /* allocate memory */
+ cptags = c->cptags = MNEW(u1, cpcount);
+ cpinfos = c->cpinfos = MNEW(void*, cpcount);
+
+ if (cpcount < 1) {
+ exceptions_throw_classformaterror(c, "Illegal constant pool size");
+ return false;
+ }
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += (sizeof(u1) + sizeof(void*)) * cpcount;
+#endif
+
+ /* initialize constantpool */
+ for (idx = 0; idx < cpcount; idx++) {
+ cptags[idx] = CONSTANT_UNUSED;
+ cpinfos[idx] = NULL;
+ }
+
+
+ /******* first pass *******/
+ /* entries which cannot be resolved now are written into
+ temporary structures and traversed again later */
+
+ idx = 1;
+ while (idx < cpcount) {
+ u4 t;
+
+ /* get constant type */
+ if (!suck_check_classbuffer_size(cb, 1))
+ return false;
+
+ t = suck_u1(cb);
+
+ switch (t) {
+ case CONSTANT_Class:
+ nfc = DNEW(forward_class);
+
+ nfc->next = forward_classes;
+ forward_classes = nfc;
+
+ nfc->thisindex = idx;
+ /* reference to CONSTANT_NameAndType */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ nfc->name_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_String:
+ nfs = DNEW(forward_string);
+
+ nfs->next = forward_strings;
+ forward_strings = nfs;
+
+ nfs->thisindex = idx;
+
+ /* reference to CONSTANT_Utf8_info with string characters */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ nfs->string_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_NameAndType:
+ nfn = DNEW(forward_nameandtype);
+
+ nfn->next = forward_nameandtypes;
+ forward_nameandtypes = nfn;
+
+ nfn->thisindex = idx;
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* reference to CONSTANT_Utf8_info containing simple name */
+ nfn->name_index = suck_u2(cb);
+
+ /* reference to CONSTANT_Utf8_info containing field or method
+ descriptor */
+ nfn->sig_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_Fieldref:
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ nff = DNEW(forward_fieldmethint);
+
+ nff->next = forward_fieldmethints;
+ forward_fieldmethints = nff;
+
+ nff->thisindex = idx;
+ /* constant type */
+ nff->tag = t;
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* class or interface type that contains the declaration of the
+ field or method */
+ nff->class_index = suck_u2(cb);
+
+ /* name and descriptor of the field or method */
+ nff->nameandtype_index = suck_u2(cb);
+
+ idx++;
+ break;
+
+ case CONSTANT_Integer: {
+ constant_integer *ci = NEW(constant_integer);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_integer);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ ci->value = suck_s4(cb);
+ cptags[idx] = CONSTANT_Integer;
+ cpinfos[idx] = ci;
+
+ idx++;
+ break;
+ }
+
+ case CONSTANT_Float: {
+ constant_float *cf = NEW(constant_float);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_float);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ cf->value = suck_float(cb);
+ cptags[idx] = CONSTANT_Float;
+ cpinfos[idx] = cf;
+
+ idx++;
+ break;
+ }
+
+ case CONSTANT_Long: {
+ constant_long *cl = NEW(constant_long);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_long);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 8))
+ return false;
+
+ cl->value = suck_s8(cb);
+ cptags[idx] = CONSTANT_Long;
+ cpinfos[idx] = cl;
+ idx += 2;
+ if (idx > cpcount) {
+ exceptions_throw_classformaterror(c, "Invalid constant pool entry");
+ return false;
+ }
+ break;
+ }
+
+ case CONSTANT_Double: {
+ constant_double *cd = NEW(constant_double);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_double);
+#endif
+
+ if (!suck_check_classbuffer_size(cb, 8))
+ return false;
+
+ cd->value = suck_double(cb);
+ cptags[idx] = CONSTANT_Double;
+ cpinfos[idx] = cd;
+ idx += 2;
+ if (idx > cpcount) {
+ exceptions_throw_classformaterror(c, "Invalid constant pool entry");
+ return false;
+ }
+ break;
+ }
+
+ case CONSTANT_Utf8: {
+ u4 length;
+
+ /* number of bytes in the bytes array (not string-length) */
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ length = suck_u2(cb);
+ cptags[idx] = CONSTANT_Utf8;
+
+ /* validate the string */
+ if (!suck_check_classbuffer_size(cb, length))
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify &&
+ !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
+ {
+ exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
+ return false;
+ }
+#endif /* ENABLE_VERIFIER */
+ /* insert utf-string into the utf-symboltable */
+ cpinfos[idx] = utf_new((char *) cb->pos, length);
+
+ /* skip bytes of the string (buffer size check above) */
+ suck_skip_nbytes(cb, length);
+ idx++;
+ break;
+ }
+
+ default:
+ exceptions_throw_classformaterror(c, "Illegal constant pool type");
+ return false;
+ } /* end switch */
+ } /* end while */
+
+
+ /* resolve entries in temporary structures */
+
+ while (forward_classes) {
+ utf *name =
+ class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
+ if (!name)
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify && !is_valid_name_utf(name)) {
+ exceptions_throw_classformaterror(c, "Class reference with invalid name");
+ return false;
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* add all class references to the descriptor_pool */
+
+ if (!descriptor_pool_add_class(descpool, name))
+ return false;
+
+ cptags[forward_classes->thisindex] = CONSTANT_Class;
+
+ /* the classref is created later */
+ cpinfos[forward_classes->thisindex] = name;
+
+ nfc = forward_classes;
+ forward_classes = forward_classes->next;
+ }
+
+ while (forward_strings) {
+ utf *text =
+ class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
+ if (!text)
+ return false;
+
+ /* resolve utf-string */
+ cptags[forward_strings->thisindex] = CONSTANT_String;
+ cpinfos[forward_strings->thisindex] = text;
+
+ nfs = forward_strings;
+ forward_strings = forward_strings->next;
+ }
+
+ while (forward_nameandtypes) {
+ constant_nameandtype *cn = NEW(constant_nameandtype);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_nameandtype);
+#endif
+
+ /* resolve simple name and descriptor */
+ cn->name = class_getconstant(c,
+ forward_nameandtypes->name_index,
+ CONSTANT_Utf8);
+ if (!cn->name)
+ return false;
+
+ cn->descriptor = class_getconstant(c,
+ forward_nameandtypes->sig_index,
+ CONSTANT_Utf8);
+ if (!cn->descriptor)
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ /* check name */
+ if (!is_valid_name_utf(cn->name)) {
+ exceptions_throw_classformaterror(c,
+ "Illegal Field name \"%s\"",
+ cn->name->text);
+
+ return false;
+ }
+
+ /* disallow referencing <clinit> among others */
+ if (cn->name->text[0] == '<' && cn->name != utf_init) {
+ exceptions_throw_classformaterror(c, "Illegal reference to special method");
+ return false;
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
+ cpinfos[forward_nameandtypes->thisindex] = cn;
+
+ nfn = forward_nameandtypes;
+ forward_nameandtypes = forward_nameandtypes->next;
+ }
+
+ while (forward_fieldmethints) {
+ constant_nameandtype *nat;
+ constant_FMIref *fmi = NEW(constant_FMIref);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_const_pool_len += sizeof(constant_FMIref);
+#endif
+ /* resolve simple name and descriptor */
+
+ nat = class_getconstant(c,
+ forward_fieldmethints->nameandtype_index,
+ CONSTANT_NameAndType);
+ if (!nat)
+ return false;
+
+ /* add all descriptors in {Field,Method}ref to the descriptor_pool */
+
+ if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
+ return false;
+
+ /* the classref is created later */
+
+ fmi->p.index = forward_fieldmethints->class_index;
+ fmi->name = nat->name;
+ fmi->descriptor = nat->descriptor;
+
+ cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
+ cpinfos[forward_fieldmethints->thisindex] = fmi;
+
+ nff = forward_fieldmethints;
+ forward_fieldmethints = forward_fieldmethints->next;
+ }
+
+ /* everything was ok */
+
+ return true;
+}
+
+
+/* loader_load_attribute_signature *********************************************
+
+ Signature_attribute {
+ u2 attribute_name_index;
+ u4 atrribute_length;
+ u2 signature_index;
+ }
+
+*******************************************************************************/
+
+#if defined(ENABLE_JAVASE)
+bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
+{
+ classinfo *c;
+ u4 attribute_length;
+ u2 signature_index;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* check remaining bytecode */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* check attribute length */
+
+ attribute_length = suck_u4(cb);
+
+ if (attribute_length != 2) {
+ exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
+ return false;
+ }
+
+ if (*signature != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple Signature attributes");
+ return false;
+ }
+
+ /* get signature */
+
+ signature_index = suck_u2(cb);
+
+ if (!(*signature = class_getconstant(c, signature_index, CONSTANT_Utf8)))
+ return false;
+
+ return true;
+}
+#endif /* defined(ENABLE_JAVASE) */
+
+
+/* load_class_from_sysloader ***************************************************
+
+ Load the class with the given name using the system class loader
+
+ IN:
+ name.............the classname
+
+ RETURN VALUE:
+ the loaded class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo *load_class_from_sysloader(utf *name)
+{
+ methodinfo *m;
+ java_handle_t *clo;
+ classloader_t *cl;
+ classinfo *c;
+
+ assert(class_java_lang_Object);
+ assert(class_java_lang_ClassLoader);
+ assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
+
+ m = class_resolveclassmethod(class_java_lang_ClassLoader,
+ utf_getSystemClassLoader,
+ utf_void__java_lang_ClassLoader,
+ class_java_lang_Object,
+ false);
+
+ if (!m)
+ return false;
+
+ clo = vm_call_method(m, NULL);
+
+ if (!clo)
+ return false;
+
+ cl = loader_hashtable_classloader_add(clo);
+
+ c = load_class_from_classloader(name, cl);
+
+ return c;
+}
+
+
+/* load_class_from_classloader *************************************************
+
+ Load the class with the given name using the given user-defined class loader.
+
+ IN:
+ name.............the classname
+ cl...............user-defined class loader
+
+ RETURN VALUE:
+ the loaded class, or
+ NULL if an exception has been thrown
+
+*******************************************************************************/
+
+classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
+{
+ java_handle_t *o;
+ classinfo *c;
+ classinfo *tmpc;
+ java_handle_t *string;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_lookup, time_prepare, time_java,
+ time_cache;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ assert(name);
+
+ /* lookup if this class has already been loaded */
+
+ c = classcache_lookup(cl, name);
+
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
+
+ if (c != NULL)
+ return c;
+
+ /* if other class loader than bootstrap, call it */
+
+ if (cl != NULL) {
+ methodinfo *lc;
+ char *text;
+ s4 namelen;
+
+ text = name->text;
+ namelen = name->blength;
+
+ /* handle array classes */
+ if (text[0] == '[') {
+ classinfo *comp;
+ utf *u;
+
+ switch (text[1]) {
+ case 'L':
+ /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+ if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
+ exceptions_throw_classnotfoundexception(name);
+ return false;
+ }
+
+ u = utf_new(text + 2, namelen - 3);
+
+ if (!(comp = load_class_from_classloader(u, cl)))
+ return false;
+
+ /* create the array class */
+
+ c = class_array_of(comp, false);
+
+ tmpc = classcache_store(cl, c, true);
+
+ if (tmpc == NULL) {
+ /* exception, free the loaded class */
+ c->state &= ~CLASS_LOADING;
+ class_free(c);
+ }
+
+ return tmpc;
+
+ case '[':
+ /* load the component class */
+
+ u = utf_new(text + 1, namelen - 1);
+
+ if (!(comp = load_class_from_classloader(u, cl)))
+ return false;
+
+ /* create the array class */
+
+ c = class_array_of(comp, false);
+
+ tmpc = classcache_store(cl, c, true);
+
+ if (tmpc == NULL) {
+ /* exception, free the loaded class */
+ c->state &= ~CLASS_LOADING;
+ class_free(c);
+ }
+
+ return tmpc;
+
+ default:
+ /* primitive array classes are loaded by the bootstrap loader */
+
+ c = load_class_bootstrap(name);
+
+ return c;
+ }
+ }
+
+ LLNI_class_get(cl, c);
+
+#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
+ /* OpenJDK uses this internal function because it's
+ synchronized. */
+
+ lc = class_resolveclassmethod(c,
+ utf_loadClassInternal,
+ utf_java_lang_String__java_lang_Class,
+ NULL,
+ true);
+#else
+ lc = class_resolveclassmethod(c,
+ utf_loadClass,
+ utf_java_lang_String__java_lang_Class,
+ NULL,
+ true);
+#endif
+
+ if (lc == NULL)
+ return false; /* exception */
+
+ /* move return value into `o' and cast it afterwards to a classinfo* */
+
+ string = javastring_new_slash_to_dot(name);
+
+ RT_TIMING_GET_TIME(time_prepare);
+
+ o = vm_call_method(lc, (java_handle_t *) cl, string);
+
+ RT_TIMING_GET_TIME(time_java);
+
+ c = LLNI_classinfo_unwrap(o);
+
+ if (c != NULL) {
+ /* Store this class in the loaded class cache. If another
+ class with the same (initloader,name) pair has been
+ stored earlier it will be returned by classcache_store
+ In this case classcache_store may not free the class
+ because it has already been exposed to Java code which
+ may have kept references to that class. */
+
+ tmpc = classcache_store(cl, c, false);
+
+ if (tmpc == NULL) {
+ /* exception, free the loaded class */
+ c->state &= ~CLASS_LOADING;
+ class_free(c);
+ }
+
+ c = tmpc;
+ }
+
+ RT_TIMING_GET_TIME(time_cache);
+
+ RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
+ RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
+ RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
+
+ /* SUN compatible -verbose:class output */
+
+ if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
+ printf("[Loaded ");
+ utf_display_printable_ascii_classname(name);
+ printf("]\n");
+ }
+
+#if defined(ENABLE_JVMTI)
+ /* fire Class Load JVMTI event */
+ if (jvmti) jvmti_ClassLoadPrepare(false, c);
+#endif
+
+
+ return c;
+ }
+
+ c = load_class_bootstrap(name);
+
+ return c;
+}
+
+
+/* load_class_bootstrap ********************************************************
+
+ Load the class with the given name using the bootstrap class loader.
+
+ IN:
+ name.............the classname
+
+ RETURN VALUE:
+ loaded classinfo, or
+ NULL if an exception has been thrown
+
+ SYNCHRONIZATION:
+ load_class_bootstrap is synchronized. It can be treated as an
+ atomic operation.
+
+*******************************************************************************/
+
+classinfo *load_class_bootstrap(utf *name)
+{
+ classbuffer *cb;
+ classinfo *c;
+ classinfo *r;
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_lookup, time_array, time_suck,
+ time_load, time_cache;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ /* for debugging */
+
+ assert(name);
+
+ /* lookup if this class has already been loaded */
+
+ r = classcache_lookup(NULL, name);
+
+ if (r != NULL) {
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
+
+ return r;
+ }
+
+ RT_TIMING_GET_TIME(time_lookup);
+ RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
+
+ /* create the classinfo */
+
+ c = class_create_classinfo(name);
+
+ /* handle array classes */
+
+ if (name->text[0] == '[') {
+ c = load_newly_created_array(c, NULL);
+
+ if (c == NULL)
+ return NULL;
+
+ assert(c->state & CLASS_LOADED);
+
+ RT_TIMING_GET_TIME(time_array);
+ RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
+
+ return c;
+ }
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getcompilingtime)
+ compilingtime_stop();
+
+ if (opt_getloadingtime)
+ loadingtime_start();
+#endif
+
+ /* load classdata, throw exception on error */
+
+ cb = suck_start(c);
+
+ if (cb == NULL) {
+ exceptions_throw_classnotfoundexception(name);
+ return NULL;
+ }
+
+ RT_TIMING_GET_TIME(time_suck);
+
+ /* load the class from the buffer */
+
+ r = load_class_from_classbuffer(cb);
+
+ RT_TIMING_GET_TIME(time_load);
+
+ if (r == NULL) {
+ /* the class could not be loaded, free the classinfo struct */
+
+ class_free(c);
+ }
+ else {
+ /* Store this class in the loaded class cache this step also
+ checks the loading constraints. If the class has been
+ loaded before, the earlier loaded class is returned. */
+
+ classinfo *res = classcache_store(NULL, c, true);
+
+ if (res == NULL) {
+ /* exception */
+ class_free(c);
+ }
+ else {
+ /* Add the package name to the boot packages. */
+
+ Package_add(c->packagename);
+ }
+
+ r = res;
+ }
+
+ RT_TIMING_GET_TIME(time_cache);
+
+ /* SUN compatible -verbose:class output */
+
+ if (opt_verboseclass && r) {
+ printf("[Loaded ");
+ utf_display_printable_ascii_classname(name);
+ printf(" from %s]\n", cb->path);
+ }
+
+ /* free memory */
+
+ suck_stop(cb);
+
+#if defined(ENABLE_STATISTICS)
+ /* measure time */
+
+ if (opt_getloadingtime)
+ loadingtime_stop();
+
+ if (opt_getcompilingtime)
+ compilingtime_start();
+#endif
+
+ RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
+ RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
+ RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
+ RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
+
+ return r;
+}
+
+
+/* load_class_from_classbuffer_intern ******************************************
+
+ Loads a class from a classbuffer into a given classinfo structure.
+ Super-classes are also loaded at this point and some verfication
+ checks are done.
+
+ SYNCHRONIZATION:
+ This function is NOT synchronized!
+
+*******************************************************************************/
+
+static bool load_class_from_classbuffer_intern(classbuffer *cb)
+{
+ classinfo *c;
+ classinfo *tc;
+ utf *name;
+ utf *supername;
+ utf **interfacesnames;
+ utf *u;
+ constant_classref *cr;
+ int16_t index;
+
+ u4 i,j;
+ u4 ma, mi;
+ descriptor_pool *descpool;
+#if defined(ENABLE_STATISTICS)
+ u4 classrefsize;
+ u4 descsize;
+#endif
+#if defined(ENABLE_RT_TIMING)
+ struct timespec time_start, time_checks, time_ndpool, time_cpool,
+ time_setup, time_fields, time_methods, time_classrefs,
+ time_descs, time_setrefs, time_parsefds, time_parsemds,
+ time_parsecpool, time_verify, time_attrs;
+#endif
+
+ RT_TIMING_GET_TIME(time_start);
+
+ /* Get the classbuffer's class. */
+
+ c = cb->clazz;
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
+ /* check signature */
+
+ if (suck_u4(cb) != MAGIC) {
+ exceptions_throw_classformaterror(c, "Bad magic number");
+ return false;
+ }
+
+ /* check version */
+
+ mi = suck_u2(cb);
+ ma = suck_u2(cb);
+
+ if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
+ exceptions_throw_unsupportedclassversionerror(c, ma, mi);
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_checks);
+
+ /* create a new descriptor pool */
+
+ descpool = descriptor_pool_new(c);
+
+ RT_TIMING_GET_TIME(time_ndpool);
+
+ /* load the constant pool */
+
+ if (!load_constantpool(cb, descpool))
+ return false;
+
+ RT_TIMING_GET_TIME(time_cpool);
+
+ /* ACC flags */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* We OR the flags here, as we set already some flags in
+ class_create_classinfo. */
+
+ c->flags |= suck_u2(cb);
+
+ /* check ACC flags consistency */
+
+ if (c->flags & ACC_INTERFACE) {
+ if (!(c->flags & ACC_ABSTRACT)) {
+ /* We work around this because interfaces in JDK 1.1 are
+ * not declared abstract. */
+
+ c->flags |= ACC_ABSTRACT;
+ }
+
+ if (c->flags & ACC_FINAL) {
+ exceptions_throw_classformaterror(c,
+ "Illegal class modifiers: 0x%X",
+ c->flags);
+ return false;
+ }
+
+ if (c->flags & ACC_SUPER) {
+ c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
+ }
+ }
+
+ if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
+ exceptions_throw_classformaterror(c,
+ "Illegal class modifiers: 0x%X",
+ c->flags);
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* This class. */
+
+ index = suck_u2(cb);
+
+ name = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (name == NULL)
+ return false;
+
+ if (c->name == utf_not_named_yet) {
+ /* we finally have a name for this class */
+ c->name = name;
+ class_set_packagename(c);
+ }
+ else if (name != c->name) {
+ exceptions_throw_noclassdeffounderror_wrong_name(c, name);
+ return false;
+ }
+
+ /* Retrieve superclass. */
+
+ c->super = NULL;
+
+ index = suck_u2(cb);
+
+ if (index == 0) {
+ supername = NULL;
+
+ /* This is only allowed for java.lang.Object. */
+
+ if (c->name != utf_java_lang_Object) {
+ exceptions_throw_classformaterror(c, "Bad superclass index");
+ return false;
+ }
+ }
+ else {
+ supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (supername == NULL)
+ return false;
+
+ /* java.lang.Object may not have a super class. */
+
+ if (c->name == utf_java_lang_Object) {
+ exceptions_throw_classformaterror(NULL, "java.lang.Object with superclass");
+ return false;
+ }
+
+ /* Detect circularity. */
+
+ if (supername == c->name) {
+ exceptions_throw_classcircularityerror(c);
+ return false;
+ }
+
+ /* Interfaces must have java.lang.Object as super class. */
+
+ if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
+ exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
+ return false;
+ }
+ }
+
+ /* Parse the super interfaces. */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ c->interfacescount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
+ return false;
+
+ c->interfaces = MNEW(classinfo*, c->interfacescount);
+
+ /* Get the names of the super interfaces. */
+
+ interfacesnames = DMNEW(utf*, c->interfacescount);
+
+ for (i = 0; i < c->interfacescount; i++) {
+ index = suck_u2(cb);
+
+ u = (utf *) class_getconstant(c, index, CONSTANT_Class);
+
+ if (u == NULL)
+ return false;
+
+ interfacesnames[i] = u;
+ }
+
+ RT_TIMING_GET_TIME(time_setup);
+
+ /* Parse fields. */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ c->fieldscount = suck_u2(cb);
+ c->fields = MNEW(fieldinfo, c->fieldscount);
+
+ MZERO(c->fields, fieldinfo, c->fieldscount);
+
+ for (i = 0; i < c->fieldscount; i++) {
+ if (!field_load(cb, &(c->fields[i]), descpool))
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_fields);
+
+ /* Parse methods. */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ c->methodscount = suck_u2(cb);
+ c->methods = MNEW(methodinfo, c->methodscount);
+
+ MZERO(c->methods, methodinfo, c->methodscount);
+
+ for (i = 0; i < c->methodscount; i++) {
+ if (!method_load(cb, &(c->methods[i]), descpool))
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_methods);
+
+ /* create the class reference table */
+
+ c->classrefs =
+ descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
+
+ RT_TIMING_GET_TIME(time_classrefs);
+
+ /* allocate space for the parsed descriptors */
+
+ descriptor_pool_alloc_parsed_descriptors(descpool);
+ c->parseddescs =
+ descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
+ count_classref_len += classrefsize;
+ count_parsed_desc_len += descsize;
+ }
+#endif
+
+ RT_TIMING_GET_TIME(time_descs);
+
+ /* put the classrefs in the constant pool */
+
+ for (i = 0; i < c->cpcount; i++) {
+ if (c->cptags[i] == CONSTANT_Class) {
+ utf *name = (utf *) c->cpinfos[i];
+ c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
+ }
+ }
+
+ /* Resolve the super class. */
+
+ if (supername != NULL) {
+ cr = descriptor_pool_lookup_classref(descpool, supername);
+
+ if (cr == NULL)
+ return false;
+
+ /* XXX This should be done better. */
+ tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+ if (tc == NULL) {
+ resolve_handle_pending_exception(true);
+ return false;
+ }
+
+ /* Interfaces are not allowed as super classes. */
+
+ if (tc->flags & ACC_INTERFACE) {
+ exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
+ return false;
+ }
+
+ /* Don't allow extending final classes */
+
+ if (tc->flags & ACC_FINAL) {
+ exceptions_throw_verifyerror(NULL,
+ "Cannot inherit from final class");
+ return false;
+ }
+
+ /* Store the super class. */
+
+ c->super = tc;
+ }
+
+ /* Resolve the super interfaces. */
+
+ for (i = 0; i < c->interfacescount; i++) {
+ u = interfacesnames[i];
+ cr = descriptor_pool_lookup_classref(descpool, u);
+
+ if (cr == NULL)
+ return false;
+
+ /* XXX This should be done better. */
+ tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
+
+ if (tc == NULL) {
+ resolve_handle_pending_exception(true);
+ return false;
+ }
+
+ /* Detect circularity. */
+
+ if (tc == c) {
+ exceptions_throw_classcircularityerror(c);
+ return false;
+ }
+
+ if (!(tc->flags & ACC_INTERFACE)) {
+ exceptions_throw_incompatibleclasschangeerror(tc,
+ "Implementing class");
+ return false;
+ }
+
+ /* Store the super interface. */
+
+ c->interfaces[i] = tc;
+ }
+
+ RT_TIMING_GET_TIME(time_setrefs);
+
+ /* Parse the field descriptors. */
+
+ for (i = 0; i < c->fieldscount; i++) {
+ c->fields[i].parseddesc =
+ descriptor_pool_parse_field_descriptor(descpool,
+ c->fields[i].descriptor);
+ if (!c->fields[i].parseddesc)
+ return false;
+ }
+
+ RT_TIMING_GET_TIME(time_parsefds);
+
+ /* parse method descriptors */
+
+ for (i = 0; i < c->methodscount; i++) {
+ methodinfo *m = &c->methods[i];
+ m->parseddesc =
+ descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
+ m->flags, class_get_self_classref(m->clazz));
+ if (!m->parseddesc)
+ return false;
+
+ for (j = 0; j < m->rawexceptiontablelength; j++) {
+ if (!m->rawexceptiontable[j].catchtype.any)
+ continue;
+
+ if ((m->rawexceptiontable[j].catchtype.ref =
+ descriptor_pool_lookup_classref(descpool,
+ (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL)
+ return false;
+ }
+
+ for (j = 0; j < m->thrownexceptionscount; j++) {
+ if (!m->thrownexceptions[j].any)
+ continue;
+
+ if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
+ (utf *) m->thrownexceptions[j].any)) == NULL)
+ return false;
+ }
+ }
+
+ RT_TIMING_GET_TIME(time_parsemds);
+
+ /* parse the loaded descriptors */
+
+ for (i = 0; i < c->cpcount; i++) {
+ constant_FMIref *fmi;
+ s4 index;
+
+ switch (c->cptags[i]) {
+ case CONSTANT_Fieldref:
+ fmi = (constant_FMIref *) c->cpinfos[i];
+ fmi->parseddesc.fd =
+ descriptor_pool_parse_field_descriptor(descpool,
+ fmi->descriptor);
+ if (!fmi->parseddesc.fd)
+ return false;
+
+ index = fmi->p.index;
+ fmi->p.classref =
+ (constant_classref *) class_getconstant(c, index,
+ CONSTANT_Class);
+ if (!fmi->p.classref)
+ return false;
+ break;
+ case CONSTANT_Methodref:
+ case CONSTANT_InterfaceMethodref:
+ fmi = (constant_FMIref *) c->cpinfos[i];
+ index = fmi->p.index;
+ fmi->p.classref =
+ (constant_classref *) class_getconstant(c, index,
+ CONSTANT_Class);
+ if (!fmi->p.classref)
+ return false;
+ fmi->parseddesc.md =
+ descriptor_pool_parse_method_descriptor(descpool,
+ fmi->descriptor,
+ ACC_UNDEF,
+ fmi->p.classref);
+ if (!fmi->parseddesc.md)
+ return false;
+ break;
+ }
+ }
+
+ RT_TIMING_GET_TIME(time_parsecpool);
+
+#ifdef ENABLE_VERIFIER
+ /* Check if all fields and methods can be uniquely
+ * identified by (name,descriptor). */
+
+ if (opt_verify) {
+ /* We use a hash table here to avoid making the
+ * average case quadratic in # of methods, fields.
+ */
+ static int shift = 0;
+ u2 *hashtab;
+ u2 *next; /* for chaining colliding hash entries */
+ size_t len;
+ size_t hashlen;
+ u2 index;
+ u2 old;
+
+ /* Allocate hashtable */
+ len = c->methodscount;
+ if (len < c->fieldscount) len = c->fieldscount;
+ hashlen = 5 * len;
+ hashtab = MNEW(u2,(hashlen + len));
+ next = hashtab + hashlen;
+
+ /* Determine bitshift (to get good hash values) */
+ if (!shift) {
+ len = sizeof(utf);
+ while (len) {
+ len >>= 1;
+ shift++;
+ }
+ }
+
+ /* Check fields */
+ memset(hashtab, 0, sizeof(u2) * (hashlen + len));
+
+ for (i = 0; i < c->fieldscount; ++i) {
+ fieldinfo *fi = c->fields + i;
+
+ /* It's ok if we lose bits here */
+ index = ((((size_t) fi->name) +
+ ((size_t) fi->descriptor)) >> shift) % hashlen;
+
+ if ((old = hashtab[index])) {
+ old--;
+ next[i] = old;
+ do {
+ if (c->fields[old].name == fi->name &&
+ c->fields[old].descriptor == fi->descriptor) {
+ exceptions_throw_classformaterror(c, "Repetitive field name/signature");
+ return false;
+ }
+ } while ((old = next[old]));
+ }
+ hashtab[index] = i + 1;
+ }
+
+ /* Check methods */
+ memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
+
+ for (i = 0; i < c->methodscount; ++i) {
+ methodinfo *mi = c->methods + i;
+
+ /* It's ok if we lose bits here */
+ index = ((((size_t) mi->name) +
+ ((size_t) mi->descriptor)) >> shift) % hashlen;
+
+ if ((old = hashtab[index])) {
+ old--;
+ next[i] = old;
+ do {
+ if (c->methods[old].name == mi->name &&
+ c->methods[old].descriptor == mi->descriptor) {
+ exceptions_throw_classformaterror(c, "Repetitive method name/signature");
+ return false;
+ }
+ } while ((old = next[old]));
+ }
+ hashtab[index] = i + 1;
+ }
+
+ MFREE(hashtab, u2, (hashlen + len));
+ }
+#endif /* ENABLE_VERIFIER */
+
+ RT_TIMING_GET_TIME(time_verify);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ size_classinfo += sizeof(classinfo*) * c->interfacescount;
+ size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
+ size_methodinfo += sizeof(methodinfo) * c->methodscount;
+ }
+#endif
+
+ /* load attribute structures */
+
+ if (!class_load_attributes(cb))
+ return false;
+
+ /* Pre Java 1.5 version don't check this. This implementation is
+ like Java 1.5 do it: for class file version 45.3 we don't check
+ it, older versions are checked. */
+
+ if (((ma == 45) && (mi > 3)) || (ma > 45)) {
+ /* check if all data has been read */
+ s4 classdata_left = ((cb->data + cb->size) - cb->pos);
+
+ if (classdata_left > 0) {
+ exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
+ return false;
+ }
+ }
+
+ RT_TIMING_GET_TIME(time_attrs);
+
+ RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
+ RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
+ RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
+ RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
+ RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
+ RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
+ RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
+ RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
+ RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
+ RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
+ RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
+ RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
+ RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
+ RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
+ RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
+
+ return true;
+}
+
+
+/* load_class_from_classbuffer *************************************************
+
+ Convenience wrapper for load_class_from_classbuffer.
+
+ SYNCHRONIZATION:
+ This function is NOT synchronized!
+
+*******************************************************************************/
+
+classinfo *load_class_from_classbuffer(classbuffer *cb)
+{
+ classinfo *c;
+ bool result;
+ int32_t dumpmarker;
+
+ /* Get the classbuffer's class. */
+
+ c = cb->clazz;
+
+ /* Check if the class is already loaded. */
+
+ if (c->state & CLASS_LOADED)
+ return c;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_class_loads++;
+#endif
+
+#if !defined(NDEBUG)
+ if (loadverbose)
+ log_message_class("Loading class: ", c);
+#endif
+
+ /* Mark start of dump memory area. */
+
+ DMARKER;
+
+ /* Class is currently loading. */
+
+ c->state |= CLASS_LOADING;
+
+ /* Parse the classbuffer. */
+
+ result = load_class_from_classbuffer_intern(cb);
+
+ /* Release dump area. */
+
+ DRELEASE;
+
+ /* An error occurred. */
+
+ if (result == false) {
+ /* Revert loading state. */
+
+ c->state = (c->state & ~CLASS_LOADING);
+
+ return NULL;
+ }
+
+ /* Revert loading state and set loaded. */
+
+ c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
+
+#if defined(ENABLE_JVMTI)
+ /* fire Class Prepare JVMTI event */
+
+ if (jvmti)
+ jvmti_ClassLoadPrepare(true, c);
+#endif
+
+#if !defined(NDEBUG)
+ if (loadverbose)
+ log_message_class("Loading done class: ", c);
+#endif
+
+ return c;
+}
+
+
+/* load_newly_created_array ****************************************************
+
+ Load a newly created array class.
+
+ RETURN VALUE:
+ c....................the array class C has been loaded
+ other classinfo......the array class was found in the class cache,
+ C has been freed
+ NULL.................an exception has been thrown
+
+ Note:
+ This is an internal function. Do not use it unless you know exactly
+ what you are doing!
+
+ Use one of the load_class_... functions for general array class loading.
+
+*******************************************************************************/
+
+classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
+{
+ classinfo *comp = NULL;
+ methodinfo *clone;
+ methoddesc *clonedesc;
+ constant_classref *classrefs;
+ char *text;
+ s4 namelen;
+ utf *u;
+
+ text = c->name->text;
+ namelen = c->name->blength;
+
+ /* Check array class name */
+
+ if ((namelen < 2) || (text[0] != '[')) {
+ exceptions_throw_classnotfoundexception(c->name);
+ return NULL;
+ }
+
+ /* Check the element type */
+
+ switch (text[1]) {
+ case '[':
+ /* c is an array of arrays. We have to create the component class. */
+
+ u = utf_new(text + 1, namelen - 1);
+
+ comp = load_class_from_classloader(u, loader);
+
+ if (comp == NULL)
+ return NULL;
+
+ assert(comp->state & CLASS_LOADED);
+
+ /* the array's flags are that of the component class */
+ c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+ c->classloader = comp->classloader;
+ break;
+
+ case 'L':
+ /* c is an array of objects. */
+
+ /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
+ if ((namelen < 4) || (text[2] == '[') || (text[namelen - 1] != ';')) {
+ exceptions_throw_classnotfoundexception(c->name);
+ return NULL;
+ }
+
+ u = utf_new(text + 2, namelen - 3);
+
+ if (!(comp = load_class_from_classloader(u, loader)))
+ return NULL;
+
+ assert(comp->state & CLASS_LOADED);
+
+ /* the array's flags are that of the component class */
+ c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
+ c->classloader = comp->classloader;
+ break;
+
+ default:
+ /* c is an array of a primitive type */
+
+ /* check for cases like `[II' and whether the character is a
+ valid primitive type */
+
+ if ((namelen > 2) || (Primitive_get_class_by_char(text[1]) == NULL)) {
+ exceptions_throw_classnotfoundexception(c->name);
+ return NULL;
+ }
+
+ /* the accessibility of the array class is public (VM Spec 5.3.3) */
+ c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
+ c->classloader = NULL;
+ }
+
+ assert(class_java_lang_Object);
+#if defined(ENABLE_JAVASE)
+ assert(class_java_lang_Cloneable);
+ assert(class_java_io_Serializable);
+#endif
+
+ /* Setup the array class. */
+
+ c->super = class_java_lang_Object;
+
+#if defined(ENABLE_JAVASE)
+
+ c->interfacescount = 2;
+ c->interfaces = MNEW(classinfo*, 2);
+ c->interfaces[0] = class_java_lang_Cloneable;
+ c->interfaces[1] = class_java_io_Serializable;
+
+#elif defined(ENABLE_JAVAME_CLDC1_1)
+
+ c->interfacescount = 0;
+ c->interfaces = NULL;
+
+#else
+# error unknow Java configuration
+#endif
+
+ c->methodscount = 1;
+ c->methods = MNEW(methodinfo, c->methodscount);
+
+ MZERO(c->methods, methodinfo, c->methodscount);
+
+ classrefs = MNEW(constant_classref, 2);
+
+ CLASSREF_INIT(classrefs[0], c, c->name);
+ CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
+
+ /* create descriptor for clone method */
+ /* we need one paramslot which is reserved for the 'this' parameter */
+ clonedesc = NEW(methoddesc);
+ clonedesc->returntype.type = TYPE_ADR;
+ clonedesc->returntype.classref = classrefs + 1;
+ clonedesc->returntype.arraydim = 0;
+ /* initialize params to "empty", add real params below in
+ descriptor_params_from_paramtypes */
+ clonedesc->paramcount = 0;
+ clonedesc->paramslots = 0;
+ clonedesc->paramtypes[0].classref = classrefs + 0;
+ clonedesc->params = NULL;
+
+ /* create methodinfo */
+
+ clone = c->methods;
+ MSET(clone, 0, methodinfo, 1);
+
+#if defined(ENABLE_THREADS)
+ lock_init_object_lock(&clone->header);
+#endif
+
+ /* ATTENTION: if you delete the ACC_NATIVE below, set
+ clone->maxlocals=1 (interpreter related) */
+
+ clone->flags = ACC_PUBLIC | ACC_NATIVE;
+ clone->name = utf_clone;
+ clone->descriptor = utf_void__java_lang_Object;
+ clone->parseddesc = clonedesc;
+ clone->clazz = c;
+
+ /* parse the descriptor to get the register allocation */
+
+ if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
+ return false;
+
+ clone->code = codegen_generate_stub_native(clone, BUILTIN_clone);
+
+ /* XXX: field: length? */
+
+ /* array classes are not loaded from class files */
+
+ c->state |= CLASS_LOADED;
+ c->parseddescs = (u1 *) clonedesc;
+ c->parseddescsize = sizeof(methodinfo);
+ c->classrefs = classrefs;
+ c->classrefcount = 1;
+
+ /* insert class into the loaded class cache */
+ /* XXX free classinfo if NULL returned? */
+
+ return classcache_store(loader, c, true);
+}
+
+
+/* loader_close ****************************************************************
+
+ Frees all resources.
+
+*******************************************************************************/
+
+void loader_close(void)
+{
+ /* empty */
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/loader.h - class loader header
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _LOADER_H
+#define _LOADER_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct classbuffer classbuffer;
+
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "vm/descriptor.h"
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
+#include "vm/utf8.h"
+
+
+/* constant pool entries *******************************************************
+
+ All constant pool entries need a data structure which contain the entrys
+ value. In some cases this structure exist already, in the remaining cases
+ this structure must be generated:
+
+ kind structure generated?
+ ----------------------------------------------------------------------
+ CONSTANT_Class constant_classref yes
+ CONSTANT_Fieldref constant_FMIref yes
+ CONSTANT_Methodref constant_FMIref yes
+ CONSTANT_InterfaceMethodref constant_FMIref yes
+ CONSTANT_String unicode no
+ CONSTANT_Integer constant_integer yes
+ CONSTANT_Float constant_float yes
+ CONSTANT_Long constant_long yes
+ CONSTANT_Double constant_double yes
+ CONSTANT_NameAndType constant_nameandtype yes
+ CONSTANT_Utf8 unicode no
+ CONSTANT_UNUSED -
+
+*******************************************************************************/
+
+typedef struct { /* Integer */
+ s4 value;
+} constant_integer;
+
+
+typedef struct { /* Float */
+ float value;
+} constant_float;
+
+
+typedef struct { /* Long */
+ s8 value;
+} constant_long;
+
+
+typedef struct { /* Double */
+ double value;
+} constant_double;
+
+
+typedef struct { /* NameAndType (Field or Method) */
+ utf *name; /* field/method name */
+ utf *descriptor; /* field/method type descriptor string */
+} constant_nameandtype;
+
+
+/* classbuffer ****************************************************************/
+
+struct classbuffer {
+ classinfo *clazz; /* pointer to classinfo structure */
+ uint8_t *data; /* pointer to byte code */
+ int32_t size; /* size of the byte code */
+ uint8_t *pos; /* current read position */
+ char *path; /* path to file (for debugging) */
+};
+
+
+/* hashtable_classloader_entry *************************************************
+
+ ATTENTION: The pointer to the classloader object needs to be the
+ first field of the entry, so that it can be used as an indirection
+ cell. This is checked by gc_init() during startup.
+
+*******************************************************************************/
+
+typedef struct hashtable_classloader_entry hashtable_classloader_entry;
+
+struct hashtable_classloader_entry {
+ java_object_t *object;
+ hashtable_classloader_entry *hashlink;
+};
+
+
+/* classloader *****************************************************************
+
+ [!ENABLE_HANDLES]: The classloader is a Java Object which cannot move.
+ [ENABLE_HANDLES] : The classloader entry itself is a static handle for a
+ given classloader (use loader_hashtable_classloader_foo).
+
+*******************************************************************************/
+
+#if defined(ENABLE_HANDLES)
+typedef hashtable_classloader_entry classloader_t;
+#else
+typedef java_object_t classloader_t;
+#endif
+
+
+/* function prototypes ********************************************************/
+
+void loader_preinit(void);
+void loader_init(void);
+
+/* classloader management functions */
+classloader_t *loader_hashtable_classloader_add(java_handle_t *cl);
+classloader_t *loader_hashtable_classloader_find(java_handle_t *cl);
+
+void loader_load_all_classes(void);
+
+bool loader_skip_attribute_body(classbuffer *cb);
+
+#if defined(ENABLE_JAVASE)
+bool loader_load_attribute_signature(classbuffer *cb, utf **signature);
+#endif
+
+/* free resources */
+void loader_close(void);
+
+/* class loading functions */
+classinfo *load_class_from_sysloader(utf *name);
+classinfo *load_class_from_classloader(utf *name, classloader_t *cl);
+classinfo *load_class_bootstrap(utf *name);
+
+/* (don't use the following directly) */
+classinfo *load_class_from_classbuffer(classbuffer *cb);
+classinfo *load_newly_created_array(classinfo *c, classloader_t *loader);
+
+#endif /* _LOADER_H */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/method.c - method functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "native/llni.h"
+
+#include "threads/lock-common.h"
+
+#include "vm/array.h"
+#include "vm/builtin.h"
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/resolve.h"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+#include "vm/jit/code.h"
+#include "vm/jit/methodheader.h"
+
+
+#if !defined(NDEBUG) && defined(ENABLE_INLINING)
+#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
+#else
+#define INLINELOG(code)
+#endif
+
+
+/* global variables ***********************************************************/
+
+methodinfo *method_java_lang_reflect_Method_invoke;
+
+
+/* method_init *****************************************************************
+
+ Initialize method subsystem.
+
+*******************************************************************************/
+
+void method_init(void)
+{
+#if defined(ENABLE_JAVASE)
+ /* Sanity check. */
+
+ if (class_java_lang_reflect_Method == NULL)
+ vm_abort("method_init: class_java_lang_reflect_Method is NULL");
+
+ /* Cache java.lang.reflect.Method.invoke() */
+
+ method_java_lang_reflect_Method_invoke =
+ class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
+
+ if (method_java_lang_reflect_Method_invoke == NULL)
+ vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
+#endif
+}
+
+
+/* method_load *****************************************************************
+
+ Loads a method from the class file and fills an existing methodinfo
+ structure.
+
+ method_info {
+ u2 access_flags;
+ u2 name_index;
+ u2 descriptor_index;
+ u2 attributes_count;
+ attribute_info attributes[attribute_count];
+ }
+
+ attribute_info {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u1 info[attribute_length];
+ }
+
+ LineNumberTable_attribute {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 line_number_table_length;
+ {
+ u2 start_pc;
+ u2 line_number;
+ } line_number_table[line_number_table_length];
+ }
+
+*******************************************************************************/
+
+bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
+{
+ classinfo *c;
+ int argcount;
+ s4 i, j, k, l;
+ utf *u;
+ u2 name_index;
+ u2 descriptor_index;
+ u2 attributes_count;
+ u2 attribute_name_index;
+ utf *attribute_name;
+ u2 code_attributes_count;
+ u2 code_attribute_name_index;
+ utf *code_attribute_name;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ LOCK_INIT_OBJECT_LOCK(&(m->header));
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_all_methods++;
+#endif
+
+ /* all fields of m have been zeroed in load_class_from_classbuffer */
+
+ m->clazz = c;
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
+ return false;
+
+ /* access flags */
+
+ m->flags = suck_u2(cb);
+
+ /* name */
+
+ name_index = suck_u2(cb);
+
+ if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8)))
+ return false;
+
+ m->name = u;
+
+ /* descriptor */
+
+ descriptor_index = suck_u2(cb);
+
+ if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
+ return false;
+
+ m->descriptor = u;
+
+ if (!descriptor_pool_add(descpool, u, &argcount))
+ return false;
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ if (!is_valid_name_utf(m->name)) {
+ exceptions_throw_classformaterror(c, "Method with invalid name");
+ return false;
+ }
+
+ if (m->name->text[0] == '<' &&
+ m->name != utf_init && m->name != utf_clinit) {
+ exceptions_throw_classformaterror(c, "Method with invalid special name");
+ return false;
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ if (!(m->flags & ACC_STATIC))
+ argcount++; /* count the 'this' argument */
+
+#ifdef ENABLE_VERIFIER
+ if (opt_verify) {
+ if (argcount > 255) {
+ exceptions_throw_classformaterror(c, "Too many arguments in signature");
+ return false;
+ }
+
+ /* check flag consistency */
+ if (m->name != utf_clinit) {
+ i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
+
+ if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
+ exceptions_throw_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
+
+ if (m->flags & ACC_ABSTRACT) {
+ if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
+ ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
+ exceptions_throw_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
+ }
+
+ if (c->flags & ACC_INTERFACE) {
+ if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
+ exceptions_throw_classformaterror(c,
+ "Illegal method modifiers: 0x%X",
+ m->flags);
+ return false;
+ }
+ }
+
+ if (m->name == utf_init) {
+ if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
+ ACC_NATIVE | ACC_ABSTRACT)) {
+ exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
+ return false;
+ }
+ }
+ }
+ }
+#endif /* ENABLE_VERIFIER */
+
+ /* mark the method as monomorphic until further notice */
+
+ m->flags |= ACC_METHOD_MONOMORPHIC;
+
+ /* non-abstract methods have an implementation in this class */
+
+ if (!(m->flags & ACC_ABSTRACT))
+ m->flags |= ACC_METHOD_IMPLEMENTED;
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* attributes count */
+
+ attributes_count = suck_u2(cb);
+
+ for (i = 0; i < attributes_count; i++) {
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* attribute name index */
+
+ attribute_name_index = suck_u2(cb);
+
+ attribute_name =
+ class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
+
+ if (attribute_name == NULL)
+ return false;
+
+ if (attribute_name == utf_Code) {
+ /* Code */
+
+ if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
+ exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
+ return false;
+ }
+
+ if (m->jcode) {
+ exceptions_throw_classformaterror(c, "Multiple Code attributes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
+ return false;
+
+ suck_u4(cb);
+ m->maxstack = suck_u2(cb);
+ m->maxlocals = suck_u2(cb);
+
+ if (m->maxlocals < argcount) {
+ exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4))
+ return false;
+
+ m->jcodelength = suck_u4(cb);
+
+ if (m->jcodelength == 0) {
+ exceptions_throw_classformaterror(c, "Code of a method has length 0");
+ return false;
+ }
+
+ if (m->jcodelength > 65535) {
+ exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, m->jcodelength))
+ return false;
+
+ m->jcode = MNEW(u1, m->jcodelength);
+ suck_nbytes(m->jcode, cb, m->jcodelength);
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ m->rawexceptiontablelength = suck_u2(cb);
+ if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
+ return false;
+
+ m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat) {
+ count_vmcode_len += m->jcodelength + 18;
+ count_extable_len +=
+ m->rawexceptiontablelength * sizeof(raw_exception_entry);
+ }
+#endif
+
+ for (j = 0; j < m->rawexceptiontablelength; j++) {
+ u4 idx;
+ m->rawexceptiontable[j].startpc = suck_u2(cb);
+ m->rawexceptiontable[j].endpc = suck_u2(cb);
+ m->rawexceptiontable[j].handlerpc = suck_u2(cb);
+
+ idx = suck_u2(cb);
+
+ if (!idx) {
+ m->rawexceptiontable[j].catchtype.any = NULL;
+ }
+ else {
+ /* the classref is created later */
+ if (!(m->rawexceptiontable[j].catchtype.any =
+ (utf *) class_getconstant(c, idx, CONSTANT_Class)))
+ return false;
+ }
+ }
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* code attributes count */
+
+ code_attributes_count = suck_u2(cb);
+
+ for (k = 0; k < code_attributes_count; k++) {
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* code attribute name index */
+
+ code_attribute_name_index = suck_u2(cb);
+
+ code_attribute_name =
+ class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
+
+ if (code_attribute_name == NULL)
+ return false;
+
+ /* check which code attribute */
+
+ if (code_attribute_name == utf_LineNumberTable) {
+ /* LineNumberTable */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* attribute length */
+
+ (void) suck_u4(cb);
+
+ /* line number table length */
+
+ m->linenumbercount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb,
+ (2 + 2) * m->linenumbercount))
+ return false;
+
+ m->linenumbers = MNEW(lineinfo, m->linenumbercount);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
+#endif
+
+ for (l = 0; l < m->linenumbercount; l++) {
+ m->linenumbers[l].start_pc = suck_u2(cb);
+ m->linenumbers[l].line_number = suck_u2(cb);
+ }
+ }
+#if defined(ENABLE_JAVASE)
+ else if (code_attribute_name == utf_StackMapTable) {
+ /* StackTableMap */
+
+ if (!stackmap_load_attribute_stackmaptable(cb, m))
+ return false;
+ }
+#endif
+ else {
+ /* unknown code attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+ }
+ else if (attribute_name == utf_Exceptions) {
+ /* Exceptions */
+
+ if (m->thrownexceptions != NULL) {
+ exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
+ return false;
+ }
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* attribute length */
+
+ (void) suck_u4(cb);
+
+ m->thrownexceptionscount = suck_u2(cb);
+
+ if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
+ return false;
+
+ m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
+
+ for (j = 0; j < m->thrownexceptionscount; j++) {
+ /* the classref is created later */
+ if (!((m->thrownexceptions)[j].any =
+ (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
+ return false;
+ }
+ }
+#if defined(ENABLE_JAVASE)
+ else if (attribute_name == utf_Signature) {
+ /* Signature */
+
+ if (!loader_load_attribute_signature(cb, &(m->signature)))
+ return false;
+ }
+
+#if defined(ENABLE_ANNOTATIONS)
+ else if (attribute_name == utf_RuntimeVisibleAnnotations) {
+ /* RuntimeVisibleAnnotations */
+ if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
+ /* RuntimeInvisibleAnnotations */
+ if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
+ /* RuntimeVisibleParameterAnnotations */
+ if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
+ /* RuntimeInvisibleParameterAnnotations */
+ if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
+ return false;
+ }
+ else if (attribute_name == utf_AnnotationDefault) {
+ /* AnnotationDefault */
+ if (!annotation_load_method_attribute_annotationdefault(cb, m))
+ return false;
+ }
+#endif
+#endif
+ else {
+ /* unknown attribute */
+
+ if (!loader_skip_attribute_body(cb))
+ return false;
+ }
+ }
+
+ if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
+ exceptions_throw_classformaterror(c, "Missing Code attribute");
+ return false;
+ }
+
+#if defined(ENABLE_REPLACEMENT)
+ /* initialize the hit countdown field */
+
+ m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
+#endif
+
+ /* everything was ok */
+
+ return true;
+}
+
+
+/* method_free *****************************************************************
+
+ Frees all memory that was allocated for this method.
+
+*******************************************************************************/
+
+void method_free(methodinfo *m)
+{
+ if (m->jcode)
+ MFREE(m->jcode, u1, m->jcodelength);
+
+ if (m->rawexceptiontable)
+ MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
+
+ code_free_code_of_method(m);
+
+ if (m->stubroutine) {
+ if (m->flags & ACC_NATIVE) {
+ removenativestub(m->stubroutine);
+
+ } else {
+ removecompilerstub(m->stubroutine);
+ }
+ }
+}
+
+
+/* method_canoverwrite *********************************************************
+
+ Check if m and old are identical with respect to type and
+ name. This means that old can be overwritten with m.
+
+*******************************************************************************/
+
+bool method_canoverwrite(methodinfo *m, methodinfo *old)
+{
+ if (m->name != old->name)
+ return false;
+
+ if (m->descriptor != old->descriptor)
+ return false;
+
+ if (m->flags & ACC_STATIC)
+ return false;
+
+ return true;
+}
+
+
+/* method_new_builtin **********************************************************
+
+ Creates a minimal methodinfo structure for builtins. This comes handy
+ when dealing with builtin stubs or stacktraces.
+
+*******************************************************************************/
+
+methodinfo *method_new_builtin(builtintable_entry *bte)
+{
+ methodinfo *m;
+
+ /* allocate the methodinfo structure */
+
+ m = NEW(methodinfo);
+
+ /* initialize methodinfo structure */
+
+ MZERO(m, methodinfo, 1);
+ LOCK_INIT_OBJECT_LOCK(&(m->header));
+
+ m->flags = ACC_METHOD_BUILTIN;
+ m->parseddesc = bte->md;
+ m->name = bte->name;
+ m->descriptor = bte->descriptor;
+
+ /* return the newly created methodinfo */
+
+ return m;
+}
+
+
+/* method_vftbl_lookup *********************************************************
+
+ Does a method lookup in the passed virtual function table. This
+ function does exactly the same thing as JIT, but additionally
+ relies on the fact, that the methodinfo pointer is at the first
+ data segment slot (even for compiler stubs).
+
+*******************************************************************************/
+
+methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
+{
+ methodptr mptr;
+ methodptr *pmptr;
+ methodinfo *resm; /* pointer to new resolved method */
+
+ /* If the method is not an instance method, just return it. */
+
+ if (m->flags & ACC_STATIC)
+ return m;
+
+ assert(vftbl);
+
+ /* Get the method from the virtual function table. Is this an
+ interface method? */
+
+ if (m->clazz->flags & ACC_INTERFACE) {
+ pmptr = vftbl->interfacetable[-(m->clazz->index)];
+ mptr = pmptr[(m - m->clazz->methods)];
+ }
+ else {
+ mptr = vftbl->table[m->vftblindex];
+ }
+
+ /* and now get the codeinfo pointer from the first data segment slot */
+
+ resm = code_get_methodinfo_for_pv(mptr);
+
+ return resm;
+}
+
+
+/* method_get_parametercount **************************************************
+
+ Use the descriptor of a method to determine the number of parameters
+ of the method. The this pointer of non-static methods is not counted.
+
+ IN:
+ m........the method of which the parameters should be counted
+
+ RETURN VALUE:
+ The parameter count or -1 on error.
+
+*******************************************************************************/
+
+int32_t method_get_parametercount(methodinfo *m)
+{
+ methoddesc *md; /* method descriptor of m */
+ int32_t paramcount = 0; /* the parameter count of m */
+
+ md = m->parseddesc;
+
+ /* is the descriptor fully parsed? */
+
+ if (md->params == NULL) {
+ if (!descriptor_params_from_paramtypes(md, m->flags)) {
+ return -1;
+ }
+ }
+
+ paramcount = md->paramcount;
+
+ /* skip `this' pointer */
+
+ if (!(m->flags & ACC_STATIC)) {
+ --paramcount;
+ }
+
+ return paramcount;
+}
+
+
+/* method_get_parametertypearray ***********************************************
+
+ Use the descriptor of a method to generate a java.lang.Class array
+ which contains the classes of the parametertypes of the method.
+
+ This function is called by java.lang.reflect.{Constructor,Method}.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
+{
+ methoddesc *md;
+ typedesc *paramtypes;
+ int32_t paramcount;
+ java_handle_objectarray_t *oa;
+ int32_t i;
+ classinfo *c;
+
+ md = m->parseddesc;
+
+ /* is the descriptor fully parsed? */
+
+ if (m->parseddesc->params == NULL)
+ if (!descriptor_params_from_paramtypes(md, m->flags))
+ return NULL;
+
+ paramtypes = md->paramtypes;
+ paramcount = md->paramcount;
+
+ /* skip `this' pointer */
+
+ if (!(m->flags & ACC_STATIC)) {
+ paramtypes++;
+ paramcount--;
+ }
+
+ /* create class-array */
+
+ oa = builtin_anewarray(paramcount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* get classes */
+
+ for (i = 0; i < paramcount; i++) {
+ if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
+ return NULL;
+
+ LLNI_array_direct(oa, i) = (java_object_t *) c;
+ }
+
+ return oa;
+}
+
+
+/* method_get_exceptionarray ***************************************************
+
+ Get the exceptions which can be thrown by a method.
+
+*******************************************************************************/
+
+java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
+{
+ java_handle_objectarray_t *oa;
+ classinfo *c;
+ s4 i;
+
+ /* create class-array */
+
+ oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
+
+ if (oa == NULL)
+ return NULL;
+
+ /* iterate over all exceptions and store the class in the array */
+
+ for (i = 0; i < m->thrownexceptionscount; i++) {
+ c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
+
+ if (c == NULL)
+ return NULL;
+
+ LLNI_array_direct(oa, i) = (java_object_t *) c;
+ }
+
+ return oa;
+}
+
+
+/* method_returntype_get *******************************************************
+
+ Get the return type of the method.
+
+*******************************************************************************/
+
+classinfo *method_returntype_get(methodinfo *m)
+{
+ typedesc *td;
+ classinfo *c;
+
+ td = &(m->parseddesc->returntype);
+
+ if (!resolve_class_from_typedesc(td, true, false, &c))
+ return NULL;
+
+ return c;
+}
+
+
+/* method_count_implementations ************************************************
+
+ Count the implementations of a method in a class cone (a class and all its
+ subclasses.)
+
+ IN:
+ m................the method to count
+ c................class at which to start the counting (this class and
+ all its subclasses will be searched)
+
+ OUT:
+ *found...........if found != NULL, *found receives the method
+ implementation that was found. This value is only
+ meaningful if the return value is 1.
+
+ RETURN VALUE:
+ the number of implementations found
+
+*******************************************************************************/
+
+s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
+{
+ s4 count;
+ methodinfo *mp;
+ methodinfo *mend;
+ classinfo *child;
+
+ count = 0;
+
+ mp = c->methods;
+ mend = mp + c->methodscount;
+
+ for (; mp < mend; ++mp) {
+ if (method_canoverwrite(mp, m)) {
+ if (found)
+ *found = mp;
+ count++;
+ break;
+ }
+ }
+
+ for (child = c->sub; child != NULL; child = child->nextsub) {
+ count += method_count_implementations(m, child, found);
+ }
+
+ return count;
+}
+
+
+/* method_get_annotations ******************************************************
+
+ Get a methods' unparsed annotations in a byte array.
+
+ IN:
+ m........the method of which the annotations should be returned
+
+ RETURN VALUE:
+ The unparsed annotations in a byte array (or NULL if there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *method_get_annotations(methodinfo *m)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* methods' declaring class */
+ int slot; /* methods' slot */
+ java_handle_t *annotations; /* methods' unparsed annotations */
+ java_handle_t *method_annotations; /* all methods' unparsed annotations */
+ /* of the declaring class */
+
+ c = m->clazz;
+ slot = m - c->methods;
+ annotations = NULL;
+
+ LLNI_classinfo_field_get(c, method_annotations, method_annotations);
+
+ /* the method_annotations array might be shorter then the method
+ * count if the methods above a certain index have no annotations.
+ */
+ if (method_annotations != NULL &&
+ array_length_get(method_annotations) > slot) {
+ annotations = array_objectarray_element_get(
+ (java_handle_objectarray_t*)method_annotations, slot);
+ }
+
+ return (java_handle_bytearray_t*)annotations;
+#else
+ return NULL;
+#endif
+}
+
+
+/* method_get_parameterannotations ********************************************
+
+ Get a methods' unparsed parameter annotations in an array of byte
+ arrays.
+
+ IN:
+ m........the method of which the parameter annotations should be
+ returned
+
+ RETURN VALUE:
+ The unparsed parameter annotations in a byte array (or NULL if
+ there aren't any).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* methods' declaring class */
+ int slot; /* methods' slot */
+ java_handle_t *parameterAnnotations; /* methods' unparsed */
+ /* parameter annotations */
+ java_handle_t *method_parameterannotations; /* all methods' unparsed */
+ /* parameter annotations of */
+ /* the declaring class */
+
+ c = m->clazz;
+ slot = m - c->methods;
+ parameterAnnotations = NULL;
+
+ LLNI_classinfo_field_get(
+ c, method_parameterannotations, method_parameterannotations);
+
+ /* the method_annotations array might be shorter then the method
+ * count if the methods above a certain index have no annotations.
+ */
+ if (method_parameterannotations != NULL &&
+ array_length_get(method_parameterannotations) > slot) {
+ parameterAnnotations = array_objectarray_element_get(
+ (java_handle_objectarray_t*)method_parameterannotations,
+ slot);
+ }
+
+ return (java_handle_bytearray_t*)parameterAnnotations;
+#else
+ return NULL;
+#endif
+}
+
+
+/* method_get_annotationdefault ***********************************************
+
+ Get a methods' unparsed annotation default value in a byte array.
+
+ IN:
+ m........the method of which the annotation default value should be
+ returned
+
+ RETURN VALUE:
+ The unparsed annotation default value in a byte array (or NULL if
+ there isn't one).
+
+*******************************************************************************/
+
+java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
+{
+#if defined(ENABLE_ANNOTATIONS)
+ classinfo *c; /* methods' declaring class */
+ int slot; /* methods' slot */
+ java_handle_t *annotationDefault; /* methods' unparsed */
+ /* annotation default value */
+ java_handle_t *method_annotationdefaults; /* all methods' unparsed */
+ /* annotation default values of */
+ /* the declaring class */
+
+ c = m->clazz;
+ slot = m - c->methods;
+ annotationDefault = NULL;
+
+ LLNI_classinfo_field_get(
+ c, method_annotationdefaults, method_annotationdefaults);
+
+ /* the method_annotations array might be shorter then the method
+ * count if the methods above a certain index have no annotations.
+ */
+ if (method_annotationdefaults != NULL &&
+ array_length_get(method_annotationdefaults) > slot) {
+ annotationDefault = array_objectarray_element_get(
+ (java_handle_objectarray_t*)method_annotationdefaults, slot);
+ }
+
+ return (java_handle_bytearray_t*)annotationDefault;
+#else
+ return NULL;
+#endif
+}
+
+
+/* method_add_to_worklist ******************************************************
+
+ Add the method to the given worklist. If the method already occurs in
+ the worklist, the worklist remains unchanged.
+
+*******************************************************************************/
+
+static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
+{
+ method_worklist *wi;
+
+ for (wi = *wl; wi != NULL; wi = wi->next)
+ if (wi->m == m)
+ return;
+
+ wi = NEW(method_worklist);
+ wi->next = *wl;
+ wi->m = m;
+
+ *wl = wi;
+}
+
+
+/* method_add_assumption_monomorphic *******************************************
+
+ Record the assumption that the method is monomorphic.
+
+ IN:
+ m.................the method
+ caller............the caller making the assumption
+
+*******************************************************************************/
+
+void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
+{
+ method_assumption *as;
+
+ /* XXX LOCKING FOR THIS FUNCTION? */
+
+ /* check if we already have registered this assumption */
+
+ for (as = m->assumptions; as != NULL; as = as->next) {
+ if (as->context == caller)
+ return;
+ }
+
+ /* register the assumption */
+
+ as = NEW(method_assumption);
+ as->next = m->assumptions;
+ as->context = caller;
+
+ m->assumptions = as;
+}
+
+/* method_break_assumption_monomorphic *****************************************
+
+ Break the assumption that this method is monomorphic. All callers that
+ have registered this assumption are added to the worklist.
+
+ IN:
+ m.................the method
+ wl................worklist where to add invalidated callers
+
+*******************************************************************************/
+
+void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
+{
+ method_assumption *as;
+
+ /* XXX LOCKING FOR THIS FUNCTION? */
+
+ for (as = m->assumptions; as != NULL; as = as->next) {
+ INLINELOG(
+ printf("ASSUMPTION BROKEN (monomorphism): ");
+ method_print(m);
+ printf(" in ");
+ method_println(as->context);
+ );
+
+ method_add_to_worklist(as->context, wl);
+
+#if defined(ENABLE_TLH) && 0
+ /* XXX hack */
+ method_assumption *as2;
+ as2 = m->assumptions;
+ m->assumptions = NULL;
+ method_break_assumption_monomorphic(as->context, wl);
+ /*
+ assert(m->assumptions == NULL);
+ m->assumptions = as2;*/
+#endif
+
+ }
+}
+
+/* method_printflags ***********************************************************
+
+ Prints the flags of a method to stdout like.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_printflags(methodinfo *m)
+{
+ if (m == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
+ if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
+ if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
+ if (m->flags & ACC_STATIC) printf(" STATIC");
+ if (m->flags & ACC_FINAL) printf(" FINAL");
+ if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
+ if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
+ if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
+ if (m->flags & ACC_NATIVE) printf(" NATIVE");
+ if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
+ if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
+ if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
+ if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
+ if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_print ****************************************************************
+
+ Prints a method to stdout like:
+
+ java.lang.Object.<init>()V
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_print(methodinfo *m)
+{
+ if (m == NULL) {
+ printf("NULL");
+ return;
+ }
+
+ if (m->clazz != NULL)
+ utf_display_printable_ascii_classname(m->clazz->name);
+ else
+ printf("NULL");
+ printf(".");
+ utf_display_printable_ascii(m->name);
+ utf_display_printable_ascii(m->descriptor);
+
+ method_printflags(m);
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_println **************************************************************
+
+ Prints a method plus new line to stdout like:
+
+ java.lang.Object.<init>()V
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_println(methodinfo *m)
+{
+ if (opt_debugcolor) printf("\033[31m"); /* red */
+ method_print(m);
+ if (opt_debugcolor) printf("\033[m");
+ printf("\n");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_methodref_print ******************************************************
+
+ Prints a method reference to stdout.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_methodref_print(constant_FMIref *mr)
+{
+ if (!mr) {
+ printf("(constant_FMIref *)NULL");
+ return;
+ }
+
+ if (IS_FMIREF_RESOLVED(mr)) {
+ printf("<method> ");
+ method_print(mr->p.method);
+ }
+ else {
+ printf("<methodref> ");
+ utf_display_printable_ascii_classname(mr->p.classref->name);
+ printf(".");
+ utf_display_printable_ascii(mr->name);
+ utf_display_printable_ascii(mr->descriptor);
+ }
+}
+#endif /* !defined(NDEBUG) */
+
+
+/* method_methodref_println ****************************************************
+
+ Prints a method reference to stdout, followed by a newline.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void method_methodref_println(constant_FMIref *mr)
+{
+ method_methodref_print(mr);
+ printf("\n");
+}
+#endif /* !defined(NDEBUG) */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/method.h - method functions header
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _METHOD_H
+#define _METHOD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* forward typedefs ***********************************************************/
+
+typedef struct methodinfo methodinfo;
+typedef struct raw_exception_entry raw_exception_entry;
+typedef struct lineinfo lineinfo;
+typedef struct method_assumption method_assumption;
+typedef struct method_worklist method_worklist;
+typedef struct codeinfo codeinfo;
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/builtin.h"
+#include "vm/descriptor.h"
+#include "vm/global.h"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/references.h"
+
+#if defined(ENABLE_JAVASE)
+# include "vm/stackmap.h"
+#endif
+
+#include "vm/utf8.h"
+
+
+#if defined(ENABLE_REPLACEMENT)
+/* Initial value for the hit countdown field of each method. */
+#define METHOD_INITIAL_HIT_COUNTDOWN 1000
+#endif
+
+
+/* methodinfo *****************************************************************/
+
+struct methodinfo { /* method structure */
+ java_object_t header; /* we need this in jit's monitorenter */
+ s4 flags; /* ACC flags */
+ utf *name; /* name of method */
+ utf *descriptor; /* JavaVM descriptor string of method */
+#if defined(ENABLE_JAVASE)
+ utf *signature; /* Signature attribute */
+ stack_map_t *stack_map; /* StackMapTable attribute */
+#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) */
+ s4 maxstack; /* maximum stack depth of method */
+ s4 maxlocals; /* maximum number of local variables */
+ s4 jcodelength; /* length of JavaVM code */
+ u1 *jcode; /* pointer to JavaVM code */
+
+ s4 rawexceptiontablelength; /* exceptiontable length */
+ raw_exception_entry *rawexceptiontable; /* the exceptiontable */
+
+ u2 thrownexceptionscount; /* number of exceptions attribute */
+ classref_or_classinfo *thrownexceptions; /* except. a method may throw */
+
+ u2 linenumbercount; /* number of linenumber attributes */
+ lineinfo *linenumbers; /* array of lineinfo items */
+
+ u1 *stubroutine; /* stub for compiling or calling natives */
+ codeinfo *code; /* current code of this method */
+
+#if defined(ENABLE_LSRA)
+ s4 maxlifetimes; /* helper for lsra */
+#endif
+
+ methodinfo *overwrites; /* method that is directly overwritten */
+ method_assumption *assumptions; /* list of assumptions about this method */
+
+#if defined(ENABLE_REPLACEMENT)
+ s4 hitcountdown; /* decreased for each hit */
+#endif
+
+#if defined(ENABLE_DEBUG_FILTER)
+ u1 filtermatches; /* flags indicating which filters the method matches */
+#endif
+
+#if defined(ENABLE_ESCAPE)
+ u1 *paramescape;
+#endif
+};
+
+/* method_assumption ***********************************************************
+
+ This struct is used for registering assumptions about methods.
+
+*******************************************************************************/
+
+struct method_assumption {
+ method_assumption *next;
+ methodinfo *context;
+};
+
+
+/* method_worklist *************************************************************
+
+ List node used for method worklists.
+
+*******************************************************************************/
+
+struct method_worklist {
+ method_worklist *next;
+ methodinfo *m;
+};
+
+
+/* raw_exception_entry ********************************************************/
+
+/* exception table entry read by the loader */
+
+struct raw_exception_entry { /* exceptiontable entry in a method */
+ classref_or_classinfo catchtype; /* catchtype of exc. (0 == catchall) */
+ u2 startpc; /* start pc of guarded area (inclusive) */
+ u2 endpc; /* end pc of guarded area (exklusive) */
+ u2 handlerpc; /* pc of exception handler */
+};
+
+
+/* lineinfo *******************************************************************/
+
+struct lineinfo {
+ u2 start_pc;
+ u2 line_number;
+};
+
+
+/* global variables ***********************************************************/
+
+extern methodinfo *method_java_lang_reflect_Method_invoke;
+
+
+/* inline functions ***********************************************************/
+
+inline static bool method_is_builtin(methodinfo* m)
+{
+ return m->flags & ACC_METHOD_BUILTIN;
+}
+
+
+/* function prototypes ********************************************************/
+
+void method_init(void);
+
+bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool);
+void method_free(methodinfo *m);
+bool method_canoverwrite(methodinfo *m, methodinfo *old);
+
+methodinfo *method_new_builtin(builtintable_entry *bte);
+
+methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m);
+
+int32_t method_get_parametercount(methodinfo *m);
+java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m);
+java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m);
+classinfo *method_returntype_get(methodinfo *m);
+
+void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller);
+void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl);
+
+s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found);
+
+java_handle_bytearray_t *method_get_annotations(methodinfo *m);
+java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m);
+java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m);
+
+#if !defined(NDEBUG)
+void method_printflags(methodinfo *m);
+void method_print(methodinfo *m);
+void method_println(methodinfo *m);
+void method_methodref_print(constant_FMIref *mr);
+void method_methodref_println(constant_FMIref *mr);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _METHOD_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/options.c - contains global options
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "mm/memory.h"
+
+#include "native/jni.h"
+
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/vm.hpp"
+
+
+/* command line option ********************************************************/
+
+s4 opt_index = 0; /* index of processed arguments */
+char *opt_arg; /* this one exports the option argument */
+
+bool opt_foo = false; /* option for development */
+
+bool opt_jar = false;
+
+#if defined(ENABLE_JIT)
+bool opt_jit = true; /* JIT mode execution (default) */
+bool opt_intrp = false; /* interpreter mode execution */
+#else
+bool opt_jit = false; /* JIT mode execution */
+bool opt_intrp = true; /* interpreter mode execution (default) */
+#endif
+
+bool opt_run = true;
+
+s4 opt_heapmaxsize = 0; /* maximum heap size */
+s4 opt_heapstartsize = 0; /* initial heap size */
+s4 opt_stacksize = 0; /* thread stack size */
+
+bool opt_verbose = false;
+bool opt_debugcolor = false; /* use ANSI terminal sequences */
+bool compileall = false;
+
+bool loadverbose = false;
+bool initverbose = false;
+
+bool opt_verboseclass = false;
+bool opt_verbosegc = false;
+bool opt_verbosejni = false;
+bool opt_verbosecall = false; /* trace all method invocation */
+
+bool showmethods = false;
+bool showconstantpool = false;
+bool showutf = false;
+
+char *opt_method = NULL;
+char *opt_signature = NULL;
+
+bool compileverbose = false; /* trace compiler actions */
+bool showstack = false;
+
+bool opt_showdisassemble = false; /* generate disassembler listing */
+bool opt_shownops = false;
+bool opt_showddatasegment = false; /* generate data segment listing */
+bool opt_showintermediate = false; /* generate intermediate code listing */
+
+bool checkbounds = true; /* check array bounds */
+bool opt_noieee = false; /* don't implement ieee compliant floats */
+bool checksync = true; /* do synchronization */
+#if defined(ENABLE_LOOP)
+bool opt_loops = false; /* optimize array accesses in loops */
+#endif
+
+bool makeinitializations = true;
+
+#if defined(ENABLE_STATISTICS)
+bool opt_stat = false;
+bool opt_getloadingtime = false; /* to measure the runtime */
+bool opt_getcompilingtime = false; /* compute compile time */
+#endif
+#if defined(ENABLE_VERIFIER)
+bool opt_verify = true; /* true if classfiles should be verified */
+#endif
+
+#if defined(ENABLE_PROFILING)
+bool opt_prof = false;
+bool opt_prof_bb = false;
+#endif
+
+#if defined(ENABLE_OPAGENT)
+bool opt_opagent = false;
+#endif
+
+/* optimization options *******************************************************/
+
+#if defined(ENABLE_IFCONV)
+bool opt_ifconv = false;
+#endif
+
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+bool opt_lsra = false;
+#endif
+#if defined(ENABLE_SSA)
+bool opt_ssa_dce = false; /* enable dead code elemination */
+bool opt_ssa_cp = false; /* enable copy propagation */
+#endif
+
+
+/* interpreter options ********************************************************/
+
+#if defined(ENABLE_INTRP)
+bool opt_no_dynamic = false; /* suppress dynamic superinstructions */
+bool opt_no_replication = false; /* don't use replication in intrp */
+bool opt_no_quicksuper = false; /* instructions for quickening cannot be
+ part of dynamic superinstructions */
+
+s4 opt_static_supers = 0x7fffffff;
+bool vm_debug = false; /* XXX this should be called `opt_trace' */
+#endif
+
+#if defined(ENABLE_DEBUG_FILTER)
+const char *opt_filter_verbosecall_include = 0;
+const char *opt_filter_verbosecall_exclude = 0;
+const char *opt_filter_show_method = 0;
+#endif
+
+
+/* -XX options ****************************************************************/
+
+/* NOTE: For better readability keep these alpha-sorted. */
+
+/* Options which must always be available (production options in
+ HotSpot). */
+
+int64_t opt_MaxDirectMemorySize = -1;
+int opt_MaxPermSize = 0;
+int opt_PermSize = 0;
+int opt_ThreadStackSize = 0;
+
+/* Debugging options which can be turned off. */
+
+int opt_DebugExceptions = 0;
+int opt_DebugFinalizer = 0;
+int opt_DebugLocalReferences = 0;
+int opt_DebugLocks = 0;
+int opt_DebugPackage = 0;
+int opt_DebugPatcher = 0;
+int opt_DebugProperties = 0;
+int opt_DebugStackFrameInfo = 0;
+int opt_DebugStackTrace = 0;
+int opt_DebugThreads = 0;
+#if defined(ENABLE_DISASSEMBLER)
+int opt_DisassembleStubs = 0;
+#endif
+#if defined(ENABLE_OPAGENT)
+int opt_EnableOpagent = 0;
+#endif
+#if defined(ENABLE_GC_CACAO)
+int opt_GCDebugRootSet = 0;
+int opt_GCStress = 0;
+#endif
+#if defined(ENABLE_INLINING)
+int opt_Inline = 0;
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+int opt_InlineAll = 0;
+int opt_InlineCount = INT_MAX;
+int opt_InlineMaxSize = INT_MAX;
+int opt_InlineMinSize = 0;
+#endif
+#endif
+int opt_PrintConfig = 0;
+int opt_ProfileGCMemoryUsage = 0;
+int opt_ProfileMemoryUsage = 0;
+FILE *opt_ProfileMemoryUsageGNUPlot = NULL;
+#if defined(ENABLE_REPLACEMENT)
+int opt_TestReplacement = 0;
+#endif
+int opt_TraceCompilerCalls = 0;
+int opt_TraceExceptions = 0;
+int opt_TraceHPI = 0;
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+int opt_TraceInlining = 0;
+#endif
+int opt_TraceJavaCalls = 0;
+int opt_TraceJNICalls = 0;
+int opt_TraceJVMCalls = 0;
+int opt_TraceJVMCallsVerbose = 0;
+int opt_TraceLinkClass = 0;
+#if defined(ENABLE_REPLACEMENT)
+int opt_TraceReplacement = 0;
+#endif
+int opt_TraceSubsystemInitialization = 0;
+int opt_TraceTraps = 0;
+
+
+enum {
+ OPT_TYPE_BOOLEAN,
+ OPT_TYPE_VALUE
+};
+
+enum {
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ OPT_MaxDirectMemorySize,
+ OPT_MaxPermSize,
+ OPT_PermSize,
+ OPT_ThreadStackSize,
+
+ /* Debugging options which can be turned off. */
+
+ OPT_DebugExceptions,
+ OPT_DebugFinalizer,
+ OPT_DebugLocalReferences,
+ OPT_DebugLocks,
+ OPT_DebugPackage,
+ OPT_DebugPatcher,
+ OPT_DebugProperties,
+ OPT_DebugStackFrameInfo,
+ OPT_DebugStackTrace,
+ OPT_DebugThreads,
+ OPT_DisassembleStubs,
+ OPT_EnableOpagent,
+ OPT_GCDebugRootSet,
+ OPT_GCStress,
+ OPT_Inline,
+ OPT_InlineAll,
+ OPT_InlineCount,
+ OPT_InlineMaxSize,
+ OPT_InlineMinSize,
+ OPT_PrintConfig,
+ OPT_ProfileGCMemoryUsage,
+ OPT_ProfileMemoryUsage,
+ OPT_ProfileMemoryUsageGNUPlot,
+ OPT_TestReplacement,
+ OPT_TraceCompilerCalls,
+ OPT_TraceExceptions,
+ OPT_TraceHPI,
+ OPT_TraceInlining,
+ OPT_TraceJavaCalls,
+ OPT_TraceJNICalls,
+ OPT_TraceJVMCalls,
+ OPT_TraceJVMCallsVerbose,
+ OPT_TraceLinkClass,
+ OPT_TraceReplacement,
+ OPT_TraceSubsystemInitialization,
+ OPT_TraceTraps,
+ OPT_Vmlog,
+ OPT_VmlogStrings,
+ OPT_VmlogIgnore
+};
+
+
+option_t options_XX[] = {
+ /* Options which must always be available (production options in
+ HotSpot). */
+
+ { "MaxDirectMemorySize", OPT_MaxDirectMemorySize, OPT_TYPE_VALUE, "Maximum total size of NIO direct-buffer allocations" },
+ { "MaxPermSize", OPT_MaxPermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "PermSize", OPT_PermSize, OPT_TYPE_VALUE, "not implemented" },
+ { "ThreadStackSize", OPT_ThreadStackSize, OPT_TYPE_VALUE, "TODO" },
+
+ /* Debugging options which can be turned off. */
+
+ { "DebugExceptions", OPT_DebugExceptions, OPT_TYPE_BOOLEAN, "debug exceptions" },
+ { "DebugFinalizer", OPT_DebugFinalizer, OPT_TYPE_BOOLEAN, "debug finalizer thread" },
+ { "DebugLocalReferences", OPT_DebugLocalReferences, OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
+ { "DebugLocks", OPT_DebugLocks, OPT_TYPE_BOOLEAN, "print debug information for locks" },
+ { "DebugPackage", OPT_DebugPackage, OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
+ { "DebugPatcher", OPT_DebugPatcher, OPT_TYPE_BOOLEAN, "debug JIT code patching" },
+ { "DebugProperties", OPT_DebugProperties, OPT_TYPE_BOOLEAN, "print debug information for properties" },
+ { "DebugStackFrameInfo", OPT_DebugStackFrameInfo, OPT_TYPE_BOOLEAN, "TODO" },
+ { "DebugStackTrace", OPT_DebugStackTrace, OPT_TYPE_BOOLEAN, "debug stacktrace creation" },
+ { "DebugThreads", OPT_DebugThreads, OPT_TYPE_BOOLEAN, "print debug information for threads" },
+#if defined(ENABLE_DISASSEMBLER)
+ { "DisassembleStubs", OPT_DisassembleStubs, OPT_TYPE_BOOLEAN, "disassemble builtin and native stubs when generated" },
+#endif
+#if defined(ENABLE_OPAGENT)
+ { "EnableOpagent", OPT_EnableOpagent, OPT_TYPE_BOOLEAN, "enable providing JIT output to Oprofile" },
+#endif
+#if defined(ENABLE_GC_CACAO)
+ { "GCDebugRootSet", OPT_GCDebugRootSet, OPT_TYPE_BOOLEAN, "GC: print root-set at collection" },
+ { "GCStress", OPT_GCStress, OPT_TYPE_BOOLEAN, "GC: forced collection at every allocation" },
+#endif
+#if defined(ENABLE_INLINING)
+ { "Inline", OPT_Inline, OPT_TYPE_BOOLEAN, "enable method inlining" },
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ { "InlineAll", OPT_InlineAll, OPT_TYPE_BOOLEAN, "use inlining in all compilations" },
+ { "InlineCount", OPT_InlineCount, OPT_TYPE_VALUE, "stop inlining after the given number of roots" },
+ { "InlineMaxSize", OPT_InlineMaxSize, OPT_TYPE_VALUE, "maximum size for inlined result" },
+ { "InlineMinSize", OPT_InlineMinSize, OPT_TYPE_VALUE, "minimum size for inlined result" },
+#endif
+#endif
+ { "PrintConfig", OPT_PrintConfig, OPT_TYPE_BOOLEAN, "print VM configuration" },
+ { "ProfileGCMemoryUsage", OPT_ProfileGCMemoryUsage, OPT_TYPE_VALUE, "profiles GC memory usage in the given interval, <value> is in seconds (default: 5)" },
+ { "ProfileMemoryUsage", OPT_ProfileMemoryUsage, OPT_TYPE_VALUE, "TODO" },
+ { "ProfileMemoryUsageGNUPlot", OPT_ProfileMemoryUsageGNUPlot, OPT_TYPE_VALUE, "TODO" },
+#if defined(ENABLE_REPLACEMENT)
+ { "TestReplacement", OPT_TestReplacement, OPT_TYPE_BOOLEAN, "activate all replacement points during code generation" },
+#endif
+ { "TraceCompilerCalls", OPT_TraceCompilerCalls, OPT_TYPE_BOOLEAN, "trace JIT compiler calls" },
+ { "TraceExceptions", OPT_TraceExceptions, OPT_TYPE_BOOLEAN, "trace Exception throwing" },
+ { "TraceHPI", OPT_TraceHPI, OPT_TYPE_BOOLEAN, "Trace Host Porting Interface (HPI)" },
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ { "TraceInlining", OPT_TraceInlining, OPT_TYPE_VALUE, "trace method inlining with the given verbosity level (default: 1)" },
+#endif
+#if !defined(ENABLE_VMLOG)
+ { "TraceJavaCalls", OPT_TraceJavaCalls, OPT_TYPE_BOOLEAN, "trace Java method calls" },
+#endif
+ { "TraceJNICalls", OPT_TraceJNICalls, OPT_TYPE_BOOLEAN, "trace JNI method calls" },
+ { "TraceJVMCalls", OPT_TraceJVMCalls, OPT_TYPE_BOOLEAN, "trace JVM method calls but omit very frequent ones" },
+ { "TraceJVMCallsVerbose", OPT_TraceJVMCallsVerbose, OPT_TYPE_BOOLEAN, "trace all JVM method calls" },
+ { "TraceLinkClass", OPT_TraceLinkClass, OPT_TYPE_BOOLEAN, "trace class linking" },
+#if defined(ENABLE_REPLACEMENT)
+ { "TraceReplacement", OPT_TraceReplacement, OPT_TYPE_VALUE, "trace on-stack replacement with the given verbosity level (default: 1)" },
+#endif
+ { "TraceSubsystemInitialization", OPT_TraceSubsystemInitialization, OPT_TYPE_BOOLEAN, "trace initialization of subsystems" },
+ { "TraceTraps", OPT_TraceTraps, OPT_TYPE_BOOLEAN, "trace traps generated by JIT code" },
+#if defined(ENABLE_VMLOG)
+ { "Vmlog", OPT_Vmlog, OPT_TYPE_VALUE, "prefix for vmlog trace files (enables vmlog)" },
+ { "VmlogStrings", OPT_VmlogStrings, OPT_TYPE_VALUE, "prefix of vmlog string file to load" },
+ { "VmlogIgnore", OPT_VmlogIgnore, OPT_TYPE_VALUE, "prefix of vmlog ignore file to load" },
+#endif
+
+ /* end marker */
+
+ { NULL, -1, -1, NULL }
+};
+
+
+/* options_get *****************************************************************
+
+ DOCUMENT ME!!!
+
+*******************************************************************************/
+
+int options_get(opt_struct *opts, JavaVMInitArgs *vm_args)
+{
+ char *option;
+ int i;
+
+ if (opt_index >= vm_args->nOptions)
+ return OPT_DONE;
+
+ /* get the current option */
+
+ option = vm_args->options[opt_index].optionString;
+
+ if ((option == NULL) || (option[0] != '-'))
+ return OPT_DONE;
+
+ for (i = 0; opts[i].name; i++) {
+ if (!opts[i].arg) {
+ /* boolean option found */
+
+ if (strcmp(option + 1, opts[i].name) == 0) {
+ opt_index++;
+ return opts[i].value;
+ }
+
+ } else {
+ /* parameter option found */
+
+ /* with a space between */
+
+ if (strcmp(option + 1, opts[i].name) == 0) {
+ opt_index++;
+
+ if (opt_index < vm_args->nOptions) {
+ opt_arg = os_strdup(vm_args->options[opt_index].optionString);
+ opt_index++;
+ return opts[i].value;
+ }
+
+ return OPT_ERROR;
+
+ } else {
+ /* parameter and option have no space between */
+
+ /* FIXME: this assumption is plain wrong, hits you if there is a
+ * parameter with no argument starting with same letter as param with argument
+ * but named after that one, ouch! */
+
+ size_t l = os_strlen(opts[i].name);
+
+ if (os_strlen(option + 1) > l) {
+ if (memcmp(option + 1, opts[i].name, l) == 0) {
+ opt_index++;
+ opt_arg = os_strdup(option + 1 + l);
+ return opts[i].value;
+ }
+ }
+ }
+ }
+ }
+
+ return OPT_ERROR;
+}
+
+
+/* options_xxusage *************************************************************
+
+ Print usage message for debugging options.
+
+*******************************************************************************/
+
+static void options_xxusage(void)
+{
+ option_t *opt;
+ int length;
+ int i;
+ const char *c;
+
+ /* Prevent compiler warning. */
+
+ length = 0;
+
+ for (opt = options_XX; opt->name != NULL; opt++) {
+ printf(" -XX:");
+
+ switch (opt->type) {
+ case OPT_TYPE_BOOLEAN:
+ printf("+%s", opt->name);
+ length = os_strlen(" -XX:+") + os_strlen(opt->name);
+ break;
+
+ case OPT_TYPE_VALUE:
+ printf("%s=<value>", opt->name);
+ length = os_strlen(" -XX:") + os_strlen(opt->name) +
+ os_strlen("=<value>");
+ break;
+
+ default:
+ vm_abort("options_xxusage: unkown option type %d", opt->type);
+ }
+
+ /* Check if the help fits into one 80-column line.
+ Documentation starts at column 29. */
+
+ if (length < (29 - 1)) {
+ /* Print missing spaces up to column 29. */
+
+ for (i = length; i < 29; i++)
+ printf(" ");
+ }
+ else {
+ printf("\n");
+ printf(" "); /* 29 spaces */
+ }
+
+ /* Check documentation length. */
+
+ length = os_strlen(opt->doc);
+
+ if (length < (80 - 29)) {
+ printf("%s", opt->doc);
+ }
+ else {
+ for (c = opt->doc, i = 29; *c != 0; c++, i++) {
+ /* If we are at the end of the line, break it. */
+
+ if (i == 80) {
+ printf("\n");
+ printf(" "); /* 29 spaces */
+ i = 29;
+ }
+
+ printf("%c", *c);
+ }
+ }
+
+ printf("\n");
+ }
+
+ /* exit with error code */
+
+ exit(1);
+}
+
+
+/* options_xx ******************************************************************
+
+ Handle -XX: options.
+
+*******************************************************************************/
+
+void options_xx(JavaVMInitArgs *vm_args)
+{
+ const char *name;
+ const char *start;
+ char *end;
+ int length;
+ int enable;
+ char *value;
+ option_t *opt;
+ char *filename;
+ FILE *file;
+ int i;
+
+ /* Iterate over all passed options. */
+
+ for (i = 0; i < vm_args->nOptions; i++) {
+ /* Get the current option. */
+
+ name = vm_args->options[i].optionString;
+
+ /* Check for help (-XX). */
+
+ if (strcmp(name, "-XX") == 0)
+ options_xxusage();
+
+ /* Check if the option start with -XX. */
+
+ start = strstr(name, "-XX:");
+
+ if ((start == NULL) || (start != name))
+ continue;
+
+ /* Check if the option is a boolean option. */
+
+ if (name[4] == '+') {
+ start = name + 4 + 1;
+ enable = 1;
+ }
+ else if (name[4] == '-') {
+ start = name + 4 + 1;
+ enable = 0;
+ }
+ else {
+ start = name + 4;
+ enable = -1;
+ }
+
+ /* Search for a '=' in the option name and get the option name
+ length and the value of the option. */
+
+ end = strchr(start, '=');
+
+ if (end == NULL) {
+ length = os_strlen(start);
+ value = NULL;
+ }
+ else {
+ length = end - start;
+ value = end + 1;
+ }
+
+ /* Search the option in the option array. */
+
+ for (opt = options_XX; opt->name != NULL; opt++) {
+ if (strncmp(opt->name, start, length) == 0) {
+ /* Check if the options passed fits to the type. */
+
+ switch (opt->type) {
+ case OPT_TYPE_BOOLEAN:
+ if ((enable == -1) || (value != NULL))
+ options_xxusage();
+ break;
+ case OPT_TYPE_VALUE:
+ if ((enable != -1) || (value == NULL))
+ options_xxusage();
+ break;
+ default:
+ vm_abort("options_xx: unknown option type %d for option %s",
+ opt->type, opt->name);
+ }
+
+ break;
+ }
+ }
+
+ /* Process the option. */
+
+ switch (opt->value) {
+
+ /* Options which must always be available (production options
+ in HotSpot). */
+
+ case OPT_MaxDirectMemorySize:
+ opt_MaxDirectMemorySize = os_atoi(value);
+ break;
+
+ case OPT_MaxPermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_PermSize:
+ /* Currently ignored. */
+ break;
+
+ case OPT_ThreadStackSize:
+ /* currently ignored */
+ break;
+
+ /* Debugging options which can be turned off. */
+
+ case OPT_DebugExceptions:
+ opt_DebugExceptions = enable;
+ break;
+
+ case OPT_DebugFinalizer:
+ opt_DebugFinalizer = enable;
+ break;
+
+ case OPT_DebugLocalReferences:
+ opt_DebugLocalReferences = enable;
+ break;
+
+ case OPT_DebugLocks:
+ opt_DebugLocks = enable;
+ break;
+
+ case OPT_DebugPackage:
+ opt_DebugPackage = enable;
+ break;
+
+ case OPT_DebugPatcher:
+ opt_DebugPatcher = enable;
+ break;
+
+ case OPT_DebugProperties:
+ opt_DebugProperties = enable;
+ break;
+
+ case OPT_DebugStackFrameInfo:
+ opt_DebugStackFrameInfo = enable;
+ break;
+
+ case OPT_DebugStackTrace:
+ opt_DebugStackTrace = enable;
+ break;
+
+ case OPT_DebugThreads:
+ opt_DebugThreads = enable;
+ break;
+
+#if defined(ENABLE_DISASSEMBLER)
+ case OPT_DisassembleStubs:
+ opt_DisassembleStubs = enable;
+ break;
+#endif
+
+#if defined(ENABLE_OPAGENT)
+ case OPT_EnableOpagent:
+ opt_EnableOpagent = enable;
+ break;
+#endif
+
+#if defined(ENABLE_GC_CACAO)
+ case OPT_GCDebugRootSet:
+ opt_GCDebugRootSet = enable;
+ break;
+
+ case OPT_GCStress:
+ opt_GCStress = enable;
+ break;
+#endif
+
+#if defined(ENABLE_INLINING)
+ case OPT_Inline:
+ opt_Inline = enable;
+ break;
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+ case OPT_InlineAll:
+ opt_InlineAll = enable;
+ break;
+
+ case OPT_InlineCount:
+ if (value != NULL)
+ opt_InlineCount = os_atoi(value);
+ break;
+
+ case OPT_InlineMaxSize:
+ if (value != NULL)
+ opt_InlineMaxSize = os_atoi(value);
+ break;
+
+ case OPT_InlineMinSize:
+ if (value != NULL)
+ opt_InlineMinSize = os_atoi(value);
+ break;
+#endif
+#endif
+
+ case OPT_PrintConfig:
+ opt_PrintConfig = enable;
+ break;
+
+ case OPT_ProfileGCMemoryUsage:
+ if (value == NULL)
+ opt_ProfileGCMemoryUsage = 5;
+ else
+ opt_ProfileGCMemoryUsage = os_atoi(value);
+ break;
+
+ case OPT_ProfileMemoryUsage:
+ if (value == NULL)
+ opt_ProfileMemoryUsage = 5;
+ else
+ opt_ProfileMemoryUsage = os_atoi(value);
+
+# if defined(ENABLE_STATISTICS)
+ /* we also need statistics */
+
+ opt_stat = true;
+# endif
+ break;
+
+ case OPT_ProfileMemoryUsageGNUPlot:
+ if (value == NULL)
+ filename = "profile.dat";
+ else
+ filename = value;
+
+ file = fopen(filename, "w");
+
+ if (file == NULL)
+ vm_abort_errno("options_xx: fopen failed");
+
+ opt_ProfileMemoryUsageGNUPlot = file;
+ break;
+
+#if defined(ENABLE_REPLACEMENT)
+ case OPT_TestReplacement:
+ opt_TestReplacement = enable;
+ break;
+#endif
+
+ case OPT_TraceCompilerCalls:
+ opt_TraceCompilerCalls = enable;
+ break;
+
+ case OPT_TraceExceptions:
+ opt_TraceExceptions = enable;
+ break;
+
+ case OPT_TraceHPI:
+ opt_TraceHPI = enable;
+ break;
+
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+ case OPT_TraceInlining:
+ if (value == NULL)
+ opt_TraceInlining = 1;
+ else
+ opt_TraceInlining = os_atoi(value);
+ break;
+#endif
+
+ case OPT_TraceJavaCalls:
+ opt_verbosecall = enable;
+ opt_TraceJavaCalls = enable;
+ break;
+
+ case OPT_TraceJNICalls:
+ opt_TraceJNICalls = enable;
+ break;
+
+ case OPT_TraceJVMCalls:
+ opt_TraceJVMCalls = enable;
+ break;
+
+ case OPT_TraceJVMCallsVerbose:
+ opt_TraceJVMCallsVerbose = enable;
+ break;
+
+ case OPT_TraceLinkClass:
+ opt_TraceLinkClass = enable;
+ break;
+
+#if defined(ENABLE_REPLACEMENT)
+ case OPT_TraceReplacement:
+ if (value == NULL)
+ opt_TraceReplacement = 1;
+ else
+ opt_TraceReplacement = os_atoi(value);
+ break;
+#endif
+
+ case OPT_TraceSubsystemInitialization:
+ opt_TraceSubsystemInitialization = enable;
+ break;
+
+ case OPT_TraceTraps:
+ opt_TraceTraps = enable;
+ break;
+
+#if defined(ENABLE_VMLOG)
+ case OPT_Vmlog:
+ if (value == NULL)
+ vmlog_cacao_set_prefix("vmlog");
+ else
+ vmlog_cacao_set_prefix(value);
+ opt_verbosecall = 1;
+ opt_TraceJavaCalls = 1;
+ break;
+
+ case OPT_VmlogStrings:
+ if (value != NULL)
+ vmlog_cacao_set_stringprefix(value);
+ break;
+
+ case OPT_VmlogIgnore:
+ if (value != NULL)
+ vmlog_cacao_set_ignoreprefix(value);
+ break;
+#endif
+
+ default:
+ printf("Unknown -XX option: %s\n", name);
+ break;
+ }
+ }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/vm/options.h - define global options extern
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _OPTIONS_H
+#define _OPTIONS_H
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "native/jni.h"
+
+#include "vm/global.h"
+
+
+/* reserved option numbers ****************************************************/
+
+/* define these negative since the other options are an enum */
+
+#define OPT_DONE -1
+#define OPT_ERROR -2
+#define OPT_IGNORE -3
+
+
+typedef struct opt_struct opt_struct;
+
+struct opt_struct {
+ const char *name;
+ bool arg;
+ int value;
+};
+
+
+typedef struct option_t option_t;
+
+struct option_t {
+ const char *name;
+ int value;
+ int type;
+ const char *doc;
+};
+
+
+/* global variables ***********************************************************/
+
+extern s4 opt_index;
+extern char *opt_arg;
+
+extern bool opt_foo;
+
+extern bool opt_jit;
+extern bool opt_intrp;
+
+extern bool opt_jar;
+extern bool opt_run;
+
+extern s4 opt_heapmaxsize;
+extern s4 opt_heapstartsize;
+extern s4 opt_stacksize;
+
+extern bool opt_verbose;
+extern bool opt_debugcolor;
+extern bool compileall;
+
+extern bool loadverbose; /* Print debug messages during loading */
+extern bool initverbose; /* Log class initialization */
+
+extern bool opt_verboseclass;
+extern bool opt_verbosegc;
+extern bool opt_verbosejni;
+extern bool opt_verbosecall;
+
+extern bool showmethods;
+extern bool showconstantpool;
+extern bool showutf;
+
+extern char *opt_method;
+extern char *opt_signature;
+
+extern bool compileverbose;
+extern bool showstack;
+
+extern bool opt_showdisassemble;
+extern bool opt_shownops;
+extern bool opt_showddatasegment;
+extern bool opt_showintermediate;
+
+extern bool checkbounds;
+extern bool opt_noieee;
+extern bool checksync;
+#if defined(ENABLE_LOOP)
+extern bool opt_loops;
+#endif
+
+extern bool makeinitializations;
+
+#if defined(ENABLE_STATISTICS)
+extern bool opt_stat;
+extern bool opt_getloadingtime;
+extern bool opt_getcompilingtime;
+#endif
+#if defined(ENABLE_VERIFIER)
+extern bool opt_verify;
+#endif
+
+#if defined(ENABLE_PROFILING)
+extern bool opt_prof;
+extern bool opt_prof_bb;
+#endif
+
+/* optimization options *******************************************************/
+
+#if defined(ENABLE_IFCONV)
+extern bool opt_ifconv;
+#endif
+
+#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
+extern bool opt_lsra;
+#endif
+#if defined(ENABLE_SSA)
+extern bool opt_ssa_dce; /* enable dead code elemination */
+extern bool opt_ssa_cp; /* enable copy propagation */
+#endif
+
+/* interpreter options ********************************************************/
+
+#if defined(ENABLE_INTRP)
+extern bool opt_no_dynamic;
+extern bool opt_no_replication;
+extern bool opt_no_quicksuper;
+
+extern s4 opt_static_supers;
+extern bool vm_debug;
+#endif
+
+/* debug output filtering options *********************************************/
+
+#if defined(ENABLE_DEBUG_FILTER)
+extern const char *opt_filter_verbosecall_include;
+extern const char *opt_filter_verbosecall_exclude;
+extern const char *opt_filter_show_method;
+#endif
+
+
+/* -XX options ****************************************************************/
+
+/* NOTE: For better readability keep these alpha-sorted. */
+
+/* Options which must always be available (production options in
+ HotSpot). */
+
+extern int64_t opt_MaxDirectMemorySize;
+extern int opt_MaxPermSize;
+extern int opt_PermSize;
+extern int opt_ThreadStackSize;
+
+/* Debugging options which can be turned off. */
+
+extern int opt_DebugExceptions;
+extern int opt_DebugFinalizer;
+extern int opt_DebugLocalReferences;
+extern int opt_DebugLocks;
+extern int opt_DebugPatcher;
+extern int opt_DebugPackage;
+extern int opt_DebugProperties;
+extern int opt_DebugStackFrameInfo;
+extern int opt_DebugStackTrace;
+extern int opt_DebugThreads;
+#if defined(ENABLE_DISASSEMBLER)
+extern int opt_DisassembleStubs;
+#endif
+#if defined(ENABLE_OPAGENT)
+extern int opt_EnableOpagent;
+#endif
+#if defined(ENABLE_GC_CACAO)
+extern int opt_GCDebugRootSet;
+extern int opt_GCStress;
+#endif
+#if defined(ENABLE_INLINING)
+extern int opt_Inline;
+#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
+extern int opt_InlineAll;
+extern int opt_InlineCount;
+extern int opt_InlineMaxSize;
+extern int opt_InlineMinSize;
+#endif
+#endif
+extern int opt_PrintConfig;
+extern int opt_ProfileGCMemoryUsage;
+extern int opt_ProfileMemoryUsage;
+extern FILE *opt_ProfileMemoryUsageGNUPlot;
+#if defined(ENABLE_REPLACEMENT)
+extern int opt_TestReplacement;
+#endif
+extern int opt_TraceCompilerCalls;
+extern int opt_TraceExceptions;
+extern int opt_TraceHPI;
+#if defined(ENABLE_INLINING) && !defined(NDEBUG)
+extern int opt_TraceInlining;
+#endif
+extern int opt_TraceJavaCalls;
+extern int opt_TraceJNICalls;
+extern int opt_TraceJVMCalls;
+extern int opt_TraceJVMCallsVerbose;
+extern int opt_TraceLinkClass;
+#if defined(ENABLE_REPLACEMENT)
+extern int opt_TraceReplacement;
+#endif
+extern int opt_TraceSubsystemInitialization;
+extern int opt_TraceTraps;
+
+
+/* function prototypes ********************************************************/
+
+int options_get(opt_struct *opts, JavaVMInitArgs *vm_args);
+void options_xx(JavaVMInitArgs *vm_args);
+
+
+/* debug **********************************************************************/
+
+#if !defined(NDEBUG)
+# define TRACESUBSYSTEMINITIALIZATION(text) \
+ do { \
+ if (opt_TraceSubsystemInitialization) { \
+ log_println("[Initializing subsystem: %s]", text); \
+ } \
+ } while (0)
+#else
+# define TRACESUBSYSTEMINITIALIZATION(text)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OPTIONS_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/vm/os.cpp - system (OS) functions
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+/* 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>
+# include <mach/host_info.h>
+#endif
+
+/* this should work on BSD */
+/* #include <sys/sysctl.h> */
+
+#include "vm/vm.hpp"
+
+
+/**
+ * Maps anonymous memory, even on systems not defining
+ * MAP_ANON(YMOUS).
+ *
+ * @param ...
+ */
+void* os::mmap_anonymous(void *addr, size_t len, int prot, int flags)
+{
+ void* p;
+
+#if defined(MAP_ANON) || defined(MAP_ANONYMOUS)
+ p = mmap(addr, len, prot,
+# if defined(MAP_ANON)
+ MAP_ANON | flags,
+# else
+ MAP_ANONYMOUS | flags,
+# endif
+ -1, 0);
+#else
+ int fd;
+
+ fd = open("/dev/zero", O_RDONLY, 0);
+
+ if (fd == -1)
+ vm_abort("os::mmap_anonymous: open failed: %s", os::strerror(errno));
+
+ p = mmap(addr, len, prot, flags, fd, 0);
+#endif
+
+#if defined(MAP_FAILED)
+ if (p == MAP_FAILED)
+#else
+ if (p == (void *) -1)
+#endif
+ vm_abort("os::mmap_anonymous: mmap failed: %s", os::strerror(errno));
+
+ return p;
+}
+
+
+/**
+ * Returns the number of online processors in the system.
+ *
+ * @return Number of online processors.
+ */
+int os::processors_online(void)
+{
+#if defined(_SC_NPROC_ONLN)
+
+ return (int) sysconf(_SC_NPROC_ONLN);
+
+#elif defined(_SC_NPROCESSORS_ONLN)
+
+ return (int) sysconf(_SC_NPROCESSORS_ONLN);
+
+#elif defined(__DARWIN__)
+
+ host_basic_info_data_t hinfo;
+ mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
+ kern_return_t rc;
+
+ rc = host_info(mach_host_self(), HOST_BASIC_INFO,
+ (host_info_t) &hinfo, &hinfo_count);
+
+ if (rc != KERN_SUCCESS) {
+ return -1;
+ }
+
+ /* XXX michi: according to my infos this should be
+ hinfo.max_cpus, can someone please confirm or deny that? */
+ return (int) hinfo.avail_cpus;
+
+#elif defined(__FREEBSD__)
+# error IMPLEMENT ME!
+
+ /* this should work in BSD */
+ /*
+ int ncpu, mib[2], rc;
+ size_t len;
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ len = sizeof(ncpu);
+ rc = sysctl(mib, 2, &ncpu, &len, NULL, 0);
+
+ return (int32_t) ncpu;
+ */
+
+#else
+
+ return 1;
+
+#endif
+}
+
+
+// Legacy C interface.
+
+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
+ int os_dlclose(void* handle) { return os::dlclose(handle); }
+ char* os_dlerror(void) { return os::dlerror(); }
+ void* os_dlopen(const char* filename, int flag) { return os::dlopen(filename, flag); }
+ void* os_dlsym(void* handle, const char* symbol) { return os::dlsym(handle, symbol); }
+ int os_fclose(FILE* fp) { return os::fclose(fp); }
+ FILE* os_fopen(const char* path, const char* mode) { return os::fopen(path, mode); }
+ 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); }
+
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/os.hpp - system (OS) functions
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _OS_HPP
+#define _OS_HPP
+
+#include "config.h"
+
+/* NOTE: In this file we check for all system headers, because we wrap
+ all system calls into inline functions for better portability. */
+
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#endif
+
+#if defined(HAVE_DLFCN_H)
+# include <dlfcn.h>
+#endif
+
+#if defined(HAVE_ERRNO_H)
+# include <errno.h>
+#endif
+
+#if defined(HAVE_FCNTL_H)
+# include <fcntl.h>
+#endif
+
+#if defined(ENABLE_JRE_LAYOUT)
+# if defined(HAVE_LIBGEN_H)
+# include <libgen.h>
+# endif
+#endif
+
+#if defined(HAVE_STDINT_H)
+# include <stdint.h>
+#endif
+
+#if defined(HAVE_STDIO_H)
+# include <stdio.h>
+#endif
+
+#if defined(HAVE_STDLIB_H)
+# include <stdlib.h>
+#endif
+
+#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(HAVE_SYS_SOCKET_H)
+# include <sys/socket.h>
+#endif
+
+#if defined(HAVE_SYS_STAT_H)
+# include <sys/stat.h>
+#endif
+
+#if defined(HAVE_SYS_TYPES_H)
+# include <sys/types.h>
+#endif
+
+
+#ifdef __cplusplus
+
+// Class wrapping system (OS) functions.
+class os {
+public:
+ // Inline functions.
+ static inline void abort();
+ static inline int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
+ static inline int access(const char *pathname, int mode);
+ static inline int atoi(const char* nptr);
+ static inline void* calloc(size_t nmemb, size_t size);
+ static inline int close(int fd);
+ static inline int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
+#if defined(ENABLE_JRE_LAYOUT)
+ static inline char* dirname(char* path);
+#endif
+ static inline int dlclose(void* handle);
+ static inline char* dlerror(void);
+ static inline void* dlopen(const char* filename, int flag);
+ static inline void* dlsym(void* handle, const char* symbol);
+ static inline int fclose(FILE* fp);
+ static inline FILE* fopen(const char* path, const char* mode);
+ static inline size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
+ static inline void free(void* ptr);
+ static inline int gethostname(char* name, size_t len);
+ static inline int getpagesize(void);
+ static inline int getsockname(int s, struct sockaddr* name, socklen_t* namelen);
+ static inline int getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen);
+ static inline int listen(int sockfd, int backlog);
+ static inline void* malloc(size_t size);
+ static inline void* memcpy(void* dest, const void* src, size_t n);
+ static inline void* memset(void* s, int c, size_t n);
+ static inline int mprotect(void* addr, size_t len, int prot);
+ static inline int scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
+ static inline int setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen);
+ static inline int shutdown(int s, int how);
+ static inline int socket(int domain, int type, int protocol);
+ static inline int stat(const char* path, struct stat* buf);
+ static inline char* strcat(char* dest, const char* src);
+ static inline char* strcpy(char* dest, const char* src);
+ static inline char* strdup(const char* s);
+ static inline size_t strlen(const char* s);
+ static inline char* strerror(int errnum);
+
+ static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
+ static int processors_online(void);
+};
+
+
+inline void os::abort(void)
+{
+#if defined(HAVE_ABORT)
+ ::abort();
+#else
+# error abort not available
+#endif
+}
+
+inline int os::accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
+{
+#if defined(HAVE_ACCEPT)
+ return ::accept(sockfd, addr, addrlen);
+#else
+# error accept not available
+#endif
+}
+
+inline int os::access(const char* pathname, int mode)
+{
+#if defined(HAVE_ACCESS)
+ return ::access(pathname, mode);
+#else
+# error access not available
+#endif
+}
+
+inline int os::atoi(const char* nptr)
+{
+#if defined(HAVE_ATOI)
+ return ::atoi(nptr);
+#else
+# error atoi not available
+#endif
+}
+
+inline void* os::calloc(size_t nmemb, size_t size)
+{
+#if defined(HAVE_CALLOC)
+ return ::calloc(nmemb, size);
+#else
+# error calloc not available
+#endif
+}
+
+inline int os::close(int fd)
+{
+#if defined(HAVE_CLOSE)
+ return ::close(fd);
+#else
+# error close not available
+#endif
+}
+
+inline int os::connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen)
+{
+#if defined(HAVE_CONNECT)
+ return ::connect(sockfd, serv_addr, addrlen);
+#else
+# error connect not available
+#endif
+}
+
+#if defined(ENABLE_JRE_LAYOUT)
+inline char* os::dirname(char* path)
+{
+#if defined(HAVE_DIRNAME)
+ return ::dirname(path);
+#else
+# error dirname not available
+#endif
+}
+#endif
+
+inline int os::dlclose(void* handle)
+{
+#if defined(HAVE_DLCLOSE)
+ return ::dlclose(handle);
+#else
+# error dlclose not available
+#endif
+}
+
+inline char* os::dlerror(void)
+{
+#if defined(HAVE_DLERROR)
+ return ::dlerror();
+#else
+# error dlerror not available
+#endif
+}
+
+inline void* os::dlopen(const char* filename, int flag)
+{
+#if defined(HAVE_DLOPEN)
+ return ::dlopen(filename, flag);
+#else
+# error dlopen not available
+#endif
+}
+
+inline void* os::dlsym(void* handle, const char* symbol)
+{
+#if defined(HAVE_DLSYM)
+ return ::dlsym(handle, symbol);
+#else
+# error dlsym not available
+#endif
+}
+
+inline int os::fclose(FILE* fp)
+{
+#if defined(HAVE_FCLOSE)
+ return ::fclose(fp);
+#else
+# error fclose not available
+#endif
+}
+
+inline FILE* os::fopen(const char* path, const char* mode)
+{
+#if defined(HAVE_FOPEN)
+ return ::fopen(path, mode);
+#else
+# error fopen not available
+#endif
+}
+
+inline size_t os::fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
+{
+#if defined(HAVE_FREAD)
+ return ::fread(ptr, size, nmemb, stream);
+#else
+# error fread not available
+#endif
+}
+
+inline void os::free(void* ptr)
+{
+#if defined(HAVE_FREE)
+ ::free(ptr);
+#else
+# error free not available
+#endif
+}
+
+inline static int system_fsync(int fd)
+{
+#if defined(HAVE_FSYNC)
+ return fsync(fd);
+#else
+# error fsync not available
+#endif
+}
+
+inline static int system_ftruncate(int fd, off_t length)
+{
+#if defined(HAVE_FTRUNCATE)
+ return ftruncate(fd, length);
+#else
+# error ftruncate not available
+#endif
+}
+
+inline int os::gethostname(char* name, size_t len)
+{
+#if defined(HAVE_GETHOSTNAME)
+ return ::gethostname(name, len);
+#else
+# error gethostname not available
+#endif
+}
+
+inline int os::getpagesize(void)
+{
+#if defined(HAVE_GETPAGESIZE)
+ return ::getpagesize();
+#else
+# error getpagesize not available
+#endif
+}
+
+inline int os::getsockname(int s, struct sockaddr* name, socklen_t* namelen)
+{
+#if defined(HAVE_GETSOCKNAME)
+ return ::getsockname(s, name, namelen);
+#else
+# error getsockname not available
+#endif
+}
+
+inline int os::getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen)
+{
+#if defined(HAVE_GETSOCKOPT)
+ return ::getsockopt(s, level, optname, optval, optlen);
+#else
+# error getsockopt not available
+#endif
+}
+
+inline int os::listen(int sockfd, int backlog)
+{
+#if defined(HAVE_LISTEN)
+ return ::listen(sockfd, backlog);
+#else
+# error listen not available
+#endif
+}
+
+inline static off_t system_lseek(int fildes, off_t offset, int whence)
+{
+#if defined(HAVE_LSEEK)
+ return lseek(fildes, offset, whence);
+#else
+# error lseek not available
+#endif
+}
+
+inline void* os::malloc(size_t size)
+{
+#if defined(HAVE_MALLOC)
+ return ::malloc(size);
+#else
+# error malloc not available
+#endif
+}
+
+inline void* os::memcpy(void* dest, const void* src, size_t n)
+{
+#if defined(HAVE_MEMCPY)
+ return ::memcpy(dest, src, n);
+#else
+# error memcpy not available
+#endif
+}
+
+inline void* os::memset(void* s, int c, size_t n)
+{
+#if defined(HAVE_MEMSET)
+ return ::memset(s, c, n);
+#else
+# error memset not available
+#endif
+}
+
+inline int os::mprotect(void* addr, size_t len, int prot)
+{
+#if defined(HAVE_MPROTECT)
+ return ::mprotect(addr, len, prot);
+#else
+# error mprotect not available
+#endif
+}
+
+inline static int system_open(const char *pathname, int flags, mode_t mode)
+{
+#if defined(HAVE_OPEN)
+ return open(pathname, flags, mode);
+#else
+# error open not available
+#endif
+}
+
+inline static ssize_t system_read(int fd, void *buf, size_t count)
+{
+#if defined(HAVE_READ)
+ return read(fd, buf, count);
+#else
+# error read not available
+#endif
+}
+
+inline static void *system_realloc(void *ptr, size_t size)
+{
+#if defined(HAVE_REALLOC)
+ return realloc(ptr, size);
+#else
+# error realloc not available
+#endif
+}
+
+inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
+/*
+#elif defined(__SOLARIS__)
+inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
+#elif defined(__IRIX__)
+inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(dirent_t *), int(*compar)(dirent_t **, dirent_t **))
+#else
+inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(struct dirent *), int(*compar)(const void *, const void *))
+#endif
+*/
+{
+#if defined(HAVE_SCANDIR)
+# if defined(__LINUX__)
+ return ::scandir(dir, namelist, filter, compar);
+# else
+ return ::scandir(dir, namelist, (int (*)(struct dirent*)) filter, compar);
+# endif
+#else
+# error scandir not available
+#endif
+}
+
+inline int os::setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen)
+{
+#if defined(HAVE_SETSOCKOPT)
+ return ::setsockopt(s, level, optname, optval, optlen);
+#else
+# error setsockopt not available
+#endif
+}
+
+inline int os::shutdown(int s, int how)
+{
+#if defined(HAVE_SHUTDOWN)
+ return ::shutdown(s, how);
+#else
+# error shutdown not available
+#endif
+}
+
+inline int os::socket(int domain, int type, int protocol)
+{
+#if defined(HAVE_SOCKET)
+ return ::socket(domain, type, protocol);
+#else
+# error socket not available
+#endif
+}
+
+inline int os::stat(const char* path, struct stat* buf)
+{
+#if defined(HAVE_STAT)
+ return ::stat(path, buf);
+#else
+# error stat not available
+#endif
+}
+
+inline char* os::strcat(char* dest, const char* src)
+{
+#if defined(HAVE_STRCAT)
+ return ::strcat(dest, src);
+#else
+# error strcat not available
+#endif
+}
+
+inline char* os::strcpy(char* dest, const char* src)
+{
+#if defined(HAVE_STRCPY)
+ return ::strcpy(dest, src);
+#else
+# error strcpy not available
+#endif
+}
+
+inline char* os::strdup(const char* s)
+{
+#if defined(HAVE_STRDUP)
+ return ::strdup(s);
+#else
+# error strdup not available
+#endif
+}
+
+inline char* os::strerror(int errnum)
+{
+#if defined(HAVE_STRERROR)
+ return ::strerror(errnum);
+#else
+# error strerror not available
+#endif
+}
+
+inline size_t os::strlen(const char* s)
+{
+#if defined(HAVE_STRLEN)
+ return ::strlen(s);
+#else
+# error strlen not available
+#endif
+}
+
+inline static ssize_t system_write(int fd, const void *buf, size_t count)
+{
+#if defined(HAVE_WRITE)
+ return write(fd, buf, count);
+#else
+# error write not available
+#endif
+}
+
+#else
+
+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);
+int os_dlclose(void* handle);
+char* os_dlerror(void);
+void* os_dlopen(const char* filename, int flag);
+void* os_dlsym(void* handle, const char* symbol);
+int os_fclose(FILE* fp);
+FILE* os_fopen(const char* path, const char* mode);
+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);
+
+#endif
+
+#endif // _OS_HPP
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c++
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "native/jni.h"
+#include "vm/options.h"
#include "vm/package.hpp"
#include "vm/string.hpp"
-
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
+#include "vm/utf8.h"
/* internal property structure ************************************************/
#include "native/llni.h"
#include "vm/builtin.h"
+#include "vm/class.h"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
#include "vm/primitive.hpp"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/utf8.h"
-
/**
* Returns the primitive class of the given class name.
#include <stdint.h>
+#include "vm/class.h"
#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/linker.h"
-#include "vmcore/utf8.h"
+#include "vm/linker.h"
+#include "vm/utf8.h"
#ifdef __cplusplus
extern primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT];
-/* this function is in src/vmcore/primitivecore.c */
+/* this function is in src/vm/primitivecore.c */
void primitive_init(void);
void primitive_postinit(void);
--- /dev/null
+/* src/vm/primitivecore.c - core functions for primitive types
+
+ Copyright (C) 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/options.h"
+#include "vm/primitive.hpp"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+
+
+/* primitivetype_table *********************************************************
+
+ Structure for primitive classes: contains the class for wrapping
+ the primitive type, the primitive class, the name of the class for
+ wrapping, the one character type signature and the name of the
+ primitive class.
+
+ CAUTION: Don't change the order of the types. This table is indexed
+ by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
+
+*******************************************************************************/
+
+primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
+ { "int" , NULL, NULL, NULL, "java/lang/Integer", 'I', "[I", NULL },
+ { "long" , NULL, NULL, NULL, "java/lang/Long", 'J', "[J", NULL },
+ { "float" , NULL, NULL, NULL, "java/lang/Float", 'F', "[F", NULL },
+ { "double" , NULL, NULL, NULL, "java/lang/Double", 'D', "[D", NULL },
+ { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
+ { "byte" , NULL, NULL, NULL, "java/lang/Byte", 'B', "[B", NULL },
+ { "char" , NULL, NULL, NULL, "java/lang/Character", 'C', "[C", NULL },
+ { "short" , NULL, NULL, NULL, "java/lang/Short", 'S', "[S", NULL },
+ { "boolean" , NULL, NULL, NULL, "java/lang/Boolean", 'Z', "[Z", NULL },
+ { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
+#if defined(ENABLE_JAVASE)
+ { "void" , NULL, NULL, NULL, "java/lang/Void", 'V', NULL, NULL }
+#else
+ { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
+#endif
+};
+
+
+/* primitive_init **************************************************************
+
+ Fill the primitive type table with the primitive-type classes,
+ array-classes and wrapper classes. This is important in the VM
+ startup.
+
+ We split this primitive-type table initialization because of
+ annotations in the bootstrap classes.
+
+ But we may get a problem if we have annotations in:
+
+ java/lang/Object
+ java/lang/Cloneable
+ java/io/Serializable
+
+ Also see: loader_preinit and linker_preinit.
+
+*******************************************************************************/
+
+void primitive_init(void)
+{
+ utf *name;
+ classinfo *c;
+ utf *u;
+ classinfo *ac;
+ int i;
+
+ TRACESUBSYSTEMINITIALIZATION("primitive_init");
+
+ /* Load and link primitive-type classes and array-classes. */
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+ /* Skip dummy entries. */
+
+ if (primitivetype_table[i].cname == NULL)
+ continue;
+
+ /* create UTF-8 name */
+
+ name = utf_new_char(primitivetype_table[i].cname);
+
+ primitivetype_table[i].name = name;
+
+ /* create primitive class */
+
+ c = class_create_classinfo(name);
+
+ /* Primitive type classes don't have a super class. */
+
+ c->super = NULL;
+
+ /* set flags and mark it as primitive class */
+
+ c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT | ACC_CLASS_PRIMITIVE;
+
+ /* prevent loader from loading primitive class */
+
+ c->state |= CLASS_LOADED;
+
+ /* INFO: don't put primitive classes into the classcache */
+
+ if (!link_class(c))
+ vm_abort("linker_init: linking failed");
+
+ /* Just to be sure. */
+
+ assert(c->state & CLASS_LOADED);
+ assert(c->state & CLASS_LINKED);
+
+ primitivetype_table[i].class_primitive = c;
+
+ /* Create primitive array class. */
+
+ if (primitivetype_table[i].arrayname != NULL) {
+ u = utf_new_char(primitivetype_table[i].arrayname);
+ ac = class_create_classinfo(u);
+ ac = load_newly_created_array(ac, NULL);
+
+ if (ac == NULL)
+ vm_abort("primitive_init: loading failed");
+
+ assert(ac->state & CLASS_LOADED);
+
+ if (!link_class(ac))
+ vm_abort("primitive_init: linking failed");
+
+ /* Just to be sure. */
+
+ assert(ac->state & CLASS_LOADED);
+ assert(ac->state & CLASS_LINKED);
+
+ primitivetype_table[i].arrayclass = ac;
+ }
+ }
+
+ /* We use two for-loops to have the array-classes already in the
+ primitive-type table (hint: annotations in wrapper-classes). */
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+ /* Skip dummy entries. */
+
+ if (primitivetype_table[i].cname == NULL)
+ continue;
+
+ /* Create class for wrapping the primitive type. */
+
+ u = utf_new_char(primitivetype_table[i].wrapname);
+ c = load_class_bootstrap(u);
+
+ if (c == NULL)
+ vm_abort("primitive_init: loading failed");
+
+ if (!link_class(c))
+ vm_abort("primitive_init: linking failed");
+
+ /* Just to be sure. */
+
+ assert(c->state & CLASS_LOADED);
+ assert(c->state & CLASS_LINKED);
+
+ primitivetype_table[i].class_wrap = c;
+ }
+}
+
+
+/* primitive_postinit **********************************************************
+
+ Finish the primitive-type table initialization. In this step we
+ set the vftbl of the primitive-type classes.
+
+ This is necessary because java/lang/Class is loaded and linked
+ after the primitive types have been linked.
+
+ We have to do that in an extra function, as the primitive types are
+ not stored in the classcache.
+
+*******************************************************************************/
+
+void primitive_postinit(void)
+{
+ classinfo *c;
+ int i;
+
+ TRACESUBSYSTEMINITIALIZATION("primitive_postinit");
+
+ assert(class_java_lang_Class);
+ assert(class_java_lang_Class->vftbl);
+
+ for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
+ /* Skip dummy entries. */
+
+ if (primitivetype_table[i].cname == NULL)
+ continue;
+
+ c = primitivetype_table[i].class_primitive;
+
+ c->object.header.vftbl = class_java_lang_Class->vftbl;
+ }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "toolbox/list.h"
#include "toolbox/util.h"
+#include "vm/class.h"
#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/properties.h"
#include "vm/string.hpp"
#include "vm/vm.hpp"
#include "vm/jit/asmpart.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
-
/* internal property structure ************************************************/
--- /dev/null
+/* src/vm/references.h - references to classes/fields/methods
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+#ifndef _REFERENCES_H_
+#define _REFERENCES_H_
+
+/* forward typedefs ***********************************************************/
+
+typedef struct constant_classref constant_classref;
+typedef struct constant_FMIref constant_FMIref;
+
+
+/* constant_classref **********************************************************/
+
+struct constant_classref {
+ void *pseudo_vftbl; /* for distinguishing it from classinfo */
+ struct classinfo *referer; /* class containing the reference */
+ struct utf *name; /* name of the class refered to */
+};
+
+
+/* classref_or_classinfo ******************************************************/
+
+typedef union classref_or_classinfo {
+ constant_classref *ref; /* a symbolic class reference */
+ struct classinfo *cls; /* an already loaded class */
+ void *any; /* used for general access (x != NULL,...) */
+} classref_or_classinfo;
+
+
+/* parseddesc_t ***************************************************************/
+
+typedef union parseddesc {
+ struct typedesc *fd; /* parsed field descriptor */
+ struct methoddesc *md; /* parsed method descriptor */
+ void *any; /* used for simple test against NULL */
+} parseddesc_t;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/class.h"
+#include "vm/descriptor.h"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/utf8.h"
+
+
+/*----------------------------------------------------------------------------*/
+/* References */
+/* */
+/* This header files defines the following types used for references to */
+/* classes/methods/fields and descriptors: */
+/* */
+/* classinfo * a loaded class */
+/* constant_classref a symbolic reference */
+/* classref_or_classinfo a loaded class or a symbolic reference */
+/* */
+/* constant_FMIref a symb. ref. to a field/method/intf.method */
+/* */
+/* typedesc * describes a field type */
+/* methoddesc * descrives a method type */
+/* parseddesc describes a field type or a method type */
+/*----------------------------------------------------------------------------*/
+
+/* structs ********************************************************************/
+
+/* constant_FMIref ************************************************************/
+
+struct constant_FMIref{ /* Fieldref, Methodref and InterfaceMethodref */
+ union {
+ s4 index; /* used only within the loader */
+ constant_classref *classref; /* class having this field/meth./intfm. */
+ fieldinfo *field; /* resolved field */
+ methodinfo *method; /* resolved method */
+ } p;
+ utf *name; /* field/method/interfacemethod name */
+ utf *descriptor; /* field/method/intfmeth. type descriptor string */
+ parseddesc_t parseddesc; /* parsed descriptor */
+};
+
+
+/* macros *********************************************************************/
+
+/* a value that never occurrs in classinfo.header.vftbl */
+#define CLASSREF_PSEUDO_VFTBL ((void *) 1)
+
+/* macro for testing if a classref_or_classinfo is a classref */
+/* `reforinfo` is only evaluated once */
+#define IS_CLASSREF(reforinfo) \
+ ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL)
+
+/* macro for testing if a constant_FMIref has been resolved */
+/* `fmiref` is only evaluated once */
+#define IS_FMIREF_RESOLVED(fmiref) \
+ ((fmiref)->p.classref->pseudo_vftbl != CLASSREF_PSEUDO_VFTBL)
+
+/* the same as IS_CLASSREF, but also check against NULL */
+#define IS_XCLASSREF(reforinfo) \
+ ((reforinfo).any && IS_CLASSREF(reforinfo))
+
+/* macro for casting a classref/classinfo * to a classref_or_classinfo */
+#define CLASSREF_OR_CLASSINFO(value) \
+ (*((classref_or_classinfo *)(&(value))))
+
+/* macro for accessing the name of a classref/classinfo */
+#define CLASSREF_OR_CLASSINFO_NAME(value) \
+ (IS_CLASSREF(value) ? (value).ref->name : (value).cls->name)
+
+/* macro for accessing the class name of a method reference */
+#define METHODREF_CLASSNAME(fmiref) \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.method->clazz->name \
+ : (fmiref)->p.classref->name)
+
+/* macro for accessing the class name of a method reference */
+#define FIELDREF_CLASSNAME(fmiref) \
+ (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.field->clazz->name \
+ : (fmiref)->p.classref->name)
+
+/* initialize a constant_classref with referer `ref` and name `classname` */
+
+#define CLASSREF_INIT(c,ref,classname) \
+ do { \
+ (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL; \
+ (c).referer = (ref); \
+ (c).name = (classname); \
+ } while (0)
+
+#endif /* _REFERENCES_H_ */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
+
#include "mm/memory.h"
#include "vm/access.h"
+#include "vm/classcache.h"
+#include "vm/descriptor.h"
#include "vm/exceptions.hpp"
#include "vm/global.h"
+#include "vm/globals.hpp"
+#include "vm/linker.h"
+#include "vm/loader.h"
+#include "vm/options.h"
#include "vm/primitive.hpp"
#include "vm/resolve.h"
#include "vm/jit/jit.h"
#include "vm/jit/verify/typeinfo.h"
-#include "vmcore/classcache.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
/******************************************************************************/
/* DEBUG HELPERS */
#include "config.h"
#include "vm/types.h"
+#include "vm/class.h"
+#include "vm/field.h"
#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/references.h"
#include "vm/jit/jit.h"
#include "vm/jit/reg.h"
#include "vm/jit/verify/typeinfo.h"
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-
/* constants ******************************************************************/
--- /dev/null
+/* src/vm/rt-timing.c - POSIX real-time timing utilities
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "vm/global.h"
+#include "vm/rt-timing.h"
+
+
+struct rt_timing_stat {
+ int index;
+ int totalindex;
+ const char *name;
+};
+
+static struct rt_timing_stat rt_timing_stat_defs[] = {
+ { RT_TIMING_JIT_CHECKS ,RT_TIMING_JIT_TOTAL , "checks at beginning" },
+ { RT_TIMING_JIT_PARSE ,RT_TIMING_JIT_TOTAL , "parse" },
+ { RT_TIMING_JIT_STACK ,RT_TIMING_JIT_TOTAL , "analyse_stack" },
+ { RT_TIMING_JIT_TYPECHECK ,RT_TIMING_JIT_TOTAL , "typecheck" },
+ { RT_TIMING_JIT_LOOP ,RT_TIMING_JIT_TOTAL , "loop" },
+ { RT_TIMING_JIT_IFCONV ,RT_TIMING_JIT_TOTAL , "if conversion" },
+ { RT_TIMING_JIT_ALLOC ,RT_TIMING_JIT_TOTAL , "register allocation" },
+ { RT_TIMING_JIT_RPLPOINTS ,RT_TIMING_JIT_TOTAL , "replacement point generation" },
+ { RT_TIMING_JIT_CODEGEN ,RT_TIMING_JIT_TOTAL , "codegen" },
+ { RT_TIMING_JIT_TOTAL ,-1 , "total compile time" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LINK_RESOLVE ,RT_TIMING_LINK_TOTAL, "link: resolve superclass/superinterfaces"},
+ { RT_TIMING_LINK_C_VFTBL ,RT_TIMING_LINK_TOTAL, "link: compute vftbl length"},
+ { RT_TIMING_LINK_ABSTRACT ,RT_TIMING_LINK_TOTAL, "link: handle abstract methods"},
+ { RT_TIMING_LINK_C_IFTBL ,RT_TIMING_LINK_TOTAL, "link: compute interface table"},
+ { RT_TIMING_LINK_F_VFTBL ,RT_TIMING_LINK_TOTAL, "link: fill vftbl"},
+ { RT_TIMING_LINK_OFFSETS ,RT_TIMING_LINK_TOTAL, "link: set offsets"},
+ { RT_TIMING_LINK_F_IFTBL ,RT_TIMING_LINK_TOTAL, "link: fill interface table"},
+ { RT_TIMING_LINK_FINALIZER ,RT_TIMING_LINK_TOTAL, "link: set finalizer"},
+ { RT_TIMING_LINK_EXCEPTS ,RT_TIMING_LINK_TOTAL, "link: resolve exception classes"},
+ { RT_TIMING_LINK_SUBCLASS ,RT_TIMING_LINK_TOTAL, "link: re-calculate subclass indices"},
+ { RT_TIMING_LINK_TOTAL ,-1 , "total link time" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LOAD_CHECKS ,RT_TIMING_LOAD_TOTAL, "load: initial checks"},
+ { RT_TIMING_LOAD_NDPOOL ,RT_TIMING_LOAD_TOTAL, "load: new descriptor pool"},
+ { RT_TIMING_LOAD_CPOOL ,RT_TIMING_LOAD_TOTAL, "load: load constant pool"},
+ { RT_TIMING_LOAD_SETUP ,RT_TIMING_LOAD_TOTAL, "load: class setup"},
+ { RT_TIMING_LOAD_FIELDS ,RT_TIMING_LOAD_TOTAL, "load: load fields"},
+ { RT_TIMING_LOAD_METHODS ,RT_TIMING_LOAD_TOTAL, "load: load methods"},
+ { RT_TIMING_LOAD_CLASSREFS ,RT_TIMING_LOAD_TOTAL, "load: create classrefs"},
+ { RT_TIMING_LOAD_DESCS ,RT_TIMING_LOAD_TOTAL, "load: allocate descriptors"},
+ { RT_TIMING_LOAD_SETREFS ,RT_TIMING_LOAD_TOTAL, "load: set classrefs"},
+ { RT_TIMING_LOAD_PARSEFDS ,RT_TIMING_LOAD_TOTAL, "load: parse field descriptors"},
+ { RT_TIMING_LOAD_PARSEMDS ,RT_TIMING_LOAD_TOTAL, "load: parse method descriptors"},
+ { RT_TIMING_LOAD_PARSECP ,RT_TIMING_LOAD_TOTAL, "load: parse descriptors in constant pool"},
+ { RT_TIMING_LOAD_VERIFY ,RT_TIMING_LOAD_TOTAL, "load: verifier checks"},
+ { RT_TIMING_LOAD_ATTRS ,RT_TIMING_LOAD_TOTAL, "load: load attributes"},
+ { RT_TIMING_LOAD_TOTAL ,-1 , "total load time (from classbuffer)"},
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LOAD_BOOT_LOOKUP,-1 , "boot: lookup in classcache"},
+ { RT_TIMING_LOAD_BOOT_ARRAY ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load array classes"},
+ { RT_TIMING_LOAD_BOOT_SUCK ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: suck class files"},
+ { RT_TIMING_LOAD_BOOT_LOAD ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load from class buffer"},
+ { RT_TIMING_LOAD_BOOT_CACHE ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: store in classcache"},
+ { RT_TIMING_LOAD_BOOT_TOTAL ,-1 , "total bootstrap loader time"},
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_LOAD_CL_LOOKUP ,-1 , "classloader: lookup in classcache" },
+ { RT_TIMING_LOAD_CL_PREPARE ,-1 , "classloader: prepare loader call" },
+ { RT_TIMING_LOAD_CL_JAVA ,-1 , "classloader: loader Java code" },
+ { RT_TIMING_LOAD_CL_CACHE ,-1 , "classloader: store in classcache" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_NEW_OBJECT ,-1 , "builtin_new time" },
+ { RT_TIMING_NEW_ARRAY ,-1 , "builtin_newarray time" },
+ { -1 ,-1 , "" },
+
+ { RT_TIMING_GC_ALLOC ,-1 , "heap allocation time" },
+#if defined(ENABLE_GC_CACAO)
+ { RT_TIMING_GC_SUSPEND ,RT_TIMING_GC_TOTAL , "gc: suspending threads" },
+ { RT_TIMING_GC_ROOTSET1 ,RT_TIMING_GC_TOTAL , "gc: rootset finding" },
+ { RT_TIMING_GC_MARK ,RT_TIMING_GC_TOTAL , "gc: marking phase" },
+ { RT_TIMING_GC_COMPACT ,RT_TIMING_GC_TOTAL , "gc: compaction phase" },
+ { RT_TIMING_GC_ROOTSET2 ,RT_TIMING_GC_TOTAL , "gc: rootset writeback" },
+ { RT_TIMING_GC_TOTAL ,-1 , "total garbage collection time" },
+#endif
+ { -1 ,-1 , "" },
+
+#if defined(ENABLE_REPLACEMENT)
+ { RT_TIMING_REPLACE ,-1 , "replacement" },
+ { -1 ,-1 , "" },
+#endif
+
+ { RT_TIMING_1 ,-1 , "temporary timer 1" },
+ { RT_TIMING_2 ,-1 , "temporary timer 2" },
+ { RT_TIMING_3 ,-1 , "temporary timer 3" },
+ { RT_TIMING_4 ,-1 , "temporary timer 4" },
+ { -1 ,-1 , "" },
+
+ { 0 ,-1 , NULL }
+};
+
+static long long rt_timing_sum[RT_TIMING_N] = { 0 };
+
+void rt_timing_gettime(struct timespec *ts)
+{
+ if (clock_gettime(CLOCK_THREAD_CPUTIME_ID,ts) != 0) {
+ fprintf(stderr,"could not get time by clock_gettime: %s\n",strerror(errno));
+ abort();
+ }
+}
+
+long rt_timing_diff_usec(struct timespec *a,struct timespec *b)
+{
+ long diff;
+ time_t atime;
+
+ diff = (b->tv_nsec - a->tv_nsec) / 1000;
+ atime = a->tv_sec;
+ while (atime < b->tv_sec) {
+ atime++;
+ diff += 1000000;
+ }
+ return diff;
+}
+
+void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index)
+{
+ long diff;
+
+ diff = rt_timing_diff_usec(a,b);
+ rt_timing_sum[index] += diff;
+}
+
+void rt_timing_print_time_stats(FILE *file)
+{
+ struct rt_timing_stat *stats;
+ double total;
+
+ for (stats = rt_timing_stat_defs; stats->name; ++stats) {
+ if (stats->index < 0) {
+ fprintf(file,"%s\n",stats->name);
+ continue;
+ }
+
+ if (stats->totalindex >= 0) {
+ total = rt_timing_sum[stats->totalindex];
+ fprintf(file,"%12lld usec %3.0f%% %s\n",
+ rt_timing_sum[stats->index],
+ (total != 0.0) ? rt_timing_sum[stats->index] / total * 100.0 : 0.0,
+ stats->name);
+ }
+ else {
+ fprintf(file,"%12lld usec %s\n",
+ rt_timing_sum[stats->index],
+ stats->name);
+ }
+ }
+}
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/rt-timing.h - POSIX real-time timing utilities
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _RT_TIMING_H
+#define _RT_TIMING_H
+
+#include "config.h"
+
+#if defined(ENABLE_RT_TIMING)
+
+#include <time.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "vm/global.h"
+
+
+#define RT_TIMING_GET_TIME(ts) \
+ rt_timing_gettime(&(ts));
+
+#define RT_TIMING_TIME_DIFF(a,b,index) \
+ rt_timing_time_diff(&(a),&(b),(index));
+
+#define RT_TIMING_JIT_CHECKS 0
+#define RT_TIMING_JIT_PARSE 1
+#define RT_TIMING_JIT_STACK 2
+#define RT_TIMING_JIT_TYPECHECK 3
+#define RT_TIMING_JIT_LOOP 4
+#define RT_TIMING_JIT_IFCONV 5
+#define RT_TIMING_JIT_ALLOC 6
+#define RT_TIMING_JIT_RPLPOINTS 7
+#define RT_TIMING_JIT_CODEGEN 8
+#define RT_TIMING_JIT_TOTAL 9
+
+#define RT_TIMING_LINK_RESOLVE 10
+#define RT_TIMING_LINK_C_VFTBL 11
+#define RT_TIMING_LINK_ABSTRACT 12
+#define RT_TIMING_LINK_C_IFTBL 13
+#define RT_TIMING_LINK_F_VFTBL 14
+#define RT_TIMING_LINK_OFFSETS 15
+#define RT_TIMING_LINK_F_IFTBL 16
+#define RT_TIMING_LINK_FINALIZER 17
+#define RT_TIMING_LINK_EXCEPTS 18
+#define RT_TIMING_LINK_SUBCLASS 19
+#define RT_TIMING_LINK_TOTAL 20
+
+#define RT_TIMING_LOAD_CHECKS 21
+#define RT_TIMING_LOAD_NDPOOL 22
+#define RT_TIMING_LOAD_CPOOL 23
+#define RT_TIMING_LOAD_SETUP 24
+#define RT_TIMING_LOAD_FIELDS 25
+#define RT_TIMING_LOAD_METHODS 26
+#define RT_TIMING_LOAD_CLASSREFS 27
+#define RT_TIMING_LOAD_DESCS 28
+#define RT_TIMING_LOAD_SETREFS 29
+#define RT_TIMING_LOAD_PARSEFDS 30
+#define RT_TIMING_LOAD_PARSEMDS 31
+#define RT_TIMING_LOAD_PARSECP 32
+#define RT_TIMING_LOAD_VERIFY 33
+#define RT_TIMING_LOAD_ATTRS 34
+#define RT_TIMING_LOAD_TOTAL 35
+
+#define RT_TIMING_LOAD_BOOT_LOOKUP 36
+#define RT_TIMING_LOAD_BOOT_ARRAY 37
+#define RT_TIMING_LOAD_BOOT_SUCK 38
+#define RT_TIMING_LOAD_BOOT_LOAD 39
+#define RT_TIMING_LOAD_BOOT_CACHE 40
+#define RT_TIMING_LOAD_BOOT_TOTAL 41
+
+#define RT_TIMING_LOAD_CL_LOOKUP 42
+#define RT_TIMING_LOAD_CL_PREPARE 43
+#define RT_TIMING_LOAD_CL_JAVA 44
+#define RT_TIMING_LOAD_CL_CACHE 45
+
+#define RT_TIMING_NEW_OBJECT 46
+#define RT_TIMING_NEW_ARRAY 47
+
+#define RT_TIMING_GC_ALLOC 48
+#define RT_TIMING_GC_SUSPEND 49
+#define RT_TIMING_GC_ROOTSET1 50
+#define RT_TIMING_GC_MARK 51
+#define RT_TIMING_GC_COMPACT 52
+#define RT_TIMING_GC_ROOTSET2 53
+#define RT_TIMING_GC_TOTAL 54
+
+#define RT_TIMING_REPLACE 55
+
+#define RT_TIMING_1 56
+#define RT_TIMING_2 57
+#define RT_TIMING_3 58
+#define RT_TIMING_4 59
+
+#define RT_TIMING_N 60
+
+void rt_timing_gettime(struct timespec *ts);
+
+void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index);
+
+long rt_timing_diff_usec(struct timespec *a,struct timespec *b);
+
+void rt_timing_print_time_stats(FILE *file);
+
+#else /* !defined(ENABLE_RT_TIMING) */
+
+#define RT_TIMING_GET_TIME(ts)
+#define RT_TIMING_TIME_DIFF(a,b,index)
+
+#endif /* defined(ENABLE_RT_TIMING) */
+
+#endif /* _RT_TIMING_H */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#include "threads/thread.hpp"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
#include "vm/signallocal.h"
#include "vm/vm.hpp"
-#include "vmcore/globals.hpp"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-
#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
+# include "vm/statistics.h"
#endif
--- /dev/null
+/* src/vm/stackmap.c - class attribute StackMapTable
+
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "vm/class.h"
+#include "vm/exceptions.hpp"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/stackmap.h"
+#include "vm/statistics.h"
+#include "vm/suck.h"
+
+
+/* stackmap_get_verification_type_info *****************************************
+
+ union verification_type_info {
+ Top_variable_info;
+ Integer_variable_info;
+ Float_variable_info;
+ Long_variable_info;
+ Double_variable_info;
+ Null_variable_info;
+ UninitializedThis_variable_info;
+ Object_variable_info;
+ Uninitialized_variable_info;
+ }
+
+ Top_variable_info {
+ u1 tag = ITEM_Top; // 0
+ }
+
+ Integer_variable_info {
+ u1 tag = ITEM_Integer; // 1
+ }
+
+ Float_variable_info {
+ u1 tag = ITEM_Float; // 2
+ }
+
+ Long_variable_info {
+ u1 tag = ITEM_Long; // 4
+ }
+
+ Double_variable_info {
+ u1 tag = ITEM_Double; // 3
+ }
+
+ Null_variable_info {
+ u1 tag = ITEM_Null; // 5
+ }
+
+ UninitializedThis_variable_info {
+ u1 tag = ITEM_UninitializedThis; // 6
+ }
+
+ Object_variable_info {
+ u1 tag = ITEM_Object; // 7
+ u2 cpool_index;
+ }
+
+ Uninitialized_variable_info {
+ u1 tag = ITEM_Uninitialized; // 8
+ u2 offset;
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
+{
+ /* get verification type */
+
+ if (!suck_check_classbuffer_size(cb, 1))
+ return false;
+
+ verification_type_info->tag = suck_u1(cb);
+
+ /* process the tag */
+
+ switch (verification_type_info->tag) {
+ case ITEM_Top:
+ case ITEM_Integer:
+ case ITEM_Float:
+ case ITEM_Long:
+ case ITEM_Double:
+ case ITEM_Null:
+ case ITEM_UninitializedThis:
+ break;
+
+ case ITEM_Object:
+ /* get constant pool index */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
+ break;
+
+ case ITEM_Uninitialized:
+ /* get offset */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
+ break;
+ }
+
+ return true;
+}
+
+
+/* stackmap_get_same_locals_1_stack_item_frame *********************************
+
+ same_locals_1_stack_item_frame {
+ u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
+ verification_type_info stack[1];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
+{
+ same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
+
+ /* for convenience */
+
+ same_locals_1_stack_item_frame =
+ &(stack_map_frame->same_locals_1_stack_item_frame);
+
+ if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_get_same_locals_1_stack_item_frame_extended ************************
+
+ same_locals_1_stack_item_frame_extended {
+ u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
+ u2 offset_delta;
+ verification_type_info stack[1];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
+{
+ same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
+
+ /* for convenience */
+
+ same_locals_1_stack_item_frame_extended =
+ &(stack_map_frame->same_locals_1_stack_item_frame_extended);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
+
+ /* process stack */
+
+ if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_get_chop_frame *****************************************************
+
+ chop_frame {
+ u1 frame_type = CHOP_FRAME; // 248-250
+ u2 offset_delta;
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_chop_frame(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ chop_frame_t *chop_frame;
+
+ /* for convenience */
+
+ chop_frame = &(stack_map_frame->chop_frame);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ chop_frame->offset_delta = suck_u2(cb);
+
+ return true;
+}
+
+
+/* stackmap_get_same_frame_extended ********************************************
+
+ same_frame_extended {
+ u1 frame_type = SAME_FRAME_EXTENDED; // 251
+ u2 offset_delta;
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_same_frame_extended(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ same_frame_extended_t *same_frame_extended;
+
+ /* for convenience */
+
+ same_frame_extended = &(stack_map_frame->same_frame_extended);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ same_frame_extended->offset_delta = suck_u2(cb);
+
+ return true;
+}
+
+
+/* stackmap_get_append_frame ***************************************************
+
+ append_frame {
+ u1 frame_type = APPEND_FRAME; // 252-254
+ u2 offset_delta;
+ verification_type_info locals[frame_Type - 251];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_append_frame(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ append_frame_t *append_frame;
+ s4 number_of_locals;
+ s4 i;
+
+ /* for convenience */
+
+ append_frame = &(stack_map_frame->append_frame);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ /* get offset delta */
+
+ append_frame->offset_delta = suck_u2(cb);
+
+ /* allocate locals array */
+
+ number_of_locals = append_frame->frame_type - 251;
+
+ append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
+
+ /* process all locals */
+
+ for (i = 0; i < number_of_locals; i++)
+ if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_get_full_frame *****************************************************
+
+ full_frame {
+ u1 frame_type = FULL_FRAME;
+ u2 offset_delta;
+ u2 number_of_locals;
+ verification_type_info locals[number_of_locals];
+ u2 number_of_stack_items;
+ verification_type_info stack[number_of_stack_items];
+ }
+
+*******************************************************************************/
+
+static bool stackmap_get_full_frame(classbuffer *cb,
+ stack_map_frame_t *stack_map_frame)
+{
+ full_frame_t *full_frame;
+ s4 i;
+
+ /* for convenience */
+
+ full_frame = &(stack_map_frame->full_frame);
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 2 + 2))
+ return false;
+
+ /* get offset delta */
+
+ stack_map_frame->full_frame.offset_delta = suck_u2(cb);
+
+ /* get number of locals */
+
+ full_frame->number_of_locals = suck_u2(cb);
+
+ /* allocate locals array */
+
+ full_frame->locals =
+ DMNEW(verification_type_info_t, full_frame->number_of_locals);
+
+ /* process all locals */
+
+ for (i = 0; i < full_frame->number_of_locals; i++)
+ if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
+ return false;
+
+ /* get number of stack items */
+
+ if (!suck_check_classbuffer_size(cb, 2))
+ return false;
+
+ full_frame->number_of_stack_items = suck_u2(cb);
+
+ /* allocate stack array */
+
+ full_frame->stack =
+ DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
+
+ /* process all stack items */
+
+ for (i = 0; i < full_frame->number_of_stack_items; i++)
+ if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
+ return false;
+
+ return true;
+}
+
+
+/* stackmap_load_attribute_stackmaptable ***************************************
+
+ stack_map {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 number_of_entries;
+ stack_map_frame entries[number_of_entries];
+ }
+
+ union stack_map_frame {
+ same_frame;
+ same_locals_1_stack_item_frame;
+ same_locals_1_stack_item_frame_extended;
+ chop_frame;
+ same_frame_extended;
+ append_frame;
+ full_frame;
+ }
+
+ same_frame {
+ u1 frame_type = SAME; // 0-63
+ }
+
+*******************************************************************************/
+
+bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
+{
+ classinfo *c;
+ stack_map_t *stack_map;
+ s4 i;
+ u1 frame_type;
+
+ /* get classinfo */
+
+ c = cb->clazz;
+
+ /* allocate stack map structure */
+
+ stack_map = DNEW(stack_map_t);
+
+ STATISTICS(size_stack_map += sizeof(stack_map_t));
+
+ /* check buffer size */
+
+ if (!suck_check_classbuffer_size(cb, 4 + 2))
+ return false;
+
+ /* attribute_length */
+
+ stack_map->attribute_length = suck_u4(cb);
+
+ if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
+ return false;
+
+ /* get number of entries */
+
+ stack_map->number_of_entries = suck_u2(cb);
+
+ /* process all entries */
+
+ stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
+
+ for (i = 0; i < stack_map->number_of_entries; i++) {
+ /* get the frame type */
+
+ frame_type = suck_u1(cb);
+
+ stack_map->entries[i].frame_type = frame_type;
+
+ /* process frame */
+
+ if (frame_type <= FRAME_TYPE_SAME) {
+ /* same_frame */
+ }
+ else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
+ /* same_locals_1_stack_item_frame */
+
+ if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type <= FRAME_TYPE_RESERVED) {
+ /* reserved */
+
+ exceptions_throw_classformaterror(c, "reserved frame type");
+ return false;
+ }
+ else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
+ /* same_locals_1_stack_item_frame_extended */
+
+ if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type <= FRAME_TYPE_CHOP) {
+ /* chop_frame */
+
+ if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
+ /* same_frame_extended */
+
+ if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type <= FRAME_TYPE_APPEND) {
+ /* append_frame */
+
+ if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ else if (frame_type == FRAME_TYPE_FULL_FRAME) {
+ /* full_frame */
+
+ if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
+ return false;
+ }
+ }
+
+ /* store stack map in method structure */
+
+#if 0
+ /* currently not used */
+
+ m->stack_map = stack_map;
+#endif
+
+ return true;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/stackmap.h - class attribute StackMapTable
+
+ Copyright (C) 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _STACKMAP_H
+#define _STACKMAP_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct stack_map_t stack_map_t;
+typedef union stack_map_frame_t stack_map_frame_t;
+typedef struct same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame_t;
+typedef struct same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended_t;
+typedef struct chop_frame_t chop_frame_t;
+typedef struct same_frame_extended_t same_frame_extended_t;
+typedef struct append_frame_t append_frame_t;
+typedef struct full_frame_t full_frame_t;
+
+typedef union verification_type_info_t verification_type_info_t;
+typedef struct Top_variable_info_t Top_variable_info_t;
+typedef struct Integer_variable_info_t Integer_variable_info_t;
+typedef struct Float_variable_info_t Float_variable_info_t;
+typedef struct Long_variable_info_t Long_variable_info_t;
+typedef struct Double_variable_info_t Double_variable_info_t;
+typedef struct Null_variable_info_t Null_variable_info_t;
+typedef struct UninitializedThis_variable_info_t UninitializedThis_variable_info_t;
+typedef struct Object_variable_info_t Object_variable_info_t;
+typedef struct Uninitialized_variable_info_t Uninitialized_variable_info_t;
+
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/method.h"
+
+
+/* verification_type_info *****************************************************/
+
+#define ITEM_Top 0
+#define ITEM_Integer 1
+#define ITEM_Float 2
+#define ITEM_Double 3
+#define ITEM_Long 4
+#define ITEM_Null 5
+#define ITEM_UninitializedThis 6
+#define ITEM_Object 7
+#define ITEM_Uninitialized 8
+
+struct Top_variable_info_t {
+ u1 tag;
+};
+
+struct Integer_variable_info_t {
+ u1 tag;
+};
+
+struct Float_variable_info_t {
+ u1 tag;
+};
+
+struct Long_variable_info_t {
+ u1 tag;
+};
+
+struct Double_variable_info_t {
+ u1 tag;
+};
+
+struct Null_variable_info_t {
+ u1 tag;
+};
+
+struct UninitializedThis_variable_info_t {
+ u1 tag;
+};
+
+struct Object_variable_info_t {
+ u1 tag;
+ u2 cpool_index;
+};
+
+struct Uninitialized_variable_info_t {
+ u1 tag;
+ u2 offset;
+};
+
+union verification_type_info_t {
+ u1 tag;
+ Top_variable_info_t Top_variable_info;
+ Integer_variable_info_t Integer_variable_info;
+ Float_variable_info_t Float_variable_info;
+ Long_variable_info_t Long_variable_info;
+ Double_variable_info_t Double_variable_info;
+ Null_variable_info_t Null_variable_info;
+ UninitializedThis_variable_info_t UninitializedThis_variable_info;
+ Object_variable_info_t Object_variable_info;
+ Uninitialized_variable_info_t Uninitialized_variable_info;
+};
+
+
+/* stack_map_t ****************************************************************/
+
+struct stack_map_t {
+ u2 attribute_name_index;
+ u4 attribute_length;
+ u2 number_of_entries;
+ stack_map_frame_t *entries;
+};
+
+
+/* same_locals_1_stack_item_frame_t *******************************************/
+
+struct same_locals_1_stack_item_frame_t {
+ u1 frame_type;
+ verification_type_info_t stack[1];
+};
+
+
+/* same_locals_1_stack_item_frame_extended_t **********************************/
+
+struct same_locals_1_stack_item_frame_extended_t {
+ u1 frame_type;
+ u2 offset_delta;
+ verification_type_info_t stack[1];
+};
+
+
+/* chop_frame_t ***************************************************************/
+
+struct chop_frame_t {
+ u1 frame_type;
+ u2 offset_delta;
+};
+
+
+/* same_frame_extended_t ******************************************************/
+
+struct same_frame_extended_t {
+ u1 frame_type;
+ u2 offset_delta;
+};
+
+
+/* append_frame_t *************************************************************/
+
+struct append_frame_t {
+ u1 frame_type;
+ u2 offset_delta;
+ verification_type_info_t *locals;
+};
+
+
+/* full_frame_t ***************************************************************/
+
+struct full_frame_t {
+ u1 frame_type;
+ u2 offset_delta;
+ u2 number_of_locals;
+ verification_type_info_t *locals;
+ u2 number_of_stack_items;
+ verification_type_info_t *stack;
+};
+
+
+/* stack_map_frame_t **********************************************************/
+
+#define FRAME_TYPE_SAME 63 /* 0-63 */
+#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM 127 /* 0-127 */
+#define FRAME_TYPE_RESERVED 246 /* 128-246 */
+#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED 247 /* 247 */
+#define FRAME_TYPE_CHOP 250 /* 248-250 */
+#define FRAME_TYPE_SAME_FRAME_EXTENDED 251 /* 251 */
+#define FRAME_TYPE_APPEND 254 /* 252-254 */
+#define FRAME_TYPE_FULL_FRAME 255 /* 255 */
+
+union stack_map_frame_t {
+ u1 frame_type;
+ same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame;
+ same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended;
+ chop_frame_t chop_frame;
+ same_frame_extended_t same_frame_extended;
+ append_frame_t append_frame;
+ full_frame_t full_frame;
+};
+
+
+/* function prototypes ********************************************************/
+
+bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m);
+
+#endif /* _STACKMAP_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/statistics.c - global variables for statistics
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <stdint.h>
+#include <string.h>
+
+#if defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#endif
+
+#if defined(HAVE_SYS_RESOURCE_H)
+# include <sys/resource.h>
+#endif
+
+#include "vm/types.h"
+
+#include "mm/gc.hpp"
+
+#include "toolbox/logging.h"
+
+#include "vm/class.h"
+#include "vm/field.h"
+#include "vm/global.h"
+#include "vm/method.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+
+#include "vm/jit/code.h"
+
+
+/* global variables ***********************************************************/
+
+static s8 loadingtime = 0; /* accumulated loading time */
+static s8 loadingstarttime = 0;
+static s8 loadingstoptime = 0;
+static s4 loadingtime_recursion = 0;
+
+static s8 compilingtime = 0; /* accumulated compile time */
+static s8 compilingstarttime = 0;
+static s8 compilingstoptime = 0;
+static s4 compilingtime_recursion = 0;
+
+s4 codememusage = 0;
+s4 maxcodememusage = 0;
+
+s4 memoryusage = 0;
+s4 maxmemusage = 0;
+
+s4 maxdumpsize = 0;
+
+s4 globalallocateddumpsize = 0;
+s4 globaluseddumpsize = 0;
+
+
+/* variables for measurements *************************************************/
+
+s4 size_classinfo = 0;
+s4 size_fieldinfo = 0;
+s4 size_methodinfo = 0;
+s4 size_lineinfo = 0;
+s4 size_codeinfo = 0;
+
+s4 size_stub_native = 0;
+
+s4 size_stack_map = 0;
+s4 size_string = 0;
+
+s4 size_threadobject = 0;
+int32_t size_thread_index_t = 0;
+int32_t size_stacksize = 0;
+
+s4 size_lock_record = 0;
+s4 size_lock_hashtable = 0;
+s4 size_lock_waiter = 0;
+
+int32_t count_linenumbertable = 0;
+int32_t size_linenumbertable = 0;
+
+s4 size_patchref = 0;
+
+u8 count_calls_java_to_native = 0;
+u8 count_calls_native_to_java = 0;
+
+int count_const_pool_len = 0;
+int count_classref_len = 0;
+int count_parsed_desc_len = 0;
+int count_vftbl_len = 0;
+int count_all_methods = 0;
+int count_methods_marked_used = 0; /* RTA */
+
+int count_vmcode_len = 0;
+int count_extable_len = 0;
+int count_class_loads = 0;
+int count_class_inits = 0;
+
+int count_utf_len = 0; /* size of utf hash */
+int count_utf_new = 0; /* calls of utf_new */
+int count_utf_new_found = 0; /* calls of utf_new with fast return */
+
+int count_locals_conflicts = 0; /* register allocator statistics */
+int count_locals_spilled = 0;
+int count_locals_register = 0;
+int count_ss_spilled = 0;
+int count_ss_register = 0;
+int count_methods_allocated_by_lsra = 0;
+int count_mem_move_bb = 0;
+int count_interface_size = 0;
+int count_argument_mem_ss = 0;
+int count_argument_reg_ss = 0;
+int count_method_in_register = 0;
+int count_mov_reg_reg = 0;
+int count_mov_mem_reg = 0;
+int count_mov_reg_mem = 0;
+int count_mov_mem_mem = 0;
+
+int count_jit_calls = 0;
+int count_methods = 0;
+int count_spills_read_ila = 0;
+int count_spills_read_flt = 0;
+int count_spills_read_dbl = 0;
+int count_spills_write_ila = 0;
+int count_spills_write_flt = 0;
+int count_spills_write_dbl = 0;
+int count_pcmd_activ = 0;
+int count_pcmd_drop = 0;
+int count_pcmd_zero = 0;
+int count_pcmd_const_store = 0;
+int count_pcmd_const_alu = 0;
+int count_pcmd_const_bra = 0;
+int count_pcmd_load = 0;
+int count_pcmd_move = 0;
+int count_load_instruction = 0;
+int count_pcmd_store = 0;
+int count_pcmd_store_comb = 0;
+int count_dup_instruction = 0;
+int count_pcmd_op = 0;
+int count_pcmd_mem = 0;
+int count_pcmd_met = 0;
+int count_pcmd_bra = 0;
+int count_pcmd_table = 0;
+int count_pcmd_return = 0;
+int count_pcmd_returnx = 0;
+int count_check_null = 0;
+int count_check_bound = 0;
+int count_max_basic_blocks = 0;
+int count_basic_blocks = 0;
+int count_javainstr = 0;
+int count_max_javainstr = 0;
+int count_javacodesize = 0;
+int count_javaexcsize = 0;
+int count_calls = 0;
+int count_tryblocks = 0;
+int count_code_len = 0;
+int count_data_len = 0;
+int count_cstub_len = 0;
+int count_max_new_stack = 0;
+int count_upper_bound_new_stack = 0;
+
+int count_emit_branch = 0;
+int count_emit_branch_8bit = 0;
+int count_emit_branch_16bit = 0;
+int count_emit_branch_32bit = 0;
+int count_emit_branch_64bit = 0;
+
+s4 count_branches_resolved = 0;
+s4 count_branches_unresolved = 0;
+
+u8 count_jni_callXmethod_calls=0;
+u8 count_jni_calls=0;
+
+
+static int count_block_stack_init[11] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+};
+int *count_block_stack = count_block_stack_init;
+static int count_analyse_iterations_init[5] = {
+ 0, 0, 0, 0, 0
+};
+int *count_analyse_iterations = count_analyse_iterations_init;
+static int count_method_bb_distribution_init[9] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+int *count_method_bb_distribution = count_method_bb_distribution_init;
+static int count_block_size_distribution_init[18] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0
+};
+int *count_block_size_distribution = count_block_size_distribution_init;
+static int count_store_length_init[21] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+};
+int *count_store_length = count_store_length_init;
+static int count_store_depth_init[11] = {
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0
+};
+int *count_store_depth = count_store_depth_init;
+
+
+/* instruction scheduler statistics *******************************************/
+
+s4 count_schedule_basic_blocks = 0;
+s4 count_schedule_nodes = 0;
+s4 count_schedule_leaders = 0;
+s4 count_schedule_max_leaders = 0;
+s4 count_schedule_critical_path = 0;
+
+
+/* jnicallXmethodinvokation ***************************************************
+
+ increments the jni CallXMethod invokation count by one
+
+*******************************************************************************/
+
+void jnicallXmethodnvokation(void)
+{
+ /* XXX do locking here */
+ count_jni_callXmethod_calls++;
+}
+
+
+/* jniinvokation *************************************************************
+
+ increments the jni overall invokation count by one
+
+*******************************************************************************/
+
+void jniinvokation(void)
+{
+ /* XXX do locking here */
+ count_jni_calls++;
+}
+
+
+/* getcputime *********************************** ******************************
+
+ Returns the used CPU time in microseconds
+
+*******************************************************************************/
+
+s8 getcputime(void)
+{
+#if defined(HAVE_GETRUSAGE)
+ struct rusage ru;
+ int sec, usec;
+
+ getrusage(RUSAGE_SELF, &ru);
+
+ sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
+ usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
+
+ return sec * 1000000 + usec;
+#else
+ /* If we don't have getrusage, simply return 0. */
+
+ return 0;
+#endif
+}
+
+
+/* loadingtime_stop ************************************************************
+
+ XXX
+
+*******************************************************************************/
+
+void loadingtime_start(void)
+{
+ loadingtime_recursion++;
+
+ if (loadingtime_recursion == 1)
+ loadingstarttime = getcputime();
+}
+
+
+/* loadingtime_stop ************************************************************
+
+ XXX
+
+*******************************************************************************/
+
+void loadingtime_stop(void)
+{
+ if (loadingtime_recursion == 1) {
+ loadingstoptime = getcputime();
+ loadingtime += (loadingstoptime - loadingstarttime);
+ }
+
+ loadingtime_recursion--;
+}
+
+
+/* compilingtime_stop **********************************************************
+
+ XXX
+
+*******************************************************************************/
+
+void compilingtime_start(void)
+{
+ compilingtime_recursion++;
+
+ if (compilingtime_recursion == 1)
+ compilingstarttime = getcputime();
+}
+
+
+/* compilingtime_stop **********************************************************
+
+ XXX
+
+*******************************************************************************/
+
+void compilingtime_stop(void)
+{
+ if (compilingtime_recursion == 1) {
+ compilingstoptime = getcputime();
+ compilingtime += (compilingstoptime - compilingstarttime);
+ }
+
+ compilingtime_recursion--;
+}
+
+
+/* print_times *****************************************************************
+
+ Prints a summary of CPU time usage.
+
+*******************************************************************************/
+
+void print_times(void)
+{
+ s8 totaltime;
+ s8 runtime;
+
+ totaltime = getcputime();
+ runtime = totaltime - loadingtime - compilingtime;
+
+#if SIZEOF_VOID_P == 8
+ dolog("Time for loading classes: %6ld ms", loadingtime / 1000);
+ dolog("Time for compiling code: %6ld ms", compilingtime / 1000);
+ dolog("Time for running program: %6ld ms", runtime / 1000);
+ dolog("Total time: %6ld ms", totaltime / 1000);
+#else
+ dolog("Time for loading classes: %6lld ms", loadingtime / 1000);
+ dolog("Time for compiling code: %6lld ms", compilingtime / 1000);
+ dolog("Time for running program: %6lld ms", runtime / 1000);
+ dolog("Total time: %6lld ms", totaltime / 1000);
+#endif
+}
+
+
+/* print_stats *****************************************************************
+
+ outputs detailed compiler statistics
+
+*******************************************************************************/
+
+void print_stats(void)
+{
+ s4 i;
+ float f;
+ s4 sum;
+
+
+ dolog("Number of JIT compiler calls: %6d", count_jit_calls);
+ dolog("Number of compiled methods: %6d", count_methods);
+
+ dolog("Number of compiled basic blocks: %6d",
+ count_basic_blocks);
+ dolog("Number of max. basic blocks per method: %6d",
+ count_max_basic_blocks);
+
+ dolog("Number of compiled JavaVM instructions: %6d",
+ count_javainstr);
+ dolog("Number of max. JavaVM instructions per method: %6d",
+ count_max_javainstr);
+ dolog("Size of compiled JavaVM instructions: %6d(%d)",
+ count_javacodesize, count_javacodesize - count_methods * 18);
+
+ dolog("Size of compiled Exception Tables: %d", count_javaexcsize);
+ dolog("Number of Machine-Instructions: %d", count_code_len >> 2);
+ dolog("Number of Spills (write to memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
+ count_spills_write_ila + count_spills_write_flt + count_spills_write_dbl,
+ count_spills_write_ila, count_spills_write_flt, count_spills_write_dbl);
+ dolog("Number of Spills (read from memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
+ count_spills_read_ila + count_spills_read_flt + count_spills_read_dbl,
+ count_spills_read_ila, count_spills_read_flt, count_spills_read_dbl);
+ dolog("Number of Activ Pseudocommands: %6d", count_pcmd_activ);
+ dolog("Number of Drop Pseudocommands: %6d", count_pcmd_drop);
+ dolog("Number of Const Pseudocommands: %6d (zero:%5d)",
+ count_pcmd_load, count_pcmd_zero);
+ dolog("Number of ConstAlu Pseudocommands: %6d (cmp: %5d, store:%5d)",
+ count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
+ dolog("Number of Move Pseudocommands: %6d", count_pcmd_move);
+ dolog("Number of Load Pseudocommands: %6d", count_load_instruction);
+ dolog("Number of Store Pseudocommands: %6d (combined: %5d)",
+ count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
+ dolog("Number of OP Pseudocommands: %6d", count_pcmd_op);
+ dolog("Number of DUP Pseudocommands: %6d", count_dup_instruction);
+ dolog("Number of Mem Pseudocommands: %6d", count_pcmd_mem);
+ dolog("Number of Method Pseudocommands: %6d", count_pcmd_met);
+ dolog("Number of Branch Pseudocommands: %6d (rets:%5d, Xrets: %5d)",
+ count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
+ log_println(" resolved branches: %6d", count_branches_resolved);
+ log_println(" unresolved branches: %6d", count_branches_unresolved);
+ dolog("Number of Table Pseudocommands: %6d", count_pcmd_table);
+ dolog("Number of Useful Pseudocommands: %6d", count_pcmd_table +
+ count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
+ dolog("Number of Null Pointer Checks: %6d", count_check_null);
+ dolog("Number of Array Bound Checks: %6d", count_check_bound);
+ dolog("Number of Try-Blocks: %d", count_tryblocks);
+
+ dolog("Number of branch_emit (total, 8bit/16bit/32bit/64bit offset): %d, %d/%d/%d/%d",
+ count_emit_branch, count_emit_branch_8bit, count_emit_branch_16bit,
+ count_emit_branch_32bit, count_emit_branch_64bit);
+
+ dolog("Maximal count of stack elements: %d", count_max_new_stack);
+ dolog("Upper bound of max stack elements: %d", count_upper_bound_new_stack);
+ dolog("Distribution of stack sizes at block boundary");
+ dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_block_stack[0], count_block_stack[1], count_block_stack[2],
+ count_block_stack[3], count_block_stack[4], count_block_stack[5],
+ count_block_stack[6], count_block_stack[7], count_block_stack[8],
+ count_block_stack[9], count_block_stack[10]);
+ dolog("Distribution of store stack depth");
+ dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_depth[0], count_store_depth[1], count_store_depth[2],
+ count_store_depth[3], count_store_depth[4], count_store_depth[5],
+ count_store_depth[6], count_store_depth[7], count_store_depth[8],
+ count_store_depth[9], count_store_depth[10]);
+ dolog("Distribution of store creator chains first part");
+ dolog(" 0 1 2 3 4 5 6 7 8 9");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_length[0], count_store_length[1], count_store_length[2],
+ count_store_length[3], count_store_length[4], count_store_length[5],
+ count_store_length[6], count_store_length[7], count_store_length[8],
+ count_store_length[9]);
+ dolog("Distribution of store creator chains second part");
+ dolog(" 10 11 12 13 14 15 16 17 18 19 >=20");
+ dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
+ count_store_length[10], count_store_length[11],
+ count_store_length[12], count_store_length[13],
+ count_store_length[14], count_store_length[15],
+ count_store_length[16], count_store_length[17],
+ count_store_length[18], count_store_length[19],
+ count_store_length[20]);
+ dolog("Distribution of analysis iterations");
+ dolog(" 1 2 3 4 >=5");
+ dolog("%6d%6d%6d%6d%6d",
+ count_analyse_iterations[0], count_analyse_iterations[1],
+ count_analyse_iterations[2], count_analyse_iterations[3],
+ count_analyse_iterations[4]);
+
+
+ /* Distribution of basic blocks per method ********************************/
+
+ log_println("Distribution of basic blocks per method:");
+ log_println(" <=5 <=10 <=15 <=20 <=30 <=40 <=50 <=75 >75");
+
+ log_start();
+ for (i = 0; i <= 8; i++)
+ log_print("%6d", count_method_bb_distribution[i]);
+ log_finish();
+
+ /* print ratio */
+
+ f = (float) count_methods;
+
+ log_start();
+ for (i = 0; i <= 8; i++)
+ log_print("%6.2f", (float) count_method_bb_distribution[i] / f);
+ log_finish();
+
+ /* print cumulated ratio */
+
+ log_start();
+ for (i = 0, sum = 0; i <= 8; i++) {
+ sum += count_method_bb_distribution[i];
+ log_print("%6.2f", (float) sum / f);
+ }
+ log_finish();
+
+
+ /* Distribution of basic block sizes **************************************/
+
+ log_println("Distribution of basic block sizes:");
+ log_println(" 0 1 2 3 4 5 6 7 8 9 <13 <15 <17 <19 <21 <26 <31 >30");
+
+ /* print block sizes */
+
+ log_start();
+ for (i = 0; i <= 17; i++)
+ log_print("%6d", count_block_size_distribution[i]);
+ log_finish();
+
+ /* print ratio */
+
+ f = (float) count_basic_blocks;
+
+ log_start();
+ for (i = 0; i <= 17; i++)
+ log_print("%6.2f", (float) count_block_size_distribution[i] / f);
+ log_finish();
+
+ /* print cumulated ratio */
+
+ log_start();
+ for (i = 0, sum = 0; i <= 17; i++) {
+ sum += count_block_size_distribution[i];
+ log_print("%6.2f", (float) sum / f);
+ }
+ log_finish();
+
+ statistics_print_memory_usage();
+
+ dolog("Number of class loads: %6d", count_class_loads);
+ dolog("Number of class inits: %6d", count_class_inits);
+ dolog("Number of loaded Methods: %6d\n", count_all_methods);
+
+ dolog("Calls of utf_new: %6d", count_utf_new);
+ dolog("Calls of utf_new (element found): %6d\n", count_utf_new_found);
+
+
+ /* LSRA statistics ********************************************************/
+
+ dolog("Moves reg -> reg: %6d", count_mov_reg_reg);
+ dolog("Moves mem -> reg: %6d", count_mov_mem_reg);
+ dolog("Moves reg -> mem: %6d", count_mov_reg_mem);
+ dolog("Moves mem -> mem: %6d", count_mov_mem_mem);
+
+ dolog("Methods allocated by LSRA: %6d",
+ count_methods_allocated_by_lsra);
+ dolog("Conflicts between local Variables: %6d", count_locals_conflicts);
+ dolog("Local Variables held in Memory: %6d", count_locals_spilled);
+ dolog("Local Variables held in Registers: %6d", count_locals_register);
+ dolog("Stackslots held in Memory: %6d", count_ss_spilled);
+ dolog("Stackslots held in Registers: %6d", count_ss_register);
+ dolog("Memory moves at BB Boundaries: %6d", count_mem_move_bb);
+ dolog("Number of interface slots: %6d\n", count_interface_size);
+ dolog("Number of Argument stack slots in register: %6d",
+ count_argument_reg_ss);
+ dolog("Number of Argument stack slots in memory: %6d\n",
+ count_argument_mem_ss);
+ dolog("Number of Methods kept in registers: %6d\n",
+ count_method_in_register);
+
+
+ /* instruction scheduler statistics ***************************************/
+
+#if defined(USE_SCHEDULER)
+ dolog("Instruction scheduler statistics:");
+ dolog("Number of basic blocks: %7d", count_schedule_basic_blocks);
+ dolog("Number of nodes: %7d", count_schedule_nodes);
+ dolog("Number of leaders nodes: %7d", count_schedule_leaders);
+ dolog("Number of max. leaders nodes: %7d", count_schedule_max_leaders);
+ dolog("Length of critical path: %7d\n", count_schedule_critical_path);
+#endif
+
+
+ /* call statistics ********************************************************/
+
+ dolog("Function call statistics:");
+ dolog("Number of jni->CallXMethod function invokations: %ld",
+ count_jni_callXmethod_calls);
+ dolog("Overall number of jni invokations: %ld",
+ count_jni_calls);
+
+ log_println("java-to-native calls: %10ld", count_calls_java_to_native);
+ log_println("native-to-java calls: %10ld", count_calls_native_to_java);
+
+
+ /* now print other statistics ********************************************/
+
+#if defined(ENABLE_INTRP)
+ print_dynamic_super_statistics();
+#endif
+}
+
+
+/* statistics_print_date *******************************************************
+
+ Print current date and time.
+
+*******************************************************************************/
+
+void statistics_print_date(void)
+{
+ time_t t;
+ struct tm tm;
+
+#if defined(HAVE_TIME)
+ time(&t);
+#else
+# error !HAVE_TIME
+#endif
+
+#if defined(HAVE_LOCALTIME_R)
+ localtime_r(&t, &tm);
+#else
+# error !HAVE_LOCALTIME_R
+#endif
+
+ log_println("%d-%02d-%02d %02d:%02d:%02d",
+ 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+}
+
+
+/* statistics_print_memory_usage ***********************************************
+
+ Print current memory usage.
+
+*******************************************************************************/
+
+void statistics_print_memory_usage(void)
+{
+ s4 sum;
+
+ log_println("memory usage ----------------------");
+ log_println("");
+ log_println("code: %10d", count_code_len);
+ log_println("data: %10d", count_data_len);
+ log_println(" ----------");
+
+ sum =
+ count_code_len +
+ count_data_len;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("classinfo (%3d B): %10d", (int) sizeof(classinfo), size_classinfo);
+ log_println("fieldinfo (%3d B): %10d", (int) sizeof(fieldinfo), size_fieldinfo);
+ log_println("methodinfo (%3d B): %10d", (int) sizeof(methodinfo), size_methodinfo);
+ log_println("lineinfo (%3d B): %10d", (int) sizeof(lineinfo), size_lineinfo);
+ log_println("codeinfo (%3d B): %10d", (int) sizeof(codeinfo), size_codeinfo);
+ log_println(" ----------");
+
+ sum =
+ size_classinfo +
+ size_fieldinfo +
+ size_methodinfo +
+ size_lineinfo +
+ size_codeinfo;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("linenumber tables (%5d): %10d", count_linenumbertable, size_linenumbertable);
+ log_println("exception tables: %10d", count_extable_len);
+ log_println("patcher references: %10d", size_patchref);
+ log_println(" ----------");
+
+ sum =
+ size_linenumbertable +
+ count_extable_len +
+ size_patchref;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("constant pool: %10d", count_const_pool_len);
+ log_println("classref: %10d", count_classref_len);
+ log_println("parsed descriptors: %10d", count_parsed_desc_len);
+ log_println("vftbl: %10d", count_vftbl_len);
+ log_println("compiler stubs: %10d", count_cstub_len);
+ log_println("native stubs: %10d", size_stub_native);
+ log_println("utf: %10d", count_utf_len);
+ log_println("vmcode: %10d", count_vmcode_len);
+ log_println("stack map: %10d", size_stack_map);
+ log_println("string: %10d", size_string);
+ log_println("threadobject: %10d", size_threadobject);
+ log_println("thread index: %10d", size_thread_index_t);
+ log_println("stack size: %10d", size_stacksize);
+ log_println("lock record: %10d", size_lock_record);
+ log_println("lock hashtable: %10d", size_lock_hashtable);
+ log_println("lock waiter: %10d", size_lock_waiter);
+ log_println(" ----------");
+
+ sum =
+ count_const_pool_len +
+ count_classref_len +
+ count_parsed_desc_len +
+ count_vftbl_len +
+ count_cstub_len +
+ size_stub_native +
+ count_utf_len +
+ count_vmcode_len +
+ size_stack_map +
+ size_string +
+ size_threadobject +
+ size_thread_index_t +
+ size_stacksize +
+ size_lock_record +
+ size_lock_hashtable +
+ size_lock_waiter;
+
+ log_println(" %10d", sum);
+
+ log_println("");
+
+ log_println("max. code memory: %10d", maxcodememusage);
+ log_println("max. heap memory: %10d", maxmemusage);
+ log_println("max. dump memory: %10d", maxdumpsize);
+ log_println("");
+ log_println("heap memory not freed: %10d", (int32_t) memoryusage);
+ log_println("dump memory not freed: %10d", (int32_t) globalallocateddumpsize);
+
+ log_println("");
+}
+
+
+/* statistics_print_gc_memory_usage ********************************************
+
+ Print current GC memory usage.
+
+*******************************************************************************/
+
+void statistics_print_gc_memory_usage(void)
+{
+ static int64_t count = 0;
+ int64_t max;
+ int64_t size;
+ int64_t free;
+ int64_t used;
+ int64_t total;
+
+ count++;
+
+ max = gc_get_max_heap_size();
+ size = gc_get_heap_size();
+ free = gc_get_free_bytes();
+ used = size - free;
+ total = gc_get_total_bytes();
+
+ if (opt_ProfileMemoryUsageGNUPlot) {
+ if (count == 1)
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "plot \"profile.dat\" using 1:2 with lines title \"max. Java heap size\", \"profile.dat\" using 1:3 with lines title \"Java heap size\", \"profile.dat\" using 1:4 with lines title \"used\", \"profile.dat\" using 1:5 with lines title \"free\"\n");
+
+#if SIZEOF_VOID_P == 8
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "%ld %ld %ld %ld %ld\n", count, max, size, used, free);
+#else
+ fprintf(opt_ProfileMemoryUsageGNUPlot, "%lld %lld %lld %lld %lld\n", count, max, size, used, free);
+#endif
+
+ fflush(opt_ProfileMemoryUsageGNUPlot);
+ }
+ else {
+ log_println("GC memory usage -------------------");
+ log_println("");
+ log_println("max. Java heap size: %10lld", max);
+ log_println("");
+ log_println("Java heap size: %10lld", size);
+ log_println("used: %10lld", used);
+ log_println("free: %10lld", free);
+ log_println("totally used: %10lld", total);
+ log_println("");
+ }
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/statistics.h - exports global varables for statistics
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _STATISTICS_H
+#define _STATISTICS_H
+
+#include "config.h"
+
+#include <stdint.h>
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+
+/* statistic macros ***********************************************************/
+
+#if defined(ENABLE_STATISTICS)
+#define STATISTICS(x) \
+ do { \
+ if (opt_stat) { \
+ x; \
+ } \
+ } while (0)
+#else
+#define STATISTICS(x) /* nothing */
+#endif
+
+/* in_ inline statistics */
+
+#define IN_MAX 9
+#define IN_UNIQUEVIRT 0x0000
+#define IN_UNIQUE_INTERFACE 0x0001
+#define IN_OUTSIDERS 0x0004
+#define IN_MAXDEPTH 0x0008
+#define IN_MAXCODE 0x0010
+#define IN_JCODELENGTH 0x0020
+#define IN_EXCEPTION 0x0040
+#define IN_NOT_UNIQUE_VIRT 0x0080
+#define IN_NOT_UNIQUE_INTERFACE 0x0100
+
+#define N_UNIQUEVIRT 0
+#define N_UNIQUE_INTERFACE 1
+#define N_OUTSIDERS 2
+#define N_MAXDEPTH 3
+#define N_MAXCODE 4
+#define N_JCODELENGTH 5
+#define N_EXCEPTION 6
+#define N_NOT_UNIQUE_VIRT 7
+#define N_NOT_UNIQUE_INTERFACE 8
+
+
+/* global variables ***********************************************************/
+
+extern s4 codememusage;
+extern s4 maxcodememusage;
+
+extern s4 memoryusage;
+extern s4 maxmemusage;
+
+extern s4 maxdumpsize;
+
+extern s4 globalallocateddumpsize;
+extern s4 globaluseddumpsize;
+
+
+/* variables for measurements *************************************************/
+
+extern s4 size_classinfo;
+extern s4 size_fieldinfo;
+extern s4 size_methodinfo;
+extern s4 size_lineinfo;
+extern s4 size_codeinfo;
+
+extern s4 size_stub_native;
+
+extern s4 size_stack_map;
+extern s4 size_string;
+
+extern s4 size_threadobject;
+extern int32_t size_thread_index_t;
+extern int32_t size_stacksize;
+
+extern s4 size_lock_record;
+extern s4 size_lock_hashtable;
+extern s4 size_lock_waiter;
+
+extern int32_t count_linenumbertable;
+extern int32_t size_linenumbertable;
+
+extern s4 size_patchref;
+
+extern u8 count_calls_java_to_native;
+extern u8 count_calls_native_to_java;
+
+extern int count_const_pool_len;
+extern int count_classref_len;
+extern int count_parsed_desc_len;
+extern int count_vftbl_len;
+extern int count_all_methods;
+extern int count_methods_marked_used; /*RTA*/
+extern int count_vmcode_len;
+extern int count_extable_len;
+extern int count_class_loads;
+extern int count_class_inits;
+
+extern int count_utf_len; /* size of utf hash */
+extern int count_utf_new;
+extern int count_utf_new_found;
+
+extern int count_locals_conflicts;
+extern int count_locals_spilled;
+extern int count_locals_register;
+extern int count_ss_spilled;
+extern int count_ss_register;
+extern int count_methods_allocated_by_lsra;
+extern int count_mem_move_bb;
+extern int count_interface_size;
+extern int count_argument_mem_ss;
+extern int count_argument_reg_ss;
+extern int count_method_in_register;
+extern int count_mov_reg_reg;
+extern int count_mov_mem_reg;
+extern int count_mov_reg_mem;
+extern int count_mov_mem_mem;
+
+extern int count_jit_calls;
+extern int count_methods;
+extern int count_spills_read_ila;
+extern int count_spills_read_flt;
+extern int count_spills_read_dbl;
+extern int count_spills_write_ila;
+extern int count_spills_write_flt;
+extern int count_spills_write_dbl;
+extern int count_pcmd_activ;
+extern int count_pcmd_drop;
+extern int count_pcmd_zero;
+extern int count_pcmd_const_store;
+extern int count_pcmd_const_alu;
+extern int count_pcmd_const_bra;
+extern int count_pcmd_load;
+extern int count_pcmd_move;
+extern int count_load_instruction;
+extern int count_pcmd_store;
+extern int count_pcmd_store_comb;
+extern int count_dup_instruction;
+extern int count_pcmd_op;
+extern int count_pcmd_mem;
+extern int count_pcmd_met;
+extern int count_pcmd_bra;
+extern int count_pcmd_table;
+extern int count_pcmd_return;
+extern int count_pcmd_returnx;
+extern int count_check_null;
+extern int count_check_bound;
+extern int count_max_basic_blocks;
+extern int count_basic_blocks;
+extern int count_max_javainstr;
+extern int count_javainstr;
+extern int count_javacodesize;
+extern int count_javaexcsize;
+extern int count_calls;
+extern int count_tryblocks;
+extern int count_code_len;
+extern int count_data_len;
+extern int count_cstub_len;
+extern int count_max_new_stack;
+extern int count_upper_bound_new_stack;
+
+extern int count_emit_branch;
+extern int count_emit_branch_8bit;
+extern int count_emit_branch_16bit;
+extern int count_emit_branch_32bit;
+extern int count_emit_branch_64bit;
+
+extern s4 count_branches_resolved;
+extern s4 count_branches_unresolved;
+
+extern int *count_block_stack;
+extern int *count_analyse_iterations;
+extern int *count_method_bb_distribution;
+extern int *count_block_size_distribution;
+extern int *count_store_length;
+extern int *count_store_depth;
+ /* in_ inline statistics */
+extern int count_in;
+extern int count_in_uniqVirt;
+extern int count_in_uniqIntf;
+extern int count_in_rejected;
+extern int count_in_rejected_mult;
+extern int count_in_outsiders;
+extern int count_in_uniqueVirt_not_inlined;
+extern int count_in_uniqueInterface_not_inlined;
+extern int count_in_maxDepth;
+extern int count_in_maxMethods;
+
+extern u2 count_in_not [512];
+
+/* instruction scheduler statistics *******************************************/
+
+extern s4 count_schedule_basic_blocks;
+extern s4 count_schedule_nodes;
+extern s4 count_schedule_leaders;
+extern s4 count_schedule_max_leaders;
+extern s4 count_schedule_critical_path;
+
+
+/* function prototypes ********************************************************/
+
+s8 getcputime(void);
+
+void loadingtime_start(void);
+void loadingtime_stop(void);
+void compilingtime_start(void);
+void compilingtime_stop(void);
+
+void print_times(void);
+void print_stats(void);
+
+void statistics_print_date(void);
+void statistics_print_memory_usage(void);
+void statistics_print_gc_memory_usage(void);
+
+void mem_usagelog(bool givewarnings);
+
+void compiledinvokation(void);
+void jnicallXmethodnvokation(void);
+void jniinvokation(void);
+
+#endif /* _STATISTICS_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
#include <assert.h>
-#include "vmcore/os.hpp"
+#include "vm/os.hpp"
#include "vm/types.h"
#include "vm/array.h"
#include "vm/builtin.h"
#include "vm/exceptions.hpp"
+#include "vm/globals.hpp"
+#include "vm/javaobjects.hpp"
+#include "vm/options.h"
#include "vm/primitive.hpp"
+#include "vm/statistics.h"
#include "vm/string.hpp"
+#include "vm/utf8.h"
#include "vm/vm.hpp"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vmcore/utf8.h"
-
/* global variables ***********************************************************/
#include "config.h"
-#include "vmcore/os.hpp"
-
#include "vm/types.h"
#include "toolbox/hashtable.h"
#include "vm/global.h"
-
-#include "vmcore/utf8.h"
+#include "vm/os.hpp"
+#include "vm/utf8.h"
/* data structure of internal javastrings stored in global hashtable **********/
--- /dev/null
+/* src/vm/suck.c - functions to read LE ordered types from a buffer
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "vm/types.h"
+
+#include "arch.h"
+
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/list.h"
+#include "toolbox/logging.h"
+#include "toolbox/util.h"
+
+#include "vm/exceptions.hpp"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
+#include "vm/properties.h"
+#include "vm/suck.h"
+#include "vm/vm.hpp"
+#include "vm/zip.h"
+
+
+/* global variables ***********************************************************/
+
+list_t *list_classpath_entries;
+
+
+/* suck_init *******************************************************************
+
+ Initializes the suck subsystem like initializing the classpath
+ entries list.
+
+*******************************************************************************/
+
+bool suck_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("suck_init");
+
+ list_classpath_entries = list_create(OFFSET(list_classpath_entry, linkage));
+
+ /* everything's ok */
+
+ return true;
+}
+
+
+/* scandir_filter **************************************************************
+
+ Filters for zip/jar files.
+
+*******************************************************************************/
+
+static int scandir_filter(const struct dirent *a)
+{
+ s4 namlen;
+
+#if defined(_DIRENT_HAVE_D_NAMLEN)
+ namlen = a->d_namlen;
+#else
+ namlen = strlen(a->d_name);
+#endif
+
+ if ((strncasecmp(a->d_name + namlen - 4, ".zip", 4) == 0) ||
+ (strncasecmp(a->d_name + namlen - 4, ".jar", 4) == 0))
+ return 1;
+
+ return 0;
+}
+
+
+/* suck_add ********************************************************************
+
+ Adds a classpath to the global classpath entries list.
+
+*******************************************************************************/
+
+void suck_add(char *classpath)
+{
+ list_classpath_entry *lce;
+ char *start;
+ char *end;
+ char *filename;
+ s4 filenamelen;
+ bool is_zip;
+ char *cwd;
+ s4 cwdlen;
+#if defined(ENABLE_ZLIB)
+ hashtable *ht;
+#endif
+
+ /* parse the classpath string */
+
+ for (start = classpath; (*start) != '\0'; ) {
+
+ /* search for ':' delimiter to get the end of the current entry */
+ for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
+
+ if (start != end) {
+ is_zip = false;
+ filenamelen = end - start;
+
+ if (filenamelen > 4) {
+ if ((strncasecmp(end - 4, ".zip", 4) == 0) ||
+ (strncasecmp(end - 4, ".jar", 4) == 0)) {
+ is_zip = true;
+ }
+ }
+
+ /* save classpath entries as absolute pathnames */
+
+ cwd = NULL;
+ cwdlen = 0;
+
+ if (*start != '/') { /* XXX fix me for win32 */
+ cwd = _Jv_getcwd();
+ cwdlen = strlen(cwd) + strlen("/");
+ }
+
+ /* allocate memory for filename and fill it */
+
+ filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
+ strlen("0"));
+
+ if (cwd) {
+ strcpy(filename, cwd);
+ strcat(filename, "/");
+ strncat(filename, start, filenamelen);
+
+ /* add cwd length to file length */
+ filenamelen += cwdlen;
+
+ } else {
+ strncpy(filename, start, filenamelen);
+ filename[filenamelen] = '\0';
+ }
+
+ lce = NULL;
+
+ if (is_zip) {
+#if defined(ENABLE_ZLIB)
+ ht = zip_open(filename);
+
+ if (ht != NULL) {
+ lce = NEW(list_classpath_entry);
+
+ lce->type = CLASSPATH_ARCHIVE;
+ lce->htclasses = ht;
+ lce->path = filename;
+ lce->pathlen = filenamelen;
+
+ /* SUN compatible -verbose:class output */
+
+ if (opt_verboseclass)
+ printf("[Opened %s]\n", filename);
+ }
+
+#else
+ vm_abort("suck_add: zip/jar files not supported");
+#endif
+ }
+ else {
+ if (filename[filenamelen - 1] != '/') {/* XXX fixme for win32 */
+ filename[filenamelen] = '/';
+ filename[filenamelen + 1] = '\0';
+ filenamelen++;
+ }
+
+ lce = NEW(list_classpath_entry);
+
+ lce->type = CLASSPATH_PATH;
+ lce->path = filename;
+ lce->pathlen = filenamelen;
+ }
+
+ /* add current classpath entry, if no error */
+
+ if (lce != NULL)
+ list_add_last(list_classpath_entries, lce);
+ }
+
+ /* goto next classpath entry, skip ':' delimiter */
+
+ if ((*end) == ':')
+ start = end + 1;
+ else
+ start = end;
+ }
+}
+
+
+/* suck_add_from_property ******************************************************
+
+ Adds a classpath form a property entry to the global classpath
+ entries list.
+
+*******************************************************************************/
+
+void suck_add_from_property(const char *key)
+{
+ const char *value;
+ const char *start;
+ const char *end;
+ char *path;
+ s4 pathlen;
+ struct dirent **namelist;
+ s4 n;
+ s4 i;
+ s4 namlen;
+ char *boot_class_path;
+ char *p;
+
+ /* get the property value */
+
+ value = properties_get(key);
+
+ if (value == NULL)
+ return;
+
+ /* get the directory entries of the property */
+
+ for (start = value; (*start) != '\0'; ) {
+
+ /* search for ':' delimiter to get the end of the current entry */
+
+ for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
+
+ /* found an entry */
+
+ if (start != end) {
+ /* allocate memory for the path entry */
+
+ pathlen = end - start;
+ path = MNEW(char, pathlen + strlen("0"));
+
+ /* copy and terminate the string */
+
+ strncpy(path, start, pathlen);
+ path[pathlen] = '\0';
+
+ /* Reset namelist to NULL for the freeing in an error case
+ (see below). */
+
+ namelist = NULL;
+
+ /* scan the directory found for zip/jar files */
+
+ n = os_scandir(path, &namelist, scandir_filter, alphasort);
+
+ /* On error, just continue, this should be ok. */
+
+ if (n > 0) {
+ for (i = 0; i < n; i++) {
+#if defined(_DIRENT_HAVE_D_NAMLEN)
+ namlen = namelist[i]->d_namlen;
+#else
+ namlen = strlen(namelist[i]->d_name);
+#endif
+
+ /* Allocate memory for bootclasspath. */
+
+ // FIXME Make boot_class_path const char*.
+ boot_class_path = (char*) properties_get("sun.boot.class.path");
+
+ p = MNEW(char,
+ pathlen + strlen("/") + namlen +
+ strlen(":") +
+ strlen(boot_class_path) +
+ strlen("0"));
+
+ /* Prepend the file found to the bootclasspath. */
+
+ strcpy(p, path);
+ strcat(p, "/");
+ strcat(p, namelist[i]->d_name);
+ strcat(p, ":");
+ strcat(p, boot_class_path);
+
+ properties_add("sun.boot.class.path", p);
+ properties_add("java.boot.class.path", p);
+
+ MFREE(boot_class_path, char, strlen(boot_class_path));
+
+ /* free the memory allocated by scandir */
+ /* (We use `free` as the memory came from the C library.) */
+
+ free(namelist[i]);
+ }
+ }
+
+ /* On some systems (like Linux) when n == 0, then namelist
+ returned from scnadir is NULL, thus we don't have to
+ free it.
+ (Use `free` as the memory came from the C library.) */
+
+ if (namelist != NULL)
+ free(namelist);
+
+ MFREE(path, char, pathlen + strlen("0"));
+ }
+
+ /* goto next entry, skip ':' delimiter */
+
+ if ((*end) == ':')
+ start = end + 1;
+ else
+ start = end;
+ }
+}
+
+
+/* suck_check_classbuffer_size *************************************************
+
+ Assert that at least <len> bytes are left to read <len> is limited
+ to the range of non-negative s4 values.
+
+*******************************************************************************/
+
+bool suck_check_classbuffer_size(classbuffer *cb, s4 len)
+{
+#ifdef ENABLE_VERIFIER
+ if (len < 0 || ((cb->data + cb->size) - cb->pos) < len) {
+ exceptions_throw_classformaterror(cb->clazz, "Truncated class file");
+ return false;
+ }
+#endif /* ENABLE_VERIFIER */
+
+ return true;
+}
+
+
+u1 suck_u1(classbuffer *cb)
+{
+ u1 a;
+
+ a = SUCK_BE_U1(cb->pos);
+ cb->pos++;
+
+ return a;
+}
+
+
+u2 suck_u2(classbuffer *cb)
+{
+ u2 a;
+
+ a = SUCK_BE_U2(cb->pos);
+ cb->pos += 2;
+
+ return a;
+}
+
+
+u4 suck_u4(classbuffer *cb)
+{
+ u4 a;
+
+ a = SUCK_BE_U4(cb->pos);
+ cb->pos += 4;
+
+ return a;
+}
+
+
+u8 suck_u8(classbuffer *cb)
+{
+#if U8_AVAILABLE == 1
+ u8 a;
+
+ a = SUCK_BE_U8(cb->pos);
+ cb->pos += 8;
+
+ return a;
+#else
+ u8 v;
+
+ v.high = suck_u4(cb);
+ v.low = suck_u4(cb);
+
+ return v;
+#endif
+}
+
+
+float suck_float(classbuffer *cb)
+{
+ float f;
+
+#if WORDS_BIGENDIAN == 0
+ u1 buffer[4];
+ u2 i;
+
+ for (i = 0; i < 4; i++)
+ buffer[3 - i] = suck_u1(cb);
+
+ MCOPY((u1 *) (&f), buffer, u1, 4);
+#else
+ suck_nbytes((u1*) (&f), cb, 4);
+#endif
+
+ assert(sizeof(float) == 4);
+
+ return f;
+}
+
+
+double suck_double(classbuffer *cb)
+{
+ double d;
+
+#if WORDS_BIGENDIAN == 0
+ u1 buffer[8];
+ u2 i;
+
+# if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
+ /*
+ * On little endian ARM processors when using FPA, word order
+ * of doubles is still big endian. So take that into account
+ * here. When using VFP, word order of doubles follows byte
+ * order. (michi 2005/07/24)
+ */
+ for (i = 0; i < 4; i++)
+ buffer[3 - i] = suck_u1(cb);
+ for (i = 0; i < 4; i++)
+ buffer[7 - i] = suck_u1(cb);
+# else
+ for (i = 0; i < 8; i++)
+ buffer[7 - i] = suck_u1(cb);
+# endif /* defined(__ARM__) && ... */
+
+ MCOPY((u1 *) (&d), buffer, u1, 8);
+#else
+ suck_nbytes((u1*) (&d), cb, 8);
+#endif
+
+ assert(sizeof(double) == 8);
+
+ return d;
+}
+
+
+/* suck_nbytes *****************************************************************
+
+ Transfer block of classfile data into a buffer.
+
+*******************************************************************************/
+
+void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
+{
+ MCOPY(buffer, cb->pos, u1, len);
+ cb->pos += len;
+}
+
+
+/* suck_skip_nbytes ************************************************************
+
+ Skip block of classfile data.
+
+*******************************************************************************/
+
+void suck_skip_nbytes(classbuffer *cb, s4 len)
+{
+ cb->pos += len;
+}
+
+
+/* suck_start ******************************************************************
+
+ Returns true if classbuffer is already loaded or a file for the
+ specified class has succussfully been read in. All directories of
+ the searchpath are used to find the classfile (<classname>.class).
+ Returns NULL if no classfile is found and writes an error message.
+
+*******************************************************************************/
+
+classbuffer *suck_start(classinfo *c)
+{
+ list_classpath_entry *lce;
+ char *filename;
+ s4 filenamelen;
+ char *path;
+ FILE *classfile;
+ s4 len;
+ struct stat buffer;
+ classbuffer *cb;
+
+ /* initialize return value */
+
+ cb = NULL;
+
+ /* get the classname as char string (do it here for the warning at
+ the end of the function) */
+
+ filenamelen = utf_bytes(c->name) + strlen(".class") + strlen("0");
+ filename = MNEW(char, filenamelen);
+
+ utf_copy(filename, c->name);
+ strcat(filename, ".class");
+
+ /* walk through all classpath entries */
+
+ for (lce = list_first(list_classpath_entries); lce != NULL && cb == NULL;
+ lce = list_next(list_classpath_entries, lce)) {
+#if defined(ENABLE_ZLIB)
+ if (lce->type == CLASSPATH_ARCHIVE) {
+
+ /* enter a monitor on zip/jar archives */
+
+ LOCK_MONITOR_ENTER(lce);
+
+ /* try to get the file in current archive */
+
+ cb = zip_get(lce, c);
+
+ /* leave the monitor */
+
+ LOCK_MONITOR_EXIT(lce);
+
+ } else {
+#endif /* defined(ENABLE_ZLIB) */
+ path = MNEW(char, lce->pathlen + filenamelen);
+ strcpy(path, lce->path);
+ strcat(path, filename);
+
+ classfile = os_fopen(path, "r");
+
+ if (classfile) { /* file exists */
+ if (!os_stat(path, &buffer)) { /* read classfile data */
+ cb = NEW(classbuffer);
+ cb->clazz = c;
+ cb->size = buffer.st_size;
+ cb->data = MNEW(u1, cb->size);
+ cb->pos = cb->data;
+ cb->path = lce->path;
+
+ /* read class data */
+
+ len = os_fread((void *) cb->data, 1, cb->size,
+ classfile);
+
+ if (len != buffer.st_size) {
+ suck_stop(cb);
+/* if (ferror(classfile)) { */
+/* } */
+ }
+
+ /* close the class file */
+
+ os_fclose(classfile);
+ }
+ }
+
+ MFREE(path, char, lce->pathlen + filenamelen);
+#if defined(ENABLE_ZLIB)
+ }
+#endif
+ }
+
+ if (opt_verbose)
+ if (cb == NULL)
+ dolog("Warning: Can not open class file '%s'", filename);
+
+ MFREE(filename, char, filenamelen);
+
+ return cb;
+}
+
+
+/* suck_stop *******************************************************************
+
+ Frees memory for buffer with classfile data.
+
+ CAUTION: This function may only be called if buffer has been
+ allocated by suck_start with reading a file.
+
+*******************************************************************************/
+
+void suck_stop(classbuffer *cb)
+{
+ /* free memory */
+
+ MFREE(cb->data, u1, cb->size);
+ FREE(cb, classbuffer);
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/vm/suck.h - functions to read LE ordered types from a buffer
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _SUCK_H
+#define _SUCK_H
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+#include "toolbox/list.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+
+
+/* list_classpath_entry *******************************************************/
+
+enum {
+ CLASSPATH_PATH,
+ CLASSPATH_ARCHIVE
+};
+
+typedef struct list_classpath_entry list_classpath_entry;
+
+struct list_classpath_entry {
+#if defined(ENABLE_THREADS)
+ java_object_t header; /* monitor locking on zip/jar files */
+#endif
+ s4 type;
+ char *path;
+ s4 pathlen;
+#if defined(ENABLE_ZLIB)
+ hashtable *htclasses;
+#endif
+ listnode_t linkage;
+};
+
+
+/* macros to read LE and BE types from a buffer ********************************
+
+ BE macros are for Java class file loading.
+ LE macros are for ZIP file loading.
+
+*******************************************************************************/
+
+/* LE macros (for ZIP files ) *************************************************/
+
+#if defined(__I386__) || defined(__X86_64__)
+
+/* we can optimize the LE access on little endian machines without alignment */
+
+#define SUCK_LE_U1(p) *((u1 *) (p))
+#define SUCK_LE_U2(p) *((u2 *) (p))
+#define SUCK_LE_U4(p) *((u4 *) (p))
+
+#if U8_AVAILABLE == 1
+#define SUCK_LE_U8(p) *((u8 *) (p))
+#endif
+
+#else /* defined(__I386__) || defined(__X86_64__) */
+
+#define SUCK_LE_U1(p) \
+ ((u1) (p)[0])
+
+#define SUCK_LE_U2(p) \
+ ((((u2) (p)[1]) << 8) + \
+ ((u2) (p)[0]))
+
+#define SUCK_LE_U4(p) \
+ ((((u4) (p)[3]) << 24) + \
+ (((u4) (p)[2]) << 16) + \
+ (((u4) (p)[1]) << 8) + \
+ ((u4) (p)[0]))
+
+#if U8_AVAILABLE == 1
+#define SUCK_LE_U8(p) \
+ ((((u8) (p)[7]) << 56) + \
+ (((u8) (p)[6]) << 48) + \
+ (((u8) (p)[5]) << 40) + \
+ (((u8) (p)[4]) << 32) + \
+ (((u8) (p)[3]) << 24) + \
+ (((u8) (p)[2]) << 16) + \
+ (((u8) (p)[1]) << 8) + \
+ ((u8) (p)[0]))
+#endif
+
+#endif /* defined(__I386__) || defined(__X86_64__) */
+
+
+/* BE macros (for Java class files ) ******************************************/
+
+#define SUCK_BE_U1(p) \
+ ((u1) (p)[0])
+
+#define SUCK_BE_U2(p) \
+ ((((u2) (p)[0]) << 8) + \
+ ((u2) (p)[1]))
+
+#define SUCK_BE_U4(p) \
+ ((((u4) (p)[0]) << 24) + \
+ (((u4) (p)[1]) << 16) + \
+ (((u4) (p)[2]) << 8) + \
+ ((u4) (p)[3]))
+
+#if U8_AVAILABLE == 1
+#define SUCK_BE_U8(p) \
+ ((((u8) (p)[0]) << 56) + \
+ (((u8) (p)[1]) << 48) + \
+ (((u8) (p)[2]) << 40) + \
+ (((u8) (p)[3]) << 32) + \
+ (((u8) (p)[4]) << 24) + \
+ (((u8) (p)[5]) << 16) + \
+ (((u8) (p)[6]) << 8) + \
+ ((u8) (p)[7]))
+#endif
+
+
+#define SUCK_BE_S1(p) (s1) SUCK_BE_U1(p)
+#define SUCK_BE_S2(p) (s2) SUCK_BE_U2(p)
+#define SUCK_BE_S4(p) (s4) SUCK_BE_U4(p)
+#define SUCK_BE_S8(p) (s8) SUCK_BE_U8(p)
+
+
+/* signed suck defines ********************************************************/
+
+#define suck_s1(a) (s1) suck_u1((a))
+#define suck_s2(a) (s2) suck_u2((a))
+#define suck_s4(a) (s4) suck_u4((a))
+#define suck_s8(a) (s8) suck_u8((a))
+
+
+/* export variables ***********************************************************/
+
+extern list_t *list_classpath_entries;
+
+
+/* function prototypes ********************************************************/
+
+bool suck_init(void);
+
+void suck_add(char *classpath);
+void suck_add_from_property(const char *key);
+
+bool suck_check_classbuffer_size(classbuffer *cb, s4 len);
+
+u1 suck_u1(classbuffer *cb);
+u2 suck_u2(classbuffer *cb);
+u4 suck_u4(classbuffer *cb);
+u8 suck_u8(classbuffer *cb);
+
+float suck_float(classbuffer *cb);
+double suck_double(classbuffer *cb);
+
+void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len);
+void suck_skip_nbytes(classbuffer *cb, s4 len);
+
+classbuffer *suck_start(classinfo *c);
+
+void suck_stop(classbuffer *cb);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SUCK_H */
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
--- /dev/null
+/* src/vm/utf8.c - utf8 string functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include "vm/types.h"
+
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/exceptions.hpp"
+#include "vm/options.h"
+
+#if defined(ENABLE_STATISTICS)
+# include "vm/statistics.h"
+#endif
+
+#include "vm/utf8.h"
+
+
+/* global variables ***********************************************************/
+
+/* hashsize must be power of 2 */
+
+#define HASHTABLE_UTF_SIZE 16384 /* initial size of utf-hash */
+
+hashtable *hashtable_utf; /* hashtable for utf8-symbols */
+
+
+/* utf-symbols for pointer comparison of frequently used strings **************/
+
+utf *utf_java_lang_Object;
+
+utf *utf_java_lang_Class;
+utf *utf_java_lang_ClassLoader;
+utf *utf_java_lang_Cloneable;
+utf *utf_java_lang_SecurityManager;
+utf *utf_java_lang_String;
+utf *utf_java_lang_ThreadGroup;
+utf *utf_java_lang_ref_SoftReference;
+utf *utf_java_lang_ref_WeakReference;
+utf *utf_java_lang_ref_PhantomReference;
+utf *utf_java_io_Serializable;
+
+utf *utf_java_lang_Throwable;
+utf *utf_java_lang_Error;
+
+utf *utf_java_lang_AbstractMethodError;
+utf *utf_java_lang_ClassCircularityError;
+utf *utf_java_lang_ClassFormatError;
+utf *utf_java_lang_ExceptionInInitializerError;
+utf *utf_java_lang_IncompatibleClassChangeError;
+utf *utf_java_lang_InstantiationError;
+utf *utf_java_lang_InternalError;
+utf *utf_java_lang_LinkageError;
+utf *utf_java_lang_NoClassDefFoundError;
+utf *utf_java_lang_NoSuchFieldError;
+utf *utf_java_lang_NoSuchMethodError;
+utf *utf_java_lang_OutOfMemoryError;
+utf *utf_java_lang_UnsatisfiedLinkError;
+utf *utf_java_lang_UnsupportedClassVersionError;
+utf *utf_java_lang_VerifyError;
+utf *utf_java_lang_VirtualMachineError;
+
+utf *utf_java_lang_Exception;
+
+utf *utf_java_lang_ArithmeticException;
+utf *utf_java_lang_ArrayIndexOutOfBoundsException;
+utf *utf_java_lang_ArrayStoreException;
+utf *utf_java_lang_ClassCastException;
+utf *utf_java_lang_ClassNotFoundException;
+utf *utf_java_lang_CloneNotSupportedException;
+utf *utf_java_lang_IllegalAccessException;
+utf *utf_java_lang_IllegalArgumentException;
+utf *utf_java_lang_IllegalMonitorStateException;
+utf *utf_java_lang_InstantiationException;
+utf *utf_java_lang_InterruptedException;
+utf *utf_java_lang_NegativeArraySizeException;
+utf *utf_java_lang_NullPointerException;
+utf *utf_java_lang_RuntimeException;
+utf *utf_java_lang_StringIndexOutOfBoundsException;
+
+utf *utf_java_lang_reflect_InvocationTargetException;
+
+utf *utf_java_security_PrivilegedActionException;
+
+#if defined(ENABLE_JAVASE)
+utf* utf_java_lang_Void;
+#endif
+
+utf* utf_java_lang_Boolean;
+utf* utf_java_lang_Byte;
+utf* utf_java_lang_Character;
+utf* utf_java_lang_Short;
+utf* utf_java_lang_Integer;
+utf* utf_java_lang_Long;
+utf* utf_java_lang_Float;
+utf* utf_java_lang_Double;
+
+#if defined(ENABLE_JAVASE)
+utf *utf_java_lang_StackTraceElement;
+utf *utf_java_lang_reflect_Constructor;
+utf *utf_java_lang_reflect_Field;
+utf *utf_java_lang_reflect_Method;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+utf *utf_java_lang_reflect_VMConstructor;
+utf *utf_java_lang_reflect_VMField;
+utf *utf_java_lang_reflect_VMMethod;
+# endif
+
+utf *utf_java_util_Vector;
+#endif
+
+utf *utf_InnerClasses; /* InnerClasses */
+utf *utf_ConstantValue; /* ConstantValue */
+utf *utf_Code; /* Code */
+utf *utf_Exceptions; /* Exceptions */
+utf *utf_LineNumberTable; /* LineNumberTable */
+utf *utf_SourceFile; /* SourceFile */
+
+#if defined(ENABLE_JAVASE)
+utf *utf_EnclosingMethod;
+utf *utf_Signature;
+utf *utf_StackMapTable;
+
+#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
+
+utf *utf_init; /* <init> */
+utf *utf_clinit; /* <clinit> */
+utf *utf_clone; /* clone */
+utf *utf_finalize; /* finalize */
+utf *utf_invoke;
+utf *utf_main;
+utf *utf_run; /* run */
+
+utf *utf_add;
+utf *utf_dispatch;
+utf *utf_remove;
+utf *utf_addThread;
+utf *utf_removeThread;
+utf *utf_put;
+utf *utf_get;
+utf *utf_uncaughtException;
+utf *utf_value;
+
+utf *utf_fillInStackTrace;
+utf *utf_findNative;
+utf *utf_getSystemClassLoader;
+utf *utf_initCause;
+utf *utf_loadClass;
+utf *utf_loadClassInternal;
+utf *utf_printStackTrace;
+
+utf *utf_division_by_zero;
+
+utf *utf_Z; /* Z */
+utf *utf_B; /* B */
+utf *utf_C; /* C */
+utf *utf_S; /* S */
+utf *utf_I; /* I */
+utf *utf_J; /* J */
+utf *utf_F; /* F */
+utf *utf_D; /* D */
+
+utf *utf_void__void; /* ()V */
+utf *utf_boolean__void; /* (Z)V */
+utf *utf_byte__void; /* (B)V */
+utf *utf_char__void; /* (C)V */
+utf *utf_short__void; /* (S)V */
+utf *utf_int__void; /* (I)V */
+utf *utf_long__void; /* (J)V */
+utf *utf_float__void; /* (F)V */
+utf *utf_double__void; /* (D)V */
+
+utf *utf_void__java_lang_ClassLoader; /* ()Ljava/lang/ClassLoader; */
+utf *utf_void__java_lang_Object; /* ()Ljava/lang/Object; */
+utf *utf_void__java_lang_Throwable; /* ()Ljava/lang/Throwable; */
+utf *utf_java_lang_ClassLoader_java_lang_String__J;
+utf *utf_java_lang_Exception__V; /* (Ljava/lang/Exception;)V */
+utf *utf_java_lang_Object__java_lang_Object;
+utf *utf_java_lang_String__void; /* (Ljava/lang/String;)V */
+utf *utf_java_lang_String__java_lang_Class;
+utf *utf_java_lang_Thread__V; /* (Ljava/lang/Thread;)V */
+utf *utf_java_lang_Thread_java_lang_Throwable__V;
+utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
+utf *utf_java_lang_Throwable__void; /* (Ljava/lang/Throwable;)V */
+utf *utf_java_lang_Throwable__java_lang_Throwable;
+
+utf *utf_not_named_yet; /* special name for unnamed classes */
+utf *utf_null;
+utf *array_packagename;
+
+
+/* utf_init ********************************************************************
+
+ Initializes the utf8 subsystem.
+
+*******************************************************************************/
+
+void utf8_init(void)
+{
+ TRACESUBSYSTEMINITIALIZATION("utf8_init");
+
+ /* create utf8 hashtable */
+
+ hashtable_utf = NEW(hashtable);
+
+ hashtable_create(hashtable_utf, HASHTABLE_UTF_SIZE);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_len += sizeof(utf*) * hashtable_utf->size;
+#endif
+
+ /* create utf-symbols for pointer comparison of frequently used strings */
+
+ utf_java_lang_Object = utf_new_char("java/lang/Object");
+
+ utf_java_lang_Class = utf_new_char("java/lang/Class");
+ utf_java_lang_ClassLoader = utf_new_char("java/lang/ClassLoader");
+ utf_java_lang_Cloneable = utf_new_char("java/lang/Cloneable");
+ utf_java_lang_SecurityManager = utf_new_char("java/lang/SecurityManager");
+ utf_java_lang_String = utf_new_char("java/lang/String");
+ utf_java_lang_ThreadGroup = utf_new_char("java/lang/ThreadGroup");
+
+ utf_java_lang_ref_SoftReference =
+ utf_new_char("java/lang/ref/SoftReference");
+
+ utf_java_lang_ref_WeakReference =
+ utf_new_char("java/lang/ref/WeakReference");
+
+ utf_java_lang_ref_PhantomReference =
+ utf_new_char("java/lang/ref/PhantomReference");
+
+ utf_java_io_Serializable = utf_new_char("java/io/Serializable");
+
+ utf_java_lang_Throwable = utf_new_char("java/lang/Throwable");
+ utf_java_lang_Error = utf_new_char("java/lang/Error");
+
+ utf_java_lang_ClassCircularityError =
+ utf_new_char("java/lang/ClassCircularityError");
+
+ utf_java_lang_ClassFormatError = utf_new_char("java/lang/ClassFormatError");
+
+ utf_java_lang_ExceptionInInitializerError =
+ utf_new_char("java/lang/ExceptionInInitializerError");
+
+ utf_java_lang_IncompatibleClassChangeError =
+ utf_new_char("java/lang/IncompatibleClassChangeError");
+
+ utf_java_lang_InstantiationError =
+ utf_new_char("java/lang/InstantiationError");
+
+ utf_java_lang_InternalError = utf_new_char("java/lang/InternalError");
+ utf_java_lang_LinkageError = utf_new_char("java/lang/LinkageError");
+
+ utf_java_lang_NoClassDefFoundError =
+ utf_new_char("java/lang/NoClassDefFoundError");
+
+ utf_java_lang_OutOfMemoryError = utf_new_char("java/lang/OutOfMemoryError");
+
+ utf_java_lang_UnsatisfiedLinkError =
+ utf_new_char("java/lang/UnsatisfiedLinkError");
+
+ utf_java_lang_UnsupportedClassVersionError =
+ utf_new_char("java/lang/UnsupportedClassVersionError");
+
+ utf_java_lang_VerifyError = utf_new_char("java/lang/VerifyError");
+
+ utf_java_lang_VirtualMachineError =
+ utf_new_char("java/lang/VirtualMachineError");
+
+#if defined(ENABLE_JAVASE)
+ utf_java_lang_AbstractMethodError =
+ utf_new_char("java/lang/AbstractMethodError");
+
+ utf_java_lang_NoSuchFieldError =
+ utf_new_char("java/lang/NoSuchFieldError");
+
+ utf_java_lang_NoSuchMethodError =
+ utf_new_char("java/lang/NoSuchMethodError");
+#endif
+
+ utf_java_lang_Exception = utf_new_char("java/lang/Exception");
+
+ utf_java_lang_ArithmeticException =
+ utf_new_char("java/lang/ArithmeticException");
+
+ utf_java_lang_ArrayIndexOutOfBoundsException =
+ utf_new_char("java/lang/ArrayIndexOutOfBoundsException");
+
+ utf_java_lang_ArrayStoreException =
+ utf_new_char("java/lang/ArrayStoreException");
+
+ utf_java_lang_ClassCastException =
+ utf_new_char("java/lang/ClassCastException");
+
+ utf_java_lang_ClassNotFoundException =
+ utf_new_char("java/lang/ClassNotFoundException");
+
+ utf_java_lang_CloneNotSupportedException =
+ utf_new_char("java/lang/CloneNotSupportedException");
+
+ utf_java_lang_IllegalAccessException =
+ utf_new_char("java/lang/IllegalAccessException");
+
+ utf_java_lang_IllegalArgumentException =
+ utf_new_char("java/lang/IllegalArgumentException");
+
+ utf_java_lang_IllegalMonitorStateException =
+ utf_new_char("java/lang/IllegalMonitorStateException");
+
+ utf_java_lang_InstantiationException =
+ utf_new_char("java/lang/InstantiationException");
+
+ utf_java_lang_InterruptedException =
+ utf_new_char("java/lang/InterruptedException");
+
+ utf_java_lang_NegativeArraySizeException =
+ utf_new_char("java/lang/NegativeArraySizeException");
+
+ utf_java_lang_NullPointerException =
+ utf_new_char("java/lang/NullPointerException");
+
+ utf_java_lang_RuntimeException =
+ utf_new_char("java/lang/RuntimeException");
+
+ utf_java_lang_StringIndexOutOfBoundsException =
+ utf_new_char("java/lang/StringIndexOutOfBoundsException");
+
+ utf_java_lang_reflect_InvocationTargetException =
+ utf_new_char("java/lang/reflect/InvocationTargetException");
+
+ utf_java_security_PrivilegedActionException =
+ utf_new_char("java/security/PrivilegedActionException");
+
+#if defined(ENABLE_JAVASE)
+ utf_java_lang_Void = utf_new_char("java/lang/Void");
+#endif
+
+ utf_java_lang_Boolean = utf_new_char("java/lang/Boolean");
+ utf_java_lang_Byte = utf_new_char("java/lang/Byte");
+ utf_java_lang_Character = utf_new_char("java/lang/Character");
+ utf_java_lang_Short = utf_new_char("java/lang/Short");
+ utf_java_lang_Integer = utf_new_char("java/lang/Integer");
+ utf_java_lang_Long = utf_new_char("java/lang/Long");
+ utf_java_lang_Float = utf_new_char("java/lang/Float");
+ utf_java_lang_Double = utf_new_char("java/lang/Double");
+
+#if defined(ENABLE_JAVASE)
+ utf_java_lang_StackTraceElement =
+ utf_new_char("java/lang/StackTraceElement");
+
+ utf_java_lang_reflect_Constructor =
+ utf_new_char("java/lang/reflect/Constructor");
+
+ utf_java_lang_reflect_Field = utf_new_char("java/lang/reflect/Field");
+ utf_java_lang_reflect_Method = utf_new_char("java/lang/reflect/Method");
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+ utf_java_lang_reflect_VMConstructor = utf_new_char("java/lang/reflect/VMConstructor");
+ utf_java_lang_reflect_VMField = utf_new_char("java/lang/reflect/VMField");
+ utf_java_lang_reflect_VMMethod = utf_new_char("java/lang/reflect/VMMethod");
+# endif
+
+ utf_java_util_Vector = utf_new_char("java/util/Vector");
+#endif
+
+ utf_InnerClasses = utf_new_char("InnerClasses");
+ utf_ConstantValue = utf_new_char("ConstantValue");
+ utf_Code = utf_new_char("Code");
+ utf_Exceptions = utf_new_char("Exceptions");
+ utf_LineNumberTable = utf_new_char("LineNumberTable");
+ utf_SourceFile = utf_new_char("SourceFile");
+
+#if defined(ENABLE_JAVASE)
+ utf_EnclosingMethod = utf_new_char("EnclosingMethod");
+ utf_Signature = utf_new_char("Signature");
+ utf_StackMapTable = utf_new_char("StackMapTable");
+
+# if defined(ENABLE_ANNOTATIONS)
+ utf_RuntimeVisibleAnnotations = utf_new_char("RuntimeVisibleAnnotations");
+ utf_RuntimeInvisibleAnnotations = utf_new_char("RuntimeInvisibleAnnotations");
+ utf_RuntimeVisibleParameterAnnotations = utf_new_char("RuntimeVisibleParameterAnnotations");
+ utf_RuntimeInvisibleParameterAnnotations = utf_new_char("RuntimeInvisibleParameterAnnotations");
+ utf_AnnotationDefault = utf_new_char("AnnotationDefault");
+# endif
+#endif
+
+ utf_init = utf_new_char("<init>");
+ utf_clinit = utf_new_char("<clinit>");
+ utf_clone = utf_new_char("clone");
+ utf_finalize = utf_new_char("finalize");
+ utf_invoke = utf_new_char("invoke");
+ utf_main = utf_new_char("main");
+ utf_run = utf_new_char("run");
+
+ utf_add = utf_new_char("add");
+ utf_dispatch = utf_new_char("dispatch");
+ utf_remove = utf_new_char("remove");
+ utf_addThread = utf_new_char("addThread");
+ utf_removeThread = utf_new_char("removeThread");
+ utf_put = utf_new_char("put");
+ utf_get = utf_new_char("get");
+ utf_uncaughtException = utf_new_char("uncaughtException");
+ utf_value = utf_new_char("value");
+
+ utf_fillInStackTrace = utf_new_char("fillInStackTrace");
+ utf_findNative = utf_new_char("findNative");
+ utf_getSystemClassLoader = utf_new_char("getSystemClassLoader");
+ utf_initCause = utf_new_char("initCause");
+ utf_loadClass = utf_new_char("loadClass");
+ utf_loadClassInternal = utf_new_char("loadClassInternal");
+ utf_printStackTrace = utf_new_char("printStackTrace");
+
+ utf_division_by_zero = utf_new_char("/ by zero");
+
+ utf_Z = utf_new_char("Z");
+ utf_B = utf_new_char("B");
+ utf_C = utf_new_char("C");
+ utf_S = utf_new_char("S");
+ utf_I = utf_new_char("I");
+ utf_J = utf_new_char("J");
+ utf_F = utf_new_char("F");
+ utf_D = utf_new_char("D");
+
+ utf_void__void = utf_new_char("()V");
+ utf_boolean__void = utf_new_char("(Z)V");
+ utf_byte__void = utf_new_char("(B)V");
+ utf_char__void = utf_new_char("(C)V");
+ utf_short__void = utf_new_char("(S)V");
+ utf_int__void = utf_new_char("(I)V");
+ utf_long__void = utf_new_char("(J)V");
+ utf_float__void = utf_new_char("(F)V");
+ utf_double__void = utf_new_char("(D)V");
+ utf_void__java_lang_Object = utf_new_char("()Ljava/lang/Object;");
+ utf_void__java_lang_Throwable = utf_new_char("()Ljava/lang/Throwable;");
+
+ utf_void__java_lang_ClassLoader =
+ utf_new_char("()Ljava/lang/ClassLoader;");
+
+ utf_java_lang_ClassLoader_java_lang_String__J =
+ utf_new_char("(Ljava/lang/ClassLoader;Ljava/lang/String;)J");
+
+ utf_java_lang_Exception__V = utf_new_char("(Ljava/lang/Exception;)V");
+
+ utf_java_lang_Object__java_lang_Object =
+ utf_new_char("(Ljava/lang/Object;)Ljava/lang/Object;");
+
+ utf_java_lang_String__void = utf_new_char("(Ljava/lang/String;)V");
+
+ utf_java_lang_String__java_lang_Class =
+ utf_new_char("(Ljava/lang/String;)Ljava/lang/Class;");
+
+ utf_java_lang_Thread__V = utf_new_char("(Ljava/lang/Thread;)V");
+
+ utf_java_lang_Thread_java_lang_Throwable__V =
+ utf_new_char("(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
+
+ utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V =
+ utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
+
+ utf_java_lang_Throwable__void = utf_new_char("(Ljava/lang/Throwable;)V");
+
+ utf_java_lang_Throwable__java_lang_Throwable =
+ utf_new_char("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
+
+ utf_null = utf_new_char("null");
+ utf_not_named_yet = utf_new_char("\t<not_named_yet>");
+ array_packagename = utf_new_char("\t<the array package>");
+}
+
+
+/* utf_hashkey *****************************************************************
+
+ The hashkey is computed from the utf-text by using up to 8
+ characters. For utf-symbols longer than 15 characters 3 characters
+ are taken from the beginning and the end, 2 characters are taken
+ from the middle.
+
+*******************************************************************************/
+
+#define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
+#define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
+
+u4 utf_hashkey(const char *text, u4 length)
+{
+ const char *start_pos = text; /* pointer to utf text */
+ u4 a;
+
+ switch (length) {
+ case 0: /* empty string */
+ return 0;
+
+ case 1: return fbs(0);
+ case 2: return fbs(0) ^ nbs(3);
+ case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
+ case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
+ case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
+ case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
+ case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
+ case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
+
+ case 9:
+ a = fbs(0);
+ a ^= nbs(1);
+ a ^= nbs(2);
+ text++;
+ return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
+
+ case 10:
+ a = fbs(0);
+ text++;
+ a ^= nbs(2);
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text++;
+ return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
+
+ case 11:
+ a = fbs(0);
+ text++;
+ a ^= nbs(2);
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text++;
+ return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
+
+ case 12:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(2);
+ a ^= nbs(3);
+ text++;
+ a ^= nbs(5);
+ a ^= nbs(6);
+ a ^= nbs(7);
+ text++;
+ return a ^ nbs(9) ^ nbs(10);
+
+ case 13:
+ a = fbs(0);
+ a ^= nbs(1);
+ text++;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
+ return a ^ nbs(9) ^ nbs(10);
+
+ case 14:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
+ return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
+
+ case 15:
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+ text += 2;
+ a ^= nbs(7);
+ a ^= nbs(8);
+ text += 2;
+ return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
+
+ default: /* 3 characters from beginning */
+ a = fbs(0);
+ text += 2;
+ a ^= nbs(3);
+ a ^= nbs(4);
+
+ /* 2 characters from middle */
+ text = start_pos + (length / 2);
+ a ^= fbs(5);
+ text += 2;
+ a ^= nbs(6);
+
+ /* 3 characters from end */
+ text = start_pos + length - 4;
+
+ a ^= fbs(7);
+ text++;
+
+ return a ^ nbs(10) ^ nbs(11);
+ }
+}
+
+/* utf_full_hashkey ************************************************************
+
+ This function computes a hash value using all bytes in the string.
+
+ The algorithm is the "One-at-a-time" algorithm as published
+ by Bob Jenkins on http://burtleburtle.net/bob/hash/doobs.html.
+
+*******************************************************************************/
+
+u4 utf_full_hashkey(const char *text, u4 length)
+{
+ register const unsigned char *p = (const unsigned char *) text;
+ register u4 hash;
+ register u4 i;
+
+ hash = 0;
+ for (i=length; i--;)
+ {
+ hash += *p++;
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+
+ return hash;
+}
+
+/* unicode_hashkey *************************************************************
+
+ Compute the hashkey of a unicode string.
+
+*******************************************************************************/
+
+u4 unicode_hashkey(u2 *text, u2 len)
+{
+ return utf_hashkey((char *) text, len);
+}
+
+
+/* utf_new *********************************************************************
+
+ Creates a new utf-symbol, the text of the symbol is passed as a
+ u1-array. The function searches the utf-hashtable for a utf-symbol
+ with this text. On success the element returned, otherwise a new
+ hashtable element is created.
+
+ If the number of entries in the hashtable exceeds twice the size of
+ the hashtable slots a reorganization of the hashtable is done and
+ the utf symbols are copied to a new hashtable with doubled size.
+
+*******************************************************************************/
+
+utf *utf_new(const char *text, u2 length)
+{
+ u4 key; /* hashkey computed from utf-text */
+ u4 slot; /* slot in hashtable */
+ utf *u; /* hashtable element */
+ u2 i;
+
+ LOCK_MONITOR_ENTER(hashtable_utf->header);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_new++;
+#endif
+
+ key = utf_hashkey(text, length);
+ slot = key & (hashtable_utf->size - 1);
+ u = hashtable_utf->ptr[slot];
+
+ /* search external hash chain for utf-symbol */
+
+ while (u) {
+ if (u->blength == length) {
+ /* compare text of hashtable elements */
+
+ for (i = 0; i < length; i++)
+ if (text[i] != u->text[i])
+ goto nomatch;
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_new_found++;
+#endif
+
+ /* symbol found in hashtable */
+
+ LOCK_MONITOR_EXIT(hashtable_utf->header);
+
+ return u;
+ }
+
+ nomatch:
+ u = u->hashlink; /* next element in external chain */
+ }
+
+ /* location in hashtable found, create new utf element */
+
+ u = NEW(utf);
+
+ u->blength = length; /* length in bytes of utfstring */
+ u->hashlink = hashtable_utf->ptr[slot]; /* link in external hashchain */
+ u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
+
+ memcpy(u->text, text, length); /* copy utf-text */
+ u->text[length] = '\0';
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_len += sizeof(utf) + length + 1;
+#endif
+
+ hashtable_utf->ptr[slot] = u; /* insert symbol into table */
+ hashtable_utf->entries++; /* update number of entries */
+
+ if (hashtable_utf->entries > (hashtable_utf->size * 2)) {
+
+ /* reorganization of hashtable, average length of the external
+ chains is approx. 2 */
+
+ hashtable *newhash; /* the new hashtable */
+ u4 i;
+ utf *u;
+ utf *nextu;
+ u4 slot;
+
+ /* create new hashtable, double the size */
+
+ newhash = hashtable_resize(hashtable_utf, hashtable_utf->size * 2);
+
+#if defined(ENABLE_STATISTICS)
+ if (opt_stat)
+ count_utf_len += sizeof(utf*) * hashtable_utf->size;
+#endif
+
+ /* transfer elements to new hashtable */
+
+ for (i = 0; i < hashtable_utf->size; i++) {
+ u = hashtable_utf->ptr[i];
+
+ while (u) {
+ nextu = u->hashlink;
+ slot = utf_hashkey(u->text, u->blength) & (newhash->size - 1);
+
+ u->hashlink = (utf *) newhash->ptr[slot];
+ newhash->ptr[slot] = u;
+
+ /* follow link in external hash chain */
+
+ u = nextu;
+ }
+ }
+
+ /* dispose old table */
+
+ hashtable_free(hashtable_utf);
+
+ hashtable_utf = newhash;
+ }
+
+ LOCK_MONITOR_EXIT(hashtable_utf->header);
+
+ return u;
+}
+
+
+/* utf_new_u2 ******************************************************************
+
+ Make utf symbol from u2 array, if isclassname is true '.' is
+ replaced by '/'.
+
+*******************************************************************************/
+
+utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
+{
+ char *buffer; /* memory buffer for unicode characters */
+ char *pos; /* pointer to current position in buffer */
+ u4 left; /* unicode characters left */
+ u4 buflength; /* utf length in bytes of the u2 array */
+ utf *result; /* resulting utf-string */
+ int i;
+
+ /* determine utf length in bytes and allocate memory */
+
+ buflength = u2_utflength(unicode_pos, unicode_length);
+ buffer = MNEW(char, buflength);
+
+ left = buflength;
+ pos = buffer;
+
+ for (i = 0; i++ < unicode_length; unicode_pos++) {
+ /* next unicode character */
+ u2 c = *unicode_pos;
+
+ if ((c != 0) && (c < 0x80)) {
+ /* 1 character */
+ left--;
+ if ((int) left < 0) break;
+ /* convert classname */
+ if (isclassname && c == '.')
+ *pos++ = '/';
+ else
+ *pos++ = (char) c;
+
+ } else if (c < 0x800) {
+ /* 2 characters */
+ unsigned char high = c >> 6;
+ unsigned char low = c & 0x3F;
+ left = left - 2;
+ if ((int) left < 0) break;
+ *pos++ = high | 0xC0;
+ *pos++ = low | 0x80;
+
+ } else {
+ /* 3 characters */
+ char low = c & 0x3f;
+ char mid = (c >> 6) & 0x3F;
+ char high = c >> 12;
+ left = left - 3;
+ if ((int) left < 0) break;
+ *pos++ = high | 0xE0;
+ *pos++ = mid | 0x80;
+ *pos++ = low | 0x80;
+ }
+ }
+
+ /* insert utf-string into symbol-table */
+ result = utf_new(buffer,buflength);
+
+ MFREE(buffer, char, buflength);
+
+ return result;
+}
+
+
+/* utf_new_char ****************************************************************
+
+ Creates a new utf symbol, the text for this symbol is passed as a
+ c-string ( = char* ).
+
+*******************************************************************************/
+
+utf *utf_new_char(const char *text)
+{
+ return utf_new(text, strlen(text));
+}
+
+
+/* utf_new_char_classname ******************************************************
+
+ Creates a new utf symbol, the text for this symbol is passed as a
+ c-string ( = char* ) "." characters are going to be replaced by
+ "/". Since the above function is used often, this is a separte
+ function, instead of an if.
+
+*******************************************************************************/
+
+utf *utf_new_char_classname(const char *text)
+{
+ if (strchr(text, '.')) {
+ char *txt = strdup(text);
+ char *end = txt + strlen(txt);
+ char *c;
+ utf *tmpRes;
+
+ for (c = txt; c < end; c++)
+ if (*c == '.') *c = '/';
+
+ tmpRes = utf_new(txt, strlen(txt));
+ FREE(txt, 0);
+
+ return tmpRes;
+
+ } else
+ return utf_new(text, strlen(text));
+}
+
+
+/* utf_nextu2 ******************************************************************
+
+ Read the next unicode character from the utf string and increment
+ the utf-string pointer accordingly.
+
+ CAUTION: This function is unsafe for input that was not checked
+ by is_valid_utf!
+
+*******************************************************************************/
+
+u2 utf_nextu2(char **utf_ptr)
+{
+ /* uncompressed unicode character */
+ u2 unicode_char = 0;
+ /* current position in utf text */
+ unsigned char *utf = (unsigned char *) (*utf_ptr);
+ /* bytes representing the unicode character */
+ unsigned char ch1, ch2, ch3;
+ /* number of bytes used to represent the unicode character */
+ int len = 0;
+
+ switch ((ch1 = utf[0]) >> 4) {
+ default: /* 1 byte */
+ (*utf_ptr)++;
+ return (u2) ch1;
+ case 0xC:
+ case 0xD: /* 2 bytes */
+ if (((ch2 = utf[1]) & 0xC0) == 0x80) {
+ unsigned char high = ch1 & 0x1F;
+ unsigned char low = ch2 & 0x3F;
+ unicode_char = (high << 6) + low;
+ len = 2;
+ }
+ break;
+
+ case 0xE: /* 2 or 3 bytes */
+ if (((ch2 = utf[1]) & 0xC0) == 0x80) {
+ if (((ch3 = utf[2]) & 0xC0) == 0x80) {
+ unsigned char low = ch3 & 0x3f;
+ unsigned char mid = ch2 & 0x3f;
+ unsigned char high = ch1 & 0x0f;
+ unicode_char = (((high << 6) + mid) << 6) + low;
+ len = 3;
+ } else
+ len = 2;
+ }
+ break;
+ }
+
+ /* update position in utf-text */
+ *utf_ptr = (char *) (utf + len);
+
+ return unicode_char;
+}
+
+
+/* utf_bytes *******************************************************************
+
+ Determine number of bytes (aka. octets) in the utf string.
+
+ IN:
+ u............utf string
+
+ OUT:
+ The number of octets of this utf string.
+ There is _no_ terminating zero included in this count.
+
+*******************************************************************************/
+
+u4 utf_bytes(utf *u)
+{
+ return u->blength;
+}
+
+
+/* utf_get_number_of_u2s_for_buffer ********************************************
+
+ Determine number of UTF-16 u2s in the given UTF-8 buffer
+
+ CAUTION: This function is unsafe for input that was not checked
+ by is_valid_utf!
+
+ CAUTION: Use this function *only* when you want to convert an UTF-8 buffer
+ to an array of u2s (UTF-16) and want to know how many of them you will get.
+ All other uses of this function are probably wrong.
+
+ IN:
+ buffer........points to first char in buffer
+ blength.......number of _bytes_ in the buffer
+
+ OUT:
+ the number of u2s needed to hold this string in UTF-16 encoding.
+ There is _no_ terminating zero included in this count.
+
+ NOTE: Unlike utf_get_number_of_u2s, this function never throws an
+ exception.
+
+*******************************************************************************/
+
+u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength)
+{
+ const char *endpos; /* points behind utf string */
+ const char *utf_ptr; /* current position in utf text */
+ u4 len = 0; /* number of unicode characters */
+
+ utf_ptr = buffer;
+ endpos = utf_ptr + blength;
+
+ while (utf_ptr < endpos) {
+ len++;
+ /* next unicode character */
+ utf_nextu2((char **)&utf_ptr);
+ }
+
+ assert(utf_ptr == endpos);
+
+ return len;
+}
+
+
+/* utf_get_number_of_u2s *******************************************************
+
+ Determine number of UTF-16 u2s in the utf string.
+
+ CAUTION: This function is unsafe for input that was not checked
+ by is_valid_utf!
+
+ CAUTION: Use this function *only* when you want to convert a utf string
+ to an array of u2s and want to know how many of them you will get.
+ All other uses of this function are probably wrong.
+
+ IN:
+ u............utf string
+
+ OUT:
+ the number of u2s needed to hold this string in UTF-16 encoding.
+ There is _no_ terminating zero included in this count.
+ XXX 0 if a NullPointerException has been thrown (see below)
+
+*******************************************************************************/
+
+u4 utf_get_number_of_u2s(utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u4 len = 0; /* number of unicode characters */
+
+ /* XXX this is probably not checked by most callers! Review this after */
+ /* the invalid uses of this function have been eliminated */
+ if (u == NULL) {
+ exceptions_throw_nullpointerexception();
+ return 0;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ len++;
+ /* next unicode character */
+ utf_nextu2(&utf_ptr);
+ }
+
+ if (utf_ptr != endpos) {
+ /* string ended abruptly */
+ exceptions_throw_internalerror("Illegal utf8 string");
+ return 0;
+ }
+
+ return len;
+}
+
+
+/* utf8_safe_number_of_u2s *****************************************************
+
+ Determine number of UTF-16 u2s needed for decoding the given UTF-8 string.
+ (For invalid UTF-8 the U+fffd replacement character will be counted.)
+
+ This function is safe even for invalid UTF-8 strings.
+
+ IN:
+ text..........zero-terminated(!) UTF-8 string (may be invalid)
+ must NOT be NULL
+ nbytes........strlen(text). (This is needed to completely emulate
+ the RI).
+
+ OUT:
+ the number of u2s needed to hold this string in UTF-16 encoding.
+ There is _no_ terminating zero included in this count.
+
+*******************************************************************************/
+
+s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes) {
+ register const unsigned char *t;
+ register s4 byte;
+ register s4 len;
+ register const unsigned char *tlimit;
+ s4 byte1;
+ s4 byte2;
+ s4 byte3;
+ s4 value;
+ s4 skip;
+
+ assert(text);
+ assert(nbytes >= 0);
+
+ len = 0;
+ t = (const unsigned char *) text;
+ tlimit = t + nbytes;
+
+ /* CAUTION: Keep this code in sync with utf8_safe_convert_to_u2s! */
+
+ while (1) {
+ byte = *t++;
+
+ if (byte & 0x80) {
+ /* highest bit set, non-ASCII character */
+
+ if ((byte & 0xe0) == 0xc0) {
+ /* 2-byte: should be 110..... 10...... ? */
+
+ if ((*t++ & 0xc0) == 0x80)
+ ; /* valid 2-byte */
+ else
+ t--; /* invalid */
+ }
+ else if ((byte & 0xf0) == 0xe0) {
+ /* 3-byte: should be 1110.... 10...... 10...... */
+ /* ^t */
+
+ if (t + 2 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ if ((*t++ & 0xc0) == 0x80) {
+ if ((*t++ & 0xc0) == 0x80)
+ ; /* valid 3-byte */
+ else
+ t--; /* invalid */
+ }
+ else
+ t--; /* invalid */
+ }
+ else if ((byte & 0xf8) == 0xf0) {
+ /* 4-byte: should be 11110... 10...... 10...... 10...... */
+ /* ^t */
+
+ if (t + 3 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ if (((byte2 = *t++) & 0xc0) == 0x80) {
+ if (((byte3 = *t++) & 0xc0) == 0x80) {
+ /* valid 4-byte UTF-8? */
+ value = ((byte & 0x07) << 18)
+ | ((byte1 & 0x3f) << 12)
+ | ((byte2 & 0x3f) << 6)
+ | ((byte3 & 0x3f) );
+
+ if (value > 0x10FFFF)
+ ; /* invalid */
+ else if (value > 0xFFFF)
+ len += 1; /* we need surrogates */
+ else
+ ; /* 16bit suffice */
+ }
+ else
+ t--; /* invalid */
+ }
+ else
+ t--; /* invalid */
+ }
+ else
+ t--; /* invalid */
+ }
+ else if ((byte & 0xfc) == 0xf8) {
+ /* invalid 5-byte */
+ if (t + 4 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ skip = 4;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ }
+ else if ((byte & 0xfe) == 0xfc) {
+ /* invalid 6-byte */
+ if (t + 5 > tlimit)
+ return len + 1; /* invalid, stop here */
+
+ skip = 5;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ }
+ else
+ ; /* invalid */
+ }
+ else {
+ /* NUL */
+
+ if (byte == 0)
+ break;
+
+ /* ASCII character, common case */
+ }
+
+ len++;
+ }
+
+ return len;
+}
+
+
+/* utf8_safe_convert_to_u2s ****************************************************
+
+ Convert the given UTF-8 string to UTF-16 into a pre-allocated buffer.
+ (Invalid UTF-8 will be replaced with the U+fffd replacement character.)
+ Use utf8_safe_number_of_u2s to determine the number of u2s to allocate.
+
+ This function is safe even for invalid UTF-8 strings.
+
+ IN:
+ text..........zero-terminated(!) UTF-8 string (may be invalid)
+ must NOT be NULL
+ nbytes........strlen(text). (This is needed to completely emulate
+ the RI).
+ buffer........a preallocated array of u2s to receive the decoded
+ string. Use utf8_safe_number_of_u2s to get the
+ required number of u2s for allocating this.
+
+*******************************************************************************/
+
+#define UNICODE_REPLACEMENT 0xfffd
+
+void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer) {
+ register const unsigned char *t;
+ register s4 byte;
+ register const unsigned char *tlimit;
+ s4 byte1;
+ s4 byte2;
+ s4 byte3;
+ s4 value;
+ s4 skip;
+
+ assert(text);
+ assert(nbytes >= 0);
+
+ t = (const unsigned char *) text;
+ tlimit = t + nbytes;
+
+ /* CAUTION: Keep this code in sync with utf8_safe_number_of_u2s! */
+
+ while (1) {
+ byte = *t++;
+
+ if (byte & 0x80) {
+ /* highest bit set, non-ASCII character */
+
+ if ((byte & 0xe0) == 0xc0) {
+ /* 2-byte: should be 110..... 10...... */
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ /* valid 2-byte UTF-8 */
+ *buffer++ = ((byte & 0x1f) << 6)
+ | ((byte1 & 0x3f) );
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else if ((byte & 0xf0) == 0xe0) {
+ /* 3-byte: should be 1110.... 10...... 10...... */
+
+ if (t + 2 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ if (((byte2 = *t++) & 0xc0) == 0x80) {
+ /* valid 3-byte UTF-8 */
+ *buffer++ = ((byte & 0x0f) << 12)
+ | ((byte1 & 0x3f) << 6)
+ | ((byte2 & 0x3f) );
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else if ((byte & 0xf8) == 0xf0) {
+ /* 4-byte: should be 11110... 10...... 10...... 10...... */
+
+ if (t + 3 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ if (((byte1 = *t++) & 0xc0) == 0x80) {
+ if (((byte2 = *t++) & 0xc0) == 0x80) {
+ if (((byte3 = *t++) & 0xc0) == 0x80) {
+ /* valid 4-byte UTF-8? */
+ value = ((byte & 0x07) << 18)
+ | ((byte1 & 0x3f) << 12)
+ | ((byte2 & 0x3f) << 6)
+ | ((byte3 & 0x3f) );
+
+ if (value > 0x10FFFF) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else if (value > 0xFFFF) {
+ /* we need surrogates */
+ *buffer++ = 0xd800 | ((value >> 10) - 0x40);
+ *buffer++ = 0xdc00 | (value & 0x03ff);
+ }
+ else
+ *buffer++ = value; /* 16bit suffice */
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else {
+ *buffer++ = UNICODE_REPLACEMENT;
+ t--;
+ }
+ }
+ else if ((byte & 0xfc) == 0xf8) {
+ if (t + 4 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ skip = 4;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else if ((byte & 0xfe) == 0xfc) {
+ if (t + 5 > tlimit) {
+ *buffer++ = UNICODE_REPLACEMENT;
+ return;
+ }
+
+ skip = 5;
+ for (; skip && ((*t & 0xc0) == 0x80); --skip)
+ t++;
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else
+ *buffer++ = UNICODE_REPLACEMENT;
+ }
+ else {
+ /* NUL */
+
+ if (byte == 0)
+ break;
+
+ /* ASCII character, common case */
+
+ *buffer++ = byte;
+ }
+ }
+}
+
+
+/* u2_utflength ****************************************************************
+
+ Returns the utf length in bytes of a u2 array.
+
+*******************************************************************************/
+
+u4 u2_utflength(u2 *text, u4 u2_length)
+{
+ u4 result_len = 0; /* utf length in bytes */
+ u2 ch; /* current unicode character */
+ u4 len;
+
+ for (len = 0; len < u2_length; len++) {
+ /* next unicode character */
+ ch = *text++;
+
+ /* determine bytes required to store unicode character as utf */
+ if (ch && (ch < 0x80))
+ result_len++;
+ else if (ch < 0x800)
+ result_len += 2;
+ else
+ result_len += 3;
+ }
+
+ return result_len;
+}
+
+
+/* utf_copy ********************************************************************
+
+ Copy the given utf string byte-for-byte to a buffer.
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_copy(char *buffer, utf *u)
+{
+ /* our utf strings are zero-terminated (done by utf_new) */
+ MCOPY(buffer, u->text, char, u->blength + 1);
+}
+
+
+/* utf_cat *********************************************************************
+
+ Append the given utf string byte-for-byte to a buffer.
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_cat(char *buffer, utf *u)
+{
+ /* our utf strings are zero-terminated (done by utf_new) */
+ MCOPY(buffer + strlen(buffer), u->text, char, u->blength + 1);
+}
+
+
+/* utf_copy_classname **********************************************************
+
+ Copy the given utf classname byte-for-byte to a buffer.
+ '/' is replaced by '.'
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_copy_classname(char *buffer, utf *u)
+{
+ char *bufptr;
+ char *srcptr;
+ char *endptr;
+ char ch;
+
+ bufptr = buffer;
+ srcptr = u->text;
+ endptr = UTF_END(u) + 1; /* utfs are zero-terminared by utf_new */
+
+ while (srcptr != endptr) {
+ ch = *srcptr++;
+ if (ch == '/')
+ ch = '.';
+ *bufptr++ = ch;
+ }
+}
+
+
+/* utf_cat *********************************************************************
+
+ Append the given utf classname byte-for-byte to a buffer.
+ '/' is replaced by '.'
+
+ IN:
+ buffer.......the buffer
+ u............the utf string
+
+*******************************************************************************/
+
+void utf_cat_classname(char *buffer, utf *u)
+{
+ utf_copy_classname(buffer + strlen(buffer), u);
+}
+
+/* utf_display_printable_ascii *************************************************
+
+ Write utf symbol to stdout (for debugging purposes).
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_display_printable_ascii(utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (u == NULL) {
+ printf("NULL");
+ fflush(stdout);
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+
+ u2 c = utf_nextu2(&utf_ptr);
+
+ if ((c >= 32) && (c <= 127))
+ printf("%c", c);
+ else
+ printf("?");
+ }
+
+ fflush(stdout);
+}
+
+
+/* utf_display_printable_ascii_classname ***************************************
+
+ Write utf symbol to stdout with `/' converted to `.' (for debugging
+ purposes).
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_display_printable_ascii_classname(utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (u == NULL) {
+ printf("NULL");
+ fflush(stdout);
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+
+ u2 c = utf_nextu2(&utf_ptr);
+
+ if (c == '/')
+ c = '.';
+
+ if ((c >= 32) && (c <= 127))
+ printf("%c", c);
+ else
+ printf("?");
+ }
+
+ fflush(stdout);
+}
+
+
+/* utf_sprint_convert_to_latin1 ************************************************
+
+ Write utf symbol into c-string (for debugging purposes).
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_sprint_convert_to_latin1(char *buffer, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u2 pos = 0; /* position in c-string */
+
+ if (!u) {
+ strcpy(buffer, "NULL");
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos)
+ /* copy next unicode character */
+ buffer[pos++] = utf_nextu2(&utf_ptr);
+
+ /* terminate string */
+ buffer[pos] = '\0';
+}
+
+
+/* utf_sprint_convert_to_latin1_classname **************************************
+
+ Write utf symbol into c-string with `/' converted to `.' (for debugging
+ purposes).
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+ u2 pos = 0; /* position in c-string */
+
+ if (!u) {
+ strcpy(buffer, "NULL");
+ return;
+ }
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* copy next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+ if (c == '/') c = '.';
+ buffer[pos++] = c;
+ }
+
+ /* terminate string */
+ buffer[pos] = '\0';
+}
+
+
+/* utf_strcat_convert_to_latin1 ************************************************
+
+ Like libc strcat, but uses an utf8 string.
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_strcat_convert_to_latin1(char *buffer, utf *u)
+{
+ utf_sprint_convert_to_latin1(buffer + strlen(buffer), u);
+}
+
+
+/* utf_strcat_convert_to_latin1_classname **************************************
+
+ Like libc strcat, but uses an utf8 string.
+ Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
+ invalid results.
+
+*******************************************************************************/
+
+void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u)
+{
+ utf_sprint_convert_to_latin1_classname(buffer + strlen(buffer), u);
+}
+
+
+/* utf_fprint_printable_ascii **************************************************
+
+ Write utf symbol into file.
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_fprint_printable_ascii(FILE *file, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (!u)
+ return;
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+
+ if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+ else fprintf(file, "?");
+ }
+}
+
+
+/* utf_fprint_printable_ascii_classname ****************************************
+
+ Write utf symbol into file with `/' converted to `.'.
+ Non-printable and non-ASCII characters are printed as '?'.
+
+*******************************************************************************/
+
+void utf_fprint_printable_ascii_classname(FILE *file, utf *u)
+{
+ char *endpos; /* points behind utf string */
+ char *utf_ptr; /* current position in utf text */
+
+ if (!u)
+ return;
+
+ endpos = UTF_END(u);
+ utf_ptr = u->text;
+
+ while (utf_ptr < endpos) {
+ /* read next unicode character */
+ u2 c = utf_nextu2(&utf_ptr);
+ if (c == '/') c = '.';
+
+ if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+ else fprintf(file, "?");
+ }
+}
+
+
+/* is_valid_utf ****************************************************************
+
+ Return true if the given string is a valid UTF-8 string.
+
+ utf_ptr...points to first character
+ end_pos...points after last character
+
+*******************************************************************************/
+
+/* static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26}; */
+
+bool is_valid_utf(char *utf_ptr, char *end_pos)
+{
+ int bytes;
+ int len,i;
+ char c;
+ unsigned long v;
+
+ if (end_pos < utf_ptr) return false;
+ bytes = end_pos - utf_ptr;
+ while (bytes--) {
+ c = *utf_ptr++;
+
+ if (!c) return false; /* 0x00 is not allowed */
+ if ((c & 0x80) == 0) continue; /* ASCII */
+
+ if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
+ else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
+ else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
+ else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
+ else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
+ else return false; /* invalid leading byte */
+
+ if (len > 2) return false; /* Java limitation */
+
+ v = (unsigned long)c & (0x3f >> len);
+
+ if ((bytes -= len) < 0) return false; /* missing bytes */
+
+ for (i = len; i--; ) {
+ c = *utf_ptr++;
+ if ((c & 0xc0) != 0x80) /* 10xx xxxx */
+ return false;
+ v = (v << 6) | (c & 0x3f);
+ }
+
+ if (v == 0) {
+ if (len != 1) return false; /* Java special */
+
+ } else {
+ /* Sun Java seems to allow overlong UTF-8 encodings */
+
+ /* if (v < min_codepoint[len]) */
+ /* XXX throw exception? */
+ }
+
+ /* surrogates in UTF-8 seem to be allowed in Java classfiles */
+ /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
+
+ /* even these seem to be allowed */
+ /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
+ }
+
+ return true;
+}
+
+
+/* is_valid_name ***************************************************************
+
+ Return true if the given string may be used as a class/field/method
+ name. (Currently this only disallows empty strings and control
+ characters.)
+
+ NOTE: The string is assumed to have passed is_valid_utf!
+
+ utf_ptr...points to first character
+ end_pos...points after last character
+
+*******************************************************************************/
+
+bool is_valid_name(char *utf_ptr, char *end_pos)
+{
+ if (end_pos <= utf_ptr) return false; /* disallow empty names */
+
+ while (utf_ptr < end_pos) {
+ unsigned char c = *utf_ptr++;
+
+ if (c < 0x20) return false; /* disallow control characters */
+ if (c == 0xc0 && (unsigned char) *utf_ptr == 0x80) /* disallow zero */
+ return false;
+ }
+
+ return true;
+}
+
+bool is_valid_name_utf(utf *u)
+{
+ return is_valid_name(u->text, UTF_END(u));
+}
+
+
+/* utf_show ********************************************************************
+
+ Writes the utf symbols in the utfhash to stdout and displays the
+ number of external hash chains grouped according to the chainlength
+ (for debugging purposes).
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+void utf_show(void)
+{
+
+#define CHAIN_LIMIT 20 /* limit for seperated enumeration */
+
+ u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
+ u4 max_chainlength = 0; /* maximum length of the chains */
+ u4 sum_chainlength = 0; /* sum of the chainlengths */
+ u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
+ u4 i;
+
+ printf("UTF-HASH:\n");
+
+ /* show element of utf-hashtable */
+
+ for (i = 0; i < hashtable_utf->size; i++) {
+ utf *u = hashtable_utf->ptr[i];
+
+ if (u) {
+ printf("SLOT %d: ", (int) i);
+
+ while (u) {
+ printf("'");
+ utf_display_printable_ascii(u);
+ printf("' ");
+ u = u->hashlink;
+ }
+ printf("\n");
+ }
+ }
+
+ printf("UTF-HASH: %d slots for %d entries\n",
+ (int) hashtable_utf->size, (int) hashtable_utf->entries );
+
+ if (hashtable_utf->entries == 0)
+ return;
+
+ printf("chains:\n chainlength number of chains %% of utfstrings\n");
+
+ for (i=0;i<CHAIN_LIMIT;i++)
+ chain_count[i]=0;
+
+ /* count numbers of hashchains according to their length */
+ for (i=0; i<hashtable_utf->size; i++) {
+
+ utf *u = (utf*) hashtable_utf->ptr[i];
+ u4 chain_length = 0;
+
+ /* determine chainlength */
+ while (u) {
+ u = u->hashlink;
+ chain_length++;
+ }
+
+ /* update sum of all chainlengths */
+ sum_chainlength+=chain_length;
+
+ /* determine the maximum length of the chains */
+ if (chain_length>max_chainlength)
+ max_chainlength = chain_length;
+
+ /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
+ if (chain_length>=CHAIN_LIMIT) {
+ beyond_limit+=chain_length;
+ chain_length=CHAIN_LIMIT-1;
+ }
+
+ /* update number of hashchains of current length */
+ chain_count[chain_length]++;
+ }
+
+ /* display results */
+ for (i=1;i<CHAIN_LIMIT-1;i++)
+ printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/hashtable_utf->entries));
+
+ printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/hashtable_utf->entries);
+
+
+ printf("max. chainlength:%5d\n",max_chainlength);
+
+ /* avg. chainlength = sum of chainlengths / number of chains */
+ printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (hashtable_utf->size-chain_count[0]));
+}
+#endif /* !defined(NDEBUG) */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/utf8.h - utf8 string functions
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _UTF_H
+#define _UTF_H
+
+/* forward typedefs ***********************************************************/
+
+typedef struct utf utf;
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+
+/* data structure for utf8 symbols ********************************************/
+
+struct utf {
+ utf *hashlink; /* link for external hash chain */
+ s4 blength; /* text length in bytes */
+ char *text; /* pointer to text */
+};
+
+/* to determine the end of utf strings */
+
+#define UTF_END(u) ((char *) u->text + u->blength)
+
+
+/* utf-symbols for pointer comparison of frequently used strings **************/
+
+extern utf *utf_java_lang_Object;
+
+extern utf *utf_java_lang_Class;
+extern utf *utf_java_lang_ClassLoader;
+extern utf *utf_java_lang_Cloneable;
+extern utf *utf_java_lang_SecurityManager;
+extern utf *utf_java_lang_String;
+extern utf *utf_java_lang_ThreadGroup;
+extern utf *utf_java_lang_ref_SoftReference;
+extern utf *utf_java_lang_ref_WeakReference;
+extern utf *utf_java_lang_ref_PhantomReference;
+extern utf *utf_java_io_Serializable;
+
+extern utf *utf_java_lang_Throwable;
+extern utf *utf_java_lang_Error;
+
+extern utf *utf_java_lang_AbstractMethodError;
+extern utf *utf_java_lang_ClassCircularityError;
+extern utf *utf_java_lang_ClassFormatError;
+extern utf *utf_java_lang_ExceptionInInitializerError;
+extern utf *utf_java_lang_IncompatibleClassChangeError;
+extern utf *utf_java_lang_InstantiationError;
+extern utf *utf_java_lang_InternalError;
+extern utf *utf_java_lang_LinkageError;
+extern utf *utf_java_lang_NoClassDefFoundError;
+extern utf *utf_java_lang_NoSuchFieldError;
+extern utf *utf_java_lang_NoSuchMethodError;
+extern utf *utf_java_lang_OutOfMemoryError;
+extern utf *utf_java_lang_UnsatisfiedLinkError;
+extern utf *utf_java_lang_UnsupportedClassVersionError;
+extern utf *utf_java_lang_VerifyError;
+extern utf *utf_java_lang_VirtualMachineError;
+
+extern utf *utf_java_lang_Exception;
+
+extern utf *utf_java_lang_ArithmeticException;
+extern utf *utf_java_lang_ArrayIndexOutOfBoundsException;
+extern utf *utf_java_lang_ArrayStoreException;
+extern utf *utf_java_lang_ClassCastException;
+extern utf *utf_java_lang_ClassNotFoundException;
+extern utf *utf_java_lang_CloneNotSupportedException;
+extern utf *utf_java_lang_IllegalAccessException;
+extern utf *utf_java_lang_IllegalArgumentException;
+extern utf *utf_java_lang_IllegalMonitorStateException;
+extern utf *utf_java_lang_InstantiationException;
+extern utf *utf_java_lang_InterruptedException;
+extern utf *utf_java_lang_NegativeArraySizeException;
+extern utf *utf_java_lang_NullPointerException;
+extern utf *utf_java_lang_RuntimeException;
+extern utf *utf_java_lang_StringIndexOutOfBoundsException;
+
+extern utf *utf_java_lang_reflect_InvocationTargetException;
+
+extern utf *utf_java_security_PrivilegedActionException;
+
+#if defined(ENABLE_JAVASE)
+extern utf* utf_java_lang_Void;
+#endif
+
+extern utf* utf_java_lang_Boolean;
+extern utf* utf_java_lang_Byte;
+extern utf* utf_java_lang_Character;
+extern utf* utf_java_lang_Short;
+extern utf* utf_java_lang_Integer;
+extern utf* utf_java_lang_Long;
+extern utf* utf_java_lang_Float;
+extern utf* utf_java_lang_Double;
+
+#if defined(ENABLE_JAVASE)
+extern utf *utf_java_lang_StackTraceElement;
+extern utf *utf_java_lang_reflect_Constructor;
+extern utf *utf_java_lang_reflect_Field;
+extern utf *utf_java_lang_reflect_Method;
+
+# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
+extern utf *utf_java_lang_reflect_VMConstructor;
+extern utf *utf_java_lang_reflect_VMField;
+extern utf *utf_java_lang_reflect_VMMethod;
+# endif
+
+extern utf *utf_java_util_Vector;
+#endif
+
+extern utf *utf_InnerClasses;
+extern utf *utf_ConstantValue;
+extern utf *utf_Code;
+extern utf *utf_Exceptions;
+extern utf *utf_LineNumberTable;
+extern utf *utf_SourceFile;
+
+#if defined(ENABLE_JAVASE)
+extern utf *utf_EnclosingMethod;
+extern utf *utf_Signature;
+extern utf *utf_StackMapTable;
+
+#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
+
+extern utf *utf_init;
+extern utf *utf_clinit;
+extern utf *utf_clone;
+extern utf *utf_finalize;
+extern utf *utf_invoke;
+extern utf *utf_main;
+extern utf *utf_run;
+
+extern utf *utf_add;
+extern utf *utf_dispatch;
+extern utf *utf_remove;
+extern utf *utf_addThread;
+extern utf *utf_removeThread;
+extern utf *utf_put;
+extern utf *utf_get;
+extern utf *utf_uncaughtException;
+extern utf *utf_value;
+
+extern utf *utf_fillInStackTrace;
+extern utf *utf_findNative;
+extern utf *utf_getSystemClassLoader;
+extern utf *utf_initCause;
+extern utf *utf_loadClass;
+extern utf *utf_loadClassInternal;
+extern utf *utf_printStackTrace;
+
+extern utf *utf_division_by_zero;
+
+extern utf *utf_Z;
+extern utf *utf_B;
+extern utf *utf_C;
+extern utf *utf_S;
+extern utf *utf_I;
+extern utf *utf_J;
+extern utf *utf_F;
+extern utf *utf_D;
+
+extern utf *utf_void__void;
+extern utf *utf_boolean__void;
+extern utf *utf_byte__void;
+extern utf *utf_char__void;
+extern utf *utf_short__void;
+extern utf *utf_int__void;
+extern utf *utf_long__void;
+extern utf *utf_float__void;
+extern utf *utf_double__void;
+
+extern utf *utf_void__java_lang_ClassLoader;
+extern utf *utf_void__java_lang_Object;
+extern utf *utf_void__java_lang_Throwable;
+extern utf *utf_java_lang_ClassLoader_java_lang_String__J;
+extern utf *utf_java_lang_Exception__V;
+extern utf *utf_java_lang_Object__java_lang_Object;
+extern utf *utf_java_lang_String__void;
+extern utf *utf_java_lang_String__java_lang_Class;
+extern utf *utf_java_lang_Thread__V;
+extern utf *utf_java_lang_Thread_java_lang_Throwable__V;
+extern utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
+extern utf *utf_java_lang_Throwable__void;
+extern utf *utf_java_lang_Throwable__java_lang_Throwable;
+
+extern utf *utf_not_named_yet;
+extern utf *utf_null;
+extern utf *array_packagename;
+
+
+/* function prototypes ********************************************************/
+
+/* initialize the utf8 subsystem */
+void utf8_init(void);
+
+u4 utf_hashkey(const char *text, u4 length);
+u4 utf_full_hashkey(const char *text, u4 length);
+
+/* determine hashkey of a unicode-symbol */
+u4 unicode_hashkey(u2 *text, u2 length);
+
+/* create new utf-symbol */
+utf *utf_new(const char *text, u2 length);
+
+/* make utf symbol from u2 array */
+utf *utf_new_u2(u2 *unicodedata, u4 unicodelength, bool isclassname);
+
+utf *utf_new_char(const char *text);
+utf *utf_new_char_classname(const char *text);
+
+/* get number of bytes */
+u4 utf_bytes(utf *u);
+
+/* get next unicode character of a utf-string */
+u2 utf_nextu2(char **utf);
+
+/* get (number of) unicode characters of a utf string (safe) */
+s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes);
+void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer);
+
+/* get (number of) unicode characters of a utf string (UNSAFE!) */
+u4 utf_get_number_of_u2s(utf *u);
+u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength);
+
+/* determine utf length in bytes of a u2 array */
+u4 u2_utflength(u2 *text, u4 u2_length);
+
+void utf_copy(char *buffer, utf *u);
+void utf_cat(char *buffer, utf *u);
+void utf_copy_classname(char *buffer, utf *u);
+void utf_cat_classname(char *buffer, utf *u);
+
+/* write utf symbol to file/buffer */
+void utf_display_printable_ascii(utf *u);
+void utf_display_printable_ascii_classname(utf *u);
+
+void utf_sprint_convert_to_latin1(char *buffer, utf *u);
+void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u);
+
+void utf_strcat_convert_to_latin1(char *buffer, utf *u);
+void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u);
+
+void utf_fprint_printable_ascii(FILE *file, utf *u);
+void utf_fprint_printable_ascii_classname(FILE *file, utf *u);
+
+/* check if a UTF-8 string is valid */
+bool is_valid_utf(char *utf_ptr, char *end_pos);
+
+/* check if a UTF-8 string may be used as a class/field/method name */
+bool is_valid_name(char *utf_ptr, char *end_pos);
+bool is_valid_name_utf(utf *u);
+
+/* show utf-table */
+void utf_show(void);
+
+#endif /* _UTF_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
#endif
#include "vm/builtin.h"
+#include "vm/classcache.h"
#include "vm/exceptions.hpp"
#include "vm/finalizer.h"
#include "vm/global.h"
+#include "vm/globals.hpp"
#include "vm/initialize.h"
+#include "vm/options.h"
+#include "vm/os.hpp"
#include "vm/package.hpp"
#include "vm/primitive.hpp"
#include "vm/properties.h"
#include "vm/signallocal.h"
+#include "vm/statistics.h"
#include "vm/string.hpp"
+#include "vm/suck.h"
#include "vm/vm.hpp"
#include "vm/jit/argument.h"
#include "vm/jit/trap.h"
-#include "vmcore/classcache.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-#include "vmcore/suck.h"
-#include "vmcore/os.hpp"
-
#if defined(ENABLE_JVMTI)
# include "native/jvmti/cacaodbg.h"
#endif
/* We need to check if the actual size of a java.lang.Class object
is smaller or equal than the assumption made in
- src/vmcore/class.h. */
+ src/vm/class.h. */
#warning FIXME We need to check the size of java.lang.Class!!!
// if (sizeof(java_lang_Class) > sizeof(dummy_java_lang_Class))
#include "vm/global.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
+#include "vm/class.h"
+#include "vm/method.h"
#ifdef __cplusplus
--- /dev/null
+/* src/vm/zip.c - ZIP file handling for bootstrap classloader
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#include "config.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <zlib.h>
+#include <sys/mman.h>
+
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "mm/memory.h"
+
+#include "vm/global.h"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+#include "vm/vm.hpp"
+#include "vm/zip.h"
+
+
+/* start size for classes hashtable *******************************************/
+
+#define HASHTABLE_CLASSES_SIZE (1 << 10)
+
+
+/* info taken from:
+ http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
+*/
+
+/* all signatures in the ZIP file have a length of 4 bytes ********************/
+
+#define SIGNATURE_LENGTH 4
+
+/* Central directory structure *************************************************
+
+ [file header 1]
+ .
+ .
+ .
+ [file header n]
+ [digital signature]
+
+ File header:
+
+ central file header signature 4 bytes (0x02014b50)
+ version made by 2 bytes
+ version needed to extract 2 bytes
+ general purpose bit flag 2 bytes
+ compression method 2 bytes
+ last mod file time 2 bytes
+ last mod file date 2 bytes
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+ file name length 2 bytes
+ extra field length 2 bytes
+ file comment length 2 bytes
+ disk number start 2 bytes
+ internal file attributes 2 bytes
+ external file attributes 4 bytes
+ relative offset of local header 4 bytes
+
+ file name (variable size)
+ extra field (variable size)
+ file comment (variable size)
+
+ Digital signature:
+
+ header signature 4 bytes (0x05054b50)
+ size of data 2 bytes
+ signature data (variable size)
+
+*******************************************************************************/
+
+#define CDSFH_HEADER_SIZE 46
+
+#define CDSFH_SIGNATURE 0x02014b50
+#define CDSFH_COMPRESSION_METHOD 10
+#define CDSFH_COMPRESSED_SIZE 20
+#define CDSFH_UNCOMPRESSED_SIZE 24
+#define CDSFH_FILE_NAME_LENGTH 28
+#define CDSFH_EXTRA_FIELD_LENGTH 30
+#define CDSFH_FILE_COMMENT_LENGTH 32
+#define CDSFH_RELATIVE_OFFSET 42
+#define CDSFH_FILENAME 46
+
+typedef struct cdsfh cdsfh;
+
+struct cdsfh {
+ u2 compressionmethod;
+ u4 compressedsize;
+ u4 uncompressedsize;
+ u2 filenamelength;
+ u2 extrafieldlength;
+ u2 filecommentlength;
+ u4 relativeoffset;
+};
+
+
+/* End of central directory record *********************************************
+
+ end of central dir signature 4 bytes (0x06054b50)
+ number of this disk 2 bytes
+ number of the disk with the
+ start of the central directory 2 bytes
+ total number of entries in the
+ central directory on this disk 2 bytes
+ total number of entries in
+ the central directory 2 bytes
+ size of the central directory 4 bytes
+ offset of start of central
+ directory with respect to
+ the starting disk number 4 bytes
+ .ZIP file comment length 2 bytes
+ .ZIP file comment (variable size)
+
+*******************************************************************************/
+
+#define EOCDR_SIGNATURE 0x06054b50
+#define EOCDR_ENTRIES 10
+#define EOCDR_OFFSET 16
+
+typedef struct eocdr eocdr;
+
+struct eocdr {
+ u2 entries;
+ u4 offset;
+};
+
+
+/* zip_open ********************************************************************
+
+ XXX
+
+*******************************************************************************/
+
+hashtable *zip_open(char *path)
+{
+ hashtable *ht;
+ hashtable_zipfile_entry *htzfe;
+ int fd;
+ u1 lfh_signature[SIGNATURE_LENGTH];
+ off_t len;
+ u1 *filep;
+ s4 i;
+ u1 *p;
+ eocdr eocdr;
+ cdsfh cdsfh;
+ const char *filename;
+ const char *classext;
+ utf *u;
+ u4 key; /* hashkey computed from utf-text */
+ u4 slot; /* slot in hashtable */
+
+ /* first of all, open the file */
+
+ if ((fd = open(path, O_RDONLY)) == -1)
+ return NULL;
+
+ /* check for signature in first local file header */
+
+ if (read(fd, lfh_signature, SIGNATURE_LENGTH) != SIGNATURE_LENGTH)
+ return NULL;
+
+ if (SUCK_LE_U4(lfh_signature) != LFH_SIGNATURE)
+ return NULL;
+
+ /* get the file length */
+
+ if ((len = lseek(fd, 0, SEEK_END)) == -1)
+ return NULL;
+
+ /* we better mmap the file */
+
+ filep = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
+
+ /* some older compilers, like DEC OSF cc, don't like comparisons
+ on void* types */
+
+ if ((ptrint) filep == (ptrint) MAP_FAILED)
+ return NULL;
+
+ /* find end of central directory record */
+
+ for (p = filep + len; p >= filep; p--)
+ if (SUCK_LE_U4(p) == EOCDR_SIGNATURE)
+ break;
+
+ /* get number of entries in central directory */
+
+ eocdr.entries = SUCK_LE_U2(p + EOCDR_ENTRIES);
+ eocdr.offset = SUCK_LE_U4(p + EOCDR_OFFSET);
+
+ /* create hashtable for filenames */
+
+ ht = NEW(hashtable);
+
+ hashtable_create(ht, HASHTABLE_CLASSES_SIZE);
+
+ /* add all file entries into the hashtable */
+
+ for (i = 0, p = filep + eocdr.offset; i < eocdr.entries; i++) {
+ /* check file header signature */
+
+ if (SUCK_LE_U4(p) != CDSFH_SIGNATURE)
+ return NULL;
+
+ /* we found an entry */
+
+ cdsfh.compressionmethod = SUCK_LE_U2(p + CDSFH_COMPRESSION_METHOD);
+ cdsfh.compressedsize = SUCK_LE_U4(p + CDSFH_COMPRESSED_SIZE);
+ cdsfh.uncompressedsize = SUCK_LE_U4(p + CDSFH_UNCOMPRESSED_SIZE);
+ cdsfh.filenamelength = SUCK_LE_U2(p + CDSFH_FILE_NAME_LENGTH);
+ cdsfh.extrafieldlength = SUCK_LE_U2(p + CDSFH_EXTRA_FIELD_LENGTH);
+ cdsfh.filecommentlength = SUCK_LE_U2(p + CDSFH_FILE_COMMENT_LENGTH);
+ cdsfh.relativeoffset = SUCK_LE_U4(p + CDSFH_RELATIVE_OFFSET);
+
+ /* create utf8 string of filename, strip .class from classes */
+
+ filename = (const char *) (p + CDSFH_FILENAME);
+ classext = filename + cdsfh.filenamelength - strlen(".class");
+
+ /* skip directory entries */
+
+ if (filename[cdsfh.filenamelength - 1] != '/') {
+ if (strncmp(classext, ".class", strlen(".class")) == 0)
+ u = utf_new(filename, cdsfh.filenamelength - strlen(".class"));
+ else
+ u = utf_new(filename, cdsfh.filenamelength);
+
+ /* insert class into hashtable */
+
+ htzfe = NEW(hashtable_zipfile_entry);
+
+ htzfe->filename = u;
+ htzfe->compressionmethod = cdsfh.compressionmethod;
+ htzfe->compressedsize = cdsfh.compressedsize;
+ htzfe->uncompressedsize = cdsfh.uncompressedsize;
+ htzfe->data = filep + cdsfh.relativeoffset;
+
+ /* get hashtable slot */
+
+ key = utf_hashkey(u->text, u->blength);
+ slot = key & (ht->size - 1);
+
+ /* insert into external chain */
+
+ htzfe->hashlink = ht->ptr[slot];
+
+ /* insert hashtable zipfile entry */
+
+ ht->ptr[slot] = htzfe;
+ ht->entries++;
+ }
+
+ /* move to next central directory structure file header */
+
+ p = p +
+ CDSFH_HEADER_SIZE +
+ cdsfh.filenamelength +
+ cdsfh.extrafieldlength +
+ cdsfh.filecommentlength;
+ }
+
+ /* return pointer to hashtable */
+
+ return ht;
+}
+
+
+/* zip_find ********************************************************************
+
+ Search for the given filename in the classpath entries of a zip file.
+
+ NOTE: The '.class' extension is stripped when reading a zip file, so if
+ you want to find a .class file, you must search for its name _without_
+ the '.class' extension.
+ XXX I dont like that, it makes foo and foo.class ambiguous. -Edwin
+
+ IN:
+ lce..........the classpath entries for the zip file
+ u............the filename to look for
+
+ RETURN VALUE:
+ hashtable_zipfile_entry * of the entry if found, or
+ NULL if not found
+
+*******************************************************************************/
+
+hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u)
+{
+ hashtable *ht;
+ u4 key; /* hashkey computed from utf-text */
+ u4 slot; /* slot in hashtable */
+ hashtable_zipfile_entry *htzfe; /* hashtable element */
+
+ /* get classes hashtable from the classpath entry */
+
+ ht = lce->htclasses;
+
+ /* get the hashtable slot of the name searched */
+
+ key = utf_hashkey(u->text, u->blength);
+ slot = key & (ht->size - 1);
+ htzfe = ht->ptr[slot];
+
+ /* search external hash chain for utf-symbol */
+
+ while (htzfe) {
+ if (htzfe->filename == u)
+ return htzfe;
+
+ /* next element in external chain */
+
+ htzfe = htzfe->hashlink;
+ }
+
+ /* file not found in this archive */
+
+ return NULL;
+}
+
+
+/* zip_get ********************************************************************
+
+ XXX
+
+*******************************************************************************/
+
+classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
+{
+ hashtable_zipfile_entry *htzfe;
+ lfh lfh;
+ u1 *indata;
+ u1 *outdata;
+ z_stream zs;
+ int err;
+ classbuffer *cb;
+
+ /* try to find the class in the current archive */
+
+ htzfe = zip_find(lce, c->name);
+
+ if (htzfe == NULL)
+ return NULL;
+
+ /* read stuff from local file header */
+
+ lfh.filenamelength = SUCK_LE_U2(htzfe->data + LFH_FILE_NAME_LENGTH);
+ lfh.extrafieldlength = SUCK_LE_U2(htzfe->data + LFH_EXTRA_FIELD_LENGTH);
+
+ indata = htzfe->data +
+ LFH_HEADER_SIZE +
+ lfh.filenamelength +
+ lfh.extrafieldlength;
+
+ /* allocate buffer for uncompressed data */
+
+ outdata = MNEW(u1, htzfe->uncompressedsize);
+
+ /* how is the file stored? */
+
+ switch (htzfe->compressionmethod) {
+ case Z_DEFLATED:
+ /* fill z_stream structure */
+
+ zs.next_in = indata;
+ zs.avail_in = htzfe->compressedsize;
+ zs.next_out = outdata;
+ zs.avail_out = htzfe->uncompressedsize;
+
+ zs.zalloc = Z_NULL;
+ zs.zfree = Z_NULL;
+ zs.opaque = Z_NULL;
+
+ /* initialize this inflate run */
+
+ if (inflateInit2(&zs, -MAX_WBITS) != Z_OK)
+ vm_abort("zip_get: inflateInit2 failed: %s", strerror(errno));
+
+ /* decompress the file into buffer */
+
+ err = inflate(&zs, Z_SYNC_FLUSH);
+
+ if ((err != Z_STREAM_END) && (err != Z_OK))
+ vm_abort("zip_get: inflate failed: %s", strerror(errno));
+
+ /* finish this inflate run */
+
+ if (inflateEnd(&zs) != Z_OK)
+ vm_abort("zip_get: inflateEnd failed: %s", strerror(errno));
+ break;
+
+ case 0:
+ /* uncompressed file, just copy the data */
+ MCOPY(outdata, indata, u1, htzfe->compressedsize);
+ break;
+
+ default:
+ vm_abort("zip_get: unknown compression method %d",
+ htzfe->compressionmethod);
+ }
+
+ /* allocate classbuffer */
+
+ cb = NEW(classbuffer);
+
+ cb->clazz = c;
+ cb->size = htzfe->uncompressedsize;
+ cb->data = outdata;
+ cb->pos = outdata;
+ cb->path = lce->path;
+
+ /* return the filled classbuffer structure */
+
+ return cb;
+}
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ * vim:noexpandtab:sw=4:ts=4:
+ */
--- /dev/null
+/* src/vm/zip.c - ZIP file handling for bootstrap classloader
+
+ Copyright (C) 1996-2005, 2006, 2007, 2008
+ CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
+
+ This file is part of CACAO.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2, or (at
+ your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+
+*/
+
+
+#ifndef _ZIP_H
+#define _ZIP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "toolbox/hashtable.h"
+
+#include "vm/class.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/suck.h"
+#include "vm/utf8.h"
+
+
+/* Local file header ***********************************************************
+
+ local file header signature 4 bytes (0x04034b50)
+ version needed to extract 2 bytes
+ general purpose bit flag 2 bytes
+ compression method 2 bytes
+ last mod file time 2 bytes
+ last mod file date 2 bytes
+ crc-32 4 bytes
+ compressed size 4 bytes
+ uncompressed size 4 bytes
+ file name length 2 bytes
+ extra field length 2 bytes
+
+ file name (variable size)
+ extra field (variable size)
+
+*******************************************************************************/
+
+#define LFH_HEADER_SIZE 30
+
+#define LFH_SIGNATURE 0x04034b50
+#define LFH_FILE_NAME_LENGTH 26
+#define LFH_EXTRA_FIELD_LENGTH 28
+
+typedef struct lfh lfh;
+
+struct lfh {
+ u2 compressionmethod;
+ u4 compressedsize;
+ u4 uncompressedsize;
+ u2 filenamelength;
+ u2 extrafieldlength;
+};
+
+/* hashtable_zipfile_entry ****************************************************/
+
+typedef struct hashtable_zipfile_entry hashtable_zipfile_entry;
+
+struct hashtable_zipfile_entry {
+ utf *filename;
+ u2 compressionmethod;
+ u4 compressedsize;
+ u4 uncompressedsize;
+ u1 *data;
+ hashtable_zipfile_entry *hashlink;
+};
+
+
+/* function prototypes ********************************************************/
+
+hashtable *zip_open(char *path);
+hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u);
+classbuffer *zip_get(list_classpath_entry *lce, classinfo *c);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ZIP_H */
+
+
+/*
+ * These are local overrides for various environment variables in Emacs.
+ * Please do not remove this and leave it at the end of the file, where
+ * Emacs will automagically detect them.
+ * ---------------------------------------------------------------------
+ * Local variables:
+ * mode: c
+ * indent-tabs-mode: t
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
+++ /dev/null
-## src/vmcore/Makefile.am
-##
-## Copyright (C) 2007, 2008
-## CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-##
-## This file is part of CACAO.
-##
-## This program is free software; you can redistribute it and/or
-## modify it under the terms of the GNU General Public License as
-## published by the Free Software Foundation; either version 2, or (at
-## your option) any later version.
-##
-## This program is distributed in the hope that it will be useful, but
-## WITHOUT ANY WARRANTY; without even the implied warranty of
-## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-## General Public License for more details.
-##
-## You should have received a copy of the GNU General Public License
-## along with this program; if not, write to the Free Software
-## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-## 02110-1301, USA.
-
-
-AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR) -I$(top_srcdir)/src/vm/jit/$(ARCH_DIR)/$(OS_DIR)
-
-LIBS =
-
-if ENABLE_JAVASE
-if ENABLE_ANNOTATIONS
-ANNOTATION_SOURCES = \
- annotation.c \
- annotation.h
-endif
-
-STACKMAP_SOURCES = \
- stackmap.c \
- stackmap.h
-endif
-
-if ENABLE_RT_TIMING
-RT_TIMING_SOURCES = \
- rt-timing.c \
- rt-timing.h
-endif
-
-if ENABLE_STATISTICS
-STATISTICS_SOURCES = \
- statistics.c \
- statistics.h
-endif
-
-if ENABLE_ZLIB
-ZLIB_SOURCES = \
- zip.c \
- zip.h
-endif
-
-noinst_LTLIBRARIES = \
- libvmcore.la
-
-libvmcore_la_SOURCES = \
- $(ANNOTATION_SOURCES) \
- class.c \
- class.h \
- classcache.c \
- classcache.h \
- descriptor.c \
- descriptor.h \
- field.c \
- field.h \
- globals.cpp \
- globals.hpp \
- javaobjects.hpp \
- javaobjects.cpp \
- linker.c \
- linker.h \
- loader.c \
- loader.h \
- method.c \
- method.h \
- options.c \
- options.h \
- os.cpp \
- os.hpp \
- primitivecore.c \
- references.h \
- $(RT_TIMING_SOURCES) \
- $(STACKMAP_SOURCES) \
- $(STATISTICS_SOURCES) \
- suck.c \
- suck.h \
- utf8.c \
- utf8.h \
- $(ZLIB_SOURCES)
-
-
-## Local variables:
-## mode: Makefile
-## indent-tabs-mode: t
-## c-basic-offset: 4
-## tab-width: 8
-## compile-command: "automake --add-missing"
-## End:
+++ /dev/null
-/* src/vmcore/annotation.c - class annotations
-
- Copyright (C) 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "native/llni.h"
-
-#include "vm/types.h"
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/primitive.hpp"
-
-#include "mm/memory.h"
-
-#include "toolbox/logging.h"
-
-#include "vmcore/annotation.h"
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/suck.h"
-
-#if !defined(ENABLE_ANNOTATIONS)
-# error annotation support has to be enabled when compling this file!
-#endif
-
-
-/* annotation_bytearrays_resize ***********************************************
-
- Resize an array of bytearrays.
-
- IN:
- bytearrays.....array of bytearrays
- size...........new size of the refered array
-
- RETURN VALUE:
- The new array if a resize was neccessarry, the old if the given size
- equals the current size or NULL if an error occured.
-
-*******************************************************************************/
-
-static java_handle_objectarray_t *annotation_bytearrays_resize(
- java_handle_objectarray_t *bytearrays, uint32_t size)
-{
- java_handle_objectarray_t *newbas = NULL; /* new array */
- uint32_t minsize = 0; /* count of object refs to copy */
- uint32_t oldsize = 0; /* size of old array */
-
- if (bytearrays != NULL) {
- oldsize = array_length_get((java_handle_t*)bytearrays);
-
- /* if the size already fits do nothing */
- if (size == oldsize) {
- return bytearrays;
- }
- }
-
- newbas = builtin_anewarray(size,
- Primitive_get_arrayclass_by_type(PRIMITIVETYPE_BYTE));
-
- /* is there a old byte array array? */
- if (newbas != NULL && bytearrays != NULL) {
- minsize = size < oldsize ? size : oldsize;
-
- LLNI_CRITICAL_START;
- MCOPY(
- LLNI_array_data(newbas), LLNI_array_data(bytearrays),
- java_object_t*, minsize);
- LLNI_CRITICAL_END;
- }
-
- return newbas;
-}
-
-
-/* annotation_bytearrays_insert ***********************************************
-
- Insert a bytearray into an array of bytearrays.
-
- IN:
- bytearrays........array of bytearrays where 'bytearray' has to be
- inserted at position 'index'.
- index.............position where 'ba' has to be inserted into
- 'bytearrays'.
- bytearray.........byte array which has to be inserted into
- 'bytearrays'.
-
- RETURN VALUE:
- The new array if a resize was neccessarry, the old if the given size
- equals the current size or NULL if an error occured.
-
-*******************************************************************************/
-
-static java_handle_t *annotation_bytearrays_insert(
- java_handle_t *bytearrays, uint32_t index,
- java_handle_bytearray_t *bytearray)
-{
- java_handle_objectarray_t *bas; /* bytearrays */
- uint32_t size = 0; /* current size of the array */
-
- /* do nothing if NULL is inserted but no array exists */
- if (bytearray == NULL && bytearrays == NULL) {
- return NULL;
- }
-
- /* get lengths if array exists */
- if (bytearrays != NULL) {
- size = array_length_get(bytearrays);
- }
-
- bas = (java_handle_objectarray_t*)bytearrays;
-
- if (bytearray == NULL) {
- /* insert NULL only if array is big enough */
- if (size > index) {
- array_objectarray_element_set(bas, index, NULL);
- }
- }
- else {
- /* resize array if it's not enough for inserted value */
- if (size <= index) {
- bas = annotation_bytearrays_resize(bas, index + 1);
-
- if (bas == NULL) {
- /* out of memory */
- return NULL;
- }
- }
-
- array_objectarray_element_set(bas, index, (java_handle_t*)bytearray);
- }
-
- return (java_handle_t*)bas;
-}
-
-
-/* annotation_load_attribute_body *********************************************
-
- This function loads the body of a generic attribute.
-
- XXX: Maybe this function should be called loader_load_attribute_body and
- located in vmcore/loader.c?
-
- attribute_info {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- errormsg_prefix....prefix for error messages (if any).
-
- OUT:
- attribute..........bytearray-pointer which will be set to the read data.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-static bool annotation_load_attribute_body(classbuffer *cb,
- java_handle_bytearray_t **attribute, const char *errormsg_prefix)
-{
- uint32_t size = 0; /* size of the attribute */
- java_handle_bytearray_t *ba = NULL; /* the raw attributes' bytes */
-
- assert(cb != NULL);
- assert(attribute != NULL);
-
- if (!suck_check_classbuffer_size(cb, 4)) {
- log_println("%s: size missing", errormsg_prefix);
- return false;
- }
-
- /* load attribute_length */
- size = suck_u4(cb);
-
- if (!suck_check_classbuffer_size(cb, size)) {
- log_println("%s: invalid size", errormsg_prefix);
- return false;
- }
-
- /* if attribute_length == 0 then NULL is
- * the right value for this attribute */
- if (size > 0) {
- ba = builtin_newarray_byte(size);
-
- if (ba == NULL) {
- /* out of memory */
- return false;
- }
-
- /* load data */
- LLNI_CRITICAL_START;
-
- suck_nbytes((uint8_t*)LLNI_array_data(ba), cb, size);
-
- LLNI_CRITICAL_END;
-
- /* return data */
- *attribute = ba;
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_annotationdefault *************************
-
- Load annotation default value.
-
- AnnotationDefault_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- element_value default_value;
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- m..................methodinfo for the method of which the annotation
- default value is read and into which the value is
- stored into.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_annotationdefault(
- classbuffer *cb, methodinfo *m)
-{
- int slot = 0;
- /* the slot of the method */
- java_handle_bytearray_t *annotationdefault = NULL;
- /* unparsed annotation defalut value */
- java_handle_t *annotationdefaults = NULL;
- /* array of unparsed annotation default values */
-
- assert(cb != NULL);
- assert(m != NULL);
-
- LLNI_classinfo_field_get(
- m->clazz, method_annotationdefaults, annotationdefaults);
-
- if (!annotation_load_attribute_body(
- cb, &annotationdefault,
- "invalid annotation default method attribute")) {
- return false;
- }
-
- if (annotationdefault != NULL) {
- slot = m - m->clazz->methods;
- annotationdefaults = annotation_bytearrays_insert(
- annotationdefaults, slot, annotationdefault);
-
- if (annotationdefaults == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- m->clazz, method_annotationdefaults, annotationdefaults);
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_runtimevisibleparameterannotations ********
-
- Load runtime visible parameter annotations.
-
- RuntimeVisibleParameterAnnotations_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 num_parameters;
- {
- u2 num_annotations;
- annotation annotations[num_annotations];
- } parameter_annotations[num_parameters];
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- m..................methodinfo for the method of which the parameter
- annotations are read and into which the parameter
- annotations are stored into.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimevisibleparameterannotations(
- classbuffer *cb, methodinfo *m)
-{
- int slot = 0;
- /* the slot of the method */
- java_handle_bytearray_t *annotations = NULL;
- /* unparsed parameter annotations */
- java_handle_t *parameterannotations = NULL;
- /* array of unparsed parameter annotations */
-
- assert(cb != NULL);
- assert(m != NULL);
-
- LLNI_classinfo_field_get(
- m->clazz, method_parameterannotations, parameterannotations);
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible parameter annotations method attribute")) {
- return false;
- }
-
- if (annotations != NULL) {
- slot = m - m->clazz->methods;
- parameterannotations = annotation_bytearrays_insert(
- parameterannotations, slot, annotations);
-
- if (parameterannotations == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- m->clazz, method_parameterannotations, parameterannotations);
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_runtimeinvisibleparameterannotations ******
-
- Load runtime invisible parameter annotations.
-
- <quote cite="http://jcp.org/en/jsr/detail?id=202">
- The RuntimeInvisibleParameterAnnotations attribute is similar to the
- RuntimeVisibleParameterAnnotations attribute, except that the annotations
- represented by a RuntimeInvisibleParameterAnnotations attribute must not be
- made available for return by reflective APIs, unless the the JVM has
- specifically been instructed to retain these annotations via some
- implementation-specific mechanism such as a command line flag. In the
- absence of such instructions, the JVM ignores this attribute.
- </quote>
-
- Hotspot loads them into the same bytearray as the runtime visible parameter
- annotations (after the runtime visible parameter annotations). But in J2SE
- the bytearray will only be parsed as if there is only one annotation
- structure in it, so the runtime invisible parameter annotatios will be
- ignored.
-
- Therefore I do not even bother to read them.
-
- RuntimeInvisibleParameterAnnotations_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 num_parameters;
- {
- u2 num_annotations;
- annotation annotations[num_annotations];
- } parameter_annotations[num_parameters];
- }
-
- IN:
- cb.................classbuffer from which to read the data.
- m..................methodinfo for the method of which the parameter
- annotations are read and into which the parameter
- annotations are stored into.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
- classbuffer *cb, methodinfo *m)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/* annotation_load_class_attribute_runtimevisibleannotations ******************
-
- Load runtime visible annotations of a class.
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_class_attribute_runtimevisibleannotations(
- classbuffer *cb)
-{
- java_handle_bytearray_t *annotations = NULL; /* unparsed annotations */
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible annotations class attribute")) {
- return false;
- }
-
- LLNI_classinfo_field_set(cb->clazz, annotations, (java_handle_t*)annotations);
-
- return true;
-}
-
-
-/* annotation_load_class_attribute_runtimeinvisibleannotations ****************
-
- Load runtime invisible annotations of a class (just skip them).
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_class_attribute_runtimeinvisibleannotations(
- classbuffer *cb)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/* annotation_load_method_attribute_runtimevisibleannotations *****************
-
- Load runtime visible annotations of a method.
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- m.........the method of which the runtime visible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimevisibleannotations(
- classbuffer *cb, methodinfo *m)
-{
- int slot = 0;
- /* slot of the method */
- java_handle_bytearray_t *annotations = NULL;
- /* unparsed annotations */
- java_handle_t *method_annotations = NULL;
- /* array of unparsed method annotations */
-
- assert(cb != NULL);
- assert(m != NULL);
-
- LLNI_classinfo_field_get(
- m->clazz, method_annotations, method_annotations);
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible annotations method attribute")) {
- return false;
- }
-
- if (annotations != NULL) {
- slot = m - m->clazz->methods;
- method_annotations = annotation_bytearrays_insert(
- method_annotations, slot, annotations);
-
- if (method_annotations == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- m->clazz, method_annotations, method_annotations);
- }
-
- return true;
-}
-
-
-/* annotation_load_method_attribute_runtimeinvisibleannotations ****************
-
- Load runtime invisible annotations of a method (just skip them).
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- m.........the method of which the runtime invisible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_method_attribute_runtimeinvisibleannotations(
- classbuffer *cb, methodinfo *m)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/* annotation_load_field_attribute_runtimevisibleannotations ******************
-
- Load runtime visible annotations of a field.
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- f.........the field of which the runtime visible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_field_attribute_runtimevisibleannotations(
- classbuffer *cb, fieldinfo *f)
-{
- int slot = 0;
- /* slot of the field */
- java_handle_bytearray_t *annotations = NULL;
- /* unparsed annotations */
- java_handle_t *field_annotations = NULL;
- /* array of unparsed field annotations */
-
- assert(cb != NULL);
- assert(f != NULL);
-
- LLNI_classinfo_field_get(
- f->clazz, field_annotations, field_annotations);
-
- if (!annotation_load_attribute_body(
- cb, &annotations,
- "invalid runtime visible annotations field attribute")) {
- return false;
- }
-
- if (annotations != NULL) {
- slot = f - f->clazz->fields;
- field_annotations = annotation_bytearrays_insert(
- field_annotations, slot, annotations);
-
- if (field_annotations == NULL) {
- return false;
- }
-
- LLNI_classinfo_field_set(
- f->clazz, field_annotations, field_annotations);
- }
-
- return true;
-}
-
-
-/* annotation_load_field_attribute_runtimeinvisibleannotations ****************
-
- Load runtime invisible annotations of a field (just skip them).
-
- IN:
- cb........the classbuffer from which the attribute has to be loaded.
- f.........the field of which the runtime invisible annotations have
- to be loaded.
-
- RETURN VALUE:
- true if all went good. false otherwhise.
-
-*******************************************************************************/
-
-bool annotation_load_field_attribute_runtimeinvisibleannotations(
- classbuffer *cb, fieldinfo *f)
-{
- return loader_skip_attribute_body(cb);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/annotation.h - class annotations
-
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
-
- 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 _ANNOTATION_H
-#define _ANNOTATION_H
-
-
-#include "config.h"
-
-#include "vm/types.h"
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-
-
-/* function prototypes ********************************************************/
-
-bool annotation_load_class_attribute_runtimevisibleannotations(
- classbuffer *cb);
-
-bool annotation_load_class_attribute_runtimeinvisibleannotations(
- classbuffer *cb);
-
-bool annotation_load_method_attribute_runtimevisibleannotations(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_method_attribute_runtimeinvisibleannotations(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_field_attribute_runtimevisibleannotations(
- classbuffer *cb, fieldinfo *f);
-
-bool annotation_load_field_attribute_runtimeinvisibleannotations(
- classbuffer *cb, fieldinfo *f);
-
-bool annotation_load_method_attribute_annotationdefault(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_method_attribute_runtimevisibleparameterannotations(
- classbuffer *cb, methodinfo *m);
-
-bool annotation_load_method_attribute_runtimeinvisibleparameterannotations(
- classbuffer *cb, methodinfo *m);
-
-#endif /* _ANNOTATION_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/class.c - class related functions
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vm/types.h"
-
-#include "arch.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/resolve.h"
-
-#include "vm/jit/asmpart.h"
-
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-/* class_set_packagename *******************************************************
-
- Derive the package name from the class name and store it in the
- struct.
-
- An internal package name consists of the package name plus the
- trailing '/', e.g. "java/lang/".
-
- For classes in the unnamed package, the package name is set to
- NULL.
-
-*******************************************************************************/
-
-void class_set_packagename(classinfo *c)
-{
- char *p;
- char *start;
-
- p = UTF_END(c->name) - 1;
- start = c->name->text;
-
- if (c->name->text[0] == '[') {
- /* Set packagename of arrays to the element's package. */
-
- for (; *start == '['; start++);
-
- /* Skip the 'L' in arrays of references. */
-
- if (*start == 'L')
- start++;
- }
-
- /* Search for last '/'. */
-
- for (; (p > start) && (*p != '/'); --p);
-
- /* If we found a '/' we set the package name plus the trailing
- '/'. Otherwise we set the packagename to NULL. */
-
- if (p > start)
- c->packagename = utf_new(start, p - start + 1);
- else
- c->packagename = NULL;
-}
-
-
-/* class_create_classinfo ******************************************************
-
- Create a new classinfo struct. The class name is set to the given utf *,
- most other fields are initialized to zero.
-
- Note: classname may be NULL. In this case a not-yet-named classinfo is
- created. The name must be filled in later and class_set_packagename
- must be called after that.
-
-*******************************************************************************/
-
-classinfo *class_create_classinfo(utf *classname)
-{
- classinfo *c;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_classinfo += sizeof(classinfo);
-#endif
-
- /* we use a safe name for temporarily unnamed classes */
-
- if (classname == NULL)
- classname = utf_not_named_yet;
-
-#if !defined(NDEBUG)
- if (initverbose)
- log_message_utf("Creating class: ", classname);
-#endif
-
-#if !defined(ENABLE_GC_BOEHM)
- c = (classinfo *) heap_alloc_uncollectable(sizeof(classinfo));
- /*c = NEW(classinfo);
- MZERO(c, classinfo, 1);*/
-#else
- c = GCNEW_UNCOLLECTABLE(classinfo, 1);
- /* GCNEW_UNCOLLECTABLE clears the allocated memory */
-#endif
-
- c->name = classname;
-
- /* Set the header.vftbl of all loaded classes to the one of
- java.lang.Class, so Java code can use a class as object. */
-
- if (class_java_lang_Class != NULL)
- if (class_java_lang_Class->vftbl != NULL)
- c->object.header.vftbl = class_java_lang_Class->vftbl;
-
-#if defined(ENABLE_JAVASE)
- /* check if the class is a reference class and flag it */
-
- if (classname == utf_java_lang_ref_SoftReference) {
- c->flags |= ACC_CLASS_REFERENCE_SOFT;
- }
- else if (classname == utf_java_lang_ref_WeakReference) {
- c->flags |= ACC_CLASS_REFERENCE_WEAK;
- }
- else if (classname == utf_java_lang_ref_PhantomReference) {
- c->flags |= ACC_CLASS_REFERENCE_PHANTOM;
- }
-#endif
-
- if (classname != utf_not_named_yet)
- class_set_packagename(c);
-
- LOCK_INIT_OBJECT_LOCK(&c->object.header);
-
- return c;
-}
-
-
-/* class_postset_header_vftbl **************************************************
-
- Set the header.vftbl of all classes created before java.lang.Class
- was linked. This is necessary that Java code can use a class as
- object.
-
-*******************************************************************************/
-
-void class_postset_header_vftbl(void)
-{
- classinfo *c;
- u4 slot;
- classcache_name_entry *nmen;
- classcache_class_entry *clsen;
-
- assert(class_java_lang_Class);
-
- for (slot = 0; slot < hashtable_classcache.size; slot++) {
- nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
-
- for (; nmen; nmen = nmen->hashlink) {
- /* iterate over all class entries */
-
- for (clsen = nmen->classes; clsen; clsen = clsen->next) {
- c = clsen->classobj;
-
- /* now set the the vftbl */
-
- if (c->object.header.vftbl == NULL)
- c->object.header.vftbl = class_java_lang_Class->vftbl;
- }
- }
- }
-}
-
-/* class_define ****************************************************************
-
- Calls the loader and defines a class in the VM.
-
-*******************************************************************************/
-
-classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd)
-{
- classinfo *c;
- classinfo *r;
- classbuffer *cb;
-
- if (name != NULL) {
- /* check if this class has already been defined */
-
- c = classcache_lookup_defined_or_initiated(cl, name);
-
- if (c != NULL) {
- exceptions_throw_linkageerror("duplicate class definition: ", c);
- return NULL;
- }
- }
-
- /* create a new classinfo struct */
-
- c = class_create_classinfo(name);
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getloadingtime)
- loadingtime_start();
-#endif
-
- /* build a classbuffer with the given data */
-
- cb = NEW(classbuffer);
-
- cb->clazz = c;
- cb->size = length;
- cb->data = data;
- cb->pos = cb->data;
-
- /* preset the defining classloader */
-
- c->classloader = cl;
-
- /* load the class from this buffer */
-
- r = load_class_from_classbuffer(cb);
-
- /* free memory */
-
- FREE(cb, classbuffer);
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getloadingtime)
- loadingtime_stop();
-#endif
-
- if (r == NULL) {
- /* If return value is NULL, we had a problem and the class is
- not loaded. Now free the allocated memory, otherwise we
- could run into a DOS. */
-
- class_free(c);
-
- return NULL;
- }
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* Store the protection domain. */
-
- c->protectiondomain = pd;
-# endif
-#endif
-
- /* Store the newly defined class in the class cache. This call
- also checks whether a class of the same name has already been
- defined by the same defining loader, and if so, replaces the
- newly created class by the one defined earlier. */
-
- /* Important: The classinfo given to classcache_store must be
- fully prepared because another thread may return
- this pointer after the lookup at to top of this
- function directly after the class cache lock has
- been released. */
-
- c = classcache_store(cl, c, true);
-
- return c;
-}
-
-
-/* class_load_attribute_sourcefile *********************************************
-
- SourceFile_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 sourcefile_index;
- }
-
-*******************************************************************************/
-
-static bool class_load_attribute_sourcefile(classbuffer *cb)
-{
- classinfo *c;
- u4 attribute_length;
- u2 sourcefile_index;
- utf *sourcefile;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* check attribute length */
-
- attribute_length = suck_u4(cb);
-
- if (attribute_length != 2) {
- exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
- return false;
- }
-
- /* there can be no more than one SourceFile attribute */
-
- if (c->sourcefile != NULL) {
- exceptions_throw_classformaterror(c, "Multiple SourceFile attributes");
- return false;
- }
-
- /* get sourcefile */
-
- sourcefile_index = suck_u2(cb);
- sourcefile = class_getconstant(c, sourcefile_index, CONSTANT_Utf8);
-
- if (sourcefile == NULL)
- return false;
-
- /* store sourcefile */
-
- c->sourcefile = sourcefile;
-
- return true;
-}
-
-
-/* class_load_attribute_enclosingmethod ****************************************
-
- EnclosingMethod_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 class_index;
- u2 method_index;
- }
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-static bool class_load_attribute_enclosingmethod(classbuffer *cb)
-{
- classinfo *c;
- u4 attribute_length;
- u2 class_index;
- u2 method_index;
- classref_or_classinfo cr;
- constant_nameandtype *cn;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
- return false;
-
- /* check attribute length */
-
- attribute_length = suck_u4(cb);
-
- if (attribute_length != 4) {
- exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
- return false;
- }
-
- /* there can be no more than one EnclosingMethod attribute */
-
- if (c->enclosingmethod != NULL) {
- exceptions_throw_classformaterror(c, "Multiple EnclosingMethod attributes");
- return false;
- }
-
- /* get class index */
-
- class_index = suck_u2(cb);
- cr.ref = innerclass_getconstant(c, class_index, CONSTANT_Class);
-
- /* get method index */
-
- method_index = suck_u2(cb);
- cn = innerclass_getconstant(c, method_index, CONSTANT_NameAndType);
-
- /* store info in classinfo */
-
- c->enclosingclass.any = cr.any;
- c->enclosingmethod = cn;
-
- return true;
-}
-#endif /* defined(ENABLE_JAVASE) */
-
-
-/* class_load_attributes *******************************************************
-
- Read attributes from ClassFile.
-
- attribute_info {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
-
- InnerClasses_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- }
-
-*******************************************************************************/
-
-bool class_load_attributes(classbuffer *cb)
-{
- classinfo *c;
- uint16_t attributes_count;
- uint16_t attribute_name_index;
- utf *attribute_name;
- innerclassinfo *info;
- classref_or_classinfo inner;
- classref_or_classinfo outer;
- utf *name;
- uint16_t flags;
- int i, j;
-
- c = cb->clazz;
-
- /* get attributes count */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- attributes_count = suck_u2(cb);
-
- for (i = 0; i < attributes_count; i++) {
- /* get attribute name */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- attribute_name_index = suck_u2(cb);
- attribute_name =
- class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
-
- if (attribute_name == NULL)
- return false;
-
- if (attribute_name == utf_InnerClasses) {
- /* InnerClasses */
-
- if (c->innerclass != NULL) {
- exceptions_throw_classformaterror(c, "Multiple InnerClasses attributes");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* skip attribute length */
- suck_u4(cb);
-
- /* number of records */
- c->innerclasscount = suck_u2(cb);
-
- if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * c->innerclasscount))
- return false;
-
- /* allocate memory for innerclass structure */
- c->innerclass = MNEW(innerclassinfo, c->innerclasscount);
-
- for (j = 0; j < c->innerclasscount; j++) {
- /* The innerclass structure contains a class with an encoded
- name, its defining scope, its simple name and a bitmask of
- the access flags. */
-
- info = c->innerclass + j;
-
- inner.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
- outer.ref = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Class);
- name = innerclass_getconstant(c, suck_u2(cb), CONSTANT_Utf8);
- flags = suck_u2(cb);
-
- /* If the current inner-class is the currently loaded
- class check for some special flags. */
-
- if (inner.ref->name == c->name) {
- /* If an inner-class is not a member, its
- outer-class is NULL. */
-
- if (outer.ref != NULL) {
- c->flags |= ACC_CLASS_MEMBER;
-
- /* A member class doesn't have an
- EnclosingMethod attribute, so set the
- enclosing-class to be the same as the
- declaring-class. */
-
- c->declaringclass = outer;
- c->enclosingclass = outer;
- }
-
- /* If an inner-class is anonymous, its name is
- NULL. */
-
- if (name == NULL)
- c->flags |= ACC_CLASS_ANONYMOUS;
- }
-
- info->inner_class = inner;
- info->outer_class = outer;
- info->name = name;
- info->flags = flags;
- }
- }
- else if (attribute_name == utf_SourceFile) {
- /* SourceFile */
-
- if (!class_load_attribute_sourcefile(cb))
- return false;
- }
-#if defined(ENABLE_JAVASE)
- else if (attribute_name == utf_EnclosingMethod) {
- /* EnclosingMethod */
-
- if (!class_load_attribute_enclosingmethod(cb))
- return false;
- }
- else if (attribute_name == utf_Signature) {
- /* Signature */
-
- if (!loader_load_attribute_signature(cb, &(c->signature)))
- return false;
- }
-#endif
-
-#if defined(ENABLE_ANNOTATIONS)
- else if (attribute_name == utf_RuntimeVisibleAnnotations) {
- /* RuntimeVisibleAnnotations */
- if (!annotation_load_class_attribute_runtimevisibleannotations(cb))
- return false;
- }
- else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
- /* RuntimeInvisibleAnnotations */
- if (!annotation_load_class_attribute_runtimeinvisibleannotations(cb))
- return false;
- }
-#endif
-
- else {
- /* unknown attribute */
-
- if (!loader_skip_attribute_body(cb))
- return false;
- }
- }
-
- return true;
-}
-
-
-/* class_freepool **************************************************************
-
- Frees all resources used by this classes Constant Pool.
-
-*******************************************************************************/
-
-static void class_freecpool(classinfo *c)
-{
- u4 idx;
- u4 tag;
- void* info;
-
- if (c->cptags && c->cpinfos) {
- for (idx = 0; idx < c->cpcount; idx++) {
- tag = c->cptags[idx];
- info = c->cpinfos[idx];
-
- if (info != NULL) {
- switch (tag) {
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- FREE(info, constant_FMIref);
- break;
- case CONSTANT_Integer:
- FREE(info, constant_integer);
- break;
- case CONSTANT_Float:
- FREE(info, constant_float);
- break;
- case CONSTANT_Long:
- FREE(info, constant_long);
- break;
- case CONSTANT_Double:
- FREE(info, constant_double);
- break;
- case CONSTANT_NameAndType:
- FREE(info, constant_nameandtype);
- break;
- }
- }
- }
- }
-
- if (c->cptags)
- MFREE(c->cptags, u1, c->cpcount);
-
- if (c->cpinfos)
- MFREE(c->cpinfos, void*, c->cpcount);
-}
-
-
-/* class_getconstant ***********************************************************
-
- Retrieves the value at position 'pos' of the constantpool of a
- class. If the type of the value is other than 'ctype', an error is
- thrown.
-
-*******************************************************************************/
-
-void* class_getconstant(classinfo *c, u4 pos, u4 ctype)
-{
- /* check index and type of constantpool entry */
- /* (pos == 0 is caught by type comparison) */
-
- if ((pos >= c->cpcount) || (c->cptags[pos] != ctype)) {
- exceptions_throw_classformaterror(c, "Illegal constant pool index");
- return NULL;
- }
-
- return c->cpinfos[pos];
-}
-
-
-/* innerclass_getconstant ******************************************************
-
- Like class_getconstant, but if cptags is ZERO, null is returned.
-
-*******************************************************************************/
-
-void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype)
-{
- /* invalid position in constantpool */
-
- if (pos >= c->cpcount) {
- exceptions_throw_classformaterror(c, "Illegal constant pool index");
- return NULL;
- }
-
- /* constantpool entry of type 0 */
-
- if (c->cptags[pos] == 0)
- return NULL;
-
- /* check type of constantpool entry */
-
- if (c->cptags[pos] != ctype) {
- exceptions_throw_classformaterror(c, "Illegal constant pool index");
- return NULL;
- }
-
- return c->cpinfos[pos];
-}
-
-
-/* class_free ******************************************************************
-
- Frees all resources used by the class.
-
-*******************************************************************************/
-
-void class_free(classinfo *c)
-{
- s4 i;
- vftbl_t *v;
-
- class_freecpool(c);
-
- if (c->interfaces != NULL)
- MFREE(c->interfaces, classinfo*, c->interfacescount);
-
- if (c->fields) {
- for (i = 0; i < c->fieldscount; i++)
- field_free(&(c->fields[i]));
- MFREE(c->fields, fieldinfo, c->fieldscount);
- }
-
- if (c->methods) {
- for (i = 0; i < c->methodscount; i++)
- method_free(&(c->methods[i]));
- MFREE(c->methods, methodinfo, c->methodscount);
- }
-
- if ((v = c->vftbl) != NULL) {
- if (v->arraydesc)
- mem_free(v->arraydesc,sizeof(arraydescriptor));
-
- for (i = 0; i < v->interfacetablelength; i++) {
- MFREE(v->interfacetable[-i], methodptr, v->interfacevftbllength[i]);
- }
- MFREE(v->interfacevftbllength, s4, v->interfacetablelength);
-
- i = sizeof(vftbl_t) + sizeof(methodptr) * (v->vftbllength - 1) +
- sizeof(methodptr*) * (v->interfacetablelength -
- (v->interfacetablelength > 0));
- v = (vftbl_t*) (((methodptr*) v) -
- (v->interfacetablelength - 1) * (v->interfacetablelength > 1));
- mem_free(v, i);
- }
-
- if (c->innerclass)
- MFREE(c->innerclass, innerclassinfo, c->innerclasscount);
-
- /* if (c->classvftbl)
- mem_free(c->header.vftbl, sizeof(vftbl) + sizeof(methodptr)*(c->vftbl->vftbllength-1)); */
-
-/* GCFREE(c); */
-}
-
-
-/* get_array_class *************************************************************
-
- Returns the array class with the given name for the given
- classloader, or NULL if an exception occurred.
-
- Note: This function does eager loading.
-
-*******************************************************************************/
-
-static classinfo *get_array_class(utf *name,classloader_t *initloader,
- classloader_t *defloader,bool link)
-{
- classinfo *c;
-
- /* lookup this class in the classcache */
- c = classcache_lookup(initloader,name);
- if (!c)
- c = classcache_lookup_defined(defloader,name);
-
- if (!c) {
- /* we have to create it */
- c = class_create_classinfo(name);
- c = load_newly_created_array(c,initloader);
- if (c == NULL)
- return NULL;
- }
-
- assert(c);
- assert(c->state & CLASS_LOADED);
- assert(c->classloader == defloader);
-
- if (link && !(c->state & CLASS_LINKED))
- if (!link_class(c))
- return NULL;
-
- assert(!link || (c->state & CLASS_LINKED));
-
- return c;
-}
-
-
-/* class_array_of **************************************************************
-
- Returns an array class with the given component class. The array
- class is dynamically created if neccessary.
-
-*******************************************************************************/
-
-classinfo *class_array_of(classinfo *component, bool link)
-{
- classloader_t *cl;
- s4 namelen;
- char *namebuf;
- utf *u;
- classinfo *c;
- int32_t dumpmarker;
-
- cl = component->classloader;
-
- DMARKER;
-
- /* Assemble the array class name */
- namelen = component->name->blength;
-
- if (component->name->text[0] == '[') {
- /* the component is itself an array */
- namebuf = DMNEW(char, namelen + 1);
- namebuf[0] = '[';
- MCOPY(namebuf + 1, component->name->text, char, namelen);
- namelen++;
- }
- else {
- /* the component is a non-array class */
- namebuf = DMNEW(char, namelen + 3);
- namebuf[0] = '[';
- namebuf[1] = 'L';
- MCOPY(namebuf + 2, component->name->text, char, namelen);
- namebuf[2 + namelen] = ';';
- namelen += 3;
- }
-
- u = utf_new(namebuf, namelen);
-
- c = get_array_class(u, cl, cl, link);
-
- DRELEASE;
-
- return c;
-}
-
-
-/* class_multiarray_of *********************************************************
-
- Returns an array class with the given dimension and element class.
- The array class is dynamically created if neccessary.
-
-*******************************************************************************/
-
-classinfo *class_multiarray_of(s4 dim, classinfo *element, bool link)
-{
- s4 namelen;
- char *namebuf;
- classinfo *c;
- int32_t dumpmarker;
-
- DMARKER;
-
- if (dim < 1) {
- log_text("Invalid array dimension requested");
- assert(0);
- }
-
- /* Assemble the array class name */
- namelen = element->name->blength;
-
- if (element->name->text[0] == '[') {
- /* the element is itself an array */
- namebuf = DMNEW(char, namelen + dim);
- memcpy(namebuf + dim, element->name->text, namelen);
- namelen += dim;
- }
- else {
- /* the element is a non-array class */
- namebuf = DMNEW(char, namelen + 2 + dim);
- namebuf[dim] = 'L';
- memcpy(namebuf + dim + 1, element->name->text, namelen);
- namelen += (2 + dim);
- namebuf[namelen - 1] = ';';
- }
- memset(namebuf, '[', dim);
-
- c = get_array_class(utf_new(namebuf, namelen),
- element->classloader,
- element->classloader,
- link);
-
- DRELEASE;
-
- return c;
-}
-
-
-/* class_lookup_classref *******************************************************
-
- Looks up the constant_classref for a given classname in the classref
- tables of a class.
-
- IN:
- cls..............the class containing the reference
- name.............the name of the class refered to
-
- RETURN VALUE:
- a pointer to a constant_classref, or
- NULL if the reference was not found
-
-*******************************************************************************/
-
-constant_classref *class_lookup_classref(classinfo *cls, utf *name)
-{
- constant_classref *ref;
- extra_classref *xref;
- int count;
-
- assert(cls);
- assert(name);
- assert(!cls->classrefcount || cls->classrefs);
-
- /* first search the main classref table */
- count = cls->classrefcount;
- ref = cls->classrefs;
- for (; count; --count, ++ref)
- if (ref->name == name)
- return ref;
-
- /* next try the list of extra classrefs */
- for (xref = cls->extclassrefs; xref; xref = xref->next) {
- if (xref->classref.name == name)
- return &(xref->classref);
- }
-
- /* not found */
- return NULL;
-}
-
-
-/* class_get_classref **********************************************************
-
- Returns the constant_classref for a given classname.
-
- IN:
- cls..............the class containing the reference
- name.............the name of the class refered to
-
- RETURN VALUE:
- a pointer to a constant_classref (never NULL)
-
- NOTE:
- The given name is not checked for validity!
-
-*******************************************************************************/
-
-constant_classref *class_get_classref(classinfo *cls, utf *name)
-{
- constant_classref *ref;
- extra_classref *xref;
-
- assert(cls);
- assert(name);
-
- ref = class_lookup_classref(cls,name);
- if (ref)
- return ref;
-
- xref = NEW(extra_classref);
- CLASSREF_INIT(xref->classref,cls,name);
-
- xref->next = cls->extclassrefs;
- cls->extclassrefs = xref;
-
- return &(xref->classref);
-}
-
-
-/* class_get_self_classref *****************************************************
-
- Returns the constant_classref to the class itself.
-
- IN:
- cls..............the class containing the reference
-
- RETURN VALUE:
- a pointer to a constant_classref (never NULL)
-
-*******************************************************************************/
-
-constant_classref *class_get_self_classref(classinfo *cls)
-{
- /* XXX this should be done in a faster way. Maybe always make */
- /* the classref of index 0 a self reference. */
- return class_get_classref(cls,cls->name);
-}
-
-/* class_get_classref_multiarray_of ********************************************
-
- Returns an array type reference with the given dimension and element class
- reference.
-
- IN:
- dim..............the requested dimension
- dim must be in [1;255]. This is NOT checked!
- ref..............the component class reference
-
- RETURN VALUE:
- a pointer to the class reference for the array type
-
- NOTE:
- The referer of `ref` is used as the referer for the new classref.
-
-*******************************************************************************/
-
-constant_classref *class_get_classref_multiarray_of(s4 dim, constant_classref *ref)
-{
- s4 namelen;
- char *namebuf;
- constant_classref *cr;
- int32_t dumpmarker;
-
- assert(ref);
- assert(dim >= 1 && dim <= 255);
-
- DMARKER;
-
- /* Assemble the array class name */
- namelen = ref->name->blength;
-
- if (ref->name->text[0] == '[') {
- /* the element is itself an array */
- namebuf = DMNEW(char, namelen + dim);
- memcpy(namebuf + dim, ref->name->text, namelen);
- namelen += dim;
- }
- else {
- /* the element is a non-array class */
- namebuf = DMNEW(char, namelen + 2 + dim);
- namebuf[dim] = 'L';
- memcpy(namebuf + dim + 1, ref->name->text, namelen);
- namelen += (2 + dim);
- namebuf[namelen - 1] = ';';
- }
- memset(namebuf, '[', dim);
-
- cr = class_get_classref(ref->referer,utf_new(namebuf, namelen));
-
- DRELEASE;
-
- return cr;
-}
-
-
-/* class_get_classref_component_of *********************************************
-
- Returns the component classref of a given array type reference
-
- IN:
- ref..............the array type reference
-
- RETURN VALUE:
- a reference to the component class, or
- NULL if `ref` is not an object array type reference
-
- NOTE:
- The referer of `ref` is used as the referer for the new classref.
-
-*******************************************************************************/
-
-constant_classref *class_get_classref_component_of(constant_classref *ref)
-{
- s4 namelen;
- char *name;
-
- assert(ref);
-
- name = ref->name->text;
- if (*name++ != '[')
- return NULL;
-
- namelen = ref->name->blength - 1;
- if (*name == 'L') {
- name++;
- namelen -= 2;
- }
- else if (*name != '[') {
- return NULL;
- }
-
- return class_get_classref(ref->referer, utf_new(name, namelen));
-}
-
-
-/* class_findmethod ************************************************************
-
- Searches a 'classinfo' structure for a method having the given name
- and descriptor. If descriptor is NULL, it is ignored.
-
-*******************************************************************************/
-
-methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc)
-{
- methodinfo *m;
- s4 i;
-
- for (i = 0; i < c->methodscount; i++) {
- m = &(c->methods[i]);
-
- if ((m->name == name) && ((desc == NULL) || (m->descriptor == desc)))
- return m;
- }
-
- return NULL;
-}
-
-
-/* class_resolvemethod *********************************************************
-
- Searches a class and it's super classes for a method.
-
- Superinterfaces are *not* searched.
-
-*******************************************************************************/
-
-methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *desc)
-{
- methodinfo *m;
-
- while (c) {
- m = class_findmethod(c, name, desc);
-
- if (m)
- return m;
-
- /* JVM Specification bug:
-
- It is important NOT to resolve special <init> and <clinit>
- methods to super classes or interfaces; yet, this is not
- explicited in the specification. Section 5.4.3.3 should be
- updated appropriately. */
-
- if (name == utf_init || name == utf_clinit)
- return NULL;
-
- c = c->super;
- }
-
- return NULL;
-}
-
-
-/* class_resolveinterfacemethod_intern *****************************************
-
- Internally used helper function. Do not use this directly.
-
-*******************************************************************************/
-
-static methodinfo *class_resolveinterfacemethod_intern(classinfo *c,
- utf *name, utf *desc)
-{
- methodinfo *m;
- s4 i;
-
- /* try to find the method in the class */
-
- m = class_findmethod(c, name, desc);
-
- if (m != NULL)
- return m;
-
- /* No method found? Try the super interfaces. */
-
- for (i = 0; i < c->interfacescount; i++) {
- m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
-
- if (m != NULL)
- return m;
- }
-
- /* no method found */
-
- return NULL;
-}
-
-
-/* class_resolveclassmethod ****************************************************
-
- Resolves a reference from REFERER to a method with NAME and DESC in
- class C.
-
- If the method cannot be resolved the return value is NULL. If
- EXCEPT is true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *desc,
- classinfo *referer, bool throwexception)
-{
- classinfo *cls;
- methodinfo *m;
- s4 i;
-
-/* if (c->flags & ACC_INTERFACE) { */
-/* if (throwexception) */
-/* *exceptionptr = */
-/* new_exception(string_java_lang_IncompatibleClassChangeError); */
-/* return NULL; */
-/* } */
-
- /* try class c and its superclasses */
-
- cls = c;
-
- m = class_resolvemethod(cls, name, desc);
-
- if (m != NULL)
- goto found;
-
- /* Try the super interfaces. */
-
- for (i = 0; i < c->interfacescount; i++) {
- m = class_resolveinterfacemethod_intern(c->interfaces[i], name, desc);
-
- if (m != NULL)
- goto found;
- }
-
- if (throwexception)
- exceptions_throw_nosuchmethoderror(c, name, desc);
-
- return NULL;
-
- found:
- if ((m->flags & ACC_ABSTRACT) && !(c->flags & ACC_ABSTRACT)) {
- if (throwexception)
- exceptions_throw_abstractmethoderror();
-
- return NULL;
- }
-
- /* XXX check access rights */
-
- return m;
-}
-
-
-/* class_resolveinterfacemethod ************************************************
-
- Resolves a reference from REFERER to a method with NAME and DESC in
- interface C.
-
- If the method cannot be resolved the return value is NULL. If
- EXCEPT is true *exceptionptr is set, too.
-
-*******************************************************************************/
-
-methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *desc,
- classinfo *referer, bool throwexception)
-{
- methodinfo *mi;
-
- if (!(c->flags & ACC_INTERFACE)) {
- if (throwexception)
- exceptions_throw_incompatibleclasschangeerror(c, "Not an interface");
-
- return NULL;
- }
-
- mi = class_resolveinterfacemethod_intern(c, name, desc);
-
- if (mi != NULL)
- return mi;
-
- /* try class java.lang.Object */
-
- mi = class_findmethod(class_java_lang_Object, name, desc);
-
- if (mi != NULL)
- return mi;
-
- if (throwexception)
- exceptions_throw_nosuchmethoderror(c, name, desc);
-
- return NULL;
-}
-
-
-/* class_findfield *************************************************************
-
- Searches for field with specified name and type in a classinfo
- structure. If no such field is found NULL is returned.
-
-*******************************************************************************/
-
-fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc)
-{
- s4 i;
-
- for (i = 0; i < c->fieldscount; i++)
- if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc))
- return &(c->fields[i]);
-
- if (c->super != NULL)
- return class_findfield(c->super, name, desc);
-
- return NULL;
-}
-
-
-/* class_findfield_approx ******************************************************
-
- Searches in 'classinfo'-structure for a field with the specified
- name.
-
-*******************************************************************************/
-
-fieldinfo *class_findfield_by_name(classinfo* c, utf* name)
-{
- for (int32_t i = 0; i < c->fieldscount; i++) {
- fieldinfo* f = &(c->fields[i]);
-
- if (f->name == name)
- return f;
- }
-
- // Field not found.
- exceptions_throw_nosuchfielderror(c, name);
- return NULL;
-}
-
-
-/****************** Function: class_resolvefield_int ***************************
-
- This is an internally used helper function. Do not use this directly.
-
- Tries to resolve a field having the given name and type.
- If the field cannot be resolved, NULL is returned.
-
-*******************************************************************************/
-
-static fieldinfo *class_resolvefield_int(classinfo *c, utf *name, utf *desc)
-{
- fieldinfo *fi;
- s4 i;
-
- /* search for field in class c */
-
- for (i = 0; i < c->fieldscount; i++) {
- if ((c->fields[i].name == name) && (c->fields[i].descriptor == desc)) {
- return &(c->fields[i]);
- }
- }
-
- /* Try super interfaces recursively. */
-
- for (i = 0; i < c->interfacescount; i++) {
- fi = class_resolvefield_int(c->interfaces[i], name, desc);
-
- if (fi != NULL)
- return fi;
- }
-
- /* Try super class. */
-
- if (c->super != NULL)
- return class_resolvefield_int(c->super, name, desc);
-
- /* not found */
-
- return NULL;
-}
-
-
-/********************* Function: class_resolvefield ***************************
-
- Resolves a reference from REFERER to a field with NAME and DESC in class C.
-
- If the field cannot be resolved, an exception is thrown and the
- return value is NULL.
-
-*******************************************************************************/
-
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer)
-{
- fieldinfo *fi;
-
- fi = class_resolvefield_int(c, name, desc);
-
- if (!fi) {
- exceptions_throw_nosuchfielderror(c, name);
- return NULL;
- }
-
- /* XXX check access rights */
-
- return fi;
-}
-
-
-/* class_issubclass ************************************************************
-
- Checks if sub is a descendant of super.
-
-*******************************************************************************/
-
-bool class_issubclass(classinfo *sub, classinfo *super)
-{
- classinfo *c;
-
- c = sub;
-
- for (;;) {
- /* We reached java/lang/Object and did not find the requested
- super class. */
-
- if (c == NULL)
- return false;
-
- /* We found the requested super class. */
-
- if (c == super)
- return true;
-
- c = c->super;
- }
-}
-
-
-/* class_isanysubclass *********************************************************
-
- Checks a subclass relation between two classes. Implemented
- interfaces are interpreted as super classes.
-
- Return value: 1 ... sub is subclass of super
- 0 ... otherwise
-
-*******************************************************************************/
-
-bool class_isanysubclass(classinfo *sub, classinfo *super)
-{
- uint32_t diffval;
- bool result;
-
- /* This is the trivial case. */
-
- if (sub == super)
- return true;
-
- /* Primitive classes are only subclasses of themselves. */
-
- if (class_is_primitive(sub) || class_is_primitive(super))
- return false;
-
- /* Check for interfaces. */
-
- if (super->flags & ACC_INTERFACE) {
- result = (sub->vftbl->interfacetablelength > super->index) &&
- (sub->vftbl->interfacetable[-super->index] != NULL);
- }
- else {
- /* java.lang.Object is the only super class of any
- interface. */
-
- if (sub->flags & ACC_INTERFACE)
- return (super == class_java_lang_Object);
-
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
- diffval = sub->vftbl->baseval - super->vftbl->baseval;
- result = diffval <= (uint32_t) super->vftbl->diffval;
-
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
- }
-
- return result;
-}
-
-
-/* class_is_assignable_from ****************************************************
-
- Return whether an instance of the "from" class parameter would be
- an instance of this class "to" as well.
-
- ARGUMENTS:
- to ..... class
- from ... class
-
- RETURN:
- true .... is assignable
- false ... is not assignable
-
-*******************************************************************************/
-
-bool class_is_assignable_from(classinfo *to, classinfo *from)
-{
- if (!(to->state & CLASS_LINKED))
- if (!link_class(to))
- return false;
-
- if (!(from->state & CLASS_LINKED))
- if (!link_class(from))
- return false;
-
- return class_isanysubclass(from, to);
-}
-
-
-/* class_is_instance ***********************************************************
-
- Return if the given Java object is an instance of the given class.
-
- ARGUMENTS:
- c ... class
- h ... Java object
-
- RETURN:
- true .... is instance
- false ... is not instance
-
-*******************************************************************************/
-
-bool class_is_instance(classinfo *c, java_handle_t *h)
-{
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- return false;
-
- return builtin_instanceof(h, c);
-}
-
-
-/* class_get_componenttype *****************************************************
-
- Return the component class of the given class. If the given class
- is not an array, return NULL.
-
-*******************************************************************************/
-
-classinfo *class_get_componenttype(classinfo *c)
-{
- classinfo *component;
- arraydescriptor *ad;
-
- /* XXX maybe we could find a way to do this without linking. */
- /* This way should be safe and easy, however. */
-
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- return NULL;
-
- ad = c->vftbl->arraydesc;
-
- if (ad == NULL)
- return NULL;
-
- if (ad->arraytype == ARRAYTYPE_OBJECT)
- component = ad->componentvftbl->clazz;
- else
- component = Primitive_get_class_by_type(ad->arraytype);
-
- return component;
-}
-
-
-/* class_get_declaredclasses ***************************************************
-
- Return an array of declared classes of the given class.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly)
-{
- classref_or_classinfo inner;
- classref_or_classinfo outer;
- utf *outername;
- int declaredclasscount; /* number of declared classes */
- int pos; /* current declared class */
- java_handle_objectarray_t *oa; /* array of declared classes */
- int i;
- classinfo *ic;
-
- declaredclasscount = 0;
-
- if (!class_is_primitive(c) && !class_is_array(c)) {
- /* Determine number of declared classes. */
-
- for (i = 0; i < c->innerclasscount; i++) {
- /* Get outer-class. If the inner-class is not a member
- class, the outer-class is NULL. */
-
- outer = c->innerclass[i].outer_class;
-
- if (outer.any == NULL)
- continue;
-
- /* Check if outer-class is a classref or a real class and
- get the class name from the structure. */
-
- outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
-
- /* Outer class is this class. */
-
- if ((outername == c->name) &&
- ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC)))
- declaredclasscount++;
- }
- }
-
- /* Allocate Class[] and check for OOM. */
-
- oa = builtin_anewarray(declaredclasscount, class_java_lang_Class);
-
- if (oa == NULL)
- return NULL;
-
- for (i = 0, pos = 0; i < c->innerclasscount; i++) {
- inner = c->innerclass[i].inner_class;
- outer = c->innerclass[i].outer_class;
-
- /* Get outer-class. If the inner-class is not a member class,
- the outer-class is NULL. */
-
- if (outer.any == NULL)
- continue;
-
- /* Check if outer_class is a classref or a real class and get
- the class name from the structure. */
-
- outername = IS_CLASSREF(outer) ? outer.ref->name : outer.cls->name;
-
- /* Outer class is this class. */
-
- if ((outername == c->name) &&
- ((publicOnly == 0) || (c->innerclass[i].flags & ACC_PUBLIC))) {
-
- ic = resolve_classref_or_classinfo_eager(inner, false);
-
- if (ic == NULL)
- return NULL;
-
- if (!(ic->state & CLASS_LINKED))
- if (!link_class(ic))
- return NULL;
-
- LLNI_array_direct(oa, pos++) = (java_object_t *) ic;
- }
- }
-
- return oa;
-}
-
-
-/**
- * Return an array of declared constructors of the given class.
- *
- * @param c class to get the constructors of
- * @param publicOnly show only public fields
- *
- * @return array of java.lang.reflect.Constructor
- */
-#if defined(ENABLE_JAVASE)
-java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly)
-{
- methodinfo* m;
- java_handle_objectarray_t* oa;
- java_handle_t* rc;
- int count;
- int index;
- int i;
-
- /* Determine number of constructors. */
-
- count = 0;
-
- for (i = 0; i < c->methodscount; i++) {
- m = &(c->methods[i]);
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
- (m->name == utf_init))
- count++;
- }
-
- /* Create array of constructors. */
-
- oa = builtin_anewarray(count, class_java_lang_reflect_Constructor);
-
- if (oa == NULL)
- return NULL;
-
- /* Get the constructors and store them in the array. */
-
- for (i = 0, index = 0; i < c->methodscount; i++) {
- m = &(c->methods[i]);
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == 0)) &&
- (m->name == utf_init)) {
- // Create a java.lang.reflect.Constructor object.
-
- rc = java_lang_reflect_Constructor_create(m);
-
- /* Store object into array. */
-
- array_objectarray_element_set(oa, index, rc);
- index++;
- }
- }
-
- return oa;
-}
-#endif
-
-
-/* class_get_declaredfields ****************************************************
-
- Return an array of declared fields of the given class.
-
- ARGUMENTS:
- c ............ class to get the fields of
- publicOnly ... show only public fields
-
- RETURN:
- array of java.lang.reflect.Field
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly)
-{
- java_handle_objectarray_t *oa;
- fieldinfo *f;
- java_handle_t *h;
- int count;
- int index;
- int i;
-
- /* Determine number of fields. */
-
- count = 0;
-
- for (i = 0; i < c->fieldscount; i++)
- if ((c->fields[i].flags & ACC_PUBLIC) || (publicOnly == 0))
- count++;
-
- /* Create array of fields. */
-
- oa = builtin_anewarray(count, class_java_lang_reflect_Field);
-
- if (oa == NULL)
- return NULL;
-
- /* Get the fields and store them in the array. */
-
- for (i = 0, index = 0; i < c->fieldscount; i++) {
- f = &(c->fields[i]);
-
- if ((f->flags & ACC_PUBLIC) || (publicOnly == 0)) {
- // Create a java.lang.reflect.Field object.
-
- h = java_lang_reflect_Field_create(f);
-
- /* Store object into array. */
-
- array_objectarray_element_set(oa, index, h);
- index++;
- }
- }
-
- return oa;
-}
-#endif
-
-
-/* class_get_declaredmethods ***************************************************
-
- Return an array of declared methods of the given class.
-
- ARGUMENTS:
- c ............ class to get the methods of
- publicOnly ... show only public methods
-
- RETURN:
- array of java.lang.reflect.Method
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly)
-{
- java_handle_objectarray_t *oa; /* result: array of Method-objects */
- methodinfo *m; /* the current method to be represented */
- java_handle_t *h;
- int count;
- int index;
- int i;
-
- /* JOWENN: array classes do not declare methods according to mauve
- test. It should be considered, if we should return to my old
- clone method overriding instead of declaring it as a member
- function. */
-
- if (class_is_array(c))
- return builtin_anewarray(0, class_java_lang_reflect_Method);
-
- /* Determine number of methods. */
-
- count = 0;
-
- for (i = 0; i < c->methodscount; i++) {
- m = &(c->methods[i]);
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
- ((m->name != utf_init) && (m->name != utf_clinit)) &&
- !(m->flags & ACC_MIRANDA))
- count++;
- }
-
- /* Create array of methods. */
-
- oa = builtin_anewarray(count, class_java_lang_reflect_Method);
-
- if (oa == NULL)
- return NULL;
-
- /* Get the methods and store them in the array. */
-
- for (i = 0, index = 0; i < c->methodscount; i++) {
- m = &(c->methods[i]);
-
- if (((m->flags & ACC_PUBLIC) || (publicOnly == false)) &&
- ((m->name != utf_init) && (m->name != utf_clinit)) &&
- !(m->flags & ACC_MIRANDA)) {
- // Create java.lang.reflect.Method object.
-
- h = java_lang_reflect_Method_create(m);
-
- /* Store object into array. */
-
- array_objectarray_element_set(oa, index, h);
- index++;
- }
- }
-
- return oa;
-}
-#endif
-
-
-/* class_get_declaringclass ****************************************************
-
- If the class or interface given is a member of another class,
- return the declaring class. For array and primitive classes return
- NULL.
-
-*******************************************************************************/
-
-classinfo *class_get_declaringclass(classinfo *c)
-{
- classref_or_classinfo cr;
- classinfo *dc;
-
- /* Get declaring class. */
-
- cr = c->declaringclass;
-
- if (cr.any == NULL)
- return NULL;
-
- /* Resolve the class if necessary. */
-
- if (IS_CLASSREF(cr)) {
-/* dc = resolve_classref_eager(cr.ref); */
- dc = resolve_classref_or_classinfo_eager(cr, true);
-
- if (dc == NULL)
- return NULL;
-
- /* Store the resolved class in the class structure. */
-
- cr.cls = dc;
- }
-
- dc = cr.cls;
-
- return dc;
-}
-
-
-/* class_get_enclosingclass ****************************************************
-
- Return the enclosing class for the given class.
-
-*******************************************************************************/
-
-classinfo *class_get_enclosingclass(classinfo *c)
-{
- classref_or_classinfo cr;
- classinfo *ec;
-
- /* Get enclosing class. */
-
- cr = c->enclosingclass;
-
- if (cr.any == NULL)
- return NULL;
-
- /* Resolve the class if necessary. */
-
- if (IS_CLASSREF(cr)) {
-/* ec = resolve_classref_eager(cr.ref); */
- ec = resolve_classref_or_classinfo_eager(cr, true);
-
- if (ec == NULL)
- return NULL;
-
- /* Store the resolved class in the class structure. */
-
- cr.cls = ec;
- }
-
- ec = cr.cls;
-
- return ec;
-}
-
-
-/**
- * Return the enclosing constructor as java.lang.reflect.Constructor
- * object for the given class.
- *
- * @param c class to return the enclosing constructor for
- *
- * @return java.lang.reflect.Constructor object of the enclosing
- * constructor
- */
-#if defined(ENABLE_JAVASE)
-java_handle_t* class_get_enclosingconstructor(classinfo *c)
-{
- methodinfo* m;
- java_handle_t* rc;
-
- m = class_get_enclosingmethod_raw(c);
-
- if (m == NULL)
- return NULL;
-
- /* Check for <init>. */
-
- if (m->name != utf_init)
- return NULL;
-
- // Create a java.lang.reflect.Constructor object.
-
- rc = java_lang_reflect_Constructor_create(m);
-
- return rc;
-}
-#endif
-
-
-/* class_get_enclosingmethod ***************************************************
-
- Return the enclosing method for the given class.
-
- IN:
- c ... class to return the enclosing method for
-
- RETURN:
- methodinfo of the enclosing method
-
-*******************************************************************************/
-
-methodinfo *class_get_enclosingmethod_raw(classinfo *c)
-{
- constant_nameandtype *cn;
- classinfo *ec;
- methodinfo *m;
-
- /* get enclosing class and method */
-
- ec = class_get_enclosingclass(c);
- cn = c->enclosingmethod;
-
- /* check for enclosing class and method */
-
- if (ec == NULL)
- return NULL;
-
- if (cn == NULL)
- return NULL;
-
- /* find method in enclosing class */
-
- m = class_findmethod(ec, cn->name, cn->descriptor);
-
- if (m == NULL) {
- exceptions_throw_internalerror("Enclosing method doesn't exist");
- return NULL;
- }
-
- return m;
-}
-
-
-/**
- * Return the enclosing method as java.lang.reflect.Method object for
- * the given class.
- *
- * @param c class to return the enclosing method for
- *
- * @return java.lang.reflect.Method object of the enclosing method
- */
-#if defined(ENABLE_JAVASE)
-java_handle_t* class_get_enclosingmethod(classinfo *c)
-{
- methodinfo* m;
- java_handle_t* rm;
-
- m = class_get_enclosingmethod_raw(c);
-
- if (m == NULL)
- return NULL;
-
- /* check for <init> */
-
- if (m->name == utf_init)
- return NULL;
-
- // Create a java.lang.reflect.Method object.
-
- rm = java_lang_reflect_Method_create(m);
-
- return rm;
-}
-#endif
-
-
-/* class_get_interfaces ********************************************************
-
- Return an array of interfaces of the given class.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *class_get_interfaces(classinfo *c)
-{
- classinfo *ic;
- java_handle_objectarray_t *oa;
- u4 i;
-
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- return NULL;
-
- oa = builtin_anewarray(c->interfacescount, class_java_lang_Class);
-
- if (oa == NULL)
- return NULL;
-
- for (i = 0; i < c->interfacescount; i++) {
- ic = c->interfaces[i];
-
- LLNI_array_direct(oa, i) = (java_object_t *) ic;
- }
-
- return oa;
-}
-
-
-/* class_get_annotations *******************************************************
-
- Get the unparsed declared annotations in a byte array
- of the given class.
-
- IN:
- c........the class of which the annotations should be returned
-
- RETURN VALUE:
- The unparsed declared annotations in a byte array
- (or NULL if there aren't any).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *class_get_annotations(classinfo *c)
-{
-#if defined(ENABLE_ANNOTATIONS)
- java_handle_t *annotations; /* unparsed annotations */
-
- LLNI_classinfo_field_get(c, annotations, annotations);
-
- return (java_handle_bytearray_t*)annotations;
-#else
- return NULL;
-#endif
-}
-
-
-/* class_get_modifiers *********************************************************
-
- Get the modifier flags of the given class.
-
- IN:
- c....the class of which the modifier flags should be returned
- ignoreInnerClassesAttrib
- RETURN VALUE:
- modifier flags
-
-*******************************************************************************/
-
-int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib)
-{
- classref_or_classinfo inner;
- classref_or_classinfo outer;
- utf *innername;
- int i;
-
- if (!ignoreInnerClassesAttrib && (c->innerclasscount != 0)) {
- /* search for passed class as inner class */
-
- for (i = 0; i < c->innerclasscount; i++) {
- inner = c->innerclass[i].inner_class;
- outer = c->innerclass[i].outer_class;
-
- /* Check if inner is a classref or a real class and get
- the name of the structure */
-
- innername = IS_CLASSREF(inner) ? inner.ref->name : inner.cls->name;
-
- /* innerclass is this class */
-
- if (innername == c->name) {
- /* has the class actually an outer class? */
-
- if (outer.any)
- /* return flags got from the outer class file */
- return c->innerclass[i].flags & ACC_CLASS_REFLECT_MASK;
- else
- return c->flags & ACC_CLASS_REFLECT_MASK;
- }
- }
- }
-
- /* passed class is no inner class or it was not requested */
-
- return c->flags & ACC_CLASS_REFLECT_MASK;
-}
-
-
-/* class_get_signature *********************************************************
-
- Return the signature of the given class. For array and primitive
- classes return NULL.
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-utf *class_get_signature(classinfo *c)
-{
- /* For array and primitive classes return NULL. */
-
- if (class_is_array(c) || class_is_primitive(c))
- return NULL;
-
- return c->signature;
-}
-#endif
-
-
-/* class_printflags ************************************************************
-
- Prints flags of a class.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_printflags(classinfo *c)
-{
- if (c == NULL) {
- printf("NULL");
- return;
- }
-
- if (c->flags & ACC_PUBLIC) printf(" PUBLIC");
- if (c->flags & ACC_PRIVATE) printf(" PRIVATE");
- if (c->flags & ACC_PROTECTED) printf(" PROTECTED");
- if (c->flags & ACC_STATIC) printf(" STATIC");
- if (c->flags & ACC_FINAL) printf(" FINAL");
- if (c->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
- if (c->flags & ACC_VOLATILE) printf(" VOLATILE");
- if (c->flags & ACC_TRANSIENT) printf(" TRANSIENT");
- if (c->flags & ACC_NATIVE) printf(" NATIVE");
- if (c->flags & ACC_INTERFACE) printf(" INTERFACE");
- if (c->flags & ACC_ABSTRACT) printf(" ABSTRACT");
-}
-#endif
-
-
-/* class_print *****************************************************************
-
- Prints classname plus flags.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_print(classinfo *c)
-{
- if (c == NULL) {
- printf("NULL");
- return;
- }
-
- utf_display_printable_ascii(c->name);
- class_printflags(c);
-}
-#endif
-
-
-/* class_classref_print ********************************************************
-
- Prints classname plus referer class.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_classref_print(constant_classref *cr)
-{
- if (cr == NULL) {
- printf("NULL");
- return;
- }
-
- utf_display_printable_ascii(cr->name);
- printf("(ref.by ");
- if (cr->referer)
- class_print(cr->referer);
- else
- printf("NULL");
- printf(")");
-}
-#endif
-
-
-/* class_println ***************************************************************
-
- Prints classname plus flags and new line.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_println(classinfo *c)
-{
- class_print(c);
- printf("\n");
-}
-#endif
-
-
-/* class_classref_println ******************************************************
-
- Prints classname plus referer class and new line.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_classref_println(constant_classref *cr)
-{
- class_classref_print(cr);
- printf("\n");
-}
-#endif
-
-
-/* class_classref_or_classinfo_print *******************************************
-
- Prints classname plus referer class.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_classref_or_classinfo_print(classref_or_classinfo c)
-{
- if (c.any == NULL) {
- printf("(classref_or_classinfo) NULL");
- return;
- }
- if (IS_CLASSREF(c))
- class_classref_print(c.ref);
- else
- class_print(c.cls);
-}
-#endif
-
-
-/* class_classref_or_classinfo_println *****************************************
-
- Prints classname plus referer class and a newline.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_classref_or_classinfo_println(classref_or_classinfo c)
-{
- class_classref_or_classinfo_print(c);
- printf("\n");
-}
-#endif
-
-
-/* class_showconstantpool ******************************************************
-
- Dump the constant pool of the given class to stdout.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_showconstantpool (classinfo *c)
-{
- u4 i;
- void* e;
-
- printf ("---- dump of constant pool ----\n");
-
- for (i=0; i<c->cpcount; i++) {
- printf ("#%d: ", (int) i);
-
- e = c -> cpinfos [i];
- if (e) {
-
- switch (c -> cptags [i]) {
- case CONSTANT_Class:
- printf ("Classreference -> ");
- utf_display_printable_ascii ( ((constant_classref*)e) -> name );
- break;
- case CONSTANT_Fieldref:
- printf ("Fieldref -> ");
- field_fieldref_print((constant_FMIref *) e);
- break;
- case CONSTANT_Methodref:
- printf ("Methodref -> ");
- method_methodref_print((constant_FMIref *) e);
- break;
- case CONSTANT_InterfaceMethodref:
- printf ("InterfaceMethod -> ");
- method_methodref_print((constant_FMIref *) e);
- break;
- case CONSTANT_String:
- printf ("String -> ");
- utf_display_printable_ascii (e);
- break;
- case CONSTANT_Integer:
- printf ("Integer -> %d", (int) ( ((constant_integer*)e) -> value) );
- break;
- case CONSTANT_Float:
- printf ("Float -> %f", ((constant_float*)e) -> value);
- break;
- case CONSTANT_Double:
- printf ("Double -> %f", ((constant_double*)e) -> value);
- break;
- case CONSTANT_Long:
- {
- u8 v = ((constant_long*)e) -> value;
-#if U8_AVAILABLE
- printf ("Long -> %ld", (long int) v);
-#else
- printf ("Long -> HI: %ld, LO: %ld\n",
- (long int) v.high, (long int) v.low);
-#endif
- }
- break;
- case CONSTANT_NameAndType:
- {
- constant_nameandtype *cnt = e;
- printf ("NameAndType: ");
- utf_display_printable_ascii (cnt->name);
- printf (" ");
- utf_display_printable_ascii (cnt->descriptor);
- }
- break;
- case CONSTANT_Utf8:
- printf ("Utf8 -> ");
- utf_display_printable_ascii (e);
- break;
- default:
- log_text("Invalid type of ConstantPool-Entry");
- assert(0);
- }
- }
-
- printf ("\n");
- }
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* class_showmethods ***********************************************************
-
- Dump info about the fields and methods of the given class to stdout.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void class_showmethods (classinfo *c)
-{
- s4 i;
-
- printf("--------- Fields and Methods ----------------\n");
- printf("Flags: ");
- class_printflags(c);
- printf("\n");
-
- printf("This: ");
- utf_display_printable_ascii(c->name);
- printf("\n");
-
- if (c->super) {
- printf("Super: ");
- utf_display_printable_ascii(c->super->name);
- printf ("\n");
- }
-
- printf("Index: %d\n", c->index);
-
- printf("Interfaces:\n");
- for (i = 0; i < c->interfacescount; i++) {
- printf(" ");
- utf_display_printable_ascii(c->interfaces[i]->name);
- printf (" (%d)\n", c->interfaces[i]->index);
- }
-
- printf("Fields:\n");
- for (i = 0; i < c->fieldscount; i++)
- field_println(&(c->fields[i]));
-
- printf("Methods:\n");
- for (i = 0; i < c->methodscount; i++) {
- methodinfo *m = &(c->methods[i]);
-
- if (!(m->flags & ACC_STATIC))
- printf("vftblindex: %d ", m->vftblindex);
-
- method_println(m);
- }
-
- printf ("Virtual function table:\n");
- for (i = 0; i < c->vftbl->vftbllength; i++)
- printf ("entry: %d, %ld\n", i, (long int) (c->vftbl->table[i]));
-}
-#endif /* !defined(NDEBUG) */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/class.h - class related functions header
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _CLASS_H
-#define _CLASS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct classinfo classinfo;
-typedef struct innerclassinfo innerclassinfo;
-typedef struct extra_classref extra_classref;
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-#include "vm/string.hpp"
-
-#if defined(ENABLE_JAVASE)
-# include "vmcore/annotation.h"
-#endif
-
-#include "vmcore/field.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vmcore/utf8.h"
-
-
-/* class state defines ********************************************************/
-
-#define CLASS_LOADING 0x0001
-#define CLASS_LOADED 0x0002
-#define CLASS_LINKING 0x0004
-#define CLASS_LINKED 0x0008
-#define CLASS_INITIALIZING 0x0010
-#define CLASS_INITIALIZED 0x0020
-#define CLASS_ERROR 0x0040
-
-
-/* some macros ****************************************************************/
-
-#define CLASS_IS_OR_ALMOST_INITIALIZED(c) \
- (((c)->state & CLASS_INITIALIZING) || ((c)->state & CLASS_INITIALIZED))
-
-
-/* classinfo ******************************************************************/
-
-/* We define this dummy structure of java_lang_Class so we can
- bootstrap cacaoh without needing a java_lang_Class.h file. Whether
- the size of the dummy structure is big enough is checked during
- runtime in vm_create. */
-
-typedef struct {
- java_object_t header;
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- intptr_t padding[4];
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- intptr_t padding[19];
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
- intptr_t padding[3];
-#else
-# error unknown classpath configuration
-#endif
-} dummy_java_lang_Class;
-
-struct classinfo { /* class structure */
- dummy_java_lang_Class object;
-
- s4 flags; /* ACC flags */
- utf *name; /* class name */
-
- s4 cpcount; /* number of entries in constant pool */
- u1 *cptags; /* constant pool tags */
- void* *cpinfos; /* pointer to constant pool info structures */
-
- s4 classrefcount; /* number of symbolic class references */
- constant_classref *classrefs; /* table of symbolic class references */
- extra_classref *extclassrefs; /* additional classrefs */
- s4 parseddescsize; /* size of the parsed descriptors block */
- u1 *parseddescs; /* parsed descriptors */
-
- classinfo *super; /* super class */
- classinfo *sub; /* sub class pointer */
- classinfo *nextsub; /* pointer to next class in sub class list */
-
- int32_t interfacescount; /* number of interfaces */
- classinfo **interfaces; /* super interfaces */
-
- int32_t fieldscount; /* number of fields */
- fieldinfo *fields; /* field table */
-
- int32_t methodscount; /* number of methods */
- methodinfo *methods; /* method table */
-
- s4 state; /* current class state */
- s4 index; /* hierarchy depth (classes) or index */
- /* (interfaces) */
- s4 instancesize; /* size of an instance of this class */
-
- vftbl_t *vftbl; /* pointer to virtual function table */
-
- methodinfo *finalizer; /* finalizer method */
-
- u2 innerclasscount; /* number of inner classes */
- innerclassinfo *innerclass;
-
- classref_or_classinfo declaringclass;
- classref_or_classinfo enclosingclass; /* enclosing class */
- constant_nameandtype *enclosingmethod; /* enclosing method */
-
- utf *packagename; /* full name of the package */
- utf *sourcefile; /* SourceFile attribute */
-#if defined(ENABLE_JAVASE)
- utf *signature; /* Signature attribute */
-#if defined(ENABLE_ANNOTATIONS)
- /* All the annotation attributes are NULL (and not a zero length array) */
- /* if there is nothing. */
- java_object_t *annotations; /* annotations of this class */
-
- java_object_t *method_annotations; /* array of annotations of the methods */
- java_object_t *method_parameterannotations; /* array of parameter */
- /* annotations of the methods */
- java_object_t *method_annotationdefaults; /* array of annotation default */
- /* values of the methods */
-
- java_object_t *field_annotations; /* array of annotations of the fields */
-
-#endif
-#endif
- classloader_t *classloader; /* NULL for bootstrap classloader */
-
-#if defined(ENABLE_JAVASE)
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- java_object_t *protectiondomain;
- java_objectarray_t *signers;
-# endif
-#endif
-};
-
-
-/* innerclassinfo *************************************************************/
-
-struct innerclassinfo {
- classref_or_classinfo inner_class; /* inner class pointer */
- classref_or_classinfo outer_class; /* outer class pointer */
- utf *name; /* innerclass name */
- s4 flags; /* ACC flags */
-};
-
-
-/* extra_classref **************************************************************
-
- for classrefs not occurring within descriptors
-
-*******************************************************************************/
-
-struct extra_classref {
- extra_classref *next;
- constant_classref classref;
-};
-
-
-/* inline functions ***********************************************************/
-
-/**
- * Returns the classname of the class, where slashes ('/') are
- * replaced by dots ('.').
- *
- * @param c class to get name of
- * @return classname
- */
-inline static java_handle_t* class_get_classname(classinfo* c)
-{
- java_handle_t *s;
-
- /* Create a java string. */
-
- s = javastring_new_slash_to_dot(c->name);
-
- return s;
-}
-
-
-/* class_is_primitive **********************************************************
-
- Checks if the given class is a primitive class.
-
-*******************************************************************************/
-
-static inline bool class_is_primitive(classinfo *c)
-{
- if (c->flags & ACC_CLASS_PRIMITIVE)
- return true;
-
- return false;
-}
-
-
-/* class_is_anonymousclass *****************************************************
-
- Checks if the given class is an anonymous class.
-
-*******************************************************************************/
-
-static inline bool class_is_anonymousclass(classinfo *c)
-{
- if (c->flags & ACC_CLASS_ANONYMOUS)
- return true;
-
- return false;
-}
-
-
-/* class_is_array **************************************************************
-
- Checks if the given class is an array class.
-
-*******************************************************************************/
-
-static inline bool class_is_array(classinfo *c)
-{
- if (!(c->state & CLASS_LINKED))
- if (!link_class(c))
- return false;
-
- return (c->vftbl->arraydesc != NULL);
-}
-
-
-/* class_is_interface **********************************************************
-
- Checks if the given class is an interface.
-
-*******************************************************************************/
-
-static inline bool class_is_interface(classinfo *c)
-{
- if (c->flags & ACC_INTERFACE)
- return true;
-
- return false;
-}
-
-
-/* class_is_localclass *********************************************************
-
- Checks if the given class is a local class.
-
-*******************************************************************************/
-
-static inline bool class_is_localclass(classinfo *c)
-{
- if ((c->enclosingmethod != NULL) && !class_is_anonymousclass(c))
- return true;
-
- return false;
-}
-
-
-/* class_is_memberclass ********************************************************
-
- Checks if the given class is a member class.
-
-*******************************************************************************/
-
-static inline bool class_is_memberclass(classinfo *c)
-{
- if (c->flags & ACC_CLASS_MEMBER)
- return true;
-
- return false;
-}
-
-
-/* class_get_classloader *******************************************************
-
- Return the classloader of the given class.
-
-*******************************************************************************/
-
-static inline classloader_t *class_get_classloader(classinfo *c)
-{
- classloader_t *cl;
-
- cl = c->classloader;
-
- /* The classloader may be NULL. */
-
- return cl;
-}
-
-
-/* class_get_superclass ********************************************************
-
- Return the super class of the given class.
-
-*******************************************************************************/
-
-static inline classinfo *class_get_superclass(classinfo *c)
-{
- /* For interfaces we return NULL. */
-
- if (c->flags & ACC_INTERFACE)
- return NULL;
-
- /* For java/lang/Object, primitive-type and Void classes c->super
- is NULL and we return NULL. */
-
- return c->super;
-}
-
-
-/* function prototypes ********************************************************/
-
-classinfo *class_create_classinfo(utf *u);
-void class_postset_header_vftbl(void);
-classinfo *class_define(utf *name, classloader_t *cl, int32_t length, uint8_t *data, java_handle_t *pd);
-void class_set_packagename(classinfo *c);
-
-bool class_load_attributes(classbuffer *cb);
-
-/* retrieve constantpool element */
-void* class_getconstant(classinfo *c, u4 pos, u4 ctype);
-void* innerclass_getconstant(classinfo *c, u4 pos, u4 ctype);
-
-/* frees all resources used by the class */
-void class_free(classinfo *);
-
-/* return an array class with the given component class */
-classinfo *class_array_of(classinfo *component,bool link);
-
-/* return an array class with the given dimension and element class */
-classinfo *class_multiarray_of(s4 dim, classinfo *element,bool link);
-
-/* return a classref for the given class name */
-/* (does a linear search!) */
-constant_classref *class_lookup_classref(classinfo *cls,utf *name);
-
-/* return a classref for the given class name */
-/* (does a linear search!) */
-constant_classref *class_get_classref(classinfo *cls,utf *name);
-
-/* return a classref to the class itself */
-/* (does a linear search!) */
-constant_classref *class_get_self_classref(classinfo *cls);
-
-/* return a classref for an array with the given dimension of with the */
-/* given component type */
-constant_classref *class_get_classref_multiarray_of(s4 dim,constant_classref *ref);
-
-/* return a classref for the component type of the given array type */
-constant_classref *class_get_classref_component_of(constant_classref *ref);
-
-/* get a class' field by name and descriptor */
-fieldinfo *class_findfield(classinfo *c, utf *name, utf *desc);
-
-/* search 'classinfo'-structure for a field with the specified name */
-fieldinfo *class_findfield_by_name(classinfo *c, utf *name);
-
-/* search class for a field */
-fieldinfo *class_resolvefield(classinfo *c, utf *name, utf *desc, classinfo *referer);
-
-/* search for a method with a specified name and descriptor */
-methodinfo *class_findmethod(classinfo *c, utf *name, utf *desc);
-methodinfo *class_resolvemethod(classinfo *c, utf *name, utf *dest);
-methodinfo *class_resolveclassmethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
-methodinfo *class_resolveinterfacemethod(classinfo *c, utf *name, utf *dest, classinfo *referer, bool throwexception);
-
-bool class_issubclass(classinfo *sub, classinfo *super);
-bool class_isanysubclass(classinfo *sub, classinfo *super);
-bool class_is_assignable_from(classinfo *to, classinfo *from);
-bool class_is_instance(classinfo *c, java_handle_t *h);
-
-classloader_t *class_get_classloader(classinfo *c);
-classinfo *class_get_superclass(classinfo *c);
-classinfo *class_get_componenttype(classinfo *c);
-java_handle_objectarray_t *class_get_declaredclasses(classinfo *c, bool publicOnly);
-java_handle_objectarray_t *class_get_declaredconstructors(classinfo *c, bool publicOnly);
-java_handle_objectarray_t *class_get_declaredfields(classinfo *c, bool publicOnly);
-java_handle_objectarray_t *class_get_declaredmethods(classinfo *c, bool publicOnly);
-classinfo *class_get_declaringclass(classinfo *c);
-classinfo *class_get_enclosingclass(classinfo *c);
-java_handle_t* class_get_enclosingconstructor(classinfo *c);
-methodinfo* class_get_enclosingmethod_raw(classinfo *c);
-java_handle_t* class_get_enclosingmethod(classinfo *c);
-java_handle_objectarray_t *class_get_interfaces(classinfo *c);
-java_handle_bytearray_t *class_get_annotations(classinfo *c);
-int32_t class_get_modifiers(classinfo *c, bool ignoreInnerClassesAttrib);
-java_handle_t *class_get_name(classinfo *c);
-
-#if defined(ENABLE_JAVASE)
-utf *class_get_signature(classinfo *c);
-#endif
-
-/* some debugging functions */
-
-#if !defined(NDEBUG)
-void class_printflags(classinfo *c);
-void class_print(classinfo *c);
-void class_println(classinfo *c);
-void class_classref_print(constant_classref *cr);
-void class_classref_println(constant_classref *cr);
-void class_classref_or_classinfo_print(classref_or_classinfo c);
-void class_classref_or_classinfo_println(classref_or_classinfo c);
-#endif
-
-/* debug purposes */
-void class_showmethods(classinfo *c);
-void class_showconstantpool(classinfo *c);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CLASS_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/classcache.c - loaded class cache and loading constraints
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
-
-#include "vm/exceptions.hpp"
-
-#include "vmcore/classcache.h"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
-
-/*************************************************************************
-
- Class Cache
-
- The classcache has two functions:
-
- 1) caching the resolution of class references
- 2) storing and checking loading constraints
-
- We will use the following terms in this description:
-
- N a class name: a utf string
- (N,L) a class reference with initiating loader L and class name N
- C a class (object): the result of resolving a reference (N,L)
- We will write resultion as
- C = *(N,L)
- (N,L1,L2) a loading constraint indicating that (N,L1) and (N,L2) must
- resolve to the same class C. So (N,L1,L2) means
- *(N,L1) = *(N,L2)
-
- The functions of the classcache require:
-
- 1) a mapping (N,L) |--> C for looking up prior resolution results.
- 2) storing the current set of loading constraints { (N,L1,L2) }
-
- These functions can be rearranged like that:
-
- a mapping N |--> (a mapping L |--> C or NULL,
- a set of constraints {(L1,L2)})
-
- Thus we can treat the mapping and constraints for each name N
- separately. The implementation does this by keeping a hash table
- mapping a name N to a `classcache_name_entry` which contains all
- info with respect to N.
-
- For a class name N we can define an equivalence relation ~N~ on
- class loaders:
-
- L1 ~N~ L2 <==> *(N,L1) = *(N,L2)
-
- A loading constraint (N,L1,L2) implies L1 ~N~ L2.
-
- Also, if two references (N,L1) and (N,L2) resolve to the same class C
- we have L1 ~N~ L2 because class loaders are required to return
- consistent resolutions for a name N [XXX].
-
- A `classcache_name_entry` keeps a set of tuples { (Cx,IL,CL) },
- where
- Cx...is a class C or NULL
- IL...is the set of initiating loaders
- CL...is the set of constrained loaders
-
- Such a tuple is called `classcache_class_entry` in the source code.
-
- The following holds for each tuple (Cx,IL,CL):
-
- . (Cx is NULL) implies IL = {}.
-
- . If Cx is a class, IL is the set of loaders that have been
- recorded as initiating loaders for Cx. IL may be the
- empty set {} in case Cx has already been defined but no
- initiating loader has been recorded, yet.
-
- . (IL u CL) is a subset of an equivalence class of ~N~.
-
- (This means that all loaders in IL and CL must resolve
- the name N to the same class.)
-
- The following holds for the set of tuples { (Cx,IL,CL) }:
-
- . For a given class C there is at most one tuple with Cx = C
- in the set. (There may be an arbitrary number of tuples
- with Cx = NULL, however.)
-
- . For a given loader L there is at most one tuple with
- L in (IL u CL).
-
- The implementation stores sets of loaders as linked lists of
- `classcache_loader_entry`s.
-
- Comments about manipulating the classcache can be found in the
- individual functions below.
-
-*************************************************************************/
-
-
-/* initial number of slots in the classcache hash table */
-#define CLASSCACHE_INIT_SIZE 2048
-
-/*============================================================================*/
-/* DEBUG HELPERS */
-/*============================================================================*/
-
-/* #define CLASSCACHE_VERBOSE */
-
-/*============================================================================*/
-/* STATISTICS */
-/*============================================================================*/
-
-/*#define CLASSCACHE_STATS*/
-
-#ifdef CLASSCACHE_STATS
-static int stat_classnames_stored = 0;
-static int stat_classes_stored = 0;
-static int stat_trivial_constraints = 0;
-static int stat_nontriv_constraints = 0;
-static int stat_nontriv_constraints_both = 0;
-static int stat_nontriv_constraints_merged = 0;
-static int stat_nontriv_constraints_one = 0;
-static int stat_nontriv_constraints_none = 0;
-static int stat_new_loader_entry = 0;
-static int stat_merge_class_entries = 0;
-static int stat_merge_loader_entries = 0;
-static int stat_lookup = 0;
-static int stat_lookup_class_entry_checked = 0;
-static int stat_lookup_loader_checked = 0;
-static int stat_lookup_name = 0;
-static int stat_lookup_name_entry = 0;
-static int stat_lookup_name_notfound = 0;
-static int stat_lookup_new_name = 0;
-static int stat_lookup_new_name_entry = 0;
-static int stat_lookup_new_name_collisions = 0;
-static int stat_rehash_names = 0;
-static int stat_rehash_names_collisions = 0;
-
-#define CLASSCACHE_COUNT(cnt) (cnt)++
-#define CLASSCACHE_COUNTIF(cond,cnt) do{if(cond) (cnt)++;} while(0)
-
-void classcache_print_statistics(FILE *file) {
- fprintf(file,"classnames stored : %8d\n",stat_classnames_stored);
- fprintf(file,"classes stored : %8d\n",stat_classes_stored);
- fprintf(file,"trivial constraints : %8d\n",stat_trivial_constraints);
- fprintf(file,"non-triv constraints: %8d\n",stat_nontriv_constraints);
- fprintf(file," both loaders rec.: %8d\n",stat_nontriv_constraints_both);
- fprintf(file," merged : %8d\n",stat_nontriv_constraints_merged);
- fprintf(file," one loader rec. : %8d\n",stat_nontriv_constraints_one);
- fprintf(file," no loaders rec. : %8d\n",stat_nontriv_constraints_none);
- fprintf(file,"new loader entries : %8d\n",stat_new_loader_entry);
- fprintf(file,"merge class entries : %8d\n",stat_merge_class_entries);
- fprintf(file,"merge loader entries: %8d\n",stat_merge_loader_entries);
- fprintf(file,"lookups : %8d\n",stat_lookup);
- fprintf(file," class entries ckd: %8d\n",stat_lookup_class_entry_checked);
- fprintf(file," loader checked : %8d\n",stat_lookup_loader_checked);
- fprintf(file,"lookup name : %8d\n",stat_lookup_name);
- fprintf(file," entries checked : %8d\n",stat_lookup_name_entry);
- fprintf(file," not found : %8d\n",stat_lookup_name_notfound);
- fprintf(file,"lookup (new) name : %8d\n",stat_lookup_new_name);
- fprintf(file," entries checked : %8d\n",stat_lookup_new_name_entry);
- fprintf(file," new collisions : %8d\n",stat_lookup_new_name_collisions);
- fprintf(file,"names rehashed : %8d times\n",stat_rehash_names);
- fprintf(file," collisions : %8d\n",stat_rehash_names_collisions);
-}
-#else
-#define CLASSCACHE_COUNT(cnt)
-#define CLASSCACHE_COUNTIF(cond,cnt)
-#endif
-
-/*============================================================================*/
-/* THREAD-SAFE LOCKING */
-/*============================================================================*/
-
- /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
- /* CAUTION: The static functions below are */
- /* NOT synchronized! */
- /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
-
-#if defined(ENABLE_THREADS)
-# define CLASSCACHE_LOCK() LOCK_MONITOR_ENTER(lock_hashtable_classcache)
-# define CLASSCACHE_UNLOCK() LOCK_MONITOR_EXIT(lock_hashtable_classcache)
-#else
-# define CLASSCACHE_LOCK()
-# define CLASSCACHE_UNLOCK()
-#endif
-
-/*============================================================================*/
-/* GLOBAL VARIABLES */
-/*============================================================================*/
-
-hashtable hashtable_classcache;
-
-#if defined(ENABLE_THREADS)
-static java_object_t *lock_hashtable_classcache;
-#endif
-
-
-/*============================================================================*/
-/* */
-/*============================================================================*/
-
-/* prototypes */
-
-static void classcache_free_class_entry(classcache_class_entry *clsen);
-static void classcache_remove_class_entry(classcache_name_entry *en,
- classcache_class_entry *clsen);
-
-/* hash function to use */
-
-#define CLASSCACHE_HASH utf_full_hashkey
-
-/* classcache_init *************************************************************
-
- Initialize the class cache
-
- Note: NOT synchronized!
-
-*******************************************************************************/
-
-bool classcache_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("classcache_init");
-
- /* create the hashtable */
-
- hashtable_create(&hashtable_classcache, CLASSCACHE_INIT_SIZE);
-
-#if defined(ENABLE_THREADS)
- /* create utf hashtable lock object */
-
- lock_hashtable_classcache = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(lock_hashtable_classcache);
-#endif
-
- /* everything's ok */
-
- return true;
-}
-
-/* classcache_new_loader_entry *************************************************
-
- Create a new classcache_loader_entry struct
- (internally used helper function)
-
- IN:
- loader...........the ClassLoader object
- next.............the next classcache_loader_entry
-
- RETURN VALUE:
- the new classcache_loader_entry
-
-*******************************************************************************/
-
-static classcache_loader_entry * classcache_new_loader_entry(
- classloader_t * loader,
- classcache_loader_entry * next)
-{
- classcache_loader_entry *lden;
-
- lden = NEW(classcache_loader_entry);
- lden->loader = loader;
- lden->next = next;
- CLASSCACHE_COUNT(stat_new_loader_entry);
-
- return lden;
-}
-
-/* classcache_merge_loaders ****************************************************
-
- Merge two lists of loaders into one
- (internally used helper function)
-
- IN:
- lista............first list (may be NULL)
- listb............second list (may be NULL)
-
- RETURN VALUE:
- the merged list (may be NULL)
-
- NOTE:
- The lists given as arguments are destroyed!
-
-*******************************************************************************/
-
-static classcache_loader_entry * classcache_merge_loaders(
- classcache_loader_entry * lista,
- classcache_loader_entry * listb)
-{
- classcache_loader_entry *result;
- classcache_loader_entry *ldenA;
- classcache_loader_entry *ldenB;
- classcache_loader_entry **chain;
-
- CLASSCACHE_COUNT(stat_merge_loader_entries);
-
- /* XXX This is a quadratic algorithm. If this ever
- * becomes a problem, the loader lists should be
- * stored as sorted lists and merged in linear time. */
-
- result = NULL;
- chain = &result;
-
- for (ldenA = lista; ldenA; ldenA = ldenA->next) {
-
- for (ldenB = listb; ldenB; ldenB = ldenB->next) {
- if (ldenB->loader == ldenA->loader)
- goto common_element;
- }
-
- /* this loader is only in lista */
- *chain = ldenA;
- chain = &(ldenA->next);
-
- common_element:
- /* XXX free the duplicated element */
- ;
- }
-
- /* concat listb to the result */
- *chain = listb;
-
- return result;
-}
-
-/* classcache_merge_class_entries **********************************************
-
- Merge two `classcache_class_entry`s into one.
- (internally used helper function)
-
- IN:
- en...............the classcache_name_entry containing both class entries
- clsenA...........first class entry, will receive the result
- clsenB...........second class entry
-
- PRE-CONDITION:
- Either both entries must have the same classobj, or one of them has
- classobj == NULL.
-
- NOTE:
- clsenB is freed by this function!
-
-*******************************************************************************/
-
-static void classcache_merge_class_entries(classcache_name_entry *en,
- classcache_class_entry *clsenA,
- classcache_class_entry *clsenB)
-{
-#ifdef CLASSCACHE_VERBOSE
- char logbuffer[1024];
-#endif
-
- assert(en);
- assert(clsenA);
- assert(clsenB);
- assert(!clsenA->classobj || !clsenB->classobj || clsenA->classobj == clsenB->classobj);
-
-#ifdef CLASSCACHE_VERBOSE
- sprintf(logbuffer,"classcache_merge_class_entries(%p,%p->%p,%p->%p) ",
- (void*)en,(void*)clsenA,(void*)clsenA->classobj,(void*)clsenB,(void*)clsenB->classobj);
- if (clsenA->classobj)
- utf_cat_classname(logbuffer, clsenA->classobj->name);
- if (clsenB->classobj)
- utf_cat_classname(logbuffer, clsenB->classobj->name);
- log_println(logbuffer);
-#endif
-
- CLASSCACHE_COUNT(stat_merge_class_entries);
-
- /* clsenB will be merged into clsenA */
- clsenA->loaders = classcache_merge_loaders(clsenA->loaders, clsenB->loaders);
- clsenB->loaders = NULL; /* these have been freed or reused */
-
- clsenA->constraints = classcache_merge_loaders(clsenA->constraints,
- clsenB->constraints);
- clsenB->constraints = NULL; /* these have been freed or reused */
-
- if (!clsenA->classobj)
- clsenA->classobj = clsenB->classobj;
-
- /* remove clsenB from the list of class entries */
- classcache_remove_class_entry(en, clsenB);
-}
-
-
-/* classcache_lookup_name ******************************************************
-
- Lookup a name in the first level of the cache
- (internally used helper function)
-
- IN:
- name.............the name to look up
-
- RETURN VALUE:
- a pointer to the classcache_name_entry for this name, or
- null if no entry was found.
-
-*******************************************************************************/
-
-static classcache_name_entry *classcache_lookup_name(utf *name)
-{
- classcache_name_entry *c; /* hash table element */
- u4 key; /* hashkey computed from classname */
- u4 slot; /* slot in hashtable */
-
- CLASSCACHE_COUNT(stat_lookup_name);
-
- key = CLASSCACHE_HASH(name->text, (u4) name->blength);
- slot = key & (hashtable_classcache.size - 1);
- c = hashtable_classcache.ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (c) {
- /* entry found in hashtable */
- CLASSCACHE_COUNT(stat_lookup_name_entry);
-
- if (c->name == name)
- return c;
-
- c = c->hashlink; /* next element in external chain */
- }
-
- /* not found */
-
- CLASSCACHE_COUNT(stat_lookup_name_notfound);
- return NULL;
-}
-
-
-/* classcache_new_name *********************************************************
-
- Return a classcache_name_entry for the given name. The entry is created
- if it is not already in the cache.
- (internally used helper function)
-
- IN:
- name.............the name to look up / create an entry for
-
- RETURN VALUE:
- a pointer to the classcache_name_entry for this name
-
-*******************************************************************************/
-
-static classcache_name_entry *classcache_new_name(utf *name)
-{
- classcache_name_entry *c; /* hash table element */
- u4 key; /* hashkey computed from classname */
- u4 slot; /* slot in hashtable */
- u4 i;
-
- CLASSCACHE_COUNT(stat_lookup_new_name);
-
- key = CLASSCACHE_HASH(name->text, (u4) name->blength);
- slot = key & (hashtable_classcache.size - 1);
- c = hashtable_classcache.ptr[slot];
-
- /* search external hash chain for the entry */
-
- while (c) {
- /* entry found in hashtable */
- CLASSCACHE_COUNT(stat_lookup_new_name_entry);
-
- if (c->name == name)
- return c;
-
- c = c->hashlink; /* next element in external chain */
- }
-
- /* location in hashtable found, create new entry */
-
- c = NEW(classcache_name_entry);
-
- c->name = name;
- c->classes = NULL;
-
- /* insert entry into hashtable */
- c->hashlink = (classcache_name_entry *) hashtable_classcache.ptr[slot];
- CLASSCACHE_COUNTIF(c->hashlink,stat_lookup_new_name_collisions);
- hashtable_classcache.ptr[slot] = c;
-
- /* update number of hashtable-entries */
- hashtable_classcache.entries++;
- CLASSCACHE_COUNT(stat_classnames_stored);
-
- if ((hashtable_classcache.entries*2) > hashtable_classcache.size) {
- /* reorganization of hashtable */
-
- classcache_name_entry *c2;
- hashtable newhash; /* the new hashtable */
-
- CLASSCACHE_COUNT(stat_rehash_names);
-
- /* create new hashtable, double the size */
-
- hashtable_create(&newhash, hashtable_classcache.size * 2);
- newhash.entries = hashtable_classcache.entries;
-
- /* transfer elements to new hashtable */
-
- for (i = 0; i < hashtable_classcache.size; i++) {
- c2 = (classcache_name_entry *) hashtable_classcache.ptr[i];
- while (c2) {
- classcache_name_entry *nextc = c2->hashlink;
- u4 newslot =
- (CLASSCACHE_HASH(c2->name->text, (u4) c2->name->blength)) & (newhash.size - 1);
-
- c2->hashlink = (classcache_name_entry *) newhash.ptr[newslot];
- CLASSCACHE_COUNTIF(c2->hashlink,stat_rehash_names_collisions);
- newhash.ptr[newslot] = c2;
-
- c2 = nextc;
- }
- }
-
- /* dispose old table */
-
- MFREE(hashtable_classcache.ptr, void *, hashtable_classcache.size);
- hashtable_classcache = newhash;
- }
-
- return c;
-}
-
-
-/* classcache_lookup ***********************************************************
-
- Lookup a possibly loaded class
-
- IN:
- initloader.......initiating loader for resolving the class name
- classname........class name to look up
-
- RETURN VALUE:
- The return value is a pointer to the cached class object,
- or NULL, if the class is not in the cache.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-classinfo *classcache_lookup(classloader_t *initloader, utf *classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
- classinfo *cls = NULL;
-
- CLASSCACHE_LOCK();
-
- CLASSCACHE_COUNT(stat_lookup);
- en = classcache_lookup_name(classname);
-
- if (en) {
- /* iterate over all class entries */
-
- for (clsen = en->classes; clsen; clsen = clsen->next) {
- CLASSCACHE_COUNT(stat_lookup_class_entry_checked);
- /* check if this entry has been loaded by initloader */
-
- for (lden = clsen->loaders; lden; lden = lden->next) {
- CLASSCACHE_COUNT(stat_lookup_loader_checked);
- if (lden->loader == initloader) {
- /* found the loaded class entry */
-
- assert(clsen->classobj);
- cls = clsen->classobj;
- goto found;
- }
- }
- }
- }
-
- found:
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-
-/* classcache_lookup_defined ***************************************************
-
- Lookup a class with the given name and defining loader
-
- IN:
- defloader........defining loader
- classname........class name
-
- RETURN VALUE:
- The return value is a pointer to the cached class object,
- or NULL, if the class is not in the cache.
-
-*******************************************************************************/
-
-classinfo *classcache_lookup_defined(classloader_t *defloader, utf *classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classinfo *cls = NULL;
-
- CLASSCACHE_LOCK();
-
- en = classcache_lookup_name(classname);
-
- if (en) {
- /* iterate over all class entries */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
- if (!clsen->classobj)
- continue;
-
- /* check if this entry has been defined by defloader */
- if (clsen->classobj->classloader == defloader) {
- cls = clsen->classobj;
- goto found;
- }
- }
- }
-
- found:
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-
-/* classcache_lookup_defined_or_initiated **************************************
-
- Lookup a class that has been defined or initiated by the given loader
-
- IN:
- loader...........defining or initiating loader
- classname........class name to look up
-
- RETURN VALUE:
- The return value is a pointer to the cached class object,
- or NULL, if the class is not in the cache.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-classinfo *classcache_lookup_defined_or_initiated(classloader_t *loader,
- utf *classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
- classinfo *cls = NULL;
-
- CLASSCACHE_LOCK();
-
- en = classcache_lookup_name(classname);
-
- if (en) {
- /* iterate over all class entries */
-
- for (clsen = en->classes; clsen; clsen = clsen->next) {
-
- /* check if this entry has been defined by loader */
- if (clsen->classobj && clsen->classobj->classloader == loader) {
- cls = clsen->classobj;
- goto found;
- }
-
- /* check if this entry has been initiated by loader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == loader) {
- /* found the loaded class entry */
-
- assert(clsen->classobj);
- cls = clsen->classobj;
- goto found;
- }
- }
- }
- }
-
- found:
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-
-/* classcache_store ************************************************************
-
- Store a loaded class. If a class of the same name has already been stored
- with the same initiating loader, then the given class CLS is freed (if
- possible) and the previously stored class is returned.
-
- IN:
- initloader.......initiating loader used to load the class
- (may be NULL indicating the bootstrap loader)
- cls..............class object to cache
- mayfree..........true if CLS may be freed in case another class is
- returned
-
- RETURN VALUE:
- cls..............everything ok, the class was stored in the cache,
- other classinfo..another class with the same (initloader,name) has been
- stored earlier. CLS has been freed[1] and the earlier
- stored class is returned.
- NULL.............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
- [1]...in case MAYFREE is true
-
-*******************************************************************************/
-
-classinfo *classcache_store(classloader_t *initloader, classinfo *cls,
- bool mayfree)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- classcache_class_entry *clsenB;
- classcache_loader_entry *lden;
-#ifdef CLASSCACHE_VERBOSE
- char logbuffer[1024];
-#endif
-
- assert(cls);
- assert(cls->state & CLASS_LOADED);
-
- CLASSCACHE_LOCK();
-
-#ifdef CLASSCACHE_VERBOSE
- sprintf(logbuffer,"classcache_store (%p,%d,%p=", (void*)initloader,mayfree,(void*)cls);
- utf_cat_classname(logbuffer, cls->name);
- strcat(logbuffer,")");
- log_println(logbuffer);
-#endif
-
- en = classcache_new_name(cls->name);
-
- assert(en);
-
- /* iterate over all class entries */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
-
- /* check if this entry has already been loaded by initloader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == initloader) {
- if (clsen->classobj != cls) {
- /* A class with the same (initloader,name) pair has been stored already. */
- /* We free the given class and return the earlier one. */
-#ifdef CLASSCACHE_VERBOSE
- log_println("replacing %p with earlier loaded class %p",cls,clsen->classobj);
-#endif
- assert(clsen->classobj);
- if (mayfree)
- class_free(cls);
- cls = clsen->classobj;
- }
- goto return_success;
- }
- }
-
- /* {This entry has not been resolved with initloader} */
-
- /* check if initloader is constrained to this entry */
- for (lden = clsen->constraints; lden; lden = lden->next) {
- if (lden->loader == initloader) {
- /* we have to use this entry. check if it has been resolved */
- if (clsen->classobj) {
- /* check if is has already been resolved to another class */
- if (clsen->classobj != cls) {
- /* a loading constraint is violated */
- exceptions_throw_linkageerror("loading constraint violated: ", cls);
- goto return_exception;
- }
-
- /* record initloader as initiating loader */
- clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
- goto return_success;
- }
-
- /* {this is the first resolution for this entry} */
- /* record initloader as initiating loader */
- clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
-
- /* maybe we can merge this entry with another one */
- for (clsenB = en->classes; clsenB; clsenB = clsenB->next) {
- /* we dont want the entry that we have already */
- if (clsenB->classobj == cls) {
- /* this entry has the same classobj. let's merge them */
- classcache_merge_class_entries(en,clsen,clsenB);
- goto return_success;
- }
- }
-
- /* record the loaded class object */
- clsen->classobj = cls;
- CLASSCACHE_COUNT(stat_classes_stored);
-
- /* done */
- goto return_success;
- }
- }
-
- }
-
- /* {There is no class entry containing initloader as initiating
- * or constrained loader.} */
-
- /* we look for a class entry with the same classobj we want to store */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
- if (clsen->classobj == cls) {
- /* this entry is about the same classobj. let's use it */
- /* check if this entry has already been loaded by initloader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == initloader)
- goto return_success;
- }
- clsen->loaders = classcache_new_loader_entry(initloader, clsen->loaders);
- goto return_success;
- }
- }
-
- /* create a new class entry for this class object with */
- /* initiating loader initloader */
-
- clsen = NEW(classcache_class_entry);
- clsen->classobj = cls;
- clsen->loaders = classcache_new_loader_entry(initloader, NULL);
- clsen->constraints = NULL;
-
- clsen->next = en->classes;
- en->classes = clsen;
- CLASSCACHE_COUNT(stat_classes_stored);
-
- return_success:
-#ifdef CLASSCACHE_VERBOSE
- classcache_debug_dump(stdout,cls->name);
-#endif
- CLASSCACHE_UNLOCK();
- return cls;
-
- return_exception:
- CLASSCACHE_UNLOCK();
- return NULL; /* exception */
-}
-
-/* classcache_store_unique *****************************************************
-
- Store a loaded class as loaded by the bootstrap loader. This is a wrapper
- aroung classcache_store that throws an exception if a class with the same
- name has already been loaded by the bootstrap loader.
-
- This function is used to register a few special classes during startup.
- It should not be used otherwise.
-
- IN:
- cls..............class object to cache
-
- RETURN VALUE:
- true.............everything ok, the class was stored.
- false............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-bool classcache_store_unique(classinfo *cls)
-{
- classinfo *result;
-
- result = classcache_store(NULL,cls,false);
- if (result == NULL)
- return false;
-
- if (result != cls) {
- exceptions_throw_internalerror("class already stored in the class cache");
- return false;
- }
-
- return true;
-}
-
-/* classcache_store_defined ****************************************************
-
- Store a loaded class after it has been defined. If the class has already
- been defined by the same defining loader in another thread, free the given
- class and returned the one which has been defined earlier.
-
- IN:
- cls..............class object to store. classloader must be set
- (classloader may be NULL, for bootloader)
-
- RETURN VALUE:
- cls..............everything ok, the class was stored the cache,
- other classinfo..the class had already been defined, CLS was freed, the
- class which was defined earlier is returned,
- NULL.............an exception has been thrown.
-
-*******************************************************************************/
-
-classinfo *classcache_store_defined(classinfo *cls)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
-#ifdef CLASSCACHE_VERBOSE
- char logbuffer[1024];
-#endif
-
- assert(cls);
- assert(cls->state & CLASS_LOADED);
-
- CLASSCACHE_LOCK();
-
-#ifdef CLASSCACHE_VERBOSE
- sprintf(logbuffer,"classcache_store_defined (%p,", (void*)cls->classloader);
- utf_cat_classname(logbuffer, cls->name);
- strcat(logbuffer,")");
- log_println(logbuffer);
-#endif
-
- en = classcache_new_name(cls->name);
-
- assert(en);
-
- /* iterate over all class entries */
- for (clsen = en->classes; clsen; clsen = clsen->next) {
-
- /* check if this class has been defined by the same classloader */
- if (clsen->classobj && clsen->classobj->classloader == cls->classloader) {
- /* we found an earlier definition, delete the newer one */
- /* (if it is a different classinfo) */
- if (clsen->classobj != cls) {
-#ifdef CLASSCACHE_VERBOSE
- log_println("replacing %p with earlier defined class %p",cls,clsen->classobj);
-#endif
- class_free(cls);
- cls = clsen->classobj;
- }
- goto return_success;
- }
- }
-
- /* create a new class entry for this class object */
- /* the list of initiating loaders is empty at this point */
-
- clsen = NEW(classcache_class_entry);
- clsen->classobj = cls;
- clsen->loaders = NULL;
- clsen->constraints = NULL;
-
- clsen->next = en->classes;
- en->classes = clsen;
- CLASSCACHE_COUNT(stat_classes_stored);
-
-return_success:
-#ifdef CLASSCACHE_VERBOSE
- classcache_debug_dump(stdout,cls->name);
-#endif
- CLASSCACHE_UNLOCK();
- return cls;
-}
-
-/* classcache_find_loader ******************************************************
-
- Find the class entry loaded by or constrained to a given loader
- (internally used helper function)
-
- IN:
- entry............the classcache_name_entry
- loader...........the loader to look for
-
- RETURN VALUE:
- the classcache_class_entry for the given loader, or
- NULL if no entry was found
-
-*******************************************************************************/
-
-static classcache_class_entry * classcache_find_loader(
- classcache_name_entry * entry,
- classloader_t * loader)
-{
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
-
- assert(entry);
-
- /* iterate over all class entries */
- for (clsen = entry->classes; clsen; clsen = clsen->next) {
-
- /* check if this entry has already been loaded by initloader */
- for (lden = clsen->loaders; lden; lden = lden->next) {
- if (lden->loader == loader)
- return clsen; /* found */
- }
-
- /* check if loader is constrained to this entry */
- for (lden = clsen->constraints; lden; lden = lden->next) {
- if (lden->loader == loader)
- return clsen; /* found */
- }
- }
-
- /* not found */
- return NULL;
-}
-
-/* classcache_free_class_entry *************************************************
-
- Free the memory used by a class entry
-
- IN:
- clsen............the classcache_class_entry to free
-
-*******************************************************************************/
-
-static void classcache_free_class_entry(classcache_class_entry * clsen)
-{
- classcache_loader_entry *lden;
- classcache_loader_entry *next;
-
- assert(clsen);
-
- for (lden = clsen->loaders; lden; lden = next) {
- next = lden->next;
- FREE(lden, classcache_loader_entry);
- }
- for (lden = clsen->constraints; lden; lden = next) {
- next = lden->next;
- FREE(lden, classcache_loader_entry);
- }
-
- FREE(clsen, classcache_class_entry);
-}
-
-/* classcache_remove_class_entry ***********************************************
-
- Remove a classcache_class_entry from the list of possible resolution of
- a name entry
- (internally used helper function)
-
- IN:
- entry............the classcache_name_entry
- clsen............the classcache_class_entry to remove
-
-*******************************************************************************/
-
-static void classcache_remove_class_entry(classcache_name_entry * entry,
- classcache_class_entry * clsen)
-{
- classcache_class_entry **chain;
-
- assert(entry);
- assert(clsen);
-
- chain = &(entry->classes);
- while (*chain) {
- if (*chain == clsen) {
- *chain = clsen->next;
- classcache_free_class_entry(clsen);
- return;
- }
- chain = &((*chain)->next);
- }
-}
-
-/* classcache_free_name_entry **************************************************
-
- Free the memory used by a name entry
-
- IN:
- entry............the classcache_name_entry to free
-
-*******************************************************************************/
-
-static void classcache_free_name_entry(classcache_name_entry * entry)
-{
- classcache_class_entry *clsen;
- classcache_class_entry *next;
-
- assert(entry);
-
- for (clsen = entry->classes; clsen; clsen = next) {
- next = clsen->next;
- classcache_free_class_entry(clsen);
- }
-
- FREE(entry, classcache_name_entry);
-}
-
-/* classcache_free *************************************************************
-
- Free the memory used by the class cache
-
- NOTE:
- The class cache may not be used any more after this call, except
- when it is reinitialized with classcache_init.
-
- Note: NOT synchronized!
-
-*******************************************************************************/
-
-void classcache_free(void)
-{
- u4 slot;
- classcache_name_entry *entry;
- classcache_name_entry *next;
-
- for (slot = 0; slot < hashtable_classcache.size; ++slot) {
- for (entry = (classcache_name_entry *) hashtable_classcache.ptr[slot]; entry; entry = next) {
- next = entry->hashlink;
- classcache_free_name_entry(entry);
- }
- }
-
- MFREE(hashtable_classcache.ptr, void*, hashtable_classcache.size);
- hashtable_classcache.size = 0;
- hashtable_classcache.entries = 0;
- hashtable_classcache.ptr = NULL;
-}
-
-/* classcache_add_constraint ***************************************************
-
- Add a loading constraint
-
- IN:
- a................first initiating loader
- b................second initiating loader
- classname........class name
-
- RETURN VALUE:
- true.............everything ok, the constraint has been added,
- false............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraint(classloader_t * a,
- classloader_t * b,
- utf * classname)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsenA;
- classcache_class_entry *clsenB;
-
- assert(classname);
-
-#ifdef CLASSCACHE_VERBOSE
- log_start();
- log_print("classcache_add_constraint(%p,%p,", (void *) a, (void *) b);
- utf_fprint_printable_ascii_classname(stdout, classname);
- log_print(")\n");
- log_finish();
-#endif
-
- /* a constraint with a == b is trivially satisfied */
- if (a == b) {
- CLASSCACHE_COUNT(stat_trivial_constraints);
- return true;
- }
-
- CLASSCACHE_LOCK();
-
- en = classcache_new_name(classname);
-
- assert(en);
- CLASSCACHE_COUNT(stat_nontriv_constraints);
-
- /* find the entry loaded by / constrained to each loader */
- clsenA = classcache_find_loader(en, a);
- clsenB = classcache_find_loader(en, b);
-
- if (clsenA && clsenB) {
- /* { both loaders have corresponding entries } */
- CLASSCACHE_COUNT(stat_nontriv_constraints_both);
-
- /* if the entries are the same, the constraint is already recorded */
- if (clsenA == clsenB)
- goto return_success;
-
- /* check if the entries can be merged */
- if (clsenA->classobj && clsenB->classobj
- && clsenA->classobj != clsenB->classobj) {
- /* no, the constraint is violated */
- exceptions_throw_linkageerror("loading constraint violated: ",
- clsenA->classobj);
- goto return_exception;
- }
-
- /* yes, merge the entries */
- classcache_merge_class_entries(en,clsenA,clsenB);
- CLASSCACHE_COUNT(stat_nontriv_constraints_merged);
- }
- else {
- /* { at most one of the loaders has a corresponding entry } */
-
- /* set clsenA to the single class entry we have */
- if (!clsenA)
- clsenA = clsenB;
-
- if (!clsenA) {
- /* { no loader has a corresponding entry } */
- CLASSCACHE_COUNT(stat_nontriv_constraints_none);
-
- /* create a new class entry with the constraint (a,b,en->name) */
- clsenA = NEW(classcache_class_entry);
- clsenA->classobj = NULL;
- clsenA->loaders = NULL;
- clsenA->constraints = classcache_new_loader_entry(b, NULL);
- clsenA->constraints = classcache_new_loader_entry(a, clsenA->constraints);
-
- clsenA->next = en->classes;
- en->classes = clsenA;
- }
- else {
- CLASSCACHE_COUNT(stat_nontriv_constraints_one);
-
- /* make b the loader that has no corresponding entry */
- if (clsenB)
- b = a;
-
- /* loader b must be added to entry clsenA */
- clsenA->constraints = classcache_new_loader_entry(b, clsenA->constraints);
- }
- }
-
- return_success:
- CLASSCACHE_UNLOCK();
- return true;
-
- return_exception:
- CLASSCACHE_UNLOCK();
- return false; /* exception */
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-/* classcache_add_constraints_for_params ***************************************
-
- Add loading constraints for the parameters and return type of
- the given method.
-
- IN:
- a................first initiating loader
- b................second initiating loader
- m................methodinfo
-
- RETURN VALUE:
- true.............everything ok, the constraints have been added,
- false............an exception has been thrown.
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraints_for_params(classloader_t * a,
- classloader_t * b,
- methodinfo *m)
-{
- methoddesc *md;
- typedesc *td;
- s4 i;
-
- /* a constraint with a == b is trivially satisfied */
-
- if (a == b) {
- return true;
- }
-
- /* get the parsed descriptor */
-
- assert(m);
- md = m->parseddesc;
- assert(md);
-
- /* constrain the return type */
-
- if (md->returntype.type == TYPE_ADR) {
- if (!classcache_add_constraint(a, b, md->returntype.classref->name))
- return false; /* exception */
- }
-
- /* constrain each reference type used in the parameters */
-
- td = md->paramtypes;
- i = md->paramcount;
- for (; i--; td++) {
- if (td->type != TYPE_ADR)
- continue;
-
- if (!classcache_add_constraint(a, b, td->classref->name))
- return false; /* exception */
- }
-
- /* everything ok */
- return true;
-}
-#endif /* defined(ENABLE_VERIFIER) */
-
-
-/* classcache_number_of_loaded_classes *****************************************
-
- Counts the number of loaded classes and returns it.
-
- Note: This function assumes that the CLASSCACHE_LOCK is held by the
- caller!
-
-*******************************************************************************/
-
-static s4 classcache_number_of_loaded_classes(void)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- s4 number;
- s4 i;
-
- /* initialize class counter */
-
- number = 0;
-
- for (i = 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)
- number++;
- }
- }
- }
-
- return number;
-}
-
-
-/* classcache_get_loaded_class_count *******************************************
-
- Counts the number of loaded classes and returns it.
-
-*******************************************************************************/
-
-s4 classcache_get_loaded_class_count(void)
-{
- s4 count;
-
- CLASSCACHE_LOCK();
-
- count = classcache_number_of_loaded_classes();
-
- CLASSCACHE_UNLOCK();
-
- return count;
-}
-
-
-/* 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.
-
-*******************************************************************************/
-
-void classcache_foreach_loaded_class(classcache_foreach_functionptr_t func,
- void *data)
-{
- classcache_name_entry *en;
- classcache_class_entry *clsen;
- s4 i;
-
- CLASSCACHE_LOCK();
-
- /* look in every slot of the hashtable */
-
- for (i = 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) {
- (*func)(clsen->classobj, data);
- }
- }
- }
- }
-
- CLASSCACHE_UNLOCK();
-}
-
-
-/*============================================================================*/
-/* DEBUG DUMPS */
-/*============================================================================*/
-
-/* classcache_debug_dump *******************************************************
-
- Print the contents of the loaded class cache to a stream
-
- IN:
- file.............output stream
- only.............if != NULL, only print entries for this name
- (Currently we print also the rest of the hash chain to
- get a feel for the average length of hash chains.)
-
- Note: synchronized with global tablelock
-
-*******************************************************************************/
-
-#ifndef NDEBUG
-void classcache_debug_dump(FILE * file,utf *only)
-{
- classcache_name_entry *c;
- classcache_class_entry *clsen;
- classcache_loader_entry *lden;
- u4 slot;
-
- CLASSCACHE_LOCK();
-
- log_println("=== [loaded class cache] =====================================");
- log_println("hash size : %d", (int) hashtable_classcache.size);
- log_println("hash entries: %d", (int) hashtable_classcache.entries);
- log_println("");
-
- if (only) {
- c = classcache_lookup_name(only);
- slot = 0; /* avoid compiler warning */
- goto dump_it;
- }
-
- for (slot = 0; slot < hashtable_classcache.size; ++slot) {
- c = (classcache_name_entry *) hashtable_classcache.ptr[slot];
-
-dump_it:
- for (; c; c = c->hashlink) {
- utf_fprint_printable_ascii_classname(file, c->name);
- fprintf(file, "\n");
-
- /* iterate over all class entries */
- for (clsen = c->classes; clsen; clsen = clsen->next) {
- if (clsen->classobj) {
- log_println(" loaded %p", (void *) clsen->classobj);
- }
- else {
- log_println(" unresolved");
- }
-
- log_start();
- log_print(" loaders: ");
- for (lden = clsen->loaders; lden; lden = lden->next) {
- log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
- }
- log_finish();
-
- log_start();
- log_print(" constraints: ");
- for (lden = clsen->constraints; lden; lden = lden->next) {
- log_print("<%p> %p ", (void *) lden, (void *) lden->loader);
- }
- log_finish();
- }
- }
-
- if (only)
- break;
- }
- fprintf(file, "\n==============================================================\n\n");
-
- CLASSCACHE_UNLOCK();
-}
-#endif /* NDEBUG */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/classcache.h - loaded class cache and loading constraints
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _CLASSCACHE_H
-#define _CLASSCACHE_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include <stdio.h> /* for FILE */
-
-#if defined(ENABLE_JVMTI)
-# include "native/jni.h"
-#endif
-
-#include "toolbox/hashtable.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/references.h"
-
-
-/* forward declarations *******************************************************/
-
-typedef struct classcache_name_entry classcache_name_entry;
-typedef struct classcache_class_entry classcache_class_entry;
-typedef struct classcache_loader_entry classcache_loader_entry;
-
-/* global variables ***********************************************************/
-
-extern hashtable hashtable_classcache;
-
-
-/* structs ********************************************************************/
-
-/*----------------------------------------------------------------------------*/
-/* The Loaded Class Cache */
-/* */
-/* The loaded class cache is implemented as a two-level data structure. */
-/* */
-/* The first level is a hash table indexed by class names. For each class */
-/* name in the cache there is a classcache_name_entry, which collects all */
-/* information about classes with this class name. */
-/* */
-/* Second level: For each classcache_name_entry there is a list of */
-/* classcache_class_entry:s representing the possible different resolutions */
-/* of the class name. */
-/* */
-/* A classcache_class_entry records the following: */
-/* */
-/* - the loaded class object, if this entry has been resolved, otherwise NULL */
-/* - the list of initiating loaders which have resolved the class name to */
-/* this class object */
-/* - the list of initiating loaders which are constrained to resolve this */
-/* class name to this class object in the future */
-/* */
-/* The classcache_class_entry:s approximate the equivalence classes created */
-/* by the loading constraints and the equivalence of loaded classes. */
-/* */
-/* When a loading constraint (loaderA,loaderB,NAME) is added, then the */
-/* classcache_class_entry:s for NAME containing loaderA and loaderB resp. */
-/* must be merged into one entry. If this is impossible, because the entries */
-/* have already been resolved to different class objects, then the constraint */
-/* is violated and an expception must be thrown. */
-/*----------------------------------------------------------------------------*/
-
-
-/* classcache_name_entry
- *
- * For each classname a classcache_name_entry struct is created.
- */
-
-struct classcache_name_entry
-{
- utf *name; /* class name */
- classcache_name_entry *hashlink; /* link for external chaining */
- classcache_class_entry *classes; /* equivalence classes for this name*/
-};
-
-struct classcache_class_entry
-{
- classinfo *classobj; /* the loaded class object, or NULL */
- classcache_loader_entry *loaders;
- classcache_loader_entry *constraints;
- classcache_class_entry *next; /* next class entry for same name */
-};
-
-struct classcache_loader_entry
-{
- classloader_t *loader; /* class loader object */
- classcache_loader_entry *next; /* next loader entry in the list */
-};
-
-
-/* callback function type for classcache_foreach_loaded_class */
-
-typedef void (*classcache_foreach_functionptr_t)(classinfo *, void *);
-
-
-/* function prototypes ********************************************************/
-
-/* initialize the loaded class cache */
-bool classcache_init(void);
-void classcache_free(void);
-
-classinfo * classcache_lookup(classloader_t *initloader,utf *classname);
-classinfo * classcache_lookup_defined(classloader_t *defloader,utf *classname);
-classinfo * classcache_lookup_defined_or_initiated(classloader_t *loader,utf *classname);
-
-bool classcache_store_unique(classinfo *cls);
-classinfo * classcache_store(classloader_t *initloader,classinfo *cls,bool mayfree);
-classinfo * classcache_store_defined(classinfo *cls);
-
-#if defined(ENABLE_VERIFIER)
-bool classcache_add_constraint(classloader_t *a,classloader_t *b,utf *classname);
-bool classcache_add_constraints_for_params(classloader_t *a,classloader_t *b,
- methodinfo *m);
-#endif
-
-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
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _CLASSCACHE_H */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
-
+++ /dev/null
-/* src/vmcore/descriptor.c - checking and parsing of field / method descriptors
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "md-abi.h"
-
-#include "mm/memory.h"
-
-#include "vm/exceptions.hpp"
-#include "vm/jit_interface.h"
-#include "vm/primitive.hpp"
-#include "vm/vm.hpp"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/options.h"
-
-
-/* constants (private to descriptor.c) ****************************************/
-
-/* initial number of entries for the classrefhash of a descriptor_pool */
-/* (currently the hash is never grown!) */
-#define CLASSREFHASH_INIT_SIZE 64
-
-/* initial number of entries for the descriptorhash of a descriptor_pool */
-/* (currently the hash is never grown!) */
-#define DESCRIPTORHASH_INIT_SIZE 128
-
-/* data structures (private to descriptor.c) **********************************/
-
-typedef struct classref_hash_entry classref_hash_entry;
-typedef struct descriptor_hash_entry descriptor_hash_entry;
-
-/* entry struct for the classrefhash of descriptor_pool */
-struct classref_hash_entry {
- classref_hash_entry *hashlink; /* for hash chaining */
- utf *name; /* name of the class refered to */
- u2 index; /* index into classref table */
-};
-
-/* entry struct for the descriptorhash of descriptor_pool */
-struct descriptor_hash_entry {
- descriptor_hash_entry *hashlink;
- utf *desc;
- parseddesc_t parseddesc;
- s2 paramslots; /* number of params, LONG/DOUBLE counted as 2 */
-};
-
-
-/****************************************************************************/
-/* MACROS FOR DESCRIPTOR PARSING (private to descriptor.c) */
-/****************************************************************************/
-
-/* SKIP_FIELDDESCRIPTOR:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * CAUTION: This macro does not check for an unexpected end of the
- * descriptor. Better use SKIP_FIELDDESCRIPTOR_SAFE.
- */
-#define SKIP_FIELDDESCRIPTOR(utf_ptr) \
- do { while (*(utf_ptr)=='[') (utf_ptr)++; \
- if (*(utf_ptr)++=='L') \
- while(*(utf_ptr)++ != ';') /* skip */; } while(0)
-
-/* SKIP_FIELDDESCRIPTOR_SAFE:
- * utf_ptr must point to the first character of a field descriptor.
- * After the macro call utf_ptr points to the first character after
- * the field descriptor.
- *
- * Input:
- * utf_ptr....points to first char of descriptor
- * end_ptr....points to first char after the end of the string
- * errorflag..must be initialized (to false) by the caller!
- * Output:
- * utf_ptr....points to first char after the descriptor
- * errorflag..set to true if the string ended unexpectedly
- */
-#define SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr,end_ptr,errorflag) \
- do { while ((utf_ptr) != (end_ptr) && *(utf_ptr)=='[') (utf_ptr)++; \
- if ((utf_ptr) == (end_ptr)) \
- (errorflag) = true; \
- else \
- if (*(utf_ptr)++=='L') { \
- while((utf_ptr) != (end_ptr) && *(utf_ptr)++ != ';') \
- /* skip */; \
- if ((utf_ptr)[-1] != ';') \
- (errorflag) = true; }} while(0)
-
-
-/****************************************************************************/
-/* DEBUG HELPERS */
-/****************************************************************************/
-
-/*#define DESCRIPTOR_VERBOSE*/
-
-/****************************************************************************/
-/* FUNCTIONS */
-/****************************************************************************/
-
-/* descriptor_to_basic_type ****************************************************
-
- Return the basic type to use for a value with this descriptor.
-
- IN:
- utf..............descriptor utf string
-
- OUT:
- A TYPE_* constant.
-
- PRECONDITIONS:
- This function assumes that the descriptor has passed
- descriptor_pool_add checks and that it does not start with '('.
-
-*******************************************************************************/
-
-int descriptor_to_basic_type(utf *descriptor)
-{
- assert(descriptor->blength >= 1);
-
- switch (descriptor->text[0]) {
- case 'Z':
- case 'B':
- case 'C':
- case 'S':
- case 'I':
- return TYPE_INT;
-
- case 'J':
- return TYPE_LNG;
-
- case 'F':
- return TYPE_FLT;
-
- case 'D':
- return TYPE_DBL;
-
- case 'L':
- case '[':
- return TYPE_ADR;
-
- default:
- vm_abort("descriptor_to_basic_type: invalid type %c",
- descriptor->text[0]);
- }
-
- /* keep the compiler happy */
-
- return 0;
-}
-
-
-/* descriptor_typesize *********************************************************
-
- Return the size in bytes needed for the given type.
-
- IN:
- td..............typedesc describing the type
-
- OUT:
- The number of bytes
-
-*******************************************************************************/
-
-int descriptor_typesize(typedesc *td)
-{
- assert(td);
-
- switch (td->type) {
- case TYPE_INT:
- case TYPE_FLT:
- return 4;
-
- case TYPE_LNG:
- case TYPE_DBL:
- return 8;
-
- case TYPE_ADR:
- return SIZEOF_VOID_P;
-
- default:
- vm_abort("descriptor_typesize: invalid type %d", td->type);
- }
-
- /* keep the compiler happy */
-
- return 0;
-}
-
-
-/* name_from_descriptor ********************************************************
-
- Return the class name indicated by the given descriptor
- (Internally used helper function)
-
- IN:
- c................class containing the descriptor
- utf_ptr..........first character of descriptor
- end_ptr..........first character after the end of the string
- mode.............a combination (binary or) of the following flags:
-
- (Flags marked with * are the default settings.)
-
- How to handle "V" descriptors:
-
- * DESCRIPTOR_VOID.....handle it like other primitive types
- DESCRIPTOR_NOVOID...treat it as an error
-
- How to deal with extra characters after the end of the
- descriptor:
-
- * DESCRIPTOR_NOCHECKEND...ignore (useful for parameter lists)
- DESCRIPTOR_CHECKEND.....treat them as an error
-
- OUT:
- *next............if non-NULL, *next is set to the first character after
- the descriptor. (Undefined if an error occurs.)
- *name............set to the utf name of the class
-
- RETURN VALUE:
- true.............descriptor parsed successfully
- false............an exception has been thrown
-
-*******************************************************************************/
-
-#define DESCRIPTOR_VOID 0 /* default */
-#define DESCRIPTOR_NOVOID 0x0040
-#define DESCRIPTOR_NOCHECKEND 0 /* default */
-#define DESCRIPTOR_CHECKEND 0x1000
-
-static bool
-name_from_descriptor(classinfo *c,
- char *utf_ptr, char *end_ptr,
- char **next, int mode, utf **name)
-{
- char *start = utf_ptr;
- bool error = false;
-
- assert(c);
- assert(utf_ptr);
- assert(end_ptr);
- assert(name);
-
- *name = NULL;
- SKIP_FIELDDESCRIPTOR_SAFE(utf_ptr, end_ptr, error);
-
- if (mode & DESCRIPTOR_CHECKEND)
- error |= (utf_ptr != end_ptr);
-
- if (!error) {
- if (next) *next = utf_ptr;
-
- switch (*start) {
- case 'V':
- if (mode & DESCRIPTOR_NOVOID)
- break;
- /* FALLTHROUGH! */
- case 'I':
- case 'J':
- case 'F':
- case 'D':
- case 'B':
- case 'C':
- case 'S':
- case 'Z':
- return true;
-
- case 'L':
- start++;
- utf_ptr--;
- /* FALLTHROUGH! */
- case '[':
- *name = utf_new(start, utf_ptr - start);
- return true;
- }
- }
-
- exceptions_throw_classformaterror(c, "Invalid descriptor");
- return false;
-}
-
-
-/* descriptor_to_typedesc ******************************************************
-
- Parse the given type descriptor and fill a typedesc struct
- (Internally used helper function)
-
- IN:
- pool.............the descriptor pool
- utf_ptr..........points to first character of type descriptor
- end_pos..........points after last character of the whole descriptor
-
- OUT:
- *next............set to next character after type descriptor
- *d...............filled with parsed information
-
- RETURN VALUE:
- true.............parsing succeeded
- false............an exception has been thrown
-
-*******************************************************************************/
-
-static bool
-descriptor_to_typedesc(descriptor_pool *pool, char *utf_ptr, char *end_pos,
- char **next, typedesc *td)
-{
- utf *name;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, next, 0, &name))
- return false;
-
- if (name) {
- /* a reference type */
- td->type = TYPE_ADR;
- td->primitivetype = TYPE_ADR;
- td->arraydim = 0;
- for (utf_ptr = name->text; *utf_ptr == '['; ++utf_ptr)
- td->arraydim++;
- td->classref = descriptor_pool_lookup_classref(pool, name);
-
- } else {
- /* a primitive type */
- switch (*utf_ptr) {
- case 'B':
- td->primitivetype = PRIMITIVETYPE_BYTE;
- td->type = TYPE_INT;
- break;
- case 'C':
- td->primitivetype = PRIMITIVETYPE_CHAR;
- td->type = TYPE_INT;
- break;
- case 'S':
- td->primitivetype = PRIMITIVETYPE_SHORT;
- td->type = TYPE_INT;
- break;
- case 'Z':
- td->primitivetype = PRIMITIVETYPE_BOOLEAN;
- td->type = TYPE_INT;
- break;
- case 'I':
- td->primitivetype = PRIMITIVETYPE_INT;
- td->type = TYPE_INT;
- break;
- case 'D':
- td->primitivetype = PRIMITIVETYPE_DOUBLE;
- td->type = TYPE_DBL;
- break;
- case 'F':
- td->primitivetype = PRIMITIVETYPE_FLOAT;
- td->type = TYPE_FLT;
- break;
- case 'J':
- td->primitivetype = PRIMITIVETYPE_LONG;
- td->type = TYPE_LNG;
- break;
- case 'V':
- td->primitivetype = PRIMITIVETYPE_VOID;
- td->type = TYPE_VOID;
- break;
- default:
- assert(false);
- }
-
- td->arraydim = 0;
- td->classref = NULL;
- }
-
- return true;
-}
-
-
-/* descriptor_pool_new *********************************************************
-
- Allocate a new descriptor_pool
-
- IN:
- referer..........class for which to create the pool
-
- RETURN VALUE:
- a pointer to the new descriptor_pool
-
-*******************************************************************************/
-
-descriptor_pool *
-descriptor_pool_new(classinfo *referer)
-{
- descriptor_pool *pool;
- u4 hashsize;
- u4 slot;
-
- pool = DNEW(descriptor_pool);
- assert(pool);
-
- pool->referer = referer;
- pool->fieldcount = 0;
- pool->methodcount = 0;
- pool->paramcount = 0;
- pool->descriptorsize = 0;
- pool->descriptors = NULL;
- pool->descriptors_next = NULL;
- pool->classrefs = NULL;
- pool->descriptor_kind = NULL;
- pool->descriptor_kind_next = NULL;
-
- hashsize = CLASSREFHASH_INIT_SIZE;
- pool->classrefhash.size = hashsize;
- pool->classrefhash.entries = 0;
- pool->classrefhash.ptr = DMNEW(void*, hashsize);
- for (slot=0; slot<hashsize; ++slot)
- pool->classrefhash.ptr[slot] = NULL;
-
- hashsize = DESCRIPTORHASH_INIT_SIZE;
- pool->descriptorhash.size = hashsize;
- pool->descriptorhash.entries = 0;
- pool->descriptorhash.ptr = DMNEW(void*, hashsize);
- for (slot=0; slot<hashsize; ++slot)
- pool->descriptorhash.ptr[slot] = NULL;
-
- return pool;
-}
-
-
-/* descriptor_pool_add_class ***************************************************
-
- Add the given class reference to the pool
-
- IN:
- pool.............the descriptor_pool
- name.............the class reference to add
-
- RETURN VALUE:
- true.............reference has been added
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool
-descriptor_pool_add_class(descriptor_pool *pool, utf *name)
-{
- u4 key,slot;
- classref_hash_entry *c;
-
- assert(pool);
- assert(name);
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_add_class(%p,",(void*)pool);
- utf_fprint_printable_ascii(stderr,name);fprintf(stderr,")\n");
-#endif
-
- /* find a place in the hashtable */
-
- key = utf_hashkey(name->text, name->blength);
- slot = key & (pool->classrefhash.size - 1);
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
-
- while (c) {
- if (c->name == name)
- return true; /* already stored */
- c = c->hashlink;
- }
-
- /* check if the name is a valid classname */
-
- if (!is_valid_name(name->text,UTF_END(name))) {
- exceptions_throw_classformaterror(pool->referer, "Invalid class name");
- return false; /* exception */
- }
-
- /* XXX check maximum array dimension */
-
- c = DNEW(classref_hash_entry);
- c->name = name;
- c->index = pool->classrefhash.entries++;
- c->hashlink = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- pool->classrefhash.ptr[slot] = c;
-
- return true;
-}
-
-
-/* descriptor_pool_add *********************************************************
-
- Check the given descriptor and add it to the pool
-
- IN:
- pool.............the descriptor_pool
- desc.............the descriptor to add. Maybe a field or method desc.
-
- OUT:
- *paramslots......if non-NULL, set to the number of parameters.
- LONG and DOUBLE are counted twice
-
- RETURN VALUE:
- true.............descriptor has been added
- false............an exception has been thrown
-
-*******************************************************************************/
-
-bool
-descriptor_pool_add(descriptor_pool *pool, utf *desc, int *paramslots)
-{
- u4 key,slot;
- descriptor_hash_entry *d;
- char *utf_ptr;
- char *end_pos;
- utf *name;
- s4 argcount = 0;
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_add(%p,",(void*)pool);
- utf_fprint_printable_ascii(stderr,desc);fprintf(stderr,")\n");
-#endif
-
- assert(pool);
- assert(desc);
-
- /* find a place in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- /* Save all method descriptors in the hashtable, since the parsed */
- /* descriptor may vary between differenf methods (static vs. non-static). */
-
- utf_ptr = desc->text;
-
- if (*utf_ptr != '(') {
- while (d) {
- if (d->desc == desc) {
- if (paramslots)
- *paramslots = d->paramslots;
- return true; /* already stored */
- }
- d = d->hashlink;
- }
- }
-
- /* add the descriptor to the pool */
-
- d = DNEW(descriptor_hash_entry);
- d->desc = desc;
- d->parseddesc.any = NULL;
- d->hashlink = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
- pool->descriptorhash.ptr[slot] = d;
-
- /* now check the descriptor */
-
- end_pos = UTF_END(desc);
-
- if (*utf_ptr == '(') {
- /* a method descriptor */
-
- pool->methodcount++;
- utf_ptr++;
-
- /* check arguments */
-
- while ((utf_ptr != end_pos) && (*utf_ptr != ')')) {
- pool->paramcount++;
-
- /* We cannot count the `this' argument here because
- * we don't know if the method is static. */
-
- if (*utf_ptr == 'J' || *utf_ptr == 'D')
- argcount += 2;
- else
- argcount++;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, &utf_ptr,
- DESCRIPTOR_NOVOID, &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool, name))
- return false;
- }
-
- if (utf_ptr == end_pos) {
- exceptions_throw_classformaterror(pool->referer,
- "Missing ')' in method descriptor");
- return false;
- }
-
- utf_ptr++; /* skip ')' */
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
- DESCRIPTOR_CHECKEND, &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool,name))
- return false;
-
- if (argcount > 255) {
- exceptions_throw_classformaterror(pool->referer,
- "Too many arguments in signature");
- return false;
- }
-
- } else {
- /* a field descriptor */
-
- pool->fieldcount++;
-
- if (!name_from_descriptor(pool->referer, utf_ptr, end_pos, NULL,
- DESCRIPTOR_NOVOID | DESCRIPTOR_CHECKEND,
- &name))
- return false;
-
- if (name)
- if (!descriptor_pool_add_class(pool,name))
- return false;
- }
-
- d->paramslots = argcount;
-
- if (paramslots)
- *paramslots = argcount;
-
- return true;
-}
-
-
-/* descriptor_pool_create_classrefs ********************************************
-
- Create a table containing all the classrefs which were added to the pool
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *count...........if count is non-NULL, this is set to the number
- of classrefs in the table
-
- RETURN VALUE:
- a pointer to the constant_classref table
-
-*******************************************************************************/
-
-constant_classref *
-descriptor_pool_create_classrefs(descriptor_pool *pool, s4 *count)
-{
- u4 nclasses;
- u4 slot;
- classref_hash_entry *c;
- constant_classref *ref;
-
- assert(pool);
-
- nclasses = pool->classrefhash.entries;
- pool->classrefs = MNEW(constant_classref,nclasses);
-
- /* fill the constant_classref structs */
-
- for (slot = 0; slot < pool->classrefhash.size; ++slot) {
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- while (c) {
- ref = pool->classrefs + c->index;
- CLASSREF_INIT(*ref, pool->referer, c->name);
- c = c->hashlink;
- }
- }
-
- if (count)
- *count = nclasses;
-
- return pool->classrefs;
-}
-
-
-/* descriptor_pool_lookup_classref *********************************************
-
- Return the constant_classref for the given class name
-
- IN:
- pool.............the descriptor_pool
- classname........name of the class to look up
-
- RETURN VALUE:
- a pointer to the constant_classref, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-constant_classref *
-descriptor_pool_lookup_classref(descriptor_pool *pool, utf *classname)
-{
- u4 key,slot;
- classref_hash_entry *c;
-
- assert(pool);
- assert(pool->classrefs);
- assert(classname);
-
- key = utf_hashkey(classname->text, classname->blength);
- slot = key & (pool->classrefhash.size - 1);
- c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
-
- while (c) {
- if (c->name == classname)
- return pool->classrefs + c->index;
- c = c->hashlink;
- }
-
- exceptions_throw_internalerror("Class reference not found in descriptor pool");
- return NULL;
-}
-
-
-/* descriptor_pool_alloc_parsed_descriptors ************************************
-
- Allocate space for the parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- NOTE:
- This function must be called after all descriptors have been added
- with descriptor_pool_add.
-
-*******************************************************************************/
-
-void
-descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool)
-{
- u4 size;
-
- assert(pool);
-
- /* TWISTI: paramcount + 1: we don't know if the method is static or */
- /* not, i have no better solution yet. */
-
- size =
- pool->fieldcount * sizeof(typedesc) +
- pool->methodcount * (sizeof(methoddesc) - sizeof(typedesc)) +
- pool->paramcount * sizeof(typedesc) +
- pool->methodcount * sizeof(typedesc); /* possible `this' pointer */
-
- pool->descriptorsize = size;
- if (size) {
- pool->descriptors = MNEW(u1, size);
- pool->descriptors_next = pool->descriptors;
- }
-
- size = pool->fieldcount + pool->methodcount;
- if (size) {
- pool->descriptor_kind = DMNEW(u1, size);
- pool->descriptor_kind_next = pool->descriptor_kind;
- }
-}
-
-
-/* descriptor_pool_parse_field_descriptor **************************************
-
- Parse the given field descriptor
-
- IN:
- pool.............the descriptor_pool
- desc.............the field descriptor
-
- RETURN VALUE:
- a pointer to the parsed field descriptor, or
- NULL if an exception has been thrown
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called (once)
- before this function is used.
-
-*******************************************************************************/
-
-typedesc *
-descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc)
-{
- u4 key,slot;
- descriptor_hash_entry *d;
- typedesc *td;
-
- assert(pool);
- assert(pool->descriptors);
- assert(pool->descriptors_next);
-
- /* lookup the descriptor in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- while (d) {
- if (d->desc == desc) {
- /* found */
- if (d->parseddesc.fd)
- return d->parseddesc.fd;
- break;
- }
- d = d->hashlink;
- }
-
- assert(d);
-
- if (desc->text[0] == '(') {
- exceptions_throw_classformaterror(pool->referer,
- "Method descriptor used in field reference");
- return NULL;
- }
-
- td = (typedesc *) pool->descriptors_next;
- pool->descriptors_next += sizeof(typedesc);
-
- if (!descriptor_to_typedesc(pool, desc->text, UTF_END(desc), NULL, td))
- return NULL;
-
- *(pool->descriptor_kind_next++) = 'f';
-
- d->parseddesc.fd = td;
-
- return td;
-}
-
-
-/* descriptor_pool_parse_method_descriptor *************************************
-
- Parse the given method descriptor
-
- IN:
- pool.............the descriptor_pool
- desc.............the method descriptor
- mflags...........the method flags
- thisclass........classref to the class containing the method.
- This is ignored if mflags contains ACC_STATIC.
- The classref is stored for inserting the 'this' argument.
-
- RETURN VALUE:
- a pointer to the parsed method descriptor, or
- NULL if an exception has been thrown
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called
- (once) before this function is used.
-
-*******************************************************************************/
-
-methoddesc *
-descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc,
- s4 mflags,constant_classref *thisclass)
-{
- u4 key, slot;
- descriptor_hash_entry *d;
- methoddesc *md;
- typedesc *td;
- char *utf_ptr;
- char *end_pos;
- s2 paramcount = 0;
- s2 paramslots = 0;
-
-#ifdef DESCRIPTOR_VERBOSE
- fprintf(stderr,"descriptor_pool_parse_method_descriptor(%p,%d,%p,",
- (void*)pool,(int)mflags,(void*)thisclass);
- utf_fprint_printable_ascii(stderr,desc); fprintf(stderr,")\n");
-#endif
-
- assert(pool);
- assert(pool->descriptors);
- assert(pool->descriptors_next);
-
- /* check that it is a method descriptor */
-
- if (desc->text[0] != '(') {
- exceptions_throw_classformaterror(pool->referer,
- "Field descriptor used in method reference");
- return NULL;
- }
-
- /* lookup the descriptor in the hashtable */
-
- key = utf_hashkey(desc->text, desc->blength);
- slot = key & (pool->descriptorhash.size - 1);
- d = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
-
- /* find an un-parsed descriptor */
-
- while (d) {
- if (d->desc == desc)
- if (!d->parseddesc.md)
- break;
- d = d->hashlink;
- }
-
- assert(d);
-
- md = (methoddesc *) pool->descriptors_next;
- pool->descriptors_next += sizeof(methoddesc) - sizeof(typedesc);
-
- utf_ptr = desc->text + 1; /* skip '(' */
- end_pos = UTF_END(desc);
-
- td = md->paramtypes;
-
- /* count the `this' pointer */
-
- if ((mflags != ACC_UNDEF) && !(mflags & ACC_STATIC)) {
- td->type = TYPE_ADR;
- td->primitivetype = TYPE_ADR;
- td->arraydim = 0;
- td->classref = thisclass;
-
- td++;
- pool->descriptors_next += sizeof(typedesc);
- paramcount++;
- paramslots++;
- }
-
- while (*utf_ptr != ')') {
- /* parse a parameter type */
-
- if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, &utf_ptr, td))
- return NULL;
-
- if (IS_2_WORD_TYPE(td->type))
- paramslots++;
-
- td++;
- pool->descriptors_next += sizeof(typedesc);
- paramcount++;
- paramslots++;
- }
- utf_ptr++; /* skip ')' */
-
- /* Skip possible `this' pointer in paramtypes array to allow a possible */
- /* memory move later in parse. */
- /* We store the thisclass reference, so we can later correctly fill in */
- /* the parameter slot of the 'this' argument. */
-
- if (mflags == ACC_UNDEF) {
- td->classref = thisclass;
- td++;
- pool->descriptors_next += sizeof(typedesc);
- }
-
- /* parse return type */
-
- if (!descriptor_to_typedesc(pool, utf_ptr, end_pos, NULL,
- &(md->returntype)))
- return NULL;
-
- md->paramcount = paramcount;
- md->paramslots = paramslots;
-
- /* If mflags != ACC_UNDEF we parse a real loaded method, so do
- param prealloc. Otherwise we do this in stack analysis. */
-
- if (mflags != ACC_UNDEF) {
- if (md->paramcount > 0) {
- /* allocate memory for params */
-
- md->params = MNEW(paramdesc, md->paramcount);
- }
- else {
- md->params = METHODDESC_NOPARAMS;
- }
-
- /* fill the paramdesc */
- /* md_param_alloc has to be called if md->paramcount == 0,
- too, so it can make the reservation for the Linkage Area,
- Return Register... */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- {
- /* As builtin-functions are native functions, we have
- to pre-allocate for the native ABI. */
-
- if (mflags & ACC_METHOD_BUILTIN)
- md_param_alloc_native(md);
- else
- md_param_alloc(md);
- }
-#endif
- }
- else {
- /* params will be allocated later by
- descriptor_params_from_paramtypes if necessary */
-
- md->params = NULL;
- }
-
- *(pool->descriptor_kind_next++) = 'm';
-
- d->parseddesc.md = md;
-
- return md;
-}
-
-/* descriptor_params_from_paramtypes *******************************************
-
- Create the paramdescs for a method descriptor. This function is called
- when we know whether the method is static or not. This function may only
- be called once for each methoddesc, and only if md->params == NULL.
-
- IN:
- md...............the parsed method descriptor
- md->params MUST be NULL.
- mflags...........the ACC_* access flags of the method. Only the
- ACC_STATIC bit is checked.
- The value ACC_UNDEF is NOT allowed.
-
- RETURN VALUE:
- true.............the paramdescs were created successfully
- false............an exception has been thrown
-
- POSTCONDITION:
- md->parms != NULL
-
-*******************************************************************************/
-
-bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags)
-{
- typedesc *td;
-
- assert(md);
- assert(md->params == NULL);
- assert(mflags != ACC_UNDEF);
-
- td = md->paramtypes;
-
- /* check for `this' pointer */
-
- if (!(mflags & ACC_STATIC)) {
- constant_classref *thisclass;
-
- /* fetch class reference from reserved param slot */
- thisclass = td[md->paramcount].classref;
- assert(thisclass);
-
- if (md->paramcount > 0) {
- /* shift param types by 1 argument */
- MMOVE(td + 1, td, typedesc, md->paramcount);
- }
-
- /* fill in first argument `this' */
-
- td->type = TYPE_ADR;
- td->primitivetype = TYPE_ADR;
- td->arraydim = 0;
- td->classref = thisclass;
-
- md->paramcount++;
- md->paramslots++;
- }
-
- /* if the method has params, process them */
-
- if (md->paramcount > 0) {
- /* allocate memory for params */
-
- md->params = MNEW(paramdesc, md->paramcount);
-
- } else {
- md->params = METHODDESC_NOPARAMS;
- }
-
- /* fill the paramdesc */
- /* md_param_alloc has to be called if md->paramcount == 0, too, so
- it can make the reservation for the Linkage Area, Return
- Register.. */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (!opt_intrp)
-# endif
- {
- /* As builtin-functions are native functions, we have to
- pre-allocate for the native ABI. */
-
- if (mflags & ACC_METHOD_BUILTIN)
- md_param_alloc_native(md);
- else
- md_param_alloc(md);
- }
-#endif
-
- return true;
-}
-
-
-/* descriptor_pool_get_parsed_descriptors **************************************
-
- Return a pointer to the block of parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *size............if size is non-NULL, this is set to the size of the
- parsed descriptor block (in u1)
-
- RETURN VALUE:
- a pointer to the block of parsed descriptors
-
- NOTE:
- descriptor_pool_alloc_parsed_descriptors must be called (once)
- before this function is used.
-
-*******************************************************************************/
-
-void *
-descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size)
-{
- assert(pool);
- assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
-
- if (size)
- *size = pool->descriptorsize;
-
- return pool->descriptors;
-}
-
-
-/* descriptor_pool_get_sizes ***************************************************
-
- Get the sizes of the class reference table and the parsed descriptors
-
- IN:
- pool.............the descriptor_pool
-
- OUT:
- *classrefsize....set to size of the class reference table
- *descsize........set to size of the parsed descriptors
-
- NOTE:
- This function may only be called after both
- descriptor_pool_create_classrefs, and
- descriptor_pool_alloc_parsed_descriptors
- have been called.
-
-*******************************************************************************/
-
-void
-descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize, u4 *descsize)
-{
- assert(pool);
- assert((!pool->fieldcount && !pool->methodcount) || pool->descriptors);
- assert(pool->classrefs);
- assert(classrefsize);
- assert(descsize);
-
- *classrefsize = pool->classrefhash.entries * sizeof(constant_classref);
- *descsize = pool->descriptorsize;
-}
-
-
-/****************************************************************************/
-/* DEBUG HELPERS */
-/****************************************************************************/
-
-#ifndef NDEBUG
-/* descriptor_debug_print_typedesc *********************************************
-
- Print the given typedesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parsed descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_typedesc(FILE *file,typedesc *d)
-{
- int ch;
-
- if (!d) {
- fprintf(file,"(typedesc *)NULL");
- return;
- }
-
- if (d->type == TYPE_ADR) {
- if (d->classref)
- utf_fprint_printable_ascii(file,d->classref->name);
- else
- fprintf(file,"<class=NULL>");
- }
- else {
- switch (d->primitivetype) {
- case PRIMITIVETYPE_INT : ch='I'; break;
- case PRIMITIVETYPE_CHAR : ch='C'; break;
- case PRIMITIVETYPE_BYTE : ch='B'; break;
- case PRIMITIVETYPE_SHORT : ch='S'; break;
- case PRIMITIVETYPE_BOOLEAN: ch='Z'; break;
- case PRIMITIVETYPE_LONG : ch='J'; break;
- case PRIMITIVETYPE_FLOAT : ch='F'; break;
- case PRIMITIVETYPE_DOUBLE : ch='D'; break;
- case PRIMITIVETYPE_VOID : ch='V'; break;
- default : ch='!';
- }
- fputc(ch,file);
- }
- if (d->arraydim)
- fprintf(file,"[%d]",d->arraydim);
-}
-
-/* descriptor_debug_print_paramdesc ********************************************
-
- Print the given paramdesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parameter descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_paramdesc(FILE *file,paramdesc *d)
-{
- if (!d) {
- fprintf(file,"(paramdesc *)NULL");
- return;
- }
-
- if (d->inmemory) {
- fprintf(file,"<m%d>",d->regoff);
- }
- else {
- fprintf(file,"<r%d>",d->regoff);
- }
-}
-
-/* descriptor_debug_print_methoddesc *******************************************
-
- Print the given methoddesc to the given stream
-
- IN:
- file.............stream to print to
- d................the parsed descriptor
-
-*******************************************************************************/
-
-void
-descriptor_debug_print_methoddesc(FILE *file,methoddesc *d)
-{
- int i;
-
- if (!d) {
- fprintf(file,"(methoddesc *)NULL");
- return;
- }
-
- fputc('(',file);
- for (i=0; i<d->paramcount; ++i) {
- if (i)
- fputc(',',file);
- descriptor_debug_print_typedesc(file,d->paramtypes + i);
- if (d->params) {
- descriptor_debug_print_paramdesc(file,d->params + i);
- }
- }
- if (d->params == METHODDESC_NOPARAMS)
- fputs("<NOPARAMS>",file);
- fputc(')',file);
- descriptor_debug_print_typedesc(file,&(d->returntype));
-}
-
-/* descriptor_pool_debug_dump **************************************************
-
- Print the state of the descriptor_pool to the given stream
-
- IN:
- pool.............the descriptor_pool
- file.............stream to print to
-
-*******************************************************************************/
-
-void
-descriptor_pool_debug_dump(descriptor_pool *pool,FILE *file)
-{
- u4 slot;
- u1 *pos;
- u1 *kind;
- u4 size;
-
- fprintf(file,"======[descriptor_pool for ");
- utf_fprint_printable_ascii(file,pool->referer->name);
- fprintf(file,"]======\n");
-
- fprintf(file,"fieldcount: %d\n",pool->fieldcount);
- fprintf(file,"methodcount: %d\n",pool->methodcount);
- fprintf(file,"paramcount: %d\n",pool->paramcount);
- fprintf(file,"classrefcount: %d\n",pool->classrefhash.entries);
- fprintf(file,"descriptorsize: %d bytes\n",pool->descriptorsize);
- fprintf(file,"classrefsize: %d bytes\n",
- (int)(pool->classrefhash.entries * sizeof(constant_classref)));
-
- fprintf(file,"class references:\n");
- for (slot=0; slot<pool->classrefhash.size; ++slot) {
- classref_hash_entry *c = (classref_hash_entry *) pool->classrefhash.ptr[slot];
- while (c) {
- fprintf(file," %4d: ",c->index);
- utf_fprint_printable_ascii(file,c->name);
- fprintf(file,"\n");
- c = c->hashlink;
- }
- }
-
- fprintf(file,"hashed descriptors:\n");
- for (slot=0; slot<pool->descriptorhash.size; ++slot) {
- descriptor_hash_entry *c = (descriptor_hash_entry *) pool->descriptorhash.ptr[slot];
- while (c) {
- fprintf(file," %p: ",c->parseddesc.any);
- utf_fprint_printable_ascii(file,c->desc);
- fprintf(file,"\n");
- c = c->hashlink;
- }
- }
-
- fprintf(file,"descriptors:\n");
- if (pool->descriptors) {
- pos = pool->descriptors;
- size = pool->descriptors_next - pool->descriptors;
- fprintf(file," size: %d bytes\n",size);
-
- if (pool->descriptor_kind) {
- kind = pool->descriptor_kind;
-
- while (pos < (pool->descriptors + size)) {
- fprintf(file," %p: ",pos);
- switch (*kind++) {
- case 'f':
- descriptor_debug_print_typedesc(file,(typedesc*)pos);
- pos += sizeof(typedesc);
- break;
- case 'm':
- descriptor_debug_print_methoddesc(file,(methoddesc*)pos);
- pos += ((methoddesc*)pos)->paramcount * sizeof(typedesc);
- pos += sizeof(methoddesc) - sizeof(typedesc);
- break;
- default:
- fprintf(file,"INVALID KIND");
- }
- fputc('\n',file);
- }
- }
- else {
- while (size >= sizeof(void*)) {
- fprintf(file," %p\n",*((void**)pos));
- pos += sizeof(void*);
- size -= sizeof(void*);
- }
- }
- }
-
- fprintf(file,"==========================================================\n");
-}
-#endif /* !defined(NDEBUG) */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
-
+++ /dev/null
-/* src/vmcore/descriptor.h - checking and parsing of field / method descriptors
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _DESCRIPTOR_H
-#define _DESCRIPTOR_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct descriptor_pool descriptor_pool;
-typedef struct typedesc typedesc;
-typedef struct paramdesc paramdesc;
-typedef struct methoddesc methoddesc;
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vmcore/utf8.h"
-
-#include "arch.h" /* needed for HAS_ADDRESS_REGISTER_FILE */
-
-/* data structures ************************************************************/
-
-/*----------------------------------------------------------------------------*/
-/* Descriptor Pools */
-/* */
-/* A descriptor_pool is a temporary data structure used during loading of */
-/* a class. The descriptor_pool is used to allocate the table of */
-/* constant_classrefs the class uses, and for parsing the field and method */
-/* descriptors which occurr within the class. The inner workings of */
-/* descriptor_pool are not important for outside code. */
-/* */
-/* You use a descriptor_pool as follows: */
-/* */
-/* 1. create one with descriptor_pool_new */
-/* 2. add all explicit class references with descriptor_pool_add_class */
-/* 3. add all field/method descriptors with descriptor_pool_add */
-/* 4. call descriptor_pool_create_classrefs */
-/* You can now lookup classrefs with descriptor_pool_lookup_classref */
-/* 5. call descriptor_pool_alloc_parsed_descriptors */
-/* 6. for each field descriptor call descriptor_pool_parse_field_descriptor */
-/* for each method descriptor call descriptor_pool_parse_method_descriptor */
-/* 7. call descriptor_pool_get_parsed_descriptors */
-/* */
-/* IMPORTANT: The descriptor_pool functions use DNEW and DMNEW for allocating */
-/* memory which can be thrown away when the steps above have been */
-/* done. */
-/*----------------------------------------------------------------------------*/
-
-struct descriptor_pool {
- classinfo *referer;
- u4 fieldcount;
- u4 methodcount;
- u4 paramcount;
- u4 descriptorsize;
- u1 *descriptors;
- u1 *descriptors_next;
- hashtable descriptorhash;
- constant_classref *classrefs;
- hashtable classrefhash;
- u1 *descriptor_kind; /* useful for debugging */
- u1 *descriptor_kind_next; /* useful for debugging */
-};
-
-
-/* data structures for parsed field/method descriptors ************************/
-
-struct typedesc {
- constant_classref *classref; /* class reference for TYPE_ADR types */
- u1 type; /* TYPE_??? constant [1] */
- u1 primitivetype; /* (PRIMITIVE)TYPE_??? constant [2] */
- u1 arraydim; /* array dimension (0 if no array) */
-};
-
-/* [1]...the type field contains the basic type used within the VM. So ints, */
-/* shorts, chars, bytes, booleans all have TYPE_INT. */
-/* [2]...the primitivetype field contains the declared type. */
-/* So short is PRIMITIVETYPE_SHORT, char is PRIMITIVETYPE_CHAR. */
-/* For non-primitive types primitivetype is TYPE_ADR. */
-
-struct paramdesc {
-#if defined(__MIPS__)
- u1 type; /* TYPE_??? of the register allocated */
-#endif
- bool inmemory; /* argument in register or on stack */
- uint32_t index; /* index into argument register array */
- uint32_t regoff; /* register index or stack offset */
-};
-
-struct methoddesc {
- s2 paramcount; /* number of parameters */
- s2 paramslots; /* like above but LONG,DOUBLE count twice */
- s4 argintreguse; /* number of used integer argument registers */
- s4 argfltreguse; /* number of used float argument registers */
-#if defined(HAS_ADDRESS_REGISTER_FILE)
- s4 argadrreguse; /* number of used address registers */
-#endif
- s4 memuse; /* number of stack slots used */
- paramdesc *params; /* allocated parameter descriptions [3] */
- typedesc returntype; /* parsed descriptor of the return type */
- typedesc paramtypes[1]; /* parameter types, variable length! */
-};
-
-/* [3]...If params is NULL, the parameter descriptions have not yet been */
-/* allocated. In this case ___the possible 'this' pointer of the method */
-/* is NOT counted in paramcount/paramslots and it is NOT included in */
-/* the paramtypes array___. */
-/* If params != NULL, the parameter descriptions have been */
-/* allocated, and the 'this' pointer of the method, if any, IS included.*/
-/* In case the method has no parameters at all, the special value */
-/* METHODDESC_NO_PARAMS is used (see below). */
-
-/* METHODDESC_NO_PARAMS is a special value for the methoddesc.params field */
-/* indicating that the method is a static method without any parameters. */
-/* This special value must be != NULL and it may only be set if */
-/* md->paramcount == 0. */
-
-#define METHODDESC_NOPARAMS ((paramdesc*)1)
-
-/* function prototypes ********************************************************/
-
-descriptor_pool * descriptor_pool_new(classinfo *referer);
-
-bool descriptor_pool_add_class(descriptor_pool *pool,utf *name);
-bool descriptor_pool_add(descriptor_pool *pool,utf *desc,int *paramslots);
-
-int descriptor_to_basic_type(utf *desc);
-int descriptor_typesize(typedesc *td);
-
-constant_classref * descriptor_pool_create_classrefs(descriptor_pool *pool,
- s4 *count);
-constant_classref * descriptor_pool_lookup_classref(descriptor_pool *pool,utf *classname);
-
-void descriptor_pool_alloc_parsed_descriptors(descriptor_pool *pool);
-
-typedesc *descriptor_pool_parse_field_descriptor(descriptor_pool *pool, utf *desc);
-methoddesc *descriptor_pool_parse_method_descriptor(descriptor_pool *pool, utf *desc, s4 mflags,
- constant_classref *thisclass);
-
-bool descriptor_params_from_paramtypes(methoddesc *md, s4 mflags);
-
-void *descriptor_pool_get_parsed_descriptors(descriptor_pool *pool, s4 *size);
-void descriptor_pool_get_sizes(descriptor_pool *pool, u4 *classrefsize,
- u4 *descsize);
-
-#ifndef NDEBUG
-void descriptor_debug_print_typedesc(FILE *file,typedesc *d);
-void descriptor_debug_print_methoddesc(FILE *file,methoddesc *d);
-void descriptor_debug_print_paramdesc(FILE *file,paramdesc *d);
-void descriptor_pool_debug_dump(descriptor_pool *pool, FILE *file);
-#endif /* !defined(NDEBUG) */
-
-#endif /* _DESCRIPTOR_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/field.c - field functions
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "vm/types.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/primitive.hpp"
-#include "vm/string.hpp"
-#include "vm/vm.hpp"
-
-#include "vmcore/annotation.h"
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/field.h"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/references.h"
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-/* field_load ******************************************************************
-
- Load everything about a class field from the class file and fill a
- fieldinfo structure.
-
-*******************************************************************************/
-
-#define field_load_NOVALUE 0xffffffff /* must be bigger than any u2 value! */
-
-bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool)
-{
- classinfo *c;
- u4 attrnum, i;
- u4 pindex = field_load_NOVALUE; /* constantvalue_index */
- utf *u;
-
- /* Get class. */
-
- c = cb->clazz;
-
- f->clazz = c;
-
- /* Get access flags. */
-
- if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
- return false;
-
- f->flags = suck_u2(cb);
-
- /* Get name. */
-
- if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
- return false;
-
- f->name = u;
-
- /* Get descriptor. */
-
- if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
- return false;
-
- f->descriptor = u;
- f->parseddesc = NULL;
-
- if (!descriptor_pool_add(descpool, u, NULL))
- return false;
-
- /* descriptor_pool_add accepts method descriptors, so we have to
- check against them here before the call of
- descriptor_to_basic_type below. */
-
- if (u->text[0] == '(') {
- exceptions_throw_classformaterror(c, "Method descriptor used for field");
- return false;
- }
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- /* check name */
- if (!is_valid_name_utf(f->name) || f->name->text[0] == '<') {
- exceptions_throw_classformaterror(c,
- "Illegal Field name \"%s\"",
- f->name->text);
- return false;
- }
-
- /* check flag consistency */
- i = f->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);
-
- if ((i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) ||
- ((f->flags & (ACC_FINAL | ACC_VOLATILE)) == (ACC_FINAL | ACC_VOLATILE))) {
- exceptions_throw_classformaterror(c,
- "Illegal field modifiers: 0x%X",
- f->flags);
- return false;
- }
-
- if (c->flags & ACC_INTERFACE) {
- if (((f->flags & (ACC_STATIC | ACC_PUBLIC | ACC_FINAL))
- != (ACC_STATIC | ACC_PUBLIC | ACC_FINAL)) ||
- f->flags & ACC_TRANSIENT) {
- exceptions_throw_classformaterror(c,
- "Illegal field modifiers: 0x%X",
- f->flags);
- return false;
- }
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- /* data type */
-
- f->type = descriptor_to_basic_type(f->descriptor);
-
- /* For static-fields allocate memory for the value and set the
- value to 0. */
-
- if (f->flags & ACC_STATIC) {
- switch (f->type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_FLT:
- case TYPE_DBL:
- f->value = NEW(imm_union);
- break;
-
- case TYPE_ADR:
-#if !defined(ENABLE_GC_BOEHM)
- f->value = NEW(imm_union);
-#else
- f->value = GCNEW_UNCOLLECTABLE(imm_union, 1);
-#endif
- break;
-
- default:
- vm_abort("field_load: invalid field type %d", f->type);
- }
-
- /* Set the field to zero, for float and double fields set the
- correct 0.0 value. */
-
- switch (f->type) {
- case TYPE_INT:
- case TYPE_LNG:
- case TYPE_ADR:
- f->value->l = 0;
- break;
-
- case TYPE_FLT:
- f->value->f = 0.0;
- break;
-
- case TYPE_DBL:
- f->value->d = 0.0;
- break;
- }
- }
- else {
- /* For instance-fields set the offset to 0. */
-
- f->offset = 0;
-
- /* For final fields, which are not static, we need a value
- structure. */
-
- if (f->flags & ACC_FINAL) {
- f->value = NEW(imm_union);
- /* XXX hack */
- f->value->l = 0;
- }
-
- switch (f->type) {
- case TYPE_ADR:
- c->flags |= ACC_CLASS_HAS_POINTERS;
- break;
- }
- }
-
- /* read attributes */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- attrnum = suck_u2(cb);
-
- for (i = 0; i < attrnum; i++) {
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- if (!(u = class_getconstant(c, suck_u2(cb), CONSTANT_Utf8)))
- return false;
-
- if (u == utf_ConstantValue) {
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* check attribute length */
-
- if (suck_u4(cb) != 2) {
- exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
- return false;
- }
-
- /* constant value attribute */
-
- if (pindex != field_load_NOVALUE) {
- exceptions_throw_classformaterror(c, "Multiple ConstantValue attributes");
- return false;
- }
-
- /* index of value in constantpool */
-
- pindex = suck_u2(cb);
-
- /* initialize field with value from constantpool */
-
- switch (f->type) {
- case TYPE_INT: {
- constant_integer *ci;
-
- if (!(ci = class_getconstant(c, pindex, CONSTANT_Integer)))
- return false;
-
- f->value->i = ci->value;
- }
- break;
-
- case TYPE_LNG: {
- constant_long *cl;
-
- if (!(cl = class_getconstant(c, pindex, CONSTANT_Long)))
- return false;
-
- f->value->l = cl->value;
- }
- break;
-
- case TYPE_FLT: {
- constant_float *cf;
-
- if (!(cf = class_getconstant(c, pindex, CONSTANT_Float)))
- return false;
-
- f->value->f = cf->value;
- }
- break;
-
- case TYPE_DBL: {
- constant_double *cd;
-
- if (!(cd = class_getconstant(c, pindex, CONSTANT_Double)))
- return false;
-
- f->value->d = cd->value;
- }
- break;
-
- case TYPE_ADR:
- if (!(u = class_getconstant(c, pindex, CONSTANT_String)))
- return false;
-
- /* Create Java-string from compressed UTF8-string. */
-
- f->value->a = literalstring_new(u);
- break;
-
- default:
- vm_abort("field_load: invalid field type %d", f->type);
- }
- }
-#if defined(ENABLE_JAVASE)
- else if (u == utf_Signature) {
- /* Signature */
-
- if (!loader_load_attribute_signature(cb, &(f->signature)))
- return false;
- }
-
-#if defined(ENABLE_ANNOTATIONS)
- else if (u == utf_RuntimeVisibleAnnotations) {
- /* RuntimeVisibleAnnotations */
- if (!annotation_load_field_attribute_runtimevisibleannotations(cb, f))
- return false;
- }
- else if (u == utf_RuntimeInvisibleAnnotations) {
- /* RuntimeInvisibleAnnotations */
- if (!annotation_load_field_attribute_runtimeinvisibleannotations(cb, f))
- return false;
- }
-#endif
-#endif
- else {
- /* unknown attribute */
-
- if (!loader_skip_attribute_body(cb))
- return false;
- }
- }
-
- /* everything was ok */
-
- return true;
-}
-
-
-/* field_get_type **************************************************************
-
- Returns the type of the field as class.
-
-*******************************************************************************/
-
-classinfo *field_get_type(fieldinfo *f)
-{
- typedesc *td;
- utf *u;
- classinfo *c;
-
- td = f->parseddesc;
-
- if (td->type == TYPE_ADR) {
- assert(td->classref);
-
- u = td->classref->name;
-
- /* load the class of the field-type with the field's
- classloader */
-
- c = load_class_from_classloader(u, f->clazz->classloader);
- }
- else {
- c = Primitive_get_class_by_type(td->primitivetype);
- }
-
- return c;
-}
-
-
-/* field_free ******************************************************************
-
- Frees a fields' resources.
-
-*******************************************************************************/
-
-void field_free(fieldinfo *f)
-{
- /* free memory for fields which have a value */
-
- if (f->value)
-#if defined(ENABLE_GC_BOEHM)
- if (f->type != TYPE_ADR)
-#endif
- FREE(f->value, imm_union);
-}
-
-
-/* field_get_annotations ******************************************************
-
- Get a fields' unparsed annotations in a byte array.
-
- IN:
- f........the field of which the annotations should be returned
-
- RETURN VALUE:
- The unparsed annotations in a byte array (or NULL if there aren't any).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *field_get_annotations(fieldinfo *f)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* declaring class */
- int slot; /* slot of this field */
- java_handle_bytearray_t *annotations; /* unparsed annotations */
- java_handle_t *field_annotations; /* array of unparsed */
- /* annotations of all fields of the declaring class */
-
- c = f->clazz;
- slot = f - c->fields;
- annotations = NULL;
-
- LLNI_classinfo_field_get(c, field_annotations, field_annotations);
-
- /* the field_annotations array might be shorter then the field
- * count if the fields above a certain index have no annotations.
- */
- if (field_annotations != NULL &&
- array_length_get(field_annotations) > slot) {
- annotations = (java_handle_bytearray_t*)array_objectarray_element_get(
- (java_handle_objectarray_t*)field_annotations, slot);
- }
-
- return annotations;
-#else
- return NULL;
-#endif
-}
-
-
-/* field_printflags ************************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_printflags(fieldinfo *f)
-{
- if (f == NULL) {
- printf("NULL");
- return;
- }
-
- if (f->flags & ACC_PUBLIC) printf(" PUBLIC");
- if (f->flags & ACC_PRIVATE) printf(" PRIVATE");
- if (f->flags & ACC_PROTECTED) printf(" PROTECTED");
- if (f->flags & ACC_STATIC) printf(" STATIC");
- if (f->flags & ACC_FINAL) printf(" FINAL");
- if (f->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
- if (f->flags & ACC_VOLATILE) printf(" VOLATILE");
- if (f->flags & ACC_TRANSIENT) printf(" TRANSIENT");
- if (f->flags & ACC_NATIVE) printf(" NATIVE");
- if (f->flags & ACC_INTERFACE) printf(" INTERFACE");
- if (f->flags & ACC_ABSTRACT) printf(" ABSTRACT");
-}
-#endif
-
-
-/* field_print *****************************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_print(fieldinfo *f)
-{
- if (f == NULL) {
- printf("(fieldinfo*)NULL");
- return;
- }
-
- utf_display_printable_ascii_classname(f->clazz->name);
- printf(".");
- utf_display_printable_ascii(f->name);
- printf(" ");
- utf_display_printable_ascii(f->descriptor);
-
- field_printflags(f);
-
- if (!(f->flags & ACC_STATIC)) {
- printf(", offset: %d", f->offset);
- }
-}
-#endif
-
-
-/* field_println ***************************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_println(fieldinfo *f)
-{
- field_print(f);
- printf("\n");
-}
-#endif
-
-/* field_fieldref_print ********************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_fieldref_print(constant_FMIref *fr)
-{
- if (fr == NULL) {
- printf("(constant_FMIref *)NULL");
- return;
- }
-
- if (IS_FMIREF_RESOLVED(fr)) {
- printf("<field> ");
- field_print(fr->p.field);
- }
- else {
- printf("<fieldref> ");
- utf_display_printable_ascii_classname(fr->p.classref->name);
- printf(".");
- utf_display_printable_ascii(fr->name);
- printf(" ");
- utf_display_printable_ascii(fr->descriptor);
- }
-}
-#endif
-
-/* field_fieldref_println ******************************************************
-
- (debugging only)
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void field_fieldref_println(constant_FMIref *fr)
-{
- field_fieldref_print(fr);
- printf("\n");
-}
-#endif
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/field.h - field functions header
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _FIELD_H
-#define _FIELD_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct fieldinfo fieldinfo;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/references.h"
-#include "vmcore/utf8.h"
-
-
-/* fieldinfo ******************************************************************/
-
-struct fieldinfo { /* field of a class */
-
- /* CAUTION: The first field must be a pointer that is never the same */
- /* value as CLASSREF_PSEUDO_VFTBL! This is used to check whether */
- /* a constant_FMIref has been resolved. */
-
- classinfo *clazz; /* needed by typechecker. Could be optimized */
- /* away by using constant_FMIref instead of */
- /* fieldinfo throughout the compiler. */
-
- s4 flags; /* ACC flags */
- s4 type; /* basic data type */
- utf *name; /* name of field */
- utf *descriptor;/* JavaVM descriptor string of field */
- utf *signature; /* Signature attribute string */
- typedesc *parseddesc;/* parsed descriptor */
-
- int32_t offset; /* offset from start of object (instance variables) */
- imm_union *value; /* storage for static values (class variables) */
-};
-
-
-/* function prototypes ********************************************************/
-
-bool field_load(classbuffer *cb, fieldinfo *f, descriptor_pool *descpool);
-classinfo *field_get_type(fieldinfo *f);
-void field_free(fieldinfo *f);
-
-java_handle_bytearray_t *field_get_annotations(fieldinfo *f);
-
-#if !defined(NDEBUG)
-void field_printflags(fieldinfo *f);
-void field_print(fieldinfo *f);
-void field_println(fieldinfo *f);
-void field_fieldref_print(constant_FMIref *fr);
-void field_fieldref_println(constant_FMIref *fr);
-#endif
-
-#endif /* _FIELD_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/globals.cpp - global variables
-
- Copyright (C) 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vmcore/class.h"
-
-
-// Classes.
-
-/* Important system classes. */
-
-classinfo *class_java_lang_Object;
-classinfo *class_java_lang_Class;
-classinfo *class_java_lang_ClassLoader;
-classinfo *class_java_lang_Cloneable;
-classinfo *class_java_lang_SecurityManager;
-classinfo *class_java_lang_String;
-classinfo *class_java_lang_System;
-classinfo *class_java_lang_Thread;
-classinfo *class_java_lang_ThreadGroup;
-classinfo *class_java_lang_Throwable;
-classinfo *class_java_io_Serializable;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-classinfo *class_java_lang_VMSystem;
-classinfo *class_java_lang_VMThread;
-classinfo *class_java_lang_VMThrowable;
-#endif
-
-/* Important system exceptions. */
-
-classinfo *class_java_lang_Exception;
-classinfo *class_java_lang_ClassNotFoundException;
-classinfo *class_java_lang_RuntimeException;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-classinfo *class_sun_misc_Signal;
-classinfo *class_sun_reflect_MagicAccessorImpl;
-#endif
-
-#if defined(ENABLE_JAVASE)
-classinfo *class_java_lang_Void;
-#endif
-classinfo *class_java_lang_Boolean;
-classinfo *class_java_lang_Byte;
-classinfo *class_java_lang_Character;
-classinfo *class_java_lang_Short;
-classinfo *class_java_lang_Integer;
-classinfo *class_java_lang_Long;
-classinfo *class_java_lang_Float;
-classinfo *class_java_lang_Double;
-
-/* some classes which may be used more often */
-
-#if defined(ENABLE_JAVASE)
-classinfo *class_java_lang_StackTraceElement;
-classinfo *class_java_lang_reflect_Constructor;
-classinfo *class_java_lang_reflect_Field;
-classinfo *class_java_lang_reflect_Method;
-classinfo *class_java_security_PrivilegedAction;
-classinfo *class_java_util_Vector;
-classinfo *class_java_util_HashMap;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-classinfo *class_java_lang_reflect_VMConstructor;
-classinfo *class_java_lang_reflect_VMField;
-classinfo *class_java_lang_reflect_VMMethod;
-# endif
-
-classinfo *arrayclass_java_lang_Object;
-
-# if defined(ENABLE_ANNOTATIONS)
-classinfo *class_sun_reflect_ConstantPool;
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-classinfo *class_sun_reflect_annotation_AnnotationParser;
-# endif
-# endif
-#endif
-
-/* pseudo classes for the typechecker */
-
-classinfo *pseudo_class_Arraystub;
-classinfo *pseudo_class_Null;
-classinfo *pseudo_class_New;
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c++
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/globals.hpp - global variables
-
- Copyright (C) 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _GLOBALS_HPP
-#define _GLOBALS_HPP
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vmcore/class.h"
-
-
-// FIXME For now we export them a C symbols.
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Classes.
-
-/* Important system classes. */
-
-extern classinfo *class_java_lang_Object;
-extern classinfo *class_java_lang_Class;
-extern classinfo *class_java_lang_ClassLoader;
-extern classinfo *class_java_lang_Cloneable;
-extern classinfo *class_java_lang_SecurityManager;
-extern classinfo *class_java_lang_String;
-extern classinfo *class_java_lang_System;
-extern classinfo *class_java_lang_Thread;
-extern classinfo *class_java_lang_ThreadGroup;
-extern classinfo *class_java_lang_Throwable;
-extern classinfo *class_java_io_Serializable;
-
-/* Important system exceptions. */
-
-extern classinfo *class_java_lang_Exception;
-extern classinfo *class_java_lang_ClassNotFoundException;
-extern classinfo *class_java_lang_RuntimeException;
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern classinfo *class_java_lang_VMSystem;
-extern classinfo *class_java_lang_VMThread;
-extern classinfo *class_java_lang_VMThrowable;
-#endif
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-extern classinfo *class_sun_misc_Signal;
-extern classinfo *class_sun_reflect_MagicAccessorImpl;
-#endif
-
-#if defined(ENABLE_JAVASE)
-extern classinfo *class_java_lang_Void;
-#endif
-
-extern classinfo *class_java_lang_Boolean;
-extern classinfo *class_java_lang_Byte;
-extern classinfo *class_java_lang_Character;
-extern classinfo *class_java_lang_Short;
-extern classinfo *class_java_lang_Integer;
-extern classinfo *class_java_lang_Long;
-extern classinfo *class_java_lang_Float;
-extern classinfo *class_java_lang_Double;
-
-/* some classes which may be used more often */
-
-#if defined(ENABLE_JAVASE)
-extern classinfo *class_java_lang_StackTraceElement;
-extern classinfo *class_java_lang_reflect_Constructor;
-extern classinfo *class_java_lang_reflect_Field;
-extern classinfo *class_java_lang_reflect_Method;
-extern classinfo *class_java_security_PrivilegedAction;
-extern classinfo *class_java_util_Vector;
-extern classinfo *class_java_util_HashMap;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern classinfo *class_java_lang_reflect_VMConstructor;
-extern classinfo *class_java_lang_reflect_VMField;
-extern classinfo *class_java_lang_reflect_VMMethod;
-# endif
-
-extern classinfo *arrayclass_java_lang_Object;
-
-# if defined(ENABLE_ANNOTATIONS)
-extern classinfo *class_sun_reflect_ConstantPool;
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern classinfo *class_sun_reflect_annotation_AnnotationParser;
-# endif
-# endif
-#endif
-
-
-/* pseudo classes for the type checker ****************************************/
-
-/*
- * pseudo_class_Arraystub
- * (extends Object implements Cloneable, java.io.Serializable)
- *
- * If two arrays of incompatible component types are merged,
- * the resulting reference has no accessible components.
- * The result does, however, implement the interfaces Cloneable
- * and java.io.Serializable. This pseudo class is used internally
- * to represent such results. (They are *not* considered arrays!)
- *
- * pseudo_class_Null
- *
- * This pseudo class is used internally to represent the
- * null type.
- *
- * pseudo_class_New
- *
- * This pseudo class is used internally to represent the
- * the 'uninitialized object' type.
- */
-
-extern classinfo *pseudo_class_Arraystub;
-extern classinfo *pseudo_class_Null;
-extern classinfo *pseudo_class_New;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // _CLASS_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:
- */
+++ /dev/null
-/* src/vmcore/javaobjects.cpp - functions to create and access Java objects
-
- Copyright (C) 2008 Theobroma Systems Ltd.
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-
-// REMOVEME
-#include "native/vm/reflection.hpp"
-
-#include "vm/access.h"
-#include "vm/builtin.h"
-#include "vm/global.h"
-#include "vm/initialize.h"
-
-#include "vmcore/globals.hpp"
-#include "vmcore/javaobjects.hpp"
-
-
-#if defined(ENABLE_JAVASE)
-
-/**
- * Constructs a Java object with the given
- * java.lang.reflect.Constructor.
- *
- * @param args Constructor arguments.
- *
- * @return Handle to Java object.
- */
-java_handle_t* java_lang_reflect_Constructor::new_instance(java_handle_objectarray_t* args)
-{
- methodinfo* m = get_method();
-
- // Should we bypass security the checks (AccessibleObject)?
- if (get_override() == false) {
- /* This method is always called like this:
- [0] java.lang.reflect.Constructor.constructNative (Native Method)
- [1] java.lang.reflect.Constructor.newInstance
- [2] <caller>
- */
-
- if (!access_check_method(m, 2))
- return NULL;
- }
-
- // Create a Java object.
- java_handle_t* h = builtin_new(m->clazz);
-
- if (h == NULL)
- return NULL;
-
- // Call initializer.
- (void) Reflection::invoke(m, h, args);
-
- return h;
-}
-
-
-/**
- * Invokes the given method.
- *
- * @param args Method arguments.
- *
- * @return return value of the method
- */
-java_handle_t* java_lang_reflect_Method::invoke(java_handle_t* o, java_handle_objectarray_t* args)
-{
- methodinfo* m = get_method();
-
- // Should we bypass security the checks (AccessibleObject)?
- if (get_override() == false) {
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* This method is always called like this:
- [0] java.lang.reflect.Method.invokeNative (Native Method)
- [1] java.lang.reflect.Method.invoke (Method.java:329)
- [2] <caller>
- */
-
- if (!access_check_method(m, 2))
- return NULL;
-#elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* We only pass 1 here as stacktrace_get_caller_class, which
- is called from access_check_method, skips
- java.lang.reflect.Method.invoke(). */
-
- if (!access_check_method(m, 1))
- return NULL;
-#else
-# error unknown classpath configuration
-#endif
- }
-
- // Check if method class is initialized.
- if (!(m->clazz->state & CLASS_INITIALIZED))
- if (!initialize_class(m->clazz))
- return NULL;
-
- // Call the Java method.
- java_handle_t* result = Reflection::invoke(m, o, args);
-
- return result;
-}
-
-
-// Legacy C interface.
-
-extern "C" {
- java_handle_t* java_lang_reflect_Constructor_create(methodinfo* m) { return java_lang_reflect_Constructor(m).get_handle(); }
- java_handle_t* java_lang_reflect_Field_create(fieldinfo* f) { return java_lang_reflect_Field(f).get_handle(); }
- java_handle_t* java_lang_reflect_Method_create(methodinfo* m) { return java_lang_reflect_Method(m).get_handle(); }
-}
-
-#endif // ENABLE_JAVASE
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c++
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/javaobjects.hpp - functions to create and access Java objects
-
- Copyright (C) 2008 Theobroma Systems Ltd.
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _JAVAOBJECTS_HPP
-#define _JAVAOBJECTS_HPP
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/method.h"
-
-
-#ifdef __cplusplus
-
-/**
- * This class provides low-level functions to access Java object
- * instance fields.
- *
- * These functions do NOT take care about the GC critical section!
- * Please use FieldAccess wherever possible.
- */
-class RawFieldAccess {
-protected:
- template<class T> static inline T raw_get(void* address, const off_t offset);
- template<class T> static inline void raw_set(void* address, const off_t offset, T value);
-};
-
-
-template<class T> inline T RawFieldAccess::raw_get(void* address, const off_t offset)
-{
- T* p = (T*) (((uintptr_t) address) + offset);
- return *p;
-}
-
-
-template<class T> inline void RawFieldAccess::raw_set(void* address, const off_t offset, T value)
-{
- T* p = (T*) (((uintptr_t) address) + offset);
- *p = value;
-}
-
-
-/**
- * This classes provides functions to access Java object instance
- * fields. These functions enter a critical GC section before
- * accessing the Java object throught the handle and leave it
- * afterwards.
- */
-class FieldAccess : private RawFieldAccess {
-protected:
- template<class T> static inline T get(java_handle_t* h, const off_t offset);
- template<class T> static inline void set(java_handle_t* h, const off_t offset, T value);
-};
-
-template<class T> inline T FieldAccess::get(java_handle_t* h, const off_t offset)
-{
- java_object_t* o;
- T result;
-
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
-
- // XXX This should be _handle->get_object();
- o = LLNI_UNWRAP(h);
-
- result = raw_get<T>(o, offset);
-
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
-
- return result;
-}
-
-template<> inline java_handle_t* FieldAccess::get(java_handle_t* h, const off_t offset)
-{
- java_object_t* o;
- java_object_t* result;
- java_handle_t* hresult;
-
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
-
- // XXX This should be _handle->get_object();
- o = LLNI_UNWRAP(h);
-
- result = raw_get<java_object_t*>(o, offset);
-
- hresult = LLNI_WRAP(result);
-
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
-
- return result;
-}
-
-
-template<class T> inline void FieldAccess::set(java_handle_t* h, const off_t offset, T value)
-{
- java_object_t* o;
-
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
-
- // XXX This should be h->get_object();
- o = LLNI_UNWRAP(h);
-
- raw_set(o, offset, value);
-
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
-}
-
-template<> inline void FieldAccess::set<java_handle_t*>(java_handle_t* h, const off_t offset, java_handle_t* value)
-{
- java_object_t* o;
- java_object_t* ovalue;
-
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
-
- // XXX This should be h->get_object();
- o = LLNI_UNWRAP(h);
- ovalue = LLNI_UNWRAP(value);
-
- raw_set(o, offset, ovalue);
-
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
-}
-
-
-/**
- * java/lang/Object
- *
- * Object layout:
- *
- * 0. object header
- */
-class java_lang_Object {
-protected:
- // Handle of Java object.
- java_handle_t* _handle;
-
-protected:
- java_lang_Object() : _handle(NULL) {}
- java_lang_Object(java_handle_t* h) : _handle(h) {}
- java_lang_Object(jobject h) : _handle((java_handle_t*) h) {}
-
-public:
- // Getters.
- virtual inline java_handle_t* get_handle() const { return _handle; }
- inline vftbl_t* get_vftbl () const;
- inline classinfo* get_Class () const;
-
- inline bool is_null () const;
- inline bool is_non_null() const;
-};
-
-
-inline vftbl_t* java_lang_Object::get_vftbl() const
-{
- // XXX Move this to a GC inline function, e.g.
- // gc->enter_critical();
- LLNI_CRITICAL_START;
-
- // XXX This should be h->get_object();
- java_object_t* o = LLNI_UNWRAP(_handle);
- vftbl_t* vftbl = o->vftbl;
-
- // XXX Move this to a GC inline function.
- // gc->leave_critical();
- LLNI_CRITICAL_END;
-
- return vftbl;
-}
-
-inline classinfo* java_lang_Object::get_Class() const
-{
- return get_vftbl()->clazz;
-}
-
-
-inline bool java_lang_Object::is_null() const
-{
- return (_handle == NULL);
-}
-
-inline bool java_lang_Object::is_non_null() const
-{
- return (_handle != NULL);
-}
-
-
-/**
- * java/lang/Boolean
- *
- * Object layout:
- *
- * 0. object header
- * 1. boolean value;
- */
-class java_lang_Boolean : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
-
-public:
- java_lang_Boolean(java_handle_t* h) : java_lang_Object(h) {}
-
- inline uint8_t get_value();
- inline void set_value(uint8_t value);
-};
-
-inline uint8_t java_lang_Boolean::get_value()
-{
- return get<int32_t>(_handle, offset_value);
-}
-
-inline void java_lang_Boolean::set_value(uint8_t value)
-{
- set(_handle, offset_value, (uint32_t) value);
-}
-
-
-/**
- * java/lang/Byte
- *
- * Object layout:
- *
- * 0. object header
- * 1. byte value;
- */
-class java_lang_Byte : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
-
-public:
- java_lang_Byte(java_handle_t* h) : java_lang_Object(h) {}
-
- inline int8_t get_value();
- inline void set_value(int8_t value);
-};
-
-inline int8_t java_lang_Byte::get_value()
-{
- return get<int32_t>(_handle, offset_value);
-}
-
-inline void java_lang_Byte::set_value(int8_t value)
-{
- set(_handle, offset_value, (int32_t) value);
-}
-
-
-/**
- * java/lang/Character
- *
- * Object layout:
- *
- * 0. object header
- * 1. char value;
- */
-class java_lang_Character : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
-
-public:
- java_lang_Character(java_handle_t* h) : java_lang_Object(h) {}
-
- inline uint16_t get_value();
- inline void set_value(uint16_t value);
-};
-
-inline uint16_t java_lang_Character::get_value()
-{
- return get<int32_t>(_handle, offset_value);
-}
-
-inline void java_lang_Character::set_value(uint16_t value)
-{
- set(_handle, offset_value, (uint32_t) value);
-}
-
-
-/**
- * java/lang/Short
- *
- * Object layout:
- *
- * 0. object header
- * 1. short value;
- */
-class java_lang_Short : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
-
-public:
- java_lang_Short(java_handle_t* h) : java_lang_Object(h) {}
-
- inline int16_t get_value();
- inline void set_value(int16_t value);
-};
-
-inline int16_t java_lang_Short::get_value()
-{
- return get<int32_t>(_handle, offset_value);
-}
-
-inline void java_lang_Short::set_value(int16_t value)
-{
- set(_handle, offset_value, (int32_t) value);
-}
-
-
-/**
- * java/lang/Integer
- *
- * Object layout:
- *
- * 0. object header
- * 1. int value;
- */
-class java_lang_Integer : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
-
-public:
- java_lang_Integer(java_handle_t* h) : java_lang_Object(h) {}
-
- inline int32_t get_value();
- inline void set_value(int32_t value);
-};
-
-inline int32_t java_lang_Integer::get_value()
-{
- return get<int32_t>(_handle, offset_value);
-}
-
-inline void java_lang_Integer::set_value(int32_t value)
-{
- set(_handle, offset_value, value);
-}
-
-
-/**
- * java/lang/Long
- *
- * Object layout:
- *
- * 0. object header
- * 1. long value;
- */
-class java_lang_Long : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int64_t));
-
-public:
- java_lang_Long(java_handle_t* h) : java_lang_Object(h) {}
-
- inline int64_t get_value();
- inline void set_value(int64_t value);
-};
-
-inline int64_t java_lang_Long::get_value()
-{
- return get<int64_t>(_handle, offset_value);
-}
-
-inline void java_lang_Long::set_value(int64_t value)
-{
- set(_handle, offset_value, value);
-}
-
-
-/**
- * java/lang/Float
- *
- * Object layout:
- *
- * 0. object header
- * 1. float value;
- */
-class java_lang_Float : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(float));
-
-public:
- java_lang_Float(java_handle_t* h) : java_lang_Object(h) {}
-
- inline float get_value();
- inline void set_value(float value);
-};
-
-inline float java_lang_Float::get_value()
-{
- return get<float>(_handle, offset_value);
-}
-
-inline void java_lang_Float::set_value(float value)
-{
- set(_handle, offset_value, value);
-}
-
-
-/**
- * java/lang/Double
- *
- * Object layout:
- *
- * 0. object header
- * 1. double value;
- */
-class java_lang_Double : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), sizeof(double));
-
-public:
- java_lang_Double(java_handle_t* h) : java_lang_Object(h) {}
-
- inline double get_value();
- inline void set_value(double value);
-};
-
-inline double java_lang_Double::get_value()
-{
- return get<double>(_handle, offset_value);
-}
-
-inline void java_lang_Double::set_value(double value)
-{
- set(_handle, offset_value, value);
-}
-
-
-#if defined(ENABLE_JAVASE)
-
-# if defined(ENABLE_ANNOTATIONS)
-/**
- * OpenJDK sun/reflect/ConstantPool
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Object constantPoolOop;
- */
-class sun_reflect_ConstantPool : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_constantPoolOop = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
-
-public:
- sun_reflect_ConstantPool(java_handle_t* h) : java_lang_Object(h) {}
- sun_reflect_ConstantPool(java_handle_t* h, jclass constantPoolOop);
-
- // Setters.
- inline void set_constantPoolOop(classinfo* value);
- inline void set_constantPoolOop(jclass value);
-};
-
-
-inline sun_reflect_ConstantPool::sun_reflect_ConstantPool(java_handle_t* h, jclass constantPoolOop) : java_lang_Object(h)
-{
- set_constantPoolOop(constantPoolOop);
-}
-
-
-inline void sun_reflect_ConstantPool::set_constantPoolOop(classinfo* value)
-{
- set(_handle, offset_constantPoolOop, value);
-}
-
-inline void sun_reflect_ConstantPool::set_constantPoolOop(jclass value)
-{
- // XXX jclass is a boxed object.
- set_constantPoolOop(LLNI_classinfo_unwrap(value));
-}
-# endif // ENABLE_ANNOTATIONS
-
-#endif // ENABLE_JAVASE
-
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-
-/**
- * GNU Classpath java/lang/Class
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Object[] signers;
- * 2. java.security.ProtectionDomain pd;
- * 3. java.lang.Object vmdata;
- * 4. java.lang.reflect.Constructor constructor;
- */
-class java_lang_Class : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_signers = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_pd = MEMORY_ALIGN(offset_signers + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_vmdata = MEMORY_ALIGN(offset_pd + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_constructor = MEMORY_ALIGN(offset_vmdata + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_Class(java_handle_t* h) : java_lang_Object(h) {}
-
- // Setters.
- inline void set_pd(java_handle_t* value);
- inline void set_pd(jobject value);
-};
-
-inline void java_lang_Class::set_pd(java_handle_t* value)
-{
- set(_handle, offset_pd, value);
-}
-
-inline void java_lang_Class::set_pd(jobject value)
-{
- set_pd((java_handle_t*) value);
-}
-
-
-/**
- * GNU Classpath java/lang/StackTraceElement
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.String fileName;
- * 2. int lineNumber;
- * 3. java.lang.String declaringClass;
- * 4. java.lang.String methodName;
- * 5. boolean isNative;
- */
-class java_lang_StackTraceElement : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_fileName = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_lineNumber = MEMORY_ALIGN(offset_fileName + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_declaringClass = MEMORY_ALIGN(offset_lineNumber + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_methodName = MEMORY_ALIGN(offset_declaringClass + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_isNative = MEMORY_ALIGN(offset_methodName + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_StackTraceElement(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_StackTraceElement(java_handle_t* h, java_handle_t* fileName, int32_t lineNumber, java_handle_t* declaringClass, java_handle_t* methodName, uint8_t isNative);
-};
-
-inline java_lang_StackTraceElement::java_lang_StackTraceElement(java_handle_t* h, java_handle_t* fileName, int32_t lineNumber, java_handle_t* declaringClass, java_handle_t* methodName, uint8_t isNative) : java_lang_Object(h)
-{
- java_lang_StackTraceElement((java_handle_t*) h);
-
- set(_handle, offset_fileName, fileName);
- set(_handle, offset_lineNumber, lineNumber);
- set(_handle, offset_declaringClass, declaringClass);
- set(_handle, offset_methodName, methodName);
- set(_handle, offset_isNative, isNative);
-}
-
-
-/**
- * GNU Classpath java/lang/String
- *
- * Object layout:
- *
- * 0. object header
- * 1. char[] value;
- * 2. int count;
- * 3. int cachedHashCode;
- * 4. int offset;
- */
-class java_lang_String : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_count = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_cachedHashCode = MEMORY_ALIGN(offset_count + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_offset = MEMORY_ALIGN(offset_cachedHashCode + sizeof(int32_t), sizeof(int32_t));
-
-public:
- java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_String(jstring h);
- java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
-
- // Getters.
- inline java_handle_chararray_t* get_value () const;
- inline int32_t get_count () const;
- inline int32_t get_offset() const;
-
- // Setters.
- inline void set_value (java_handle_chararray_t* value);
- inline void set_count (int32_t value);
- inline void set_offset(int32_t value);
-};
-
-inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
-{
- java_lang_String((java_handle_t*) h);
-}
-
-inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
-{
- set_value(value);
- set_count(count);
- set_offset(offset);
-}
-
-inline java_handle_chararray_t* java_lang_String::get_value() const
-{
- return get<java_handle_chararray_t*>(_handle, offset_value);
-}
-
-inline int32_t java_lang_String::get_count() const
-{
- return get<int32_t>(_handle, offset_count);
-}
-
-inline int32_t java_lang_String::get_offset() const
-{
- return get<int32_t>(_handle, offset_offset);
-}
-
-inline void java_lang_String::set_value(java_handle_chararray_t* value)
-{
- set(_handle, offset_value, value);
-}
-
-inline void java_lang_String::set_count(int32_t value)
-{
- set(_handle, offset_count, value);
-}
-
-inline void java_lang_String::set_offset(int32_t value)
-{
- set(_handle, offset_offset, value);
-}
-
-
-/**
- * GNU Classpath java/lang/Thread
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.VMThread vmThread;
- * 2. java.lang.ThreadGroup group;
- * 3. java.lang.Runnable runnable;
- * 4. java.lang.String name;
- * 5. boolean daemon;
- * 6. int priority;
- * 7. long stacksize;
- * 8. java.lang.Throwable stillborn;
- * 9. java.lang.ClassLoader contextClassLoader;
- * 10. boolean contextClassLoaderIsSystemClassLoader;
- * 11. long threadId;
- * 12. java.lang.Object parkBlocker;
- * 13. gnu.java.util.WeakIdentityHashMap locals;
- * 14. java_lang_Thread_UncaughtExceptionHandler exceptionHandler;
- */
-class java_lang_Thread : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_vmThread = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_group = MEMORY_ALIGN(offset_vmThread + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_runnable = MEMORY_ALIGN(offset_group + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_name = MEMORY_ALIGN(offset_runnable + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_daemon = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_priority = MEMORY_ALIGN(offset_daemon + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_stacksize = MEMORY_ALIGN(offset_priority + sizeof(int32_t), sizeof(int64_t));
- static const off_t offset_stillborn = MEMORY_ALIGN(offset_stacksize + sizeof(int64_t), SIZEOF_VOID_P);
- static const off_t offset_contextClassLoader = MEMORY_ALIGN(offset_stillborn + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_contextClassLoaderIsSystemClassLoader = MEMORY_ALIGN(offset_contextClassLoader + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_threadId = MEMORY_ALIGN(offset_contextClassLoaderIsSystemClassLoader + sizeof(int32_t), sizeof(int64_t));
- static const off_t offset_parkBlocker = MEMORY_ALIGN(offset_threadId + sizeof(int64_t), SIZEOF_VOID_P);
- static const off_t offset_locals = MEMORY_ALIGN(offset_parkBlocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_exceptionHandler = MEMORY_ALIGN(offset_locals + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
-// java_lang_Thread(threadobject* t);
-
- // Getters.
- inline java_handle_t* get_vmThread () const;
- inline java_handle_t* get_group () const;
- inline java_handle_t* get_name () const;
- inline int32_t get_daemon () const;
- inline int32_t get_priority () const;
- inline java_handle_t* get_exceptionHandler() const;
-
- // Setters.
- inline void set_group(java_handle_t* value);
-};
-
-
-// inline java_lang_Thread::java_lang_Thread(threadobject* t) : java_lang_Object(h)
-// {
-// java_lang_Thread(thread_get_object(t));
-// }
-
-
-inline java_handle_t* java_lang_Thread::get_vmThread() const
-{
- return get<java_handle_t*>(_handle, offset_vmThread);
-}
-
-inline java_handle_t* java_lang_Thread::get_group() const
-{
- return get<java_handle_t*>(_handle, offset_group);
-}
-
-inline java_handle_t* java_lang_Thread::get_name() const
-{
- return get<java_handle_t*>(_handle, offset_name);
-}
-
-inline int32_t java_lang_Thread::get_daemon() const
-{
- return get<int32_t>(_handle, offset_daemon);
-}
-
-inline int32_t java_lang_Thread::get_priority() const
-{
- return get<int32_t>(_handle, offset_priority);
-}
-
-inline java_handle_t* java_lang_Thread::get_exceptionHandler() const
-{
- return get<java_handle_t*>(_handle, offset_exceptionHandler);
-}
-
-
-inline void java_lang_Thread::set_group(java_handle_t* value)
-{
- set(_handle, offset_group, value);
-}
-
-
-/**
- * GNU Classpath java/lang/VMThread
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Thread thread;
- * 2. boolean running;
- * 3. java.lang.VMThread vmdata;
- */
-class java_lang_VMThread : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_thread = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_running = MEMORY_ALIGN(offset_thread + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_vmdata = MEMORY_ALIGN(offset_running + sizeof(int32_t), SIZEOF_VOID_P);
-
-public:
- java_lang_VMThread(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_VMThread(jobject h);
- java_lang_VMThread(java_handle_t* h, java_handle_t* thread, threadobject* vmdata);
-
- // Getters.
- inline java_handle_t* get_thread() const;
- inline threadobject* get_vmdata() const;
-
- // Setters.
- inline void set_thread(java_handle_t* value);
- inline void set_vmdata(threadobject* value);
-};
-
-
-inline java_lang_VMThread::java_lang_VMThread(jobject h) : java_lang_Object(h)
-{
- java_lang_VMThread((java_handle_t*) h);
-}
-
-inline java_lang_VMThread::java_lang_VMThread(java_handle_t* h, java_handle_t* thread, threadobject* vmdata) : java_lang_Object(h)
-{
- set_thread(thread);
- set_vmdata(vmdata);
-}
-
-
-inline java_handle_t* java_lang_VMThread::get_thread() const
-{
- return get<java_handle_t*>(_handle, offset_thread);
-}
-
-inline threadobject* java_lang_VMThread::get_vmdata() const
-{
- return get<threadobject*>(_handle, offset_vmdata);
-}
-
-
-inline void java_lang_VMThread::set_thread(java_handle_t* value)
-{
- set(_handle, offset_thread, value);
-}
-
-inline void java_lang_VMThread::set_vmdata(threadobject* value)
-{
- set(_handle, offset_vmdata, value);
-}
-
-
-/**
- * GNU Classpath java/lang/Throwable
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.String detailMessage;
- * 2. java.lang.Throwable cause;
- * 3. java.lang.StackTraceElement[] stackTrace;
- * 4. java.lang.VMThrowable vmState;
- */
-class java_lang_Throwable : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_detailMessage = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_cause = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_stackTrace = MEMORY_ALIGN(offset_cause + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_vmState = MEMORY_ALIGN(offset_stackTrace + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
-
- // Getters.
- inline java_handle_t* get_detailMessage() const;
- inline java_handle_t* get_cause () const;
- inline java_handle_t* get_vmState () const;
-};
-
-
-inline java_handle_t* java_lang_Throwable::get_detailMessage() const
-{
- return get<java_handle_t*>(_handle, offset_detailMessage);
-}
-
-inline java_handle_t* java_lang_Throwable::get_cause() const
-{
- return get<java_handle_t*>(_handle, offset_cause);
-}
-
-inline java_handle_t* java_lang_Throwable::get_vmState() const
-{
- return get<java_handle_t*>(_handle, offset_vmState);
-}
-
-
-/**
- * GNU Classpath java/lang/VMThrowable
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Object vmdata;
- */
-class java_lang_VMThrowable : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_vmdata = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
-
-public:
- java_lang_VMThrowable(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_VMThrowable(jobject h);
-
- inline java_handle_bytearray_t* get_vmdata() const;
- inline void set_vmdata(java_handle_bytearray_t* value);
-};
-
-inline java_lang_VMThrowable::java_lang_VMThrowable(jobject h) : java_lang_Object(h)
-{
- java_lang_VMThrowable((java_handle_t*) h);
-}
-
-inline java_handle_bytearray_t* java_lang_VMThrowable::get_vmdata() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_vmdata);
-}
-
-inline void java_lang_VMThrowable::set_vmdata(java_handle_bytearray_t* value)
-{
- set(_handle, offset_vmdata, value);
-}
-
-
-/**
- * GNU Classpath java/lang/reflect/VMConstructor
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Class clazz;
- * 2. int slot;
- * 3. byte[] annotations;
- * 4. byte[] parameterAnnotations;
- * 5. java.util.Map declaredAnnotations;
- * 6. java.lang.reflect.Constructor cons;
- */
-class java_lang_reflect_VMConstructor : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_cons = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_VMConstructor(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_VMConstructor(jobject h);
- java_lang_reflect_VMConstructor(methodinfo* m);
-
- // Getters.
- inline classinfo* get_clazz () const;
- inline int32_t get_slot () const;
- inline java_handle_bytearray_t* get_annotations () const;
- inline java_handle_bytearray_t* get_parameterAnnotations() const;
- inline java_handle_t* get_declaredAnnotations () const;
- inline java_handle_t* get_cons () const;
-
- // Setters.
- inline void set_clazz (classinfo* value);
- inline void set_slot (int32_t value);
- inline void set_annotations (java_handle_bytearray_t* value);
- inline void set_parameterAnnotations(java_handle_bytearray_t* value);
- inline void set_declaredAnnotations (java_handle_t* value);
- inline void set_cons (java_handle_t* value);
-
- // Convenience functions.
- inline methodinfo* get_method();
-};
-
-
-inline java_lang_reflect_VMConstructor::java_lang_reflect_VMConstructor(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_VMConstructor((java_handle_t*) h);
-}
-
-inline java_lang_reflect_VMConstructor::java_lang_reflect_VMConstructor(methodinfo* m)
-{
- _handle = builtin_new(class_java_lang_reflect_VMConstructor);
-
- if (is_null())
- return;
-
- int slot = m - m->clazz->methods;
- java_handle_bytearray_t* annotations = method_get_annotations(m);
- java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
-
- set_clazz(m->clazz);
- set_slot(slot);
- set_annotations(annotations);
- set_parameterAnnotations(parameterAnnotations);
-}
-
-
-inline classinfo* java_lang_reflect_VMConstructor::get_clazz() const
-{
- return get<classinfo*>(_handle, offset_clazz);
-}
-
-inline int32_t java_lang_reflect_VMConstructor::get_slot() const
-{
- return get<int32_t>(_handle, offset_slot);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_VMConstructor::get_annotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotations);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_VMConstructor::get_parameterAnnotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
-}
-
-inline java_handle_t* java_lang_reflect_VMConstructor::get_declaredAnnotations() const
-{
- return get<java_handle_t*>(_handle, offset_declaredAnnotations);
-}
-
-inline java_handle_t* java_lang_reflect_VMConstructor::get_cons() const
-{
- return get<java_handle_t*>(_handle, offset_cons);
-}
-
-inline void java_lang_reflect_VMConstructor::set_clazz(classinfo* value)
-{
- set(_handle, offset_clazz, value);
-}
-
-inline void java_lang_reflect_VMConstructor::set_slot(int32_t value)
-{
- set(_handle, offset_slot, value);
-}
-
-inline void java_lang_reflect_VMConstructor::set_annotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_annotations, value);
-}
-
-inline void java_lang_reflect_VMConstructor::set_parameterAnnotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_parameterAnnotations, value);
-}
-
-inline void java_lang_reflect_VMConstructor::set_declaredAnnotations(java_handle_t* value)
-{
- set(_handle, offset_declaredAnnotations, value);
-}
-
-inline void java_lang_reflect_VMConstructor::set_cons(java_handle_t* value)
-{
- set(_handle, offset_cons, value);
-}
-
-inline methodinfo* java_lang_reflect_VMConstructor::get_method()
-{
- classinfo* c = get_clazz();
- int32_t slot = get_slot();
- methodinfo* m = &(c->methods[slot]);
- return m;
-}
-
-
-/**
- * GNU Classpath java/lang/reflect/Constructor
- *
- * Object layout:
- *
- * 0. object header
- * 1. boolean flag;
- * 2. gnu.java.lang.reflect.MethodSignatureParser p;
- * 3. java.lang.reflect.VMConstructor cons;
- */
-class java_lang_reflect_Constructor : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_cons = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_Constructor(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_Constructor(jobject h);
- java_lang_reflect_Constructor(methodinfo* m);
-
- java_handle_t* new_instance(java_handle_objectarray_t* args);
-
- // Getters.
- inline int32_t get_flag() const;
- inline java_handle_t* get_cons() const;
-
- // Setters.
- inline void set_cons(java_handle_t* value);
-
- // Convenience functions.
- inline methodinfo* get_method () const;
- inline int32_t get_override() const;
-};
-
-
-inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_Constructor((java_handle_t*) h);
-}
-
-inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(methodinfo* m)
-{
- java_lang_reflect_VMConstructor jlrvmc(m);
-
- if (jlrvmc.is_null())
- return;
-
- _handle = builtin_new(class_java_lang_reflect_Constructor);
-
- if (is_null())
- return;
-
- // Link the two Java objects.
- set_cons(jlrvmc.get_handle());
- jlrvmc.set_cons(get_handle());
-}
-
-
-inline int32_t java_lang_reflect_Constructor::get_flag() const
-{
- return get<int32_t>(_handle, offset_flag);
-}
-
-inline java_handle_t* java_lang_reflect_Constructor::get_cons() const
-{
- return get<java_handle_t*>(_handle, offset_cons);
-}
-
-
-inline void java_lang_reflect_Constructor::set_cons(java_handle_t* value)
-{
- set(_handle, offset_cons, value);
-}
-
-
-inline methodinfo* java_lang_reflect_Constructor::get_method() const
-{
- java_lang_reflect_VMConstructor jlrvmc(get_cons());
- return jlrvmc.get_method();
-}
-
-inline int32_t java_lang_reflect_Constructor::get_override() const
-{
- return get_flag();
-}
-
-
-/**
- * GNU Classpath java/lang/reflect/VMField
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Class clazz;
- * 2. java.lang.String name;
- * 3. int slot;
- * 4. byte[] annotations;
- * 5. java.lang.Map declaredAnnotations;
- * 6. java.lang.reflect.Field f;
- */
-class java_lang_reflect_VMField : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_name = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_slot = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_f = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_VMField(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_VMField(jobject h);
- java_lang_reflect_VMField(fieldinfo* f);
-
- // Getters.
- inline classinfo* get_clazz () const;
- inline int32_t get_slot () const;
- inline java_handle_bytearray_t* get_annotations () const;
- inline java_handle_t* get_declaredAnnotations() const;
- inline java_handle_t* get_f () const;
-
- // Setters.
- inline void set_clazz (classinfo* value);
- inline void set_name (java_handle_t* value);
- inline void set_slot (int32_t value);
- inline void set_annotations (java_handle_bytearray_t* value);
- inline void set_declaredAnnotations(java_handle_t* value);
- inline void set_f (java_handle_t* value);
-
- // Convenience functions.
- inline fieldinfo* get_field() const;
-};
-
-
-inline java_lang_reflect_VMField::java_lang_reflect_VMField(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_VMField((java_handle_t*) h);
-}
-
-inline java_lang_reflect_VMField::java_lang_reflect_VMField(fieldinfo* f)
-{
- _handle = builtin_new(class_java_lang_reflect_VMField);
-
- if (is_null())
- return;
-
- java_handle_t* name = javastring_intern(javastring_new(f->name));
- int slot = f - f->clazz->fields;
- java_handle_bytearray_t* annotations = field_get_annotations(f);
-
- set_clazz(f->clazz);
- set_name(name);
- set_slot(slot);
- set_annotations(annotations);
-}
-
-
-inline classinfo* java_lang_reflect_VMField::get_clazz() const
-{
- return get<classinfo*>(_handle, offset_clazz);
-}
-
-inline int32_t java_lang_reflect_VMField::get_slot() const
-{
- return get<int32_t>(_handle, offset_slot);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_VMField::get_annotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotations);
-}
-
-inline java_handle_t* java_lang_reflect_VMField::get_declaredAnnotations() const
-{
- return get<java_handle_t*>(_handle, offset_declaredAnnotations);
-}
-
-inline java_handle_t* java_lang_reflect_VMField::get_f() const
-{
- return get<java_handle_t*>(_handle, offset_f);
-}
-
-
-inline void java_lang_reflect_VMField::set_clazz(classinfo* value)
-{
- set(_handle, offset_clazz, value);
-}
-
-inline void java_lang_reflect_VMField::set_name(java_handle_t* value)
-{
- set(_handle, offset_name, value);
-}
-
-inline void java_lang_reflect_VMField::set_slot(int32_t value)
-{
- set(_handle, offset_slot, value);
-}
-
-inline void java_lang_reflect_VMField::set_annotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_annotations, value);
-}
-
-inline void java_lang_reflect_VMField::set_declaredAnnotations(java_handle_t* value)
-{
- set(_handle, offset_declaredAnnotations, value);
-}
-
-inline void java_lang_reflect_VMField::set_f(java_handle_t* value)
-{
- set(_handle, offset_f, value);
-}
-
-inline fieldinfo* java_lang_reflect_VMField::get_field() const
-{
- classinfo* c = get_clazz();
- int32_t slot = get_slot();
- fieldinfo* f = &(c->fields[slot]);
- return f;
-}
-
-
-/**
- * GNU Classpath java/lang/reflect/Field
- *
- * Object layout:
- *
- * 0. object header
- * 1. boolean flag;
- * 2. gnu.java.lang.reflect.FieldSignatureParser p;
- * 3. java.lang.reflect.VMField f;
- */
-class java_lang_reflect_Field : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_f = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_Field(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_Field(jobject h);
- java_lang_reflect_Field(fieldinfo* f);
-
- // Getters.
- inline int32_t get_flag() const;
- inline java_handle_t* get_f() const;
-
- // Setters.
- inline void set_f(java_handle_t* value);
-
- // Convenience functions.
- inline fieldinfo* get_field() const;
-};
-
-
-inline java_lang_reflect_Field::java_lang_reflect_Field(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_Field((java_handle_t*) h);
-}
-
-inline java_lang_reflect_Field::java_lang_reflect_Field(fieldinfo* f)
-{
- java_lang_reflect_VMField jlrvmf(f);
-
- if (jlrvmf.is_null())
- return;
-
- _handle = builtin_new(class_java_lang_reflect_Field);
-
- if (is_null())
- return;
-
- // Link the two Java objects.
- set_f(jlrvmf.get_handle());
- jlrvmf.set_f(get_handle());
-}
-
-
-inline int32_t java_lang_reflect_Field::get_flag() const
-{
- return get<int32_t>(_handle, offset_flag);
-}
-
-inline java_handle_t* java_lang_reflect_Field::get_f() const
-{
- return get<java_handle_t*>(_handle, offset_f);
-}
-
-
-inline void java_lang_reflect_Field::set_f(java_handle_t* value)
-{
- set(_handle, offset_f, value);
-}
-
-
-inline fieldinfo* java_lang_reflect_Field::get_field() const
-{
- java_lang_reflect_VMField jlrvmf(get_f());
- return jlrvmf.get_field();
-}
-
-
-/**
- * GNU Classpath java/lang/reflect/VMMethod
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Class clazz;
- * 2. java.lang.String name;
- * 3. int slot;
- * 4. byte[] annotations;
- * 5. byte[] parameterAnnotations;
- * 6. byte[] annotationDefault;
- * 7. java.lang.Map declaredAnnotations;
- * 8. java.lang.reflect.Method m;
- */
-class java_lang_reflect_VMMethod : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_clazz = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_name = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_slot = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_annotations = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_annotationDefault = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_annotationDefault + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_m = MEMORY_ALIGN(offset_declaredAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_VMMethod(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_VMMethod(jobject h);
- java_lang_reflect_VMMethod(methodinfo* m);
-
- // Getters.
- inline classinfo* get_clazz () const;
- inline int32_t get_slot () const;
- inline java_handle_bytearray_t* get_annotations () const;
- inline java_handle_bytearray_t* get_parameterAnnotations() const;
- inline java_handle_bytearray_t* get_annotationDefault () const;
- inline java_handle_t* get_declaredAnnotations () const;
- inline java_handle_t* get_m () const;
-
- // Setters.
- inline void set_clazz (classinfo* value);
- inline void set_name (java_handle_t* value);
- inline void set_slot (int32_t value);
- inline void set_annotations (java_handle_bytearray_t* value);
- inline void set_parameterAnnotations(java_handle_bytearray_t* value);
- inline void set_annotationDefault (java_handle_bytearray_t* value);
- inline void set_declaredAnnotations (java_handle_t* value);
- inline void set_m (java_handle_t* value);
-
- // Convenience functions.
- inline methodinfo* get_method() const;
-};
-
-inline java_lang_reflect_VMMethod::java_lang_reflect_VMMethod(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_VMMethod((java_handle_t*) h);
-}
-
-inline java_lang_reflect_VMMethod::java_lang_reflect_VMMethod(methodinfo* m)
-{
- _handle = builtin_new(class_java_lang_reflect_VMMethod);
-
- if (is_null())
- return;
-
- java_handle_t* name = javastring_intern(javastring_new(m->name));
- int slot = m - m->clazz->methods;
- java_handle_bytearray_t* annotations = method_get_annotations(m);
- java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
- java_handle_bytearray_t* annotationDefault = method_get_annotationdefault(m);
-
- set_clazz(m->clazz);
- set_name(name);
- set_slot(slot);
- set_annotations(annotations);
- set_parameterAnnotations(parameterAnnotations);
- set_annotationDefault(annotationDefault);
-}
-
-inline classinfo* java_lang_reflect_VMMethod::get_clazz() const
-{
- return get<classinfo*>(_handle, offset_clazz);
-}
-
-inline int32_t java_lang_reflect_VMMethod::get_slot() const
-{
- return get<int32_t>(_handle, offset_slot);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_annotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotations);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_parameterAnnotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_VMMethod::get_annotationDefault() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotationDefault);
-}
-
-inline java_handle_t* java_lang_reflect_VMMethod::get_declaredAnnotations() const
-{
- return get<java_handle_t*>(_handle, offset_declaredAnnotations);
-}
-
-inline java_handle_t* java_lang_reflect_VMMethod::get_m() const
-{
- return get<java_handle_t*>(_handle, offset_m);
-}
-
-inline void java_lang_reflect_VMMethod::set_clazz(classinfo* value)
-{
- set(_handle, offset_clazz, value);
-}
-
-inline void java_lang_reflect_VMMethod::set_name(java_handle_t* value)
-{
- set(_handle, offset_name, value);
-}
-
-inline void java_lang_reflect_VMMethod::set_slot(int32_t value)
-{
- set(_handle, offset_slot, value);
-}
-
-inline void java_lang_reflect_VMMethod::set_annotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_annotations, value);
-}
-
-inline void java_lang_reflect_VMMethod::set_parameterAnnotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_parameterAnnotations, value);
-}
-
-inline void java_lang_reflect_VMMethod::set_annotationDefault(java_handle_bytearray_t* value)
-{
- set(_handle, offset_annotationDefault, value);
-}
-
-inline void java_lang_reflect_VMMethod::set_declaredAnnotations(java_handle_t* value)
-{
- set(_handle, offset_declaredAnnotations, value);
-}
-
-inline void java_lang_reflect_VMMethod::set_m(java_handle_t* value)
-{
- set(_handle, offset_m, value);
-}
-
-inline methodinfo* java_lang_reflect_VMMethod::get_method() const
-{
- classinfo* c = get_clazz();
- int32_t slot = get_slot();
- methodinfo* m = &(c->methods[slot]);
- return m;
-}
-
-
-/**
- * GNU Classpath java/lang/reflect/Method
- *
- * Object layout:
- *
- * 0. object header
- * 1. boolean flag;
- * 2. gnu.java.lang.reflect.MethodSignatureParser p;
- * 3. java.lang.reflect.VMMethod m;
- */
-class java_lang_reflect_Method : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_flag = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_p = MEMORY_ALIGN(offset_flag + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_m = MEMORY_ALIGN(offset_p + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_Method(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_Method(jobject h);
- java_lang_reflect_Method(methodinfo* m);
-
- java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
-
- // Getters.
- inline int32_t get_flag() const;
- inline java_handle_t* get_m() const;
-
- // Setters.
- inline void set_m(java_handle_t* value);
-
- // Convenience functions.
- inline methodinfo* get_method () const;
- inline int32_t get_override() const;
-};
-
-
-inline java_lang_reflect_Method::java_lang_reflect_Method(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_Method((java_handle_t*) h);
-}
-
-inline java_lang_reflect_Method::java_lang_reflect_Method(methodinfo* m)
-{
- java_lang_reflect_VMMethod jlrvmm(m);
-
- if (jlrvmm.is_null())
- return;
-
- _handle = builtin_new(class_java_lang_reflect_Method);
-
- if (is_null())
- return;
-
- // Link the two Java objects.
- set_m(jlrvmm.get_handle());
- jlrvmm.set_m(get_handle());
-}
-
-
-inline int32_t java_lang_reflect_Method::get_flag() const
-{
- return get<int32_t>(_handle, offset_flag);
-}
-
-inline java_handle_t* java_lang_reflect_Method::get_m() const
-{
- return get<java_handle_t*>(_handle, offset_m);
-}
-
-
-inline void java_lang_reflect_Method::set_m(java_handle_t* value)
-{
- set(_handle, offset_m, value);
-}
-
-
-inline methodinfo* java_lang_reflect_Method::get_method() const
-{
- java_lang_reflect_VMMethod jlrvmm(get_m());
- return jlrvmm.get_method();
-}
-
-inline int32_t java_lang_reflect_Method::get_override() const
-{
- return get_flag();
-}
-
-
-/**
- * GNU Classpath java/nio/Buffer
- *
- * Object layout:
- *
- * 0. object header
- * 1. int cap;
- * 2. int limit;
- * 3. int pos;
- * 4. int mark;
- * 5. gnu.classpath.Pointer address;
- */
-class java_nio_Buffer : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_cap = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_limit = MEMORY_ALIGN(offset_cap + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_pos = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_mark = MEMORY_ALIGN(offset_pos + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_address = MEMORY_ALIGN(offset_mark + sizeof(int32_t), SIZEOF_VOID_P);
-
-public:
- java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
-
- // Getters.
- inline int32_t get_cap() const;
-};
-
-inline int32_t java_nio_Buffer::get_cap() const
-{
- return get<int32_t>(_handle, offset_cap);
-}
-
-
-/**
- * GNU Classpath java/nio/DirectByteBufferImpl
- *
- * Object layout:
- *
- * 0. object header
- * 1. int cap;
- * 2. int limit;
- * 3. int pos;
- * 4. int mark;
- * 5. gnu.classpath.Pointer address;
- * 6. java.nio.ByteOrder endian;
- * 7. byte[] backing_buffer;
- * 8. int array_offset;
- * 9. java.lang.Object owner;
- */
-class java_nio_DirectByteBufferImpl : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_cap = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_limit = MEMORY_ALIGN(offset_cap + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_pos = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_mark = MEMORY_ALIGN(offset_pos + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_address = MEMORY_ALIGN(offset_mark + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_endian = MEMORY_ALIGN(offset_address + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_backing_buffer = MEMORY_ALIGN(offset_endian + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_array_offset = MEMORY_ALIGN(offset_backing_buffer + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_owner = MEMORY_ALIGN(offset_array_offset + sizeof(int32_t), SIZEOF_VOID_P);
-
-public:
- java_nio_DirectByteBufferImpl(java_handle_t* h) : java_lang_Object(h) {}
- java_nio_DirectByteBufferImpl(jobject h);
-
- // Getters.
- inline java_handle_t* get_address() const;
-};
-
-inline java_nio_DirectByteBufferImpl::java_nio_DirectByteBufferImpl(jobject h) : java_lang_Object(h)
-{
- java_nio_DirectByteBufferImpl((java_handle_t*) h);
-}
-
-inline java_handle_t* java_nio_DirectByteBufferImpl::get_address() const
-{
- return get<java_handle_t*>(_handle, offset_address);
-}
-
-
-/**
- * GNU Classpath gnu/classpath/Pointer
- *
- * Actually there are two classes, gnu.classpath.Pointer32 and
- * gnu.classpath.Pointer64, but we only define the abstract super
- * class and use the int/long field as void* type.
- *
- * Object layout:
- *
- * 0. object header
- * 1. int/long data;
- */
-class gnu_classpath_Pointer : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_data = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
-
-public:
- gnu_classpath_Pointer(java_handle_t* h) : java_lang_Object(h) {}
- gnu_classpath_Pointer(java_handle_t* h, void* data);
-
- // Setters.
- inline void* get_data() const;
-
- // Setters.
- inline void set_data(void* value);
-};
-
-inline gnu_classpath_Pointer::gnu_classpath_Pointer(java_handle_t* h, void* data) : java_lang_Object(h)
-{
- set_data(data);
-}
-
-inline void* gnu_classpath_Pointer::get_data() const
-{
- return get<void*>(_handle, offset_data);
-}
-
-inline void gnu_classpath_Pointer::set_data(void* value)
-{
- set(_handle, offset_data, value);
-}
-
-#endif // WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH
-
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
-
-/**
- * OpenJDK java/lang/AssertionStatusDirectives
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.String[] classes;
- * 2. boolean[] classEnabled;
- * 3. java.lang.String[] packages;
- * 4. boolean[] packageEnabled;
- * 5. boolean deflt;
- */
-class java_lang_AssertionStatusDirectives : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_classes = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_classEnabled = MEMORY_ALIGN(offset_classes + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_packages = MEMORY_ALIGN(offset_classEnabled + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_packageEnabled = MEMORY_ALIGN(offset_packages + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_deflt = MEMORY_ALIGN(offset_packageEnabled + SIZEOF_VOID_P, sizeof(int32_t));
-
-public:
- java_lang_AssertionStatusDirectives(java_handle_objectarray_t* classes, java_handle_booleanarray_t* classEnabled, java_handle_objectarray_t* packages, java_handle_booleanarray_t* packageEnabled);
-};
-
-inline java_lang_AssertionStatusDirectives::java_lang_AssertionStatusDirectives(java_handle_objectarray_t* classes, java_handle_booleanarray_t* classEnabled, java_handle_objectarray_t* packages, java_handle_booleanarray_t* packageEnabled)
-{
- classinfo* c = load_class_bootstrap(utf_new_char("java/lang/AssertionStatusDirectives"));
-
- // FIXME Load the class at VM startup.
- if (c == NULL)
- return;
-
- _handle = builtin_new(c);
-
- if (is_null())
- return;
-
- set(_handle, offset_classes, classes);
- set(_handle, offset_classEnabled, classEnabled);
- set(_handle, offset_packages, packages);
- set(_handle, offset_packageEnabled, packageEnabled);
-}
-
-
-/**
- * OpenJDK java/lang/StackTraceElement
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.String declaringClass;
- * 2. java.lang.String methodName;
- * 3. java.lang.String fileName;
- * 4. int lineNumber;
- */
-class java_lang_StackTraceElement : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_declaringClass = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_methodName = MEMORY_ALIGN(offset_declaringClass + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_fileName = MEMORY_ALIGN(offset_methodName + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_lineNumber = MEMORY_ALIGN(offset_fileName + SIZEOF_VOID_P, sizeof(int32_t));
-
-public:
- java_lang_StackTraceElement(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_StackTraceElement(java_handle_t* declaringClass, java_handle_t* methodName, java_handle_t* fileName, int32_t lineNumber);
-};
-
-inline java_lang_StackTraceElement::java_lang_StackTraceElement(java_handle_t* declaringClass, java_handle_t* methodName, java_handle_t* fileName, int32_t lineNumber)
-{
- _handle = builtin_new(class_java_lang_StackTraceElement);
-
- if (is_null())
- return;
-
- set(_handle, offset_declaringClass, declaringClass);
- set(_handle, offset_methodName, methodName);
- set(_handle, offset_fileName, fileName);
- set(_handle, offset_lineNumber, lineNumber);
-}
-
-
-/**
- * OpenJDK java/lang/String
- *
- * Object layout:
- *
- * 0. object header
- * 1. char[] value;
- * 2. int offset;
- * 3. int count;
- * 4. int hash;
- */
-class java_lang_String : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_offset = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_count = MEMORY_ALIGN(offset_offset + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_hash = MEMORY_ALIGN(offset_count + sizeof(int32_t), sizeof(int32_t));
-
-public:
- java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_String(jstring h);
- java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
-
- // Getters.
- inline java_handle_chararray_t* get_value () const;
- inline int32_t get_offset() const;
- inline int32_t get_count () const;
-
- // Setters.
- inline void set_value (java_handle_chararray_t* value);
- inline void set_offset(int32_t value);
- inline void set_count (int32_t value);
-};
-
-inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
-{
- java_lang_String((java_handle_t*) h);
-}
-
-inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
-{
- set_value(value);
- set_offset(offset);
- set_count(count);
-}
-
-inline java_handle_chararray_t* java_lang_String::get_value() const
-{
- return get<java_handle_chararray_t*>(_handle, offset_value);
-}
-
-inline int32_t java_lang_String::get_offset() const
-{
- return get<int32_t>(_handle, offset_offset);
-}
-
-inline int32_t java_lang_String::get_count() const
-{
- return get<int32_t>(_handle, offset_count);
-}
-
-inline void java_lang_String::set_value(java_handle_chararray_t* value)
-{
- set(_handle, offset_value, value);
-}
-
-inline void java_lang_String::set_offset(int32_t value)
-{
- set(_handle, offset_offset, value);
-}
-
-inline void java_lang_String::set_count(int32_t value)
-{
- set(_handle, offset_count, value);
-}
-
-
-/**
- * OpenJDK java/lang/Thread
- *
- * Object layout:
- *
- * 0. object header
- * 1. char[] name;
- * 2. int priority;
- * 3. java_lang_Thread threadQ;
- * 4. long eetop;
- * 5. boolean single_step;
- * 6. boolean daemon;
- * 7. boolean stillborn;
- * 8. java_lang_Runnable target;
- * 9. java_lang_ThreadGroup group;
- * 10. java_lang_ClassLoader contextClassLoader;
- * 11. java_security_AccessControlContext inheritedAccessControlContext;
- * 12. java_lang_ThreadLocal_ThreadLocalMap threadLocals;
- * 13. java_lang_ThreadLocal_ThreadLocalMap inheritableThreadLocals;
- * 14. long stackSize;
- * 15. long nativeParkEventPointer;
- * 16. long tid;
- * 17. int threadStatus;
- * 18. java_lang_Object parkBlocker;
- * 19. sun_nio_ch_Interruptible blocker;
- * 20. java_lang_Object blockerLock;
- * 21. boolean stopBeforeStart;
- * 22. java_lang_Throwable throwableFromStop;
- * 23. java.lang.Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
- */
-class java_lang_Thread : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_name = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_priority = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_threadQ = MEMORY_ALIGN(offset_priority + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_eetop = MEMORY_ALIGN(offset_threadQ + SIZEOF_VOID_P, sizeof(int64_t));
- static const off_t offset_single_step = MEMORY_ALIGN(offset_eetop + sizeof(int64_t), sizeof(int32_t));
- static const off_t offset_daemon = MEMORY_ALIGN(offset_single_step + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_stillborn = MEMORY_ALIGN(offset_daemon + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_target = MEMORY_ALIGN(offset_stillborn + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_group = MEMORY_ALIGN(offset_target + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_contextClassLoader = MEMORY_ALIGN(offset_group + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_inheritedAccessControlContext = MEMORY_ALIGN(offset_contextClassLoader + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_threadLocals = MEMORY_ALIGN(offset_inheritedAccessControlContext + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_inheritableThreadLocals = MEMORY_ALIGN(offset_threadLocals + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_stackSize = MEMORY_ALIGN(offset_inheritableThreadLocals + SIZEOF_VOID_P, sizeof(int64_t));
- static const off_t offset_nativeParkEventPointer = MEMORY_ALIGN(offset_stackSize + sizeof(int64_t), sizeof(int64_t));
- static const off_t offset_tid = MEMORY_ALIGN(offset_nativeParkEventPointer + sizeof(int64_t), sizeof(int64_t));
- static const off_t offset_threadStatus = MEMORY_ALIGN(offset_tid + sizeof(int64_t), sizeof(int32_t));
- static const off_t offset_parkBlocker = MEMORY_ALIGN(offset_threadStatus + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_blocker = MEMORY_ALIGN(offset_parkBlocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_blockerLock = MEMORY_ALIGN(offset_blocker + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_stopBeforeStart = MEMORY_ALIGN(offset_blockerLock + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_throwableFromStop = MEMORY_ALIGN(offset_stopBeforeStart + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_uncaughtExceptionHandler = MEMORY_ALIGN(offset_throwableFromStop + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
-// java_lang_Thread(threadobject* t);
-
- // Getters.
- inline int32_t get_priority () const;
- inline int32_t get_daemon () const;
- inline java_handle_t* get_group () const;
- inline java_handle_t* get_uncaughtExceptionHandler() const;
-
- // Setters.
- inline void set_priority(int32_t value);
- inline void set_group (java_handle_t* value);
-};
-
-
-inline int32_t java_lang_Thread::get_priority() const
-{
- return get<int32_t>(_handle, offset_priority);
-}
-
-inline int32_t java_lang_Thread::get_daemon() const
-{
- return get<int32_t>(_handle, offset_daemon);
-}
-
-inline java_handle_t* java_lang_Thread::get_group() const
-{
- return get<java_handle_t*>(_handle, offset_group);
-}
-
-inline java_handle_t* java_lang_Thread::get_uncaughtExceptionHandler() const
-{
- return get<java_handle_t*>(_handle, offset_uncaughtExceptionHandler);
-}
-
-
-inline void java_lang_Thread::set_priority(int32_t value)
-{
- set(_handle, offset_priority, value);
-}
-
-inline void java_lang_Thread::set_group(java_handle_t* value)
-{
- set(_handle, offset_group, value);
-}
-
-
-
-/**
- * OpenJDK java/lang/Throwable
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.Object backtrace;
- * 2. java.lang.String detailMessage;
- * 3. java.lang.Throwable cause;
- * 4. java.lang.StackTraceElement[] stackTrace;
- */
-class java_lang_Throwable : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_backtrace = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_detailMessage = MEMORY_ALIGN(offset_backtrace + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_cause = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_stackTrace = MEMORY_ALIGN(offset_cause + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_Throwable(jobject h);
- java_lang_Throwable(jobject h, java_handle_bytearray_t* backtrace);
-
- // Getters.
- inline java_handle_bytearray_t* get_backtrace () const;
- inline java_handle_t* get_detailMessage() const;
- inline java_handle_t* get_cause () const;
-
- // Setters.
- inline void set_backtrace(java_handle_bytearray_t* value);
-};
-
-
-inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
-{
- java_lang_Throwable((java_handle_t*) h);
-}
-
-inline java_lang_Throwable::java_lang_Throwable(jobject h, java_handle_bytearray_t* backtrace) : java_lang_Object(h)
-{
- java_lang_Throwable((java_handle_t*) h);
- set_backtrace(backtrace);
-}
-
-
-inline java_handle_bytearray_t* java_lang_Throwable::get_backtrace() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_backtrace);
-}
-
-inline java_handle_t* java_lang_Throwable::get_detailMessage() const
-{
- return get<java_handle_t*>(_handle, offset_detailMessage);
-}
-
-inline java_handle_t* java_lang_Throwable::get_cause() const
-{
- return get<java_handle_t*>(_handle, offset_cause);
-}
-
-
-inline void java_lang_Throwable::set_backtrace(java_handle_bytearray_t* value)
-{
- set(_handle, offset_backtrace, value);
-}
-
-
-/**
- * OpenJDK java/lang/reflect/Constructor
- *
- * Object layout:
- *
- * 0. object header
- * 1. boolean override;
- * 2. java.lang.Class clazz;
- * 3. int slot;
- * 4. java.lang.Class[] parameterTypes;
- * 5. java.lang.Class[] exceptionTypes;
- * 6. int modifiers;
- * 7. java.lang.String signature;
- * 8. sun.reflect.generics.repository.ConstructorRepository genericInfo;
- * 9. byte[] annotations;
- * 10. byte[] parameterAnnotations;
- * 11. java.lang.Class securityCheckCache;
- * 12. sun.reflect.ConstructorAccessor constructorAccessor;
- * 13. java.lang.reflect.Constructor root;
- * 14. java.util.Map declaredAnnotations;
- */
-class java_lang_reflect_Constructor : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_parameterTypes = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_exceptionTypes = MEMORY_ALIGN(offset_parameterTypes + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_modifiers = MEMORY_ALIGN(offset_exceptionTypes + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_constructorAccessor = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_root = MEMORY_ALIGN(offset_constructorAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_Constructor(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_Constructor(jobject h);
- java_lang_reflect_Constructor(methodinfo* m);
-
- java_handle_t* new_instance(java_handle_objectarray_t* args);
-
- // Getters.
- inline int32_t get_override () const;
- inline classinfo* get_clazz () const;
- inline int32_t get_slot () const;
- inline java_handle_bytearray_t* get_annotations() const;
-
- // Setters.
- inline void set_clazz (classinfo* value);
- inline void set_slot (int32_t value);
- inline void set_parameterTypes (java_handle_objectarray_t* value);
- inline void set_exceptionTypes (java_handle_objectarray_t* value);
- inline void set_modifiers (int32_t value);
- inline void set_signature (java_handle_t* value);
- inline void set_annotations (java_handle_bytearray_t* value);
- inline void set_parameterAnnotations(java_handle_bytearray_t* value);
-
- // Convenience functions.
- inline methodinfo* get_method();
-};
-
-
-inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_Constructor((java_handle_t*) h);
-}
-
-inline java_lang_reflect_Constructor::java_lang_reflect_Constructor(methodinfo* m)
-{
- _handle = builtin_new(class_java_lang_reflect_Constructor);
-
- if (is_null())
- return;
-
- int slot = m - m->clazz->methods;
- java_handle_objectarray_t* parameterTypes = method_get_parametertypearray(m);
- java_handle_objectarray_t* exceptionTypes = method_get_exceptionarray(m);
- java_handle_bytearray_t* annotations = method_get_annotations(m);
- java_handle_bytearray_t* parameterAnnotations = method_get_parameterannotations(m);
-
- set_clazz(m->clazz);
- set_slot(slot);
- set_parameterTypes(parameterTypes);
- set_exceptionTypes(exceptionTypes);
- set_modifiers(m->flags & ACC_CLASS_REFLECT_MASK);
- set_signature(m->signature ? javastring_new(m->signature) : NULL);
- set_annotations(annotations);
- set_parameterAnnotations(parameterAnnotations);
-}
-
-
-inline int32_t java_lang_reflect_Constructor::get_override() const
-{
- return get<int32_t>(_handle, offset_override);
-}
-
-inline classinfo* java_lang_reflect_Constructor::get_clazz() const
-{
- return get<classinfo*>(_handle, offset_clazz);
-}
-
-inline int32_t java_lang_reflect_Constructor::get_slot() const
-{
- return get<int32_t>(_handle, offset_slot);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_Constructor::get_annotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotations);
-}
-
-
-inline void java_lang_reflect_Constructor::set_clazz(classinfo* value)
-{
- set(_handle, offset_clazz, value);
-}
-
-inline void java_lang_reflect_Constructor::set_slot(int32_t value)
-{
- set(_handle, offset_slot, value);
-}
-
-inline void java_lang_reflect_Constructor::set_parameterTypes(java_handle_objectarray_t* value)
-{
- set(_handle, offset_parameterTypes, value);
-}
-
-inline void java_lang_reflect_Constructor::set_exceptionTypes(java_handle_objectarray_t* value)
-{
- set(_handle, offset_exceptionTypes, value);
-}
-
-inline void java_lang_reflect_Constructor::set_modifiers(int32_t value)
-{
- set(_handle, offset_modifiers, value);
-}
-
-inline void java_lang_reflect_Constructor::set_signature(java_handle_t* value)
-{
- set(_handle, offset_signature, value);
-}
-
-inline void java_lang_reflect_Constructor::set_annotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_annotations, value);
-}
-
-inline void java_lang_reflect_Constructor::set_parameterAnnotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_parameterAnnotations, value);
-}
-
-
-inline methodinfo* java_lang_reflect_Constructor::get_method()
-{
- classinfo* c = get_clazz();
- int32_t slot = get_slot();
- methodinfo* m = &(c->methods[slot]);
- return m;
-}
-
-
-/**
- * OpenJDK java/lang/reflect/Field
- *
- * Object layout:
- *
- * 0. object header
- * 1. boolean override;
- * 2. java.lang.Class clazz;
- * 3. int slot;
- * 4. java.lang.String name;
- * 5. java.lang.Class type;
- * 6. int modifiers;
- * 7. java.lang.String signature;
- * 8. sun.reflect.generics.repository.FieldRepository genericInfo;
- * 9. byte[] annotations;
- * 10. sun.reflect.FieldAccessor fieldAccessor;
- * 11. sun.reflect.FieldAccessor overrideFieldAccessor;
- * 12. java.lang.reflect.Field root;
- * 13. java.lang.Class securityCheckCache;
- * 14. java.lang.Class securityCheckTargetClassCache;
- * 15. java.util.Map declaredAnnotations;
- */
-class java_lang_reflect_Field : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_name = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_type = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_modifiers = MEMORY_ALIGN(offset_type + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_fieldAccessor = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_overrideFieldAccessor = MEMORY_ALIGN(offset_fieldAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_root = MEMORY_ALIGN(offset_overrideFieldAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_securityCheckTargetClassCache = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_securityCheckTargetClassCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_Field(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_Field(jobject h);
- java_lang_reflect_Field(fieldinfo* f);
-
- // Getters.
- inline int32_t get_override () const;
- inline classinfo* get_clazz () const;
- inline int32_t get_slot () const;
- inline java_handle_bytearray_t* get_annotations() const;
-
- // Setters.
- inline void set_clazz (classinfo* value);
- inline void set_slot (int32_t value);
- inline void set_name (java_handle_t* value);
- inline void set_type (classinfo* value);
- inline void set_modifiers (int32_t value);
- inline void set_signature (java_handle_t* value);
- inline void set_annotations(java_handle_bytearray_t* value);
-
- // Convenience functions.
- inline fieldinfo* get_field() const;
-};
-
-
-inline java_lang_reflect_Field::java_lang_reflect_Field(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_Field((java_handle_t*) h);
-}
-
-inline java_lang_reflect_Field::java_lang_reflect_Field(fieldinfo* f)
-{
- _handle = builtin_new(class_java_lang_reflect_Field);
-
- // OOME.
- if (is_null())
- return;
-
- set_clazz(f->clazz);
- set_slot(f - f->clazz->fields);
- set_name(javastring_intern(javastring_new(f->name)));
- set_type(field_get_type(f));
- set_modifiers(f->flags);
- set_signature(f->signature ? javastring_new(f->signature) : NULL);
- set_annotations(field_get_annotations(f));
-}
-
-
-inline int32_t java_lang_reflect_Field::get_override() const
-{
- return get<int32_t>(_handle, offset_override);
-}
-
-inline classinfo* java_lang_reflect_Field::get_clazz() const
-{
- return get<classinfo*>(_handle, offset_clazz);
-}
-
-inline int32_t java_lang_reflect_Field::get_slot() const
-{
- return get<int32_t>(_handle, offset_slot);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_Field::get_annotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotations);
-}
-
-
-inline void java_lang_reflect_Field::set_clazz(classinfo* value)
-{
- set(_handle, offset_clazz, value);
-}
-
-inline void java_lang_reflect_Field::set_slot(int32_t value)
-{
- set(_handle, offset_slot, value);
-}
-
-inline void java_lang_reflect_Field::set_name(java_handle_t* value)
-{
- set(_handle, offset_name, value);
-}
-
-inline void java_lang_reflect_Field::set_type(classinfo* value)
-{
- set(_handle, offset_type, value);
-}
-
-inline void java_lang_reflect_Field::set_modifiers(int32_t value)
-{
- set(_handle, offset_modifiers, value);
-}
-
-inline void java_lang_reflect_Field::set_signature(java_handle_t* value)
-{
- set(_handle, offset_signature, value);
-}
-
-inline void java_lang_reflect_Field::set_annotations(java_handle_bytearray_t* value)
-{
- set(_handle, offset_annotations, value);
-}
-
-
-inline fieldinfo* java_lang_reflect_Field::get_field() const
-{
- classinfo* c = get_clazz();
- int32_t slot = get_slot();
- fieldinfo* f = &(c->fields[slot]);
- return f;
-}
-
-
-/**
- * OpenJDK java/lang/reflect/Method
- *
- * Object layout:
- *
- * 0. object header
- * 1. boolean override;
- * 2. java.lang.Class clazz;
- * 3. int slot;
- * 4. java.lang.String name;
- * 5. java.lang.Class returnType;
- * 6. java.lang.Class[] parameterTypes;
- * 7. java.lang.Class[] exceptionTypes;
- * 8. int modifiers;
- * 9. java.lang.String signature;
- * 10 sun.reflect.generics.repository.ConstructorRepository genericInfo;
- * 11. byte[] annotations;
- * 12. byte[] parameterAnnotations;
- * 13. byte[] annotationDefault;
- * 14. sun.reflect.MethodAccessor methodAccessor;
- * 15. java.lang.reflect.Method root;
- * 16. java.lang.Class securityCheckCache;
- * 17. java.lang.Class securityCheckTargetClassCache;
- * 18. java.util.Map declaredAnnotations;
- */
-class java_lang_reflect_Method : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_override = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_clazz = MEMORY_ALIGN(offset_override + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_slot = MEMORY_ALIGN(offset_clazz + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_name = MEMORY_ALIGN(offset_slot + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_returnType = MEMORY_ALIGN(offset_name + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_parameterTypes = MEMORY_ALIGN(offset_returnType + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_exceptionTypes = MEMORY_ALIGN(offset_parameterTypes + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_modifiers = MEMORY_ALIGN(offset_exceptionTypes + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_signature = MEMORY_ALIGN(offset_modifiers + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_genericInfo = MEMORY_ALIGN(offset_signature + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_annotations = MEMORY_ALIGN(offset_genericInfo + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_parameterAnnotations = MEMORY_ALIGN(offset_annotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_annotationDefault = MEMORY_ALIGN(offset_parameterAnnotations + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_methodAccessor = MEMORY_ALIGN(offset_annotationDefault + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_root = MEMORY_ALIGN(offset_methodAccessor + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_securityCheckCache = MEMORY_ALIGN(offset_root + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_securityCheckTargetClassCache = MEMORY_ALIGN(offset_securityCheckCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_declaredAnnotations = MEMORY_ALIGN(offset_securityCheckTargetClassCache + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_reflect_Method(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_reflect_Method(jobject h);
- java_lang_reflect_Method(methodinfo* m);
-
- java_handle_t* invoke(java_handle_t* o, java_handle_objectarray_t* args);
-
- // Getters.
- inline int32_t get_override () const;
- inline classinfo* get_clazz () const;
- inline int32_t get_slot () const;
- inline java_handle_bytearray_t* get_annotations () const;
- inline java_handle_bytearray_t* get_parameterAnnotations() const;
- inline java_handle_bytearray_t* get_annotationDefault () const;
-
- // Setters.
-
- // Convenience functions.
- inline methodinfo* get_method() const;
-};
-
-
-inline java_lang_reflect_Method::java_lang_reflect_Method(jobject h) : java_lang_Object(h)
-{
- java_lang_reflect_Method((java_handle_t*) h);
-}
-
-inline java_lang_reflect_Method::java_lang_reflect_Method(methodinfo* m)
-{
- _handle = builtin_new(class_java_lang_reflect_Method);
-
- if (is_null())
- return;
-
- set(_handle, offset_clazz, m->clazz);
- set(_handle, offset_slot, m - m->clazz->methods);
- set(_handle, offset_name, javastring_intern(javastring_new(m->name)));
- set(_handle, offset_returnType, method_returntype_get(m));
- set(_handle, offset_parameterTypes, method_get_parametertypearray(m));
- set(_handle, offset_exceptionTypes, method_get_exceptionarray(m));
- set(_handle, offset_modifiers, m->flags & ACC_CLASS_REFLECT_MASK);
- set(_handle, offset_signature, m->signature ? javastring_new(m->signature) : NULL);
- set(_handle, offset_annotations, method_get_annotations(m));
- set(_handle, offset_parameterAnnotations, method_get_parameterannotations(m));
- set(_handle, offset_annotationDefault, method_get_annotationdefault(m));
-}
-
-
-inline int32_t java_lang_reflect_Method::get_override() const
-{
- return get<int32_t>(_handle, offset_override);
-}
-
-inline classinfo* java_lang_reflect_Method::get_clazz() const
-{
- return get<classinfo*>(_handle, offset_clazz);
-}
-
-inline int32_t java_lang_reflect_Method::get_slot() const
-{
- return get<int32_t>(_handle, offset_slot);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_Method::get_annotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotations);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_Method::get_parameterAnnotations() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_parameterAnnotations);
-}
-
-inline java_handle_bytearray_t* java_lang_reflect_Method::get_annotationDefault() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_annotationDefault);
-}
-
-
-inline methodinfo* java_lang_reflect_Method::get_method() const
-{
- classinfo* c = get_clazz();
- int32_t slot = get_slot();
- methodinfo* m = &(c->methods[slot]);
- return m;
-}
-
-
-/**
- * OpenJDK java/nio/Buffer
- *
- * Object layout:
- *
- * 0. object header
- * 1. int mark;
- * 2. int position;
- * 3. int limit;
- * 4. int capacity;
- * 5. long address;
- */
-class java_nio_Buffer : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_mark = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_position = MEMORY_ALIGN(offset_mark + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_limit = MEMORY_ALIGN(offset_position + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_capacity = MEMORY_ALIGN(offset_limit + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_address = MEMORY_ALIGN(offset_capacity + sizeof(int32_t), sizeof(int64_t));
-
-public:
- java_nio_Buffer(java_handle_t* h) : java_lang_Object(h) {}
- java_nio_Buffer(jobject h) : java_lang_Object(h) {}
-
- // Getters.
- inline void* get_address() const;
-};
-
-
-inline void* java_nio_Buffer::get_address() const
-{
- return get<void*>(_handle, offset_address);
-}
-
-#endif // WITH_JAVA_RUNTIME_LIBRARY_OPENJDK
-
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1)
-
-/**
- * CLDC 1.1 com/sun/cldchi/jvm/FileDescriptor
- *
- * Object layout:
- *
- * 0. object header
- * 1. long pointer;
- * 2. int position;
- * 3. int length;
- */
-class com_sun_cldchi_jvm_FileDescriptor : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_pointer = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int64_t));
- static const off_t offset_position = MEMORY_ALIGN(offset_pointer + sizeof(int64_t), sizeof(int32_t));
- static const off_t offset_length = MEMORY_ALIGN(offset_position + sizeof(int32_t), sizeof(int32_t));
-
-public:
- com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h) : java_lang_Object(h) {}
- com_sun_cldchi_jvm_FileDescriptor(jobject h);
- com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, int64_t pointer, int32_t position, int32_t length);
- com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, com_sun_cldchi_jvm_FileDescriptor& fd);
-
- // Getters.
- inline int64_t get_pointer () const;
- inline int32_t get_position() const;
- inline int32_t get_length () const;
-
- // Setters.
- inline void set_pointer (int64_t value);
- inline void set_position(int32_t value);
- inline void set_length (int32_t value);
-};
-
-
-inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(jobject h) : java_lang_Object(h)
-{
- com_sun_cldchi_jvm_FileDescriptor((java_handle_t*) h);
-}
-
-inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, int64_t pointer, int32_t position, int32_t length) : java_lang_Object(h)
-{
- set_pointer(pointer);
- set_position(position);
- set_length(length);
-}
-
-inline com_sun_cldchi_jvm_FileDescriptor::com_sun_cldchi_jvm_FileDescriptor(java_handle_t* h, com_sun_cldchi_jvm_FileDescriptor& fd) : java_lang_Object(h)
-{
- com_sun_cldchi_jvm_FileDescriptor(h, fd.get_pointer(), fd.get_position(), fd.get_length());
-}
-
-
-inline int64_t com_sun_cldchi_jvm_FileDescriptor::get_pointer() const
-{
- return get<int64_t>(_handle, offset_pointer);
-}
-
-inline int32_t com_sun_cldchi_jvm_FileDescriptor::get_position() const
-{
- return get<int32_t>(_handle, offset_position);
-}
-
-inline int32_t com_sun_cldchi_jvm_FileDescriptor::get_length() const
-{
- return get<int32_t>(_handle, offset_length);
-}
-
-
-inline void com_sun_cldchi_jvm_FileDescriptor::set_pointer(int64_t value)
-{
- set(_handle, offset_pointer, value);
-}
-
-inline void com_sun_cldchi_jvm_FileDescriptor::set_position(int32_t value)
-{
- set(_handle, offset_position, value);
-}
-
-inline void com_sun_cldchi_jvm_FileDescriptor::set_length(int32_t value)
-{
- set(_handle, offset_length, value);
-}
-
-
-/**
- * CLDC 1.1 java/lang/String
- *
- * Object layout:
- *
- * 0. object header
- * 1. char[] value;
- * 2. int offset;
- * 3. int count;
- */
-class java_lang_String : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_value = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_offset = MEMORY_ALIGN(offset_value + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_count = MEMORY_ALIGN(offset_offset + sizeof(int32_t), sizeof(int32_t));
-
-public:
- java_lang_String(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_String(jstring h);
- java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset = 0);
-
- // Getters.
- inline java_handle_chararray_t* get_value () const;
- inline int32_t get_offset() const;
- inline int32_t get_count () const;
-
- // Setters.
- inline void set_value (java_handle_chararray_t* value);
- inline void set_offset(int32_t value);
- inline void set_count (int32_t value);
-};
-
-inline java_lang_String::java_lang_String(jstring h) : java_lang_Object(h)
-{
- java_lang_String((java_handle_t*) h);
-}
-
-inline java_lang_String::java_lang_String(java_handle_t* h, java_handle_chararray_t* value, int32_t count, int32_t offset) : java_lang_Object(h)
-{
- set_value(value);
- set_offset(offset);
- set_count(count);
-}
-
-inline java_handle_chararray_t* java_lang_String::get_value() const
-{
- return get<java_handle_chararray_t*>(_handle, offset_value);
-}
-
-inline int32_t java_lang_String::get_offset() const
-{
- return get<int32_t>(_handle, offset_offset);
-}
-
-inline int32_t java_lang_String::get_count() const
-{
- return get<int32_t>(_handle, offset_count);
-}
-
-inline void java_lang_String::set_value(java_handle_chararray_t* value)
-{
- set(_handle, offset_value, value);
-}
-
-inline void java_lang_String::set_offset(int32_t value)
-{
- set(_handle, offset_offset, value);
-}
-
-inline void java_lang_String::set_count(int32_t value)
-{
- set(_handle, offset_count, value);
-}
-
-
-/**
- * CLDC 1.1 java/lang/Thread
- *
- * Object layout:
- *
- * 0. object header
- * 1. int priority;
- * 2. java.lang.Runnable runnable;
- * 3. java.lang.Object vm_thread;
- * 4. int is_terminated;
- * 5. int is_stillborn;
- * 6. char[] name;
- */
-class java_lang_Thread : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_priority = MEMORY_ALIGN(sizeof(java_object_t), sizeof(int32_t));
- static const off_t offset_runnable = MEMORY_ALIGN(offset_priority + sizeof(int32_t), SIZEOF_VOID_P);
- static const off_t offset_vm_thread = MEMORY_ALIGN(offset_runnable + SIZEOF_VOID_P, SIZEOF_VOID_P);
- static const off_t offset_is_terminated = MEMORY_ALIGN(offset_vm_thread + SIZEOF_VOID_P, sizeof(int32_t));
- static const off_t offset_is_stillborn = MEMORY_ALIGN(offset_is_terminated + sizeof(int32_t), sizeof(int32_t));
- static const off_t offset_name = MEMORY_ALIGN(offset_is_stillborn + sizeof(int32_t), SIZEOF_VOID_P);
-
-public:
- java_lang_Thread(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_Thread(jobject h);
-// java_lang_Thread(threadobject* t);
-
- // Getters.
- inline int32_t get_priority () const;
- inline threadobject* get_vm_thread() const;
- inline java_handle_chararray_t* get_name () const;
-
- // Setters.
- inline void set_vm_thread(threadobject* value);
-};
-
-
-inline java_lang_Thread::java_lang_Thread(jobject h) : java_lang_Object(h)
-{
- java_lang_Thread((java_handle_t*) h);
-}
-
-// inline java_lang_Thread::java_lang_Thread(threadobject* t) : java_lang_Object(h)
-// {
-// java_lang_Thread(thread_get_object(t));
-// }
-
-
-inline int32_t java_lang_Thread::get_priority() const
-{
- return get<int32_t>(_handle, offset_priority);
-}
-
-inline threadobject* java_lang_Thread::get_vm_thread() const
-{
- return get<threadobject*>(_handle, offset_vm_thread);
-}
-
-inline java_handle_chararray_t* java_lang_Thread::get_name() const
-{
- return get<java_handle_chararray_t*>(_handle, offset_name);
-}
-
-
-inline void java_lang_Thread::set_vm_thread(threadobject* value)
-{
- set(_handle, offset_vm_thread, value);
-}
-
-
-/**
- * CLDC 1.1 java/lang/Throwable
- *
- * Object layout:
- *
- * 0. object header
- * 1. java.lang.String detailMessage;
- * 2. java.lang.Object backtrace;
- */
-class java_lang_Throwable : public java_lang_Object, private FieldAccess {
-private:
- // Static offsets of the object's instance fields.
- // TODO These offsets need to be checked on VM startup.
- static const off_t offset_detailMessage = MEMORY_ALIGN(sizeof(java_object_t), SIZEOF_VOID_P);
- static const off_t offset_backtrace = MEMORY_ALIGN(offset_detailMessage + SIZEOF_VOID_P, SIZEOF_VOID_P);
-
-public:
- java_lang_Throwable(java_handle_t* h) : java_lang_Object(h) {}
- java_lang_Throwable(jobject h);
-
- // Getters.
- inline java_handle_t* get_detailMessage() const;
- inline java_handle_bytearray_t* get_backtrace () const;
-
- // Setters.
- inline void set_backtrace(java_handle_bytearray_t* value);
-};
-
-
-inline java_lang_Throwable::java_lang_Throwable(jobject h) : java_lang_Object(h)
-{
- java_lang_Throwable((java_handle_t*) h);
-}
-
-
-inline java_handle_t* java_lang_Throwable::get_detailMessage() const
-{
- return get<java_handle_t*>(_handle, offset_detailMessage);
-}
-
-inline java_handle_bytearray_t* java_lang_Throwable::get_backtrace() const
-{
- return get<java_handle_bytearray_t*>(_handle, offset_backtrace);
-}
-
-
-inline void java_lang_Throwable::set_backtrace(java_handle_bytearray_t* value)
-{
- set(_handle, offset_backtrace, value);
-}
-
-#endif // WITH_JAVA_RUNTIME_LIBRARY_CLDC1_1
-
-#else
-
-// Legacy C interface.
-java_handle_t* java_lang_reflect_Constructor_create(methodinfo* m);
-java_handle_t* java_lang_reflect_Field_create(fieldinfo* f);
-java_handle_t* java_lang_reflect_Method_create(methodinfo* m);
-
-#endif
-
-#endif // _JAVAOBJECTS_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:
- */
+++ /dev/null
-/* src/vmcore/linker.c - class linker functions
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/native.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/logging.h"
-
-#include "vm/access.h"
-#include "vm/array.h"
-#include "vm/exceptions.hpp"
-#include "vm/primitive.hpp"
-#include "vm/string.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit_interface.h"
-
-#include "vmcore/class.h"
-#include "vmcore/classcache.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-
-
-/* debugging macros ***********************************************************/
-
-#if !defined(NDEBUG)
-# define TRACELINKCLASS(c) \
- do { \
- if (opt_TraceLinkClass) { \
- log_start(); \
- log_print("[Linking "); \
- class_print((c)); \
- log_print("]"); \
- log_finish(); \
- } \
- } while (0)
-#else
-# define TRACELINKCLASS(c)
-#endif
-
-
-/* #include "vm/resolve.h" */
-/* copied prototype to avoid bootstrapping problem: */
-classinfo *resolve_classref_or_classinfo_eager(classref_or_classinfo cls, bool checkaccess);
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
-#else
-#define INLINELOG(code)
-#endif
-
-
-/* global variables ***********************************************************/
-
-static s4 interfaceindex; /* sequential numbering of interfaces */
-static s4 classvalue;
-
-java_object_t *linker_classrenumber_lock;
-
-
-/* private functions **********************************************************/
-
-static classinfo *link_class_intern(classinfo *c);
-static arraydescriptor *link_array(classinfo *c);
-static void linker_compute_class_values(classinfo *c);
-static void linker_compute_subclasses(classinfo *c);
-static bool linker_addinterface(classinfo *c, classinfo *ic);
-static s4 class_highestinterface(classinfo *c);
-
-
-/* linker_init *****************************************************************
-
- Initializes the linker subsystem and links classes required for the
- primitive table.
-
-*******************************************************************************/
-
-void linker_preinit(void)
-{
- TRACESUBSYSTEMINITIALIZATION("linker_preinit");
-
- /* Reset interface index. */
-
- interfaceindex = 0;
-
-#if defined(ENABLE_THREADS)
- /* create the global lock object */
-
- linker_classrenumber_lock = NEW(java_object_t);
-
- LOCK_INIT_OBJECT_LOCK(linker_classrenumber_lock);
-#endif
-
- /* Link the most basic classes. */
-
- if (!link_class(class_java_lang_Object))
- vm_abort("linker_preinit: linking java/lang/Object failed");
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_Cloneable))
- vm_abort("linker_preinit: linking java/lang/Cloneable failed");
-
- if (!link_class(class_java_io_Serializable))
- vm_abort("linker_preinit: linking java/io/Serializable failed");
-#endif
-}
-
-
-/* linker_init *****************************************************************
-
- Links all classes required in the VM.
-
-*******************************************************************************/
-
-void linker_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("linker_init");
-
- /* Link java.lang.Class as first class of the system, because we
- need it's vftbl for all other classes so we can use a class as
- object. */
-
- if (!link_class(class_java_lang_Class))
- vm_abort("linker_init: linking java/lang/Class failed");
-
- /* Now set the header.vftbl of all classes which were created
- before java.lang.Class was linked. */
-
- class_postset_header_vftbl();
-
- /* Link primitive-type wrapping classes. */
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_Void))
- vm_abort("linker_init: linking failed");
-#endif
-
- if (!link_class(class_java_lang_Boolean))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Byte))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Character))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Short))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Integer))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Long))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Float))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Double))
- vm_abort("linker_init: linking failed");
-
- /* Link important system classes. */
-
- if (!link_class(class_java_lang_String))
- vm_abort("linker_init: linking java/lang/String failed");
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_ClassLoader))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_SecurityManager))
- vm_abort("linker_init: linking failed");
-#endif
-
- if (!link_class(class_java_lang_System))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_Thread))
- vm_abort("linker_init: linking failed");
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_ThreadGroup))
- vm_abort("linker_init: linking failed");
-#endif
-
- if (!link_class(class_java_lang_Throwable))
- vm_abort("linker_init: linking failed");
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- if (!link_class(class_java_lang_VMSystem))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_VMThread))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_VMThrowable))
- vm_abort("linker_init: linking failed");
-#endif
-
- /* Important system exceptions. */
-
- if (!link_class(class_java_lang_Exception))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_ClassNotFoundException))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_RuntimeException))
- vm_abort("linker_init: linking failed");
-
- /* some classes which may be used more often */
-
-#if defined(ENABLE_JAVASE)
- if (!link_class(class_java_lang_StackTraceElement))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_Constructor))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_Field))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_Method))
- vm_abort("linker_init: linking failed");
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- if (!link_class(class_java_lang_reflect_VMConstructor))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_VMField))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_lang_reflect_VMMethod))
- vm_abort("linker_init: linking failed");
-# endif
-
- if (!link_class(class_java_security_PrivilegedAction))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_util_Vector))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_java_util_HashMap))
- vm_abort("linker_init: linking failed");
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- if (!link_class(class_sun_misc_Signal))
- vm_abort("linker_init: linking failed");
-
- if (!link_class(class_sun_reflect_MagicAccessorImpl))
- vm_abort("linker_init: linking failed");
-# endif
-
- if (!link_class(arrayclass_java_lang_Object))
- vm_abort("linker_init: linking failed");
-#endif
-
-
- /* create pseudo classes used by the typechecker */
-
- /* pseudo class for Arraystubs (extends java.lang.Object) */
-
- pseudo_class_Arraystub =
- class_create_classinfo(utf_new_char("$ARRAYSTUB$"));
- pseudo_class_Arraystub->state |= CLASS_LOADED;
- pseudo_class_Arraystub->super = class_java_lang_Object;
-
-#if defined(ENABLE_JAVASE)
-
- pseudo_class_Arraystub->interfacescount = 2;
- pseudo_class_Arraystub->interfaces = MNEW(classinfo*, 2);
- pseudo_class_Arraystub->interfaces[0] = class_java_lang_Cloneable;
- pseudo_class_Arraystub->interfaces[1] = class_java_io_Serializable;
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- pseudo_class_Arraystub->interfacescount = 0;
- pseudo_class_Arraystub->interfaces = NULL;
-
-#else
-# error unknown Java configuration
-#endif
-
- if (!classcache_store_unique(pseudo_class_Arraystub))
- vm_abort("linker_init: could not cache pseudo_class_Arraystub");
-
- if (!link_class(pseudo_class_Arraystub))
- vm_abort("linker_init: linking pseudo_class_Arraystub failed");
-
- /* pseudo class representing the null type */
-
- pseudo_class_Null = class_create_classinfo(utf_new_char("$NULL$"));
- pseudo_class_Null->state |= CLASS_LOADED;
- pseudo_class_Null->super = class_java_lang_Object;
-
- if (!classcache_store_unique(pseudo_class_Null))
- vm_abort("linker_init: could not cache pseudo_class_Null");
-
- if (!link_class(pseudo_class_Null))
- vm_abort("linker_init: linking failed");
-
- /* pseudo class representing new uninitialized objects */
-
- pseudo_class_New = class_create_classinfo(utf_new_char("$NEW$"));
- pseudo_class_New->state |= CLASS_LOADED;
- pseudo_class_New->state |= CLASS_LINKED; /* XXX is this allright? */
- pseudo_class_New->super = class_java_lang_Object;
-
- if (!classcache_store_unique(pseudo_class_New))
- vm_abort("linker_init: could not cache pseudo_class_New");
-
- /* Correct vftbl-entries (retarded loading and linking of class
- java/lang/String). */
-
- stringtable_update();
-}
-
-
-/* link_class ******************************************************************
-
- Wrapper function for link_class_intern to ease monitor enter/exit
- and exception handling.
-
-*******************************************************************************/
-
-classinfo *link_class(classinfo *c)
-{
- classinfo *r;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_end;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- if (c == NULL) {
- exceptions_throw_nullpointerexception();
- return NULL;
- }
-
- LOCK_MONITOR_ENTER(c);
-
- /* Maybe the class is currently linking or is already linked.*/
-
- if ((c->state & CLASS_LINKING) || (c->state & CLASS_LINKED)) {
- LOCK_MONITOR_EXIT(c);
-
- return c;
- }
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- compilingtime_stop();
-
- if (opt_getloadingtime)
- loadingtime_start();
-#endif
-
- /* call the internal function */
-
- r = link_class_intern(c);
-
- /* If return value is NULL, we had a problem and the class is not
- linked. */
-
- if (r == NULL)
- c->state &= ~CLASS_LINKING;
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getloadingtime)
- loadingtime_stop();
-
- if (opt_getcompilingtime)
- compilingtime_start();
-#endif
-
- LOCK_MONITOR_EXIT(c);
-
- RT_TIMING_GET_TIME(time_end);
-
- RT_TIMING_TIME_DIFF(time_start,time_end,RT_TIMING_LINK_TOTAL);
-
- return r;
-}
-
-
-/* linker_overwrite_method *****************************************************
-
- Overwrite a method with another one, update method flags and check
- assumptions.
-
- IN:
- mg................the general method being overwritten
- ms................the overwriting (more specialized) method
- wl................worklist where to add invalidated methods
-
- RETURN VALUE:
- true..............everything ok
- false.............an exception has been thrown
-
-*******************************************************************************/
-
-static bool linker_overwrite_method(methodinfo *mg,
- methodinfo *ms,
- method_worklist **wl)
-{
- classinfo *cg;
- classinfo *cs;
-
- cg = mg->clazz;
- cs = ms->clazz;
-
- /* overriding a final method is illegal */
-
- if (mg->flags & ACC_FINAL) {
- exceptions_throw_verifyerror(mg, "Overriding final method");
- return false;
- }
-
- /* method ms overwrites method mg */
-
-#if defined(ENABLE_VERIFIER)
- /* Add loading constraints (for the more general types of method mg). */
- /* Not for <init>, as it is not invoked virtually. */
-
- if ((ms->name != utf_init)
- && !classcache_add_constraints_for_params(
- cs->classloader, cg->classloader, mg))
- {
- return false;
- }
-#endif
-
- /* inherit the vftbl index, and record the overwriting */
-
- ms->vftblindex = mg->vftblindex;
- ms->overwrites = mg;
-
- /* update flags and check assumptions */
- /* <init> methods are a special case, as they are never dispatched dynamically */
-
- if ((ms->flags & ACC_METHOD_IMPLEMENTED) && ms->name != utf_init) {
- do {
-
-#if defined(ENABLE_TLH)
- if (mg->flags & ACC_METHOD_MONOMORPHY_USED) {
- printf("%s/%s is evil! the siner is %s/%s\n", mg->clazz->name->text, mg->name->text,
- ms->clazz->name->text, ms->name->text);
- ms->flags |= ACC_METHOD_PARENT_MONOMORPHY_USED;
- }
-#endif
-
- if (mg->flags & ACC_METHOD_IMPLEMENTED) {
- /* this adds another implementation */
-
- mg->flags &= ~ACC_METHOD_MONOMORPHIC;
-
- INLINELOG( printf("becomes polymorphic: "); method_println(mg); );
-
- method_break_assumption_monomorphic(mg, wl);
- }
- else {
- /* this is the first implementation */
-
- mg->flags |= ACC_METHOD_IMPLEMENTED;
-
- INLINELOG( printf("becomes implemented: "); method_println(mg); );
- }
-
- ms = mg;
- mg = mg->overwrites;
- } while (mg != NULL);
- }
-
- return true;
-}
-
-
-/* link_class_intern ***********************************************************
-
- Tries to link a class. The function calculates the length in bytes
- that an instance of this class requires as well as the VTBL for
- methods and interface methods.
-
-*******************************************************************************/
-
-static classinfo *link_class_intern(classinfo *c)
-{
- classinfo *super; /* super class */
- classinfo *tc; /* temporary class variable */
- s4 supervftbllength; /* vftbllegnth of super class */
- s4 vftbllength; /* vftbllength of current class */
- s4 interfacetablelength; /* interface table length */
- vftbl_t *v; /* vftbl of current class */
- s4 i; /* interface/method/field counter */
- arraydescriptor *arraydesc; /* descriptor for array classes */
- method_worklist *worklist; /* worklist for recompilation */
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_resolving, time_compute_vftbl,
- time_abstract, time_compute_iftbl, time_fill_vftbl,
- time_offsets, time_fill_iftbl, time_finalizer,
- time_subclasses;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- TRACELINKCLASS(c);
-
- /* the class must be loaded */
-
- /* XXX should this be a specific exception? */
- assert(c->state & CLASS_LOADED);
-
- /* This is check in link_class. */
-
- assert(!(c->state & CLASS_LINKED));
-
- /* cache the self-reference of this class */
- /* we do this for cases where the defining loader of the class */
- /* has not yet been recorded as an initiating loader for the class */
- /* this is needed so subsequent code can assume that self-refs */
- /* will always resolve lazily */
- /* No need to do it for the bootloader - it is always registered */
- /* as initiating loader for the classes it loads. */
- if (c->classloader)
- classcache_store(c->classloader,c,false);
-
- /* this class is currently linking */
-
- c->state |= CLASS_LINKING;
-
- arraydesc = NULL;
- worklist = NULL;
-
- /* Link the super interfaces. */
-
- for (i = 0; i < c->interfacescount; i++) {
- tc = c->interfaces[i];
-
- if (!(tc->state & CLASS_LINKED))
- if (!link_class(tc))
- return NULL;
- }
-
- /* check super class */
-
- super = NULL;
-
- /* Check for java/lang/Object. */
-
- if (c->super == NULL) {
- c->index = 0;
- c->instancesize = sizeof(java_object_t);
-
- vftbllength = supervftbllength = 0;
-
- c->finalizer = NULL;
- }
- else {
- /* Get super class. */
-
- super = c->super;
-
- /* Link the super class if necessary. */
-
- if (!(super->state & CLASS_LINKED))
- if (!link_class(super))
- return NULL;
-
- /* OR the ACC_CLASS_HAS_POINTERS and the ACC_CLASS_REFERENCE_*
- flags. */
-
- c->flags |= (super->flags &
- (ACC_CLASS_HAS_POINTERS | ACC_CLASS_REFERENCE_MASK));
-
- /* handle array classes */
-
- if (c->name->text[0] == '[')
- if (!(arraydesc = link_array(c)))
- return NULL;
-
- if (c->flags & ACC_INTERFACE)
- c->index = interfaceindex++;
- else
- c->index = super->index + 1;
-
- c->instancesize = super->instancesize;
-
- vftbllength = supervftbllength = super->vftbl->vftbllength;
-
- c->finalizer = super->finalizer;
- }
- RT_TIMING_GET_TIME(time_resolving);
-
-
- /* compute vftbl length */
-
- for (i = 0; i < c->methodscount; i++) {
- methodinfo *m = &(c->methods[i]);
-
- if (!(m->flags & ACC_STATIC)) { /* is instance method */
- tc = super;
-
- while (tc) {
- s4 j;
-
- for (j = 0; j < tc->methodscount; j++) {
- if (method_canoverwrite(m, &(tc->methods[j]))) {
- if (tc->methods[j].flags & ACC_PRIVATE)
- goto notfoundvftblindex;
-
- /* package-private methods in other packages */
- /* must not be overridden */
- /* (see Java Language Specification 8.4.8.1) */
- if ( !(tc->methods[j].flags & (ACC_PUBLIC | ACC_PROTECTED))
- && !SAME_PACKAGE(c,tc) )
- {
- goto notfoundvftblindex;
- }
-
- if (!linker_overwrite_method(&(tc->methods[j]), m, &worklist))
- return NULL;
-
- goto foundvftblindex;
- }
- }
-
- tc = tc->super;
- }
-
- notfoundvftblindex:
- m->vftblindex = (vftbllength++);
- foundvftblindex:
- ;
- }
- }
- RT_TIMING_GET_TIME(time_compute_vftbl);
-
-
- /* Check all interfaces of an abstract class (maybe be an
- interface too) for unimplemented methods. Such methods are
- called miranda-methods and are marked with the ACC_MIRANDA
- flag. VMClass.getDeclaredMethods does not return such
- methods. */
-
- if (c->flags & ACC_ABSTRACT) {
- classinfo *ic;
- methodinfo *im;
- s4 abstractmethodscount;
- s4 j;
- s4 k;
-
- abstractmethodscount = 0;
-
- /* check all interfaces of the abstract class */
-
- for (i = 0; i < c->interfacescount; i++) {
- ic = c->interfaces[i];
-
- for (j = 0; j < ic->methodscount; j++) {
- im = &(ic->methods[j]);
-
- /* skip `<clinit>' and `<init>' */
-
- if ((im->name == utf_clinit) || (im->name == utf_init))
- continue;
-
- for (tc = c; tc != NULL; tc = tc->super) {
- for (k = 0; k < tc->methodscount; k++) {
- if (method_canoverwrite(im, &(tc->methods[k])))
- goto noabstractmethod;
- }
- }
-
- abstractmethodscount++;
-
- noabstractmethod:
- ;
- }
- }
-
- if (abstractmethodscount > 0) {
- methodinfo *am;
-
- /* reallocate methods memory */
-
- c->methods = MREALLOC(c->methods, methodinfo, c->methodscount,
- c->methodscount + abstractmethodscount);
-
- for (i = 0; i < c->interfacescount; i++) {
- ic = c->interfaces[i];
-
- for (j = 0; j < ic->methodscount; j++) {
- im = &(ic->methods[j]);
-
- /* skip `<clinit>' and `<init>' */
-
- if ((im->name == utf_clinit) || (im->name == utf_init))
- continue;
-
- for (tc = c; tc != NULL; tc = tc->super) {
- for (k = 0; k < tc->methodscount; k++) {
- if (method_canoverwrite(im, &(tc->methods[k])))
- goto noabstractmethod2;
- }
- }
-
- /* Copy the method found into the new c->methods
- array and tag it as miranda-method. */
-
- am = &(c->methods[c->methodscount]);
- c->methodscount++;
-
- MCOPY(am, im, methodinfo, 1);
-
- am->vftblindex = (vftbllength++);
- am->clazz = c;
- am->flags |= ACC_MIRANDA;
-
- noabstractmethod2:
- ;
- }
- }
- }
- }
- RT_TIMING_GET_TIME(time_abstract);
-
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_vftbl_len +=
- sizeof(vftbl_t) + (sizeof(methodptr) * (vftbllength - 1));
-#endif
-
- /* compute interfacetable length */
-
- interfacetablelength = 0;
-
- for (tc = c; tc != NULL; tc = tc->super) {
- for (i = 0; i < tc->interfacescount; i++) {
- s4 h = class_highestinterface(tc->interfaces[i]) + 1;
-
- if (h > interfacetablelength)
- interfacetablelength = h;
- }
- }
- RT_TIMING_GET_TIME(time_compute_iftbl);
-
- /* allocate virtual function table */
-
- v = (vftbl_t *) mem_alloc(sizeof(vftbl_t) +
- sizeof(methodptr) * (vftbllength - 1) +
- sizeof(methodptr*) * (interfacetablelength - (interfacetablelength > 0)));
- v = (vftbl_t *) (((methodptr *) v) +
- (interfacetablelength - 1) * (interfacetablelength > 1));
-
- c->vftbl = v;
- v->clazz = c;
- v->vftbllength = vftbllength;
- v->interfacetablelength = interfacetablelength;
- v->arraydesc = arraydesc;
-
- /* store interface index in vftbl */
-
- if (c->flags & ACC_INTERFACE)
- v->baseval = -(c->index);
-
- /* copy virtual function table of super class */
-
- for (i = 0; i < supervftbllength; i++)
- v->table[i] = super->vftbl->table[i];
-
- /* Fill the remaining vftbl slots with the AbstractMethodError
- stub (all after the super class slots, because they are already
- initialized). */
-
- for (; i < vftbllength; i++) {
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
- else
-# endif
- v->table[i] = (methodptr) (ptrint) &asm_abstractmethoderror;
-#else
- v->table[i] = (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
-#endif
- }
-
- /* add method stubs into virtual function table */
-
- for (i = 0; i < c->methodscount; i++) {
- methodinfo *m = &(c->methods[i]);
-
- assert(m->stubroutine == NULL);
-
- /* Don't create a compiler stub for abstract methods as they
- throw an AbstractMethodError with the default stub in the
- vftbl. This entry is simply copied by sub-classes. */
-
- if (m->flags & ACC_ABSTRACT)
- continue;
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- m->stubroutine = intrp_createcompilerstub(m);
- else
-#endif
- m->stubroutine = codegen_generate_stub_compiler(m);
-#else
- m->stubroutine = intrp_createcompilerstub(m);
-#endif
-
- /* static methods are not in the vftbl */
-
- if (m->flags & ACC_STATIC)
- continue;
-
- /* insert the stubroutine into the vftbl */
-
- v->table[m->vftblindex] = (methodptr) (ptrint) m->stubroutine;
- }
- RT_TIMING_GET_TIME(time_fill_vftbl);
-
- /* compute instance size and offset of each field */
-
- for (i = 0; i < c->fieldscount; i++) {
- s4 dsize;
- fieldinfo *f = &(c->fields[i]);
-
- if (!(f->flags & ACC_STATIC)) {
- dsize = descriptor_typesize(f->parseddesc);
- c->instancesize = MEMORY_ALIGN(c->instancesize, dsize);
- f->offset = c->instancesize;
- c->instancesize += dsize;
- }
- }
- RT_TIMING_GET_TIME(time_offsets);
-
- /* initialize interfacetable and interfacevftbllength */
-
- v->interfacevftbllength = MNEW(s4, interfacetablelength);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_vftbl_len += (4 + sizeof(s4)) * v->interfacetablelength;
-#endif
-
- for (i = 0; i < interfacetablelength; i++) {
- v->interfacevftbllength[i] = 0;
- v->interfacetable[-i] = NULL;
- }
-
- /* add interfaces */
-
- for (tc = c; tc != NULL; tc = tc->super)
- for (i = 0; i < tc->interfacescount; i++)
- if (!linker_addinterface(c, tc->interfaces[i]))
- return NULL;
-
- RT_TIMING_GET_TIME(time_fill_iftbl);
-
- /* add finalizer method (not for java.lang.Object) */
-
- if (super) {
- methodinfo *fi;
-
- fi = class_findmethod(c, utf_finalize, utf_void__void);
-
- if (fi)
- if (!(fi->flags & ACC_STATIC))
- c->finalizer = fi;
- }
- RT_TIMING_GET_TIME(time_finalizer);
-
- /* final tasks */
-
- linker_compute_subclasses(c);
-
- RT_TIMING_GET_TIME(time_subclasses);
-
- /* revert the linking state and class is linked */
-
- c->state = (c->state & ~CLASS_LINKING) | CLASS_LINKED;
-
- /* check worklist */
-
- /* XXX must this also be done in case of exception? */
-
- while (worklist != NULL) {
- method_worklist *wi = worklist;
-
- worklist = worklist->next;
-
- INLINELOG( printf("MUST BE RECOMPILED: "); method_println(wi->m); );
- jit_invalidate_code(wi->m);
-
- /* XXX put worklist into dump memory? */
- FREE(wi, method_worklist);
- }
-
- RT_TIMING_TIME_DIFF(time_start ,time_resolving ,RT_TIMING_LINK_RESOLVE);
- RT_TIMING_TIME_DIFF(time_resolving ,time_compute_vftbl,RT_TIMING_LINK_C_VFTBL);
- RT_TIMING_TIME_DIFF(time_compute_vftbl,time_abstract ,RT_TIMING_LINK_ABSTRACT);
- RT_TIMING_TIME_DIFF(time_abstract ,time_compute_iftbl,RT_TIMING_LINK_C_IFTBL);
- RT_TIMING_TIME_DIFF(time_compute_iftbl,time_fill_vftbl ,RT_TIMING_LINK_F_VFTBL);
- RT_TIMING_TIME_DIFF(time_fill_vftbl ,time_offsets ,RT_TIMING_LINK_OFFSETS);
- RT_TIMING_TIME_DIFF(time_offsets ,time_fill_iftbl ,RT_TIMING_LINK_F_IFTBL);
- RT_TIMING_TIME_DIFF(time_fill_iftbl ,time_finalizer ,RT_TIMING_LINK_FINALIZER);
- RT_TIMING_TIME_DIFF(time_finalizer ,time_subclasses ,RT_TIMING_LINK_SUBCLASS);
-
- /* just return c to show that we didn't had a problem */
-
- return c;
-}
-
-
-/* link_array ******************************************************************
-
- This function is called by link_class to create the arraydescriptor
- for an array class.
-
- This function returns NULL if the array cannot be linked because
- the component type has not been linked yet.
-
-*******************************************************************************/
-
-static arraydescriptor *link_array(classinfo *c)
-{
- classinfo *comp;
- s4 namelen;
- arraydescriptor *desc;
- vftbl_t *compvftbl;
- utf *u;
-
- comp = NULL;
- namelen = c->name->blength;
-
- /* Check the component type */
-
- switch (c->name->text[1]) {
- case '[':
- /* c is an array of arrays. */
- u = utf_new(c->name->text + 1, namelen - 1);
- if (!(comp = load_class_from_classloader(u, c->classloader)))
- return NULL;
- break;
-
- case 'L':
- /* c is an array of objects. */
- u = utf_new(c->name->text + 2, namelen - 3);
- if (!(comp = load_class_from_classloader(u, c->classloader)))
- return NULL;
- break;
- }
-
- /* If the component type has not been linked, link it now */
-
- assert(!comp || (comp->state & CLASS_LOADED));
-
- if (comp && !(comp->state & CLASS_LINKED))
- if (!link_class(comp))
- return NULL;
-
- /* Allocate the arraydescriptor */
-
- desc = NEW(arraydescriptor);
-
- if (comp) {
- /* c is an array of references */
- desc->arraytype = ARRAYTYPE_OBJECT;
- desc->componentsize = sizeof(void*);
- desc->dataoffset = OFFSET(java_objectarray_t, data);
-
- compvftbl = comp->vftbl;
-
- if (!compvftbl) {
- log_text("Component class has no vftbl");
- assert(0);
- }
-
- desc->componentvftbl = compvftbl;
-
- if (compvftbl->arraydesc) {
- desc->elementvftbl = compvftbl->arraydesc->elementvftbl;
-
- if (compvftbl->arraydesc->dimension >= 255) {
- log_text("Creating array of dimension >255");
- assert(0);
- }
-
- desc->dimension = compvftbl->arraydesc->dimension + 1;
- desc->elementtype = compvftbl->arraydesc->elementtype;
-
- } else {
- desc->elementvftbl = compvftbl;
- desc->dimension = 1;
- desc->elementtype = ARRAYTYPE_OBJECT;
- }
-
- } else {
- /* c is an array of a primitive type */
- switch (c->name->text[1]) {
- case 'Z':
- desc->arraytype = ARRAYTYPE_BOOLEAN;
- desc->dataoffset = OFFSET(java_booleanarray_t,data);
- desc->componentsize = sizeof(u1);
- break;
-
- case 'B':
- desc->arraytype = ARRAYTYPE_BYTE;
- desc->dataoffset = OFFSET(java_bytearray_t,data);
- desc->componentsize = sizeof(u1);
- break;
-
- case 'C':
- desc->arraytype = ARRAYTYPE_CHAR;
- desc->dataoffset = OFFSET(java_chararray_t,data);
- desc->componentsize = sizeof(u2);
- break;
-
- case 'D':
- desc->arraytype = ARRAYTYPE_DOUBLE;
- desc->dataoffset = OFFSET(java_doublearray_t,data);
- desc->componentsize = sizeof(double);
- break;
-
- case 'F':
- desc->arraytype = ARRAYTYPE_FLOAT;
- desc->dataoffset = OFFSET(java_floatarray_t,data);
- desc->componentsize = sizeof(float);
- break;
-
- case 'I':
- desc->arraytype = ARRAYTYPE_INT;
- desc->dataoffset = OFFSET(java_intarray_t,data);
- desc->componentsize = sizeof(s4);
- break;
-
- case 'J':
- desc->arraytype = ARRAYTYPE_LONG;
- desc->dataoffset = OFFSET(java_longarray_t,data);
- desc->componentsize = sizeof(s8);
- break;
-
- case 'S':
- desc->arraytype = ARRAYTYPE_SHORT;
- desc->dataoffset = OFFSET(java_shortarray_t,data);
- desc->componentsize = sizeof(s2);
- break;
-
- default:
- exceptions_throw_noclassdeffounderror(c->name);
- return NULL;
- }
-
- desc->componentvftbl = NULL;
- desc->elementvftbl = NULL;
- desc->dimension = 1;
- desc->elementtype = desc->arraytype;
- }
-
- return desc;
-}
-
-
-/* linker_compute_subclasses ***************************************************
-
- XXX
-
- ATTENTION: DO NOT REMOVE ANY OF THE LOCKING MECHANISMS BELOW:
- This function needs to take the class renumber lock and stop the
- world during class renumbering. The lock is used in C code which
- is not that performance critical. Whereas JIT code uses critical
- sections to atomically access the class values.
-
-*******************************************************************************/
-
-static void linker_compute_subclasses(classinfo *c)
-{
- LOCK_MONITOR_ENTER(linker_classrenumber_lock);
-
- if (!(c->flags & ACC_INTERFACE)) {
- c->nextsub = NULL;
- c->sub = NULL;
- }
-
- if (!(c->flags & ACC_INTERFACE) && (c->super != NULL)) {
- c->nextsub = c->super->sub;
- c->super->sub = c;
- }
-
- classvalue = 0;
-
- /* compute class values */
-
- linker_compute_class_values(class_java_lang_Object);
-
- LOCK_MONITOR_EXIT(linker_classrenumber_lock);
-}
-
-
-/* linker_compute_class_values *************************************************
-
- XXX
-
-*******************************************************************************/
-
-static void linker_compute_class_values(classinfo *c)
-{
- classinfo *subs;
-
- c->vftbl->baseval = ++classvalue;
-
- subs = c->sub;
-
- while (subs) {
- linker_compute_class_values(subs);
-
- subs = subs->nextsub;
- }
-
- c->vftbl->diffval = classvalue - c->vftbl->baseval;
-}
-
-
-/* linker_addinterface *********************************************************
-
- Is needed by link_class for adding a VTBL to a class. All
- interfaces implemented by ic are added as well.
-
- RETURN VALUE:
- true.........everything ok
- false........an exception has been thrown
-
-*******************************************************************************/
-
-static bool linker_addinterface(classinfo *c, classinfo *ic)
-{
- s4 j, k;
- vftbl_t *v;
- s4 i;
- classinfo *sc;
- methodinfo *m;
-
- v = c->vftbl;
- i = ic->index;
-
- if (i >= v->interfacetablelength)
- vm_abort("Internal error: interfacetable overflow");
-
- /* if this interface has already been added, return immediately */
-
- if (v->interfacetable[-i] != NULL)
- return true;
-
- if (ic->methodscount == 0) { /* fake entry needed for subtype test */
- v->interfacevftbllength[i] = 1;
- v->interfacetable[-i] = MNEW(methodptr, 1);
- v->interfacetable[-i][0] = NULL;
- }
- else {
- v->interfacevftbllength[i] = ic->methodscount;
- v->interfacetable[-i] = MNEW(methodptr, ic->methodscount);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_vftbl_len += sizeof(methodptr) *
- (ic->methodscount + (ic->methodscount == 0));
-#endif
-
- for (j = 0; j < ic->methodscount; j++) {
- for (sc = c; sc != NULL; sc = sc->super) {
- for (k = 0; k < sc->methodscount; k++) {
- m = &(sc->methods[k]);
-
- if (method_canoverwrite(m, &(ic->methods[j]))) {
- /* method m overwrites the (abstract) method */
-#if defined(ENABLE_VERIFIER)
- /* Add loading constraints (for the more
- general types of the method
- ic->methods[j]). */
- if (!classcache_add_constraints_for_params(
- c->classloader, ic->classloader,
- &(ic->methods[j])))
- {
- return false;
- }
-#endif
-
- /* XXX taken from gcj */
- /* check for ACC_STATIC: IncompatibleClassChangeError */
-
- /* check for !ACC_PUBLIC: IllegalAccessError */
-
- /* check for ACC_ABSTRACT: AbstracMethodError,
- not sure about that one */
-
- v->interfacetable[-i][j] = v->table[m->vftblindex];
- goto foundmethod;
- }
- }
- }
-
- /* If no method was found, insert the AbstractMethodError
- stub. */
-
-#if defined(ENABLE_JIT)
-# if defined(ENABLE_INTRP)
- if (opt_intrp)
- v->interfacetable[-i][j] =
- (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
- else
-# endif
- v->interfacetable[-i][j] =
- (methodptr) (ptrint) &asm_abstractmethoderror;
-#else
- v->interfacetable[-i][j] =
- (methodptr) (ptrint) &intrp_asm_abstractmethoderror;
-#endif
-
- foundmethod:
- ;
- }
- }
-
- /* add superinterfaces of this interface */
-
- for (j = 0; j < ic->interfacescount; j++)
- if (!linker_addinterface(c, ic->interfaces[j]))
- return false;
-
- /* everything ok */
-
- return true;
-}
-
-
-/* class_highestinterface ******************************************************
-
- Used by the function link_class to determine the amount of memory
- needed for the interface table.
-
-*******************************************************************************/
-
-static s4 class_highestinterface(classinfo *c)
-{
- s4 h;
- s4 h2;
- s4 i;
-
- /* check for ACC_INTERFACE bit already done in link_class_intern */
-
- h = c->index;
-
- for (i = 0; i < c->interfacescount; i++) {
- h2 = class_highestinterface(c->interfaces[i]);
-
- if (h2 > h)
- h = h2;
- }
-
- return h;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/linker.h - class linker header
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _LINKER_H
-#define _LINKER_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct _vftbl vftbl_t;
-typedef struct arraydescriptor arraydescriptor;
-typedef struct primitivetypeinfo primitivetypeinfo;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vmcore/class.h"
-#include "vmcore/references.h"
-
-
-/* virtual function table ******************************************************
-
- The vtbl has a bidirectional layout with open ends at both sides.
- interfacetablelength gives the number of entries of the interface
- table at the start of the vftbl. The vftbl pointer points to
- &interfacetable[0]. vftbllength gives the number of entries of
- table at the end of the vftbl.
-
- runtime type check (checkcast):
-
- Different methods are used for runtime type check depending on the
- argument of checkcast/instanceof.
-
- A check against a class is implemented via relative numbering on
- the class hierachy tree. The tree is numbered in a depth first
- traversal setting the base field and the diff field. The diff field
- gets the result of (high - base) so that a range check can be
- implemented by an unsigned compare. A sub type test is done by
- checking the inclusion of base of the sub class in the range of the
- superclass.
-
- A check against an interface is implemented via the
- interfacevftbl. If the interfacevftbl contains a nonnull value a
- class is a subclass of this interface.
-
- interfacetable:
-
- Like standard virtual methods interface methods are called using
- virtual function tables. All interfaces are numbered sequentially
- (starting with zero). For each class there exist an interface table
- of virtual function tables for each implemented interface. The
- length of the interface table is determined by the highest number
- of an implemented interface.
-
- The following example assumes a class which implements interface 0 and 3:
-
- interfacetablelength = 4
-
- | ... | +----------+
- +-----------+ | method 2 |---> method z
- | class | | method 1 |---> method y
- +-----------+ | method 0 |---> method x
- | ivftbl 0 |----------> +----------+
- vftblptr ---> +-----------+
- | ivftbl -1 |--> NULL +----------+
- | ivftbl -2 |--> NULL | method 1 |---> method x
- | ivftbl -3 |-----+ | method 0 |---> method a
- +-----------+ +----> +----------+
-
- +---------------+
- | length 3 = 2 |
- | length 2 = 0 |
- | length 1 = 0 |
- | length 0 = 3 |
- interfacevftbllength ---> +---------------+
-
-*******************************************************************************/
-
-struct _vftbl {
- methodptr *interfacetable[1]; /* interface table (access via macro) */
- classinfo *clazz; /* class, the vtbl belongs to */
- arraydescriptor *arraydesc; /* for array classes, otherwise NULL */
- s4 vftbllength; /* virtual function table length */
- s4 interfacetablelength; /* interface table length */
- s4 baseval; /* base for runtime type check */
- /* (-index for interfaces) */
- s4 diffval; /* high - base for runtime type check */
- s4 *interfacevftbllength; /* length of interface vftbls */
- methodptr table[1]; /* class vftbl */
-};
-
-
-/* arraydescriptor *************************************************************
-
- For every array class an arraydescriptor is allocated which
- describes the array class. The arraydescriptor is referenced from
- the vftbl of the array class.
-
-*******************************************************************************/
-
-struct arraydescriptor {
- vftbl_t *componentvftbl; /* vftbl of the component type, NULL for primit. */
- vftbl_t *elementvftbl; /* vftbl of the element type, NULL for primitive */
- s2 arraytype; /* ARRAYTYPE_* constant */
- s2 dimension; /* dimension of the array (always >= 1) */
- s4 dataoffset; /* offset of the array data from object pointer */
- s4 componentsize; /* size of a component in bytes */
- s2 elementtype; /* ARRAYTYPE_* constant */
-};
-
-
-/* global variables ***********************************************************/
-
-/* This lock must be taken while renumbering classes or while atomically */
-/* accessing classes. */
-
-extern java_object_t *linker_classrenumber_lock;
-
-
-/* function prototypes ********************************************************/
-
-void linker_preinit(void);
-void linker_init(void);
-classinfo *link_class(classinfo *c);
-
-#endif /* _LINKER_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/loader.c - class loader functions
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/hashtable.h"
-#include "toolbox/logging.h"
-
-#include "vm/builtin.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/package.hpp"
-#include "vm/primitive.hpp"
-#include "vm/resolve.h"
-#include "vm/string.hpp"
-#include "vm/vm.hpp"
-
-#include "vm/jit_interface.h"
-
-#if defined(ENABLE_JAVASE)
-# include "vmcore/annotation.h"
-# include "vmcore/stackmap.h"
-#endif
-
-#include "vmcore/classcache.h"
-#include "vmcore/field.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/rt-timing.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/suck.h"
-
-#if defined(ENABLE_ZLIB)
-# include "vmcore/zip.h"
-#endif
-
-#if defined(ENABLE_JVMTI)
-# include "native/jvmti/cacaodbg.h"
-#endif
-
-
-/* global variables ***********************************************************/
-
-static hashtable *hashtable_classloader;
-
-
-/* loader_preinit **************************************************************
-
- Initializes the classpath list and loads classes required for the
- primitive table.
-
- NOTE: Exceptions thrown during VM initialization are caught in the
- exception functions themselves.
-
-*******************************************************************************/
-
-void loader_preinit(void)
-{
-#if defined(ENABLE_THREADS)
- list_classpath_entry *lce;
-#endif
-
- TRACESUBSYSTEMINITIALIZATION("loader_preinit");
-
-#if defined(ENABLE_THREADS)
- /* Initialize the monitor pointer for zip/jar file locking. */
-
- for (lce = list_first(list_classpath_entries); lce != NULL;
- lce = list_next(list_classpath_entries, lce)) {
- if (lce->type == CLASSPATH_ARCHIVE)
- LOCK_INIT_OBJECT_LOCK(lce);
- }
-#endif
-
- /* initialize classloader hashtable, 10 entries should be enough */
-
- hashtable_classloader = NEW(hashtable);
- hashtable_create(hashtable_classloader, 10);
-
- /* Load the most basic classes. */
-
- assert(VM_is_initializing() == true);
-
- class_java_lang_Object = load_class_bootstrap(utf_java_lang_Object);
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_Cloneable = load_class_bootstrap(utf_java_lang_Cloneable);
- class_java_io_Serializable = load_class_bootstrap(utf_java_io_Serializable);
-#endif
-}
-
-
-/* loader_init *****************************************************************
-
- Loads all classes required in the VM.
-
- NOTE: Exceptions thrown during VM initialization are caught in the
- exception functions themselves.
-
-*******************************************************************************/
-
-void loader_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("loader_init");
-
- /* Load primitive-type wrapping classes. */
-
- assert(VM_is_initializing() == true);
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_Void = load_class_bootstrap(utf_java_lang_Void);
-#endif
-
- class_java_lang_Boolean = load_class_bootstrap(utf_java_lang_Boolean);
- class_java_lang_Byte = load_class_bootstrap(utf_java_lang_Byte);
- class_java_lang_Character = load_class_bootstrap(utf_java_lang_Character);
- class_java_lang_Short = load_class_bootstrap(utf_java_lang_Short);
- class_java_lang_Integer = load_class_bootstrap(utf_java_lang_Integer);
- class_java_lang_Long = load_class_bootstrap(utf_java_lang_Long);
- class_java_lang_Float = load_class_bootstrap(utf_java_lang_Float);
- class_java_lang_Double = load_class_bootstrap(utf_java_lang_Double);
-
- /* Load important system classes. */
-
- class_java_lang_Class = load_class_bootstrap(utf_java_lang_Class);
- class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_ClassLoader =
- load_class_bootstrap(utf_java_lang_ClassLoader);
-
- class_java_lang_SecurityManager =
- load_class_bootstrap(utf_java_lang_SecurityManager);
-#endif
-
- class_java_lang_System =
- load_class_bootstrap(utf_new_char("java/lang/System"));
-
- class_java_lang_Thread =
- load_class_bootstrap(utf_new_char("java/lang/Thread"));
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_ThreadGroup =
- load_class_bootstrap(utf_java_lang_ThreadGroup);
-#endif
-
- class_java_lang_Throwable = load_class_bootstrap(utf_java_lang_Throwable);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- class_java_lang_VMSystem =
- load_class_bootstrap(utf_new_char("java/lang/VMSystem"));
-
- class_java_lang_VMThread =
- load_class_bootstrap(utf_new_char("java/lang/VMThread"));
-
- class_java_lang_VMThrowable =
- load_class_bootstrap(utf_new_char("java/lang/VMThrowable"));
-#endif
-
- /* Important system exceptions. */
-
- class_java_lang_Exception = load_class_bootstrap(utf_java_lang_Exception);
-
- class_java_lang_ClassNotFoundException =
- load_class_bootstrap(utf_java_lang_ClassNotFoundException);
-
- class_java_lang_RuntimeException =
- load_class_bootstrap(utf_java_lang_RuntimeException);
-
- /* Some classes which may be used often. */
-
-#if defined(ENABLE_JAVASE)
- class_java_lang_StackTraceElement = load_class_bootstrap(utf_java_lang_StackTraceElement);
-
- class_java_lang_reflect_Constructor = load_class_bootstrap(utf_java_lang_reflect_Constructor);
- class_java_lang_reflect_Field = load_class_bootstrap(utf_java_lang_reflect_Field);
- class_java_lang_reflect_Method = load_class_bootstrap(utf_java_lang_reflect_Method);
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- class_java_lang_reflect_VMConstructor = load_class_bootstrap(utf_java_lang_reflect_VMConstructor);
- class_java_lang_reflect_VMField = load_class_bootstrap(utf_java_lang_reflect_VMField);
- class_java_lang_reflect_VMMethod = load_class_bootstrap(utf_java_lang_reflect_VMMethod);
-# endif
-
- class_java_security_PrivilegedAction = load_class_bootstrap(utf_new_char("java/security/PrivilegedAction"));
-
- class_java_util_HashMap = load_class_bootstrap(utf_new_char("java/util/HashMap"));
- class_java_util_Vector = load_class_bootstrap(utf_java_util_Vector);
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- class_sun_misc_Signal = load_class_bootstrap(utf_new_char("sun/misc/Signal"));
- class_sun_reflect_MagicAccessorImpl = load_class_bootstrap(utf_new_char("sun/reflect/MagicAccessorImpl"));
-# endif
-
- arrayclass_java_lang_Object =
- load_class_bootstrap(utf_new_char("[Ljava/lang/Object;"));
-
-# if defined(ENABLE_ANNOTATIONS)
- /* needed by annotation support */
- class_sun_reflect_ConstantPool =
- load_class_bootstrap(utf_new_char("sun/reflect/ConstantPool"));
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- /* needed by GNU Classpaths annotation support */
- class_sun_reflect_annotation_AnnotationParser =
- load_class_bootstrap(utf_new_char("sun/reflect/annotation/AnnotationParser"));
-# endif
-# endif
-#endif
-}
-
-
-/* loader_hashtable_classloader_add ********************************************
-
- Adds an entry to the classloader hashtable.
-
- REMEMBER: Also use this to register native loaders!
-
-*******************************************************************************/
-
-classloader_t *loader_hashtable_classloader_add(java_handle_t *cl)
-{
- hashtable_classloader_entry *cle;
- u4 key;
- u4 slot;
-
- if (cl == NULL)
- return NULL;
-
- LOCK_MONITOR_ENTER(hashtable_classloader->header);
-
- LLNI_CRITICAL_START;
-
- /* key for entry is the hashcode of the classloader;
- aligned to 16-byte boundaries */
-
- key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
- slot = key & (hashtable_classloader->size - 1);
- cle = hashtable_classloader->ptr[slot];
-
- /* search hashchain for existing entry */
-
- while (cle) {
- if (cle->object == LLNI_DIRECT(cl))
- break;
-
- cle = cle->hashlink;
- }
-
- LLNI_CRITICAL_END;
-
- /* if no classloader was found, we create a new entry here */
-
- if (cle == NULL) {
- cle = NEW(hashtable_classloader_entry);
-
-#if defined(ENABLE_GC_CACAO)
- /* register the classloader object with the GC */
-
- gc_reference_register(&(cle->object), GC_REFTYPE_CLASSLOADER);
-#endif
-
- LLNI_CRITICAL_START;
-
- cle->object = LLNI_DIRECT(cl);
-
- LLNI_CRITICAL_END;
-
-/*#define LOADER_DEBUG_CLASSLOADER*/
-#ifdef LOADER_DEBUG_CLASSLOADER
- printf("CLASSLOADER: adding new classloader entry %p for %p: ", cle, cl);
- class_print(LLNI_vftbl_direct(cl)->class);
- printf("\n");
- fflush(stdout);
-#endif
-
- /* insert entry into hashtable */
-
- cle->hashlink = hashtable_classloader->ptr[slot];
- hashtable_classloader->ptr[slot] = cle;
-
- /* update number of entries */
-
- hashtable_classloader->entries++;
- }
-
-
- LOCK_MONITOR_EXIT(hashtable_classloader->header);
-
-#if defined(ENABLE_HANDLES)
- return cle;
-#else
- return cl;
-#endif
-}
-
-
-/* loader_hashtable_classloader_find *******************************************
-
- Find an entry in the classloader hashtable.
-
-*******************************************************************************/
-
-classloader_t *loader_hashtable_classloader_find(java_handle_t *cl)
-{
- hashtable_classloader_entry *cle;
- u4 key;
- u4 slot;
-
- if (cl == NULL)
- return NULL;
-
- LLNI_CRITICAL_START;
-
- /* key for entry is the hashcode of the classloader;
- aligned to 16-byte boundaries */
-
- key = heap_hashcode(LLNI_DIRECT(cl)) >> 4;
- slot = key & (hashtable_classloader->size - 1);
- cle = hashtable_classloader->ptr[slot];
-
- /* search hashchain for existing entry */
-
- while (cle) {
- if (cle->object == LLNI_DIRECT(cl))
- break;
-
- cle = cle->hashlink;
- }
-
-#ifdef LOADER_DEBUG_CLASSLOADER
- if (cle == NULL) {
- printf("CLASSLOADER: unable to find classloader entry for %p: ", cl);
- class_print(LLNI_vftbl_direct(cl)->class);
- printf("\n");
- fflush(stdout);
- }
-#endif
-
- LLNI_CRITICAL_END;
-
-#if defined(ENABLE_HANDLES)
- return cle;
-#else
- return cl;
-#endif
-}
-
-
-/* loader_load_all_classes *****************************************************
-
- Loads all classes specified in the BOOTCLASSPATH.
-
-*******************************************************************************/
-
-void loader_load_all_classes(void)
-{
- list_classpath_entry *lce;
-#if defined(ENABLE_ZLIB)
- hashtable *ht;
- s4 slot;
- hashtable_zipfile_entry *htzfe;
- utf *u;
-#endif
-
- for (lce = list_first(list_classpath_entries); lce != NULL;
- lce = list_next(list_classpath_entries, lce)) {
-#if defined(ENABLE_ZLIB)
- if (lce->type == CLASSPATH_ARCHIVE) {
- /* get the classes hashtable */
-
- ht = lce->htclasses;
-
- for (slot = 0; slot < ht->size; slot++) {
- htzfe = (hashtable_zipfile_entry *) ht->ptr[slot];
-
- for (; htzfe; htzfe = htzfe->hashlink) {
- u = htzfe->filename;
-
- /* skip all entries in META-INF and .properties,
- .png files */
-
- if (!strncmp(u->text, "META-INF", strlen("META-INF")) ||
- strstr(u->text, ".properties") ||
- strstr(u->text, ".png"))
- continue;
-
- /* load class from bootstrap classloader */
-
- if (!load_class_bootstrap(u)) {
- fprintf(stderr, "Error loading: ");
- utf_fprint_printable_ascii_classname(stderr, u);
- fprintf(stderr, "\n");
-
-#if !defined(NDEBUG)
- /* print out exception and cause */
-
- exceptions_print_current_exception();
-#endif
- }
- }
- }
-
- } else {
-#endif
-#if defined(ENABLE_ZLIB)
- }
-#endif
- }
-}
-
-
-/* loader_skip_attribute_body **************************************************
-
- Skips an attribute the attribute_name_index has already been read.
-
- attribute_info {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
-
-*******************************************************************************/
-
-bool loader_skip_attribute_body(classbuffer *cb)
-{
- u4 attribute_length;
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- attribute_length = suck_u4(cb);
-
- if (!suck_check_classbuffer_size(cb, attribute_length))
- return false;
-
- suck_skip_nbytes(cb, attribute_length);
-
- return true;
-}
-
-
-/* load_constantpool ***********************************************************
-
- Loads the constantpool of a class, the entries are transformed into
- a simpler format by resolving references (a detailed overview of
- the compact structures can be found in global.h).
-
-*******************************************************************************/
-
-static bool load_constantpool(classbuffer *cb, descriptor_pool *descpool)
-{
-
- /* The following structures are used to save information which cannot be
- processed during the first pass. After the complete constantpool has
- been traversed the references can be resolved.
- (only in specific order) */
-
- /* CONSTANT_Class entries */
- typedef struct forward_class {
- struct forward_class *next;
- u2 thisindex;
- u2 name_index;
- } forward_class;
-
- /* CONSTANT_String */
- typedef struct forward_string {
- struct forward_string *next;
- u2 thisindex;
- u2 string_index;
- } forward_string;
-
- /* CONSTANT_NameAndType */
- typedef struct forward_nameandtype {
- struct forward_nameandtype *next;
- u2 thisindex;
- u2 name_index;
- u2 sig_index;
- } forward_nameandtype;
-
- /* CONSTANT_Fieldref, CONSTANT_Methodref or CONSTANT_InterfaceMethodref */
- typedef struct forward_fieldmethint {
- struct forward_fieldmethint *next;
- u2 thisindex;
- u1 tag;
- u2 class_index;
- u2 nameandtype_index;
- } forward_fieldmethint;
-
-
- classinfo *c;
- u4 idx;
-
- forward_class *forward_classes = NULL;
- forward_string *forward_strings = NULL;
- forward_nameandtype *forward_nameandtypes = NULL;
- forward_fieldmethint *forward_fieldmethints = NULL;
-
- forward_class *nfc;
- forward_string *nfs;
- forward_nameandtype *nfn;
- forward_fieldmethint *nff;
-
- u4 cpcount;
- u1 *cptags;
- void** cpinfos;
-
- c = cb->clazz;
-
- /* number of entries in the constant_pool table plus one */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- cpcount = c->cpcount = suck_u2(cb);
-
- /* allocate memory */
- cptags = c->cptags = MNEW(u1, cpcount);
- cpinfos = c->cpinfos = MNEW(void*, cpcount);
-
- if (cpcount < 1) {
- exceptions_throw_classformaterror(c, "Illegal constant pool size");
- return false;
- }
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += (sizeof(u1) + sizeof(void*)) * cpcount;
-#endif
-
- /* initialize constantpool */
- for (idx = 0; idx < cpcount; idx++) {
- cptags[idx] = CONSTANT_UNUSED;
- cpinfos[idx] = NULL;
- }
-
-
- /******* first pass *******/
- /* entries which cannot be resolved now are written into
- temporary structures and traversed again later */
-
- idx = 1;
- while (idx < cpcount) {
- u4 t;
-
- /* get constant type */
- if (!suck_check_classbuffer_size(cb, 1))
- return false;
-
- t = suck_u1(cb);
-
- switch (t) {
- case CONSTANT_Class:
- nfc = DNEW(forward_class);
-
- nfc->next = forward_classes;
- forward_classes = nfc;
-
- nfc->thisindex = idx;
- /* reference to CONSTANT_NameAndType */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- nfc->name_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_String:
- nfs = DNEW(forward_string);
-
- nfs->next = forward_strings;
- forward_strings = nfs;
-
- nfs->thisindex = idx;
-
- /* reference to CONSTANT_Utf8_info with string characters */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- nfs->string_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_NameAndType:
- nfn = DNEW(forward_nameandtype);
-
- nfn->next = forward_nameandtypes;
- forward_nameandtypes = nfn;
-
- nfn->thisindex = idx;
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* reference to CONSTANT_Utf8_info containing simple name */
- nfn->name_index = suck_u2(cb);
-
- /* reference to CONSTANT_Utf8_info containing field or method
- descriptor */
- nfn->sig_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_Fieldref:
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- nff = DNEW(forward_fieldmethint);
-
- nff->next = forward_fieldmethints;
- forward_fieldmethints = nff;
-
- nff->thisindex = idx;
- /* constant type */
- nff->tag = t;
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* class or interface type that contains the declaration of the
- field or method */
- nff->class_index = suck_u2(cb);
-
- /* name and descriptor of the field or method */
- nff->nameandtype_index = suck_u2(cb);
-
- idx++;
- break;
-
- case CONSTANT_Integer: {
- constant_integer *ci = NEW(constant_integer);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_integer);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- ci->value = suck_s4(cb);
- cptags[idx] = CONSTANT_Integer;
- cpinfos[idx] = ci;
-
- idx++;
- break;
- }
-
- case CONSTANT_Float: {
- constant_float *cf = NEW(constant_float);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_float);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- cf->value = suck_float(cb);
- cptags[idx] = CONSTANT_Float;
- cpinfos[idx] = cf;
-
- idx++;
- break;
- }
-
- case CONSTANT_Long: {
- constant_long *cl = NEW(constant_long);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_long);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 8))
- return false;
-
- cl->value = suck_s8(cb);
- cptags[idx] = CONSTANT_Long;
- cpinfos[idx] = cl;
- idx += 2;
- if (idx > cpcount) {
- exceptions_throw_classformaterror(c, "Invalid constant pool entry");
- return false;
- }
- break;
- }
-
- case CONSTANT_Double: {
- constant_double *cd = NEW(constant_double);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_double);
-#endif
-
- if (!suck_check_classbuffer_size(cb, 8))
- return false;
-
- cd->value = suck_double(cb);
- cptags[idx] = CONSTANT_Double;
- cpinfos[idx] = cd;
- idx += 2;
- if (idx > cpcount) {
- exceptions_throw_classformaterror(c, "Invalid constant pool entry");
- return false;
- }
- break;
- }
-
- case CONSTANT_Utf8: {
- u4 length;
-
- /* number of bytes in the bytes array (not string-length) */
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- length = suck_u2(cb);
- cptags[idx] = CONSTANT_Utf8;
-
- /* validate the string */
- if (!suck_check_classbuffer_size(cb, length))
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify &&
- !is_valid_utf((char *) cb->pos, (char *) (cb->pos + length)))
- {
- exceptions_throw_classformaterror(c, "Invalid UTF-8 string");
- return false;
- }
-#endif /* ENABLE_VERIFIER */
- /* insert utf-string into the utf-symboltable */
- cpinfos[idx] = utf_new((char *) cb->pos, length);
-
- /* skip bytes of the string (buffer size check above) */
- suck_skip_nbytes(cb, length);
- idx++;
- break;
- }
-
- default:
- exceptions_throw_classformaterror(c, "Illegal constant pool type");
- return false;
- } /* end switch */
- } /* end while */
-
-
- /* resolve entries in temporary structures */
-
- while (forward_classes) {
- utf *name =
- class_getconstant(c, forward_classes->name_index, CONSTANT_Utf8);
- if (!name)
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify && !is_valid_name_utf(name)) {
- exceptions_throw_classformaterror(c, "Class reference with invalid name");
- return false;
- }
-#endif /* ENABLE_VERIFIER */
-
- /* add all class references to the descriptor_pool */
-
- if (!descriptor_pool_add_class(descpool, name))
- return false;
-
- cptags[forward_classes->thisindex] = CONSTANT_Class;
-
- /* the classref is created later */
- cpinfos[forward_classes->thisindex] = name;
-
- nfc = forward_classes;
- forward_classes = forward_classes->next;
- }
-
- while (forward_strings) {
- utf *text =
- class_getconstant(c, forward_strings->string_index, CONSTANT_Utf8);
- if (!text)
- return false;
-
- /* resolve utf-string */
- cptags[forward_strings->thisindex] = CONSTANT_String;
- cpinfos[forward_strings->thisindex] = text;
-
- nfs = forward_strings;
- forward_strings = forward_strings->next;
- }
-
- while (forward_nameandtypes) {
- constant_nameandtype *cn = NEW(constant_nameandtype);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_nameandtype);
-#endif
-
- /* resolve simple name and descriptor */
- cn->name = class_getconstant(c,
- forward_nameandtypes->name_index,
- CONSTANT_Utf8);
- if (!cn->name)
- return false;
-
- cn->descriptor = class_getconstant(c,
- forward_nameandtypes->sig_index,
- CONSTANT_Utf8);
- if (!cn->descriptor)
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- /* check name */
- if (!is_valid_name_utf(cn->name)) {
- exceptions_throw_classformaterror(c,
- "Illegal Field name \"%s\"",
- cn->name->text);
-
- return false;
- }
-
- /* disallow referencing <clinit> among others */
- if (cn->name->text[0] == '<' && cn->name != utf_init) {
- exceptions_throw_classformaterror(c, "Illegal reference to special method");
- return false;
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- cptags[forward_nameandtypes->thisindex] = CONSTANT_NameAndType;
- cpinfos[forward_nameandtypes->thisindex] = cn;
-
- nfn = forward_nameandtypes;
- forward_nameandtypes = forward_nameandtypes->next;
- }
-
- while (forward_fieldmethints) {
- constant_nameandtype *nat;
- constant_FMIref *fmi = NEW(constant_FMIref);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_const_pool_len += sizeof(constant_FMIref);
-#endif
- /* resolve simple name and descriptor */
-
- nat = class_getconstant(c,
- forward_fieldmethints->nameandtype_index,
- CONSTANT_NameAndType);
- if (!nat)
- return false;
-
- /* add all descriptors in {Field,Method}ref to the descriptor_pool */
-
- if (!descriptor_pool_add(descpool, nat->descriptor, NULL))
- return false;
-
- /* the classref is created later */
-
- fmi->p.index = forward_fieldmethints->class_index;
- fmi->name = nat->name;
- fmi->descriptor = nat->descriptor;
-
- cptags[forward_fieldmethints->thisindex] = forward_fieldmethints->tag;
- cpinfos[forward_fieldmethints->thisindex] = fmi;
-
- nff = forward_fieldmethints;
- forward_fieldmethints = forward_fieldmethints->next;
- }
-
- /* everything was ok */
-
- return true;
-}
-
-
-/* loader_load_attribute_signature *********************************************
-
- Signature_attribute {
- u2 attribute_name_index;
- u4 atrribute_length;
- u2 signature_index;
- }
-
-*******************************************************************************/
-
-#if defined(ENABLE_JAVASE)
-bool loader_load_attribute_signature(classbuffer *cb, utf **signature)
-{
- classinfo *c;
- u4 attribute_length;
- u2 signature_index;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- /* check remaining bytecode */
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* check attribute length */
-
- attribute_length = suck_u4(cb);
-
- if (attribute_length != 2) {
- exceptions_throw_classformaterror(c, "Wrong size for VALUE attribute");
- return false;
- }
-
- if (*signature != NULL) {
- exceptions_throw_classformaterror(c, "Multiple Signature attributes");
- return false;
- }
-
- /* get signature */
-
- signature_index = suck_u2(cb);
-
- if (!(*signature = class_getconstant(c, signature_index, CONSTANT_Utf8)))
- return false;
-
- return true;
-}
-#endif /* defined(ENABLE_JAVASE) */
-
-
-/* load_class_from_sysloader ***************************************************
-
- Load the class with the given name using the system class loader
-
- IN:
- name.............the classname
-
- RETURN VALUE:
- the loaded class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-classinfo *load_class_from_sysloader(utf *name)
-{
- methodinfo *m;
- java_handle_t *clo;
- classloader_t *cl;
- classinfo *c;
-
- assert(class_java_lang_Object);
- assert(class_java_lang_ClassLoader);
- assert(class_java_lang_ClassLoader->state & CLASS_LINKED);
-
- m = class_resolveclassmethod(class_java_lang_ClassLoader,
- utf_getSystemClassLoader,
- utf_void__java_lang_ClassLoader,
- class_java_lang_Object,
- false);
-
- if (!m)
- return false;
-
- clo = vm_call_method(m, NULL);
-
- if (!clo)
- return false;
-
- cl = loader_hashtable_classloader_add(clo);
-
- c = load_class_from_classloader(name, cl);
-
- return c;
-}
-
-
-/* load_class_from_classloader *************************************************
-
- Load the class with the given name using the given user-defined class loader.
-
- IN:
- name.............the classname
- cl...............user-defined class loader
-
- RETURN VALUE:
- the loaded class, or
- NULL if an exception has been thrown
-
-*******************************************************************************/
-
-classinfo *load_class_from_classloader(utf *name, classloader_t *cl)
-{
- java_handle_t *o;
- classinfo *c;
- classinfo *tmpc;
- java_handle_t *string;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_lookup, time_prepare, time_java,
- time_cache;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- assert(name);
-
- /* lookup if this class has already been loaded */
-
- c = classcache_lookup(cl, name);
-
- RT_TIMING_GET_TIME(time_lookup);
- RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_CL_LOOKUP);
-
- if (c != NULL)
- return c;
-
- /* if other class loader than bootstrap, call it */
-
- if (cl != NULL) {
- methodinfo *lc;
- char *text;
- s4 namelen;
-
- text = name->text;
- namelen = name->blength;
-
- /* handle array classes */
- if (text[0] == '[') {
- classinfo *comp;
- utf *u;
-
- switch (text[1]) {
- case 'L':
- /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
- if (namelen < 4 || text[2] == '[' || text[namelen - 1] != ';') {
- exceptions_throw_classnotfoundexception(name);
- return false;
- }
-
- u = utf_new(text + 2, namelen - 3);
-
- if (!(comp = load_class_from_classloader(u, cl)))
- return false;
-
- /* create the array class */
-
- c = class_array_of(comp, false);
-
- tmpc = classcache_store(cl, c, true);
-
- if (tmpc == NULL) {
- /* exception, free the loaded class */
- c->state &= ~CLASS_LOADING;
- class_free(c);
- }
-
- return tmpc;
-
- case '[':
- /* load the component class */
-
- u = utf_new(text + 1, namelen - 1);
-
- if (!(comp = load_class_from_classloader(u, cl)))
- return false;
-
- /* create the array class */
-
- c = class_array_of(comp, false);
-
- tmpc = classcache_store(cl, c, true);
-
- if (tmpc == NULL) {
- /* exception, free the loaded class */
- c->state &= ~CLASS_LOADING;
- class_free(c);
- }
-
- return tmpc;
-
- default:
- /* primitive array classes are loaded by the bootstrap loader */
-
- c = load_class_bootstrap(name);
-
- return c;
- }
- }
-
- LLNI_class_get(cl, c);
-
-#if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
- /* OpenJDK uses this internal function because it's
- synchronized. */
-
- lc = class_resolveclassmethod(c,
- utf_loadClassInternal,
- utf_java_lang_String__java_lang_Class,
- NULL,
- true);
-#else
- lc = class_resolveclassmethod(c,
- utf_loadClass,
- utf_java_lang_String__java_lang_Class,
- NULL,
- true);
-#endif
-
- if (lc == NULL)
- return false; /* exception */
-
- /* move return value into `o' and cast it afterwards to a classinfo* */
-
- string = javastring_new_slash_to_dot(name);
-
- RT_TIMING_GET_TIME(time_prepare);
-
- o = vm_call_method(lc, (java_handle_t *) cl, string);
-
- RT_TIMING_GET_TIME(time_java);
-
- c = LLNI_classinfo_unwrap(o);
-
- if (c != NULL) {
- /* Store this class in the loaded class cache. If another
- class with the same (initloader,name) pair has been
- stored earlier it will be returned by classcache_store
- In this case classcache_store may not free the class
- because it has already been exposed to Java code which
- may have kept references to that class. */
-
- tmpc = classcache_store(cl, c, false);
-
- if (tmpc == NULL) {
- /* exception, free the loaded class */
- c->state &= ~CLASS_LOADING;
- class_free(c);
- }
-
- c = tmpc;
- }
-
- RT_TIMING_GET_TIME(time_cache);
-
- RT_TIMING_TIME_DIFF(time_lookup , time_prepare, RT_TIMING_LOAD_CL_PREPARE);
- RT_TIMING_TIME_DIFF(time_prepare, time_java , RT_TIMING_LOAD_CL_JAVA);
- RT_TIMING_TIME_DIFF(time_java , time_cache , RT_TIMING_LOAD_CL_CACHE);
-
- /* SUN compatible -verbose:class output */
-
- if (opt_verboseclass && (c != NULL) && (c->classloader == cl)) {
- printf("[Loaded ");
- utf_display_printable_ascii_classname(name);
- printf("]\n");
- }
-
-#if defined(ENABLE_JVMTI)
- /* fire Class Load JVMTI event */
- if (jvmti) jvmti_ClassLoadPrepare(false, c);
-#endif
-
-
- return c;
- }
-
- c = load_class_bootstrap(name);
-
- return c;
-}
-
-
-/* load_class_bootstrap ********************************************************
-
- Load the class with the given name using the bootstrap class loader.
-
- IN:
- name.............the classname
-
- RETURN VALUE:
- loaded classinfo, or
- NULL if an exception has been thrown
-
- SYNCHRONIZATION:
- load_class_bootstrap is synchronized. It can be treated as an
- atomic operation.
-
-*******************************************************************************/
-
-classinfo *load_class_bootstrap(utf *name)
-{
- classbuffer *cb;
- classinfo *c;
- classinfo *r;
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_lookup, time_array, time_suck,
- time_load, time_cache;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- /* for debugging */
-
- assert(name);
-
- /* lookup if this class has already been loaded */
-
- r = classcache_lookup(NULL, name);
-
- if (r != NULL) {
- RT_TIMING_GET_TIME(time_lookup);
- RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
-
- return r;
- }
-
- RT_TIMING_GET_TIME(time_lookup);
- RT_TIMING_TIME_DIFF(time_start,time_lookup,RT_TIMING_LOAD_BOOT_LOOKUP);
-
- /* create the classinfo */
-
- c = class_create_classinfo(name);
-
- /* handle array classes */
-
- if (name->text[0] == '[') {
- c = load_newly_created_array(c, NULL);
-
- if (c == NULL)
- return NULL;
-
- assert(c->state & CLASS_LOADED);
-
- RT_TIMING_GET_TIME(time_array);
- RT_TIMING_TIME_DIFF(time_start,time_array,RT_TIMING_LOAD_BOOT_ARRAY);
-
- return c;
- }
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getcompilingtime)
- compilingtime_stop();
-
- if (opt_getloadingtime)
- loadingtime_start();
-#endif
-
- /* load classdata, throw exception on error */
-
- cb = suck_start(c);
-
- if (cb == NULL) {
- exceptions_throw_classnotfoundexception(name);
- return NULL;
- }
-
- RT_TIMING_GET_TIME(time_suck);
-
- /* load the class from the buffer */
-
- r = load_class_from_classbuffer(cb);
-
- RT_TIMING_GET_TIME(time_load);
-
- if (r == NULL) {
- /* the class could not be loaded, free the classinfo struct */
-
- class_free(c);
- }
- else {
- /* Store this class in the loaded class cache this step also
- checks the loading constraints. If the class has been
- loaded before, the earlier loaded class is returned. */
-
- classinfo *res = classcache_store(NULL, c, true);
-
- if (res == NULL) {
- /* exception */
- class_free(c);
- }
- else {
- /* Add the package name to the boot packages. */
-
- Package_add(c->packagename);
- }
-
- r = res;
- }
-
- RT_TIMING_GET_TIME(time_cache);
-
- /* SUN compatible -verbose:class output */
-
- if (opt_verboseclass && r) {
- printf("[Loaded ");
- utf_display_printable_ascii_classname(name);
- printf(" from %s]\n", cb->path);
- }
-
- /* free memory */
-
- suck_stop(cb);
-
-#if defined(ENABLE_STATISTICS)
- /* measure time */
-
- if (opt_getloadingtime)
- loadingtime_stop();
-
- if (opt_getcompilingtime)
- compilingtime_start();
-#endif
-
- RT_TIMING_TIME_DIFF(time_lookup, time_suck , RT_TIMING_LOAD_BOOT_SUCK);
- RT_TIMING_TIME_DIFF(time_suck , time_load , RT_TIMING_LOAD_BOOT_LOAD);
- RT_TIMING_TIME_DIFF(time_load , time_cache, RT_TIMING_LOAD_BOOT_CACHE);
- RT_TIMING_TIME_DIFF(time_lookup, time_cache, RT_TIMING_LOAD_BOOT_TOTAL);
-
- return r;
-}
-
-
-/* load_class_from_classbuffer_intern ******************************************
-
- Loads a class from a classbuffer into a given classinfo structure.
- Super-classes are also loaded at this point and some verfication
- checks are done.
-
- SYNCHRONIZATION:
- This function is NOT synchronized!
-
-*******************************************************************************/
-
-static bool load_class_from_classbuffer_intern(classbuffer *cb)
-{
- classinfo *c;
- classinfo *tc;
- utf *name;
- utf *supername;
- utf **interfacesnames;
- utf *u;
- constant_classref *cr;
- int16_t index;
-
- u4 i,j;
- u4 ma, mi;
- descriptor_pool *descpool;
-#if defined(ENABLE_STATISTICS)
- u4 classrefsize;
- u4 descsize;
-#endif
-#if defined(ENABLE_RT_TIMING)
- struct timespec time_start, time_checks, time_ndpool, time_cpool,
- time_setup, time_fields, time_methods, time_classrefs,
- time_descs, time_setrefs, time_parsefds, time_parsemds,
- time_parsecpool, time_verify, time_attrs;
-#endif
-
- RT_TIMING_GET_TIME(time_start);
-
- /* Get the classbuffer's class. */
-
- c = cb->clazz;
-
- if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
- return false;
-
- /* check signature */
-
- if (suck_u4(cb) != MAGIC) {
- exceptions_throw_classformaterror(c, "Bad magic number");
- return false;
- }
-
- /* check version */
-
- mi = suck_u2(cb);
- ma = suck_u2(cb);
-
- if (!(ma < MAJOR_VERSION || (ma == MAJOR_VERSION && mi <= MINOR_VERSION))) {
- exceptions_throw_unsupportedclassversionerror(c, ma, mi);
- return false;
- }
-
- RT_TIMING_GET_TIME(time_checks);
-
- /* create a new descriptor pool */
-
- descpool = descriptor_pool_new(c);
-
- RT_TIMING_GET_TIME(time_ndpool);
-
- /* load the constant pool */
-
- if (!load_constantpool(cb, descpool))
- return false;
-
- RT_TIMING_GET_TIME(time_cpool);
-
- /* ACC flags */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* We OR the flags here, as we set already some flags in
- class_create_classinfo. */
-
- c->flags |= suck_u2(cb);
-
- /* check ACC flags consistency */
-
- if (c->flags & ACC_INTERFACE) {
- if (!(c->flags & ACC_ABSTRACT)) {
- /* We work around this because interfaces in JDK 1.1 are
- * not declared abstract. */
-
- c->flags |= ACC_ABSTRACT;
- }
-
- if (c->flags & ACC_FINAL) {
- exceptions_throw_classformaterror(c,
- "Illegal class modifiers: 0x%X",
- c->flags);
- return false;
- }
-
- if (c->flags & ACC_SUPER) {
- c->flags &= ~ACC_SUPER; /* kjc seems to set this on interfaces */
- }
- }
-
- if ((c->flags & (ACC_ABSTRACT | ACC_FINAL)) == (ACC_ABSTRACT | ACC_FINAL)) {
- exceptions_throw_classformaterror(c,
- "Illegal class modifiers: 0x%X",
- c->flags);
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* This class. */
-
- index = suck_u2(cb);
-
- name = (utf *) class_getconstant(c, index, CONSTANT_Class);
-
- if (name == NULL)
- return false;
-
- if (c->name == utf_not_named_yet) {
- /* we finally have a name for this class */
- c->name = name;
- class_set_packagename(c);
- }
- else if (name != c->name) {
- exceptions_throw_noclassdeffounderror_wrong_name(c, name);
- return false;
- }
-
- /* Retrieve superclass. */
-
- c->super = NULL;
-
- index = suck_u2(cb);
-
- if (index == 0) {
- supername = NULL;
-
- /* This is only allowed for java.lang.Object. */
-
- if (c->name != utf_java_lang_Object) {
- exceptions_throw_classformaterror(c, "Bad superclass index");
- return false;
- }
- }
- else {
- supername = (utf *) class_getconstant(c, index, CONSTANT_Class);
-
- if (supername == NULL)
- return false;
-
- /* java.lang.Object may not have a super class. */
-
- if (c->name == utf_java_lang_Object) {
- exceptions_throw_classformaterror(NULL, "java.lang.Object with superclass");
- return false;
- }
-
- /* Detect circularity. */
-
- if (supername == c->name) {
- exceptions_throw_classcircularityerror(c);
- return false;
- }
-
- /* Interfaces must have java.lang.Object as super class. */
-
- if ((c->flags & ACC_INTERFACE) && (supername != utf_java_lang_Object)) {
- exceptions_throw_classformaterror(c, "Interfaces must have java.lang.Object as superclass");
- return false;
- }
- }
-
- /* Parse the super interfaces. */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- c->interfacescount = suck_u2(cb);
-
- if (!suck_check_classbuffer_size(cb, 2 * c->interfacescount))
- return false;
-
- c->interfaces = MNEW(classinfo*, c->interfacescount);
-
- /* Get the names of the super interfaces. */
-
- interfacesnames = DMNEW(utf*, c->interfacescount);
-
- for (i = 0; i < c->interfacescount; i++) {
- index = suck_u2(cb);
-
- u = (utf *) class_getconstant(c, index, CONSTANT_Class);
-
- if (u == NULL)
- return false;
-
- interfacesnames[i] = u;
- }
-
- RT_TIMING_GET_TIME(time_setup);
-
- /* Parse fields. */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- c->fieldscount = suck_u2(cb);
- c->fields = MNEW(fieldinfo, c->fieldscount);
-
- MZERO(c->fields, fieldinfo, c->fieldscount);
-
- for (i = 0; i < c->fieldscount; i++) {
- if (!field_load(cb, &(c->fields[i]), descpool))
- return false;
- }
-
- RT_TIMING_GET_TIME(time_fields);
-
- /* Parse methods. */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- c->methodscount = suck_u2(cb);
- c->methods = MNEW(methodinfo, c->methodscount);
-
- MZERO(c->methods, methodinfo, c->methodscount);
-
- for (i = 0; i < c->methodscount; i++) {
- if (!method_load(cb, &(c->methods[i]), descpool))
- return false;
- }
-
- RT_TIMING_GET_TIME(time_methods);
-
- /* create the class reference table */
-
- c->classrefs =
- descriptor_pool_create_classrefs(descpool, &(c->classrefcount));
-
- RT_TIMING_GET_TIME(time_classrefs);
-
- /* allocate space for the parsed descriptors */
-
- descriptor_pool_alloc_parsed_descriptors(descpool);
- c->parseddescs =
- descriptor_pool_get_parsed_descriptors(descpool, &(c->parseddescsize));
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- descriptor_pool_get_sizes(descpool, &classrefsize, &descsize);
- count_classref_len += classrefsize;
- count_parsed_desc_len += descsize;
- }
-#endif
-
- RT_TIMING_GET_TIME(time_descs);
-
- /* put the classrefs in the constant pool */
-
- for (i = 0; i < c->cpcount; i++) {
- if (c->cptags[i] == CONSTANT_Class) {
- utf *name = (utf *) c->cpinfos[i];
- c->cpinfos[i] = descriptor_pool_lookup_classref(descpool, name);
- }
- }
-
- /* Resolve the super class. */
-
- if (supername != NULL) {
- cr = descriptor_pool_lookup_classref(descpool, supername);
-
- if (cr == NULL)
- return false;
-
- /* XXX This should be done better. */
- tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
-
- if (tc == NULL) {
- resolve_handle_pending_exception(true);
- return false;
- }
-
- /* Interfaces are not allowed as super classes. */
-
- if (tc->flags & ACC_INTERFACE) {
- exceptions_throw_incompatibleclasschangeerror(c, "class %s has interface %s as super class");
- return false;
- }
-
- /* Don't allow extending final classes */
-
- if (tc->flags & ACC_FINAL) {
- exceptions_throw_verifyerror(NULL,
- "Cannot inherit from final class");
- return false;
- }
-
- /* Store the super class. */
-
- c->super = tc;
- }
-
- /* Resolve the super interfaces. */
-
- for (i = 0; i < c->interfacescount; i++) {
- u = interfacesnames[i];
- cr = descriptor_pool_lookup_classref(descpool, u);
-
- if (cr == NULL)
- return false;
-
- /* XXX This should be done better. */
- tc = resolve_classref_or_classinfo_eager(CLASSREF_OR_CLASSINFO(cr), false);
-
- if (tc == NULL) {
- resolve_handle_pending_exception(true);
- return false;
- }
-
- /* Detect circularity. */
-
- if (tc == c) {
- exceptions_throw_classcircularityerror(c);
- return false;
- }
-
- if (!(tc->flags & ACC_INTERFACE)) {
- exceptions_throw_incompatibleclasschangeerror(tc,
- "Implementing class");
- return false;
- }
-
- /* Store the super interface. */
-
- c->interfaces[i] = tc;
- }
-
- RT_TIMING_GET_TIME(time_setrefs);
-
- /* Parse the field descriptors. */
-
- for (i = 0; i < c->fieldscount; i++) {
- c->fields[i].parseddesc =
- descriptor_pool_parse_field_descriptor(descpool,
- c->fields[i].descriptor);
- if (!c->fields[i].parseddesc)
- return false;
- }
-
- RT_TIMING_GET_TIME(time_parsefds);
-
- /* parse method descriptors */
-
- for (i = 0; i < c->methodscount; i++) {
- methodinfo *m = &c->methods[i];
- m->parseddesc =
- descriptor_pool_parse_method_descriptor(descpool, m->descriptor,
- m->flags, class_get_self_classref(m->clazz));
- if (!m->parseddesc)
- return false;
-
- for (j = 0; j < m->rawexceptiontablelength; j++) {
- if (!m->rawexceptiontable[j].catchtype.any)
- continue;
-
- if ((m->rawexceptiontable[j].catchtype.ref =
- descriptor_pool_lookup_classref(descpool,
- (utf *) m->rawexceptiontable[j].catchtype.any)) == NULL)
- return false;
- }
-
- for (j = 0; j < m->thrownexceptionscount; j++) {
- if (!m->thrownexceptions[j].any)
- continue;
-
- if ((m->thrownexceptions[j].ref = descriptor_pool_lookup_classref(descpool,
- (utf *) m->thrownexceptions[j].any)) == NULL)
- return false;
- }
- }
-
- RT_TIMING_GET_TIME(time_parsemds);
-
- /* parse the loaded descriptors */
-
- for (i = 0; i < c->cpcount; i++) {
- constant_FMIref *fmi;
- s4 index;
-
- switch (c->cptags[i]) {
- case CONSTANT_Fieldref:
- fmi = (constant_FMIref *) c->cpinfos[i];
- fmi->parseddesc.fd =
- descriptor_pool_parse_field_descriptor(descpool,
- fmi->descriptor);
- if (!fmi->parseddesc.fd)
- return false;
-
- index = fmi->p.index;
- fmi->p.classref =
- (constant_classref *) class_getconstant(c, index,
- CONSTANT_Class);
- if (!fmi->p.classref)
- return false;
- break;
- case CONSTANT_Methodref:
- case CONSTANT_InterfaceMethodref:
- fmi = (constant_FMIref *) c->cpinfos[i];
- index = fmi->p.index;
- fmi->p.classref =
- (constant_classref *) class_getconstant(c, index,
- CONSTANT_Class);
- if (!fmi->p.classref)
- return false;
- fmi->parseddesc.md =
- descriptor_pool_parse_method_descriptor(descpool,
- fmi->descriptor,
- ACC_UNDEF,
- fmi->p.classref);
- if (!fmi->parseddesc.md)
- return false;
- break;
- }
- }
-
- RT_TIMING_GET_TIME(time_parsecpool);
-
-#ifdef ENABLE_VERIFIER
- /* Check if all fields and methods can be uniquely
- * identified by (name,descriptor). */
-
- if (opt_verify) {
- /* We use a hash table here to avoid making the
- * average case quadratic in # of methods, fields.
- */
- static int shift = 0;
- u2 *hashtab;
- u2 *next; /* for chaining colliding hash entries */
- size_t len;
- size_t hashlen;
- u2 index;
- u2 old;
-
- /* Allocate hashtable */
- len = c->methodscount;
- if (len < c->fieldscount) len = c->fieldscount;
- hashlen = 5 * len;
- hashtab = MNEW(u2,(hashlen + len));
- next = hashtab + hashlen;
-
- /* Determine bitshift (to get good hash values) */
- if (!shift) {
- len = sizeof(utf);
- while (len) {
- len >>= 1;
- shift++;
- }
- }
-
- /* Check fields */
- memset(hashtab, 0, sizeof(u2) * (hashlen + len));
-
- for (i = 0; i < c->fieldscount; ++i) {
- fieldinfo *fi = c->fields + i;
-
- /* It's ok if we lose bits here */
- index = ((((size_t) fi->name) +
- ((size_t) fi->descriptor)) >> shift) % hashlen;
-
- if ((old = hashtab[index])) {
- old--;
- next[i] = old;
- do {
- if (c->fields[old].name == fi->name &&
- c->fields[old].descriptor == fi->descriptor) {
- exceptions_throw_classformaterror(c, "Repetitive field name/signature");
- return false;
- }
- } while ((old = next[old]));
- }
- hashtab[index] = i + 1;
- }
-
- /* Check methods */
- memset(hashtab, 0, sizeof(u2) * (hashlen + hashlen/5));
-
- for (i = 0; i < c->methodscount; ++i) {
- methodinfo *mi = c->methods + i;
-
- /* It's ok if we lose bits here */
- index = ((((size_t) mi->name) +
- ((size_t) mi->descriptor)) >> shift) % hashlen;
-
- if ((old = hashtab[index])) {
- old--;
- next[i] = old;
- do {
- if (c->methods[old].name == mi->name &&
- c->methods[old].descriptor == mi->descriptor) {
- exceptions_throw_classformaterror(c, "Repetitive method name/signature");
- return false;
- }
- } while ((old = next[old]));
- }
- hashtab[index] = i + 1;
- }
-
- MFREE(hashtab, u2, (hashlen + len));
- }
-#endif /* ENABLE_VERIFIER */
-
- RT_TIMING_GET_TIME(time_verify);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- size_classinfo += sizeof(classinfo*) * c->interfacescount;
- size_fieldinfo += sizeof(fieldinfo) * c->fieldscount;
- size_methodinfo += sizeof(methodinfo) * c->methodscount;
- }
-#endif
-
- /* load attribute structures */
-
- if (!class_load_attributes(cb))
- return false;
-
- /* Pre Java 1.5 version don't check this. This implementation is
- like Java 1.5 do it: for class file version 45.3 we don't check
- it, older versions are checked. */
-
- if (((ma == 45) && (mi > 3)) || (ma > 45)) {
- /* check if all data has been read */
- s4 classdata_left = ((cb->data + cb->size) - cb->pos);
-
- if (classdata_left > 0) {
- exceptions_throw_classformaterror(c, "Extra bytes at the end of class file");
- return false;
- }
- }
-
- RT_TIMING_GET_TIME(time_attrs);
-
- RT_TIMING_TIME_DIFF(time_start , time_checks , RT_TIMING_LOAD_CHECKS);
- RT_TIMING_TIME_DIFF(time_checks , time_ndpool , RT_TIMING_LOAD_NDPOOL);
- RT_TIMING_TIME_DIFF(time_ndpool , time_cpool , RT_TIMING_LOAD_CPOOL);
- RT_TIMING_TIME_DIFF(time_cpool , time_setup , RT_TIMING_LOAD_SETUP);
- RT_TIMING_TIME_DIFF(time_setup , time_fields , RT_TIMING_LOAD_FIELDS);
- RT_TIMING_TIME_DIFF(time_fields , time_methods , RT_TIMING_LOAD_METHODS);
- RT_TIMING_TIME_DIFF(time_methods , time_classrefs , RT_TIMING_LOAD_CLASSREFS);
- RT_TIMING_TIME_DIFF(time_classrefs , time_descs , RT_TIMING_LOAD_DESCS);
- RT_TIMING_TIME_DIFF(time_descs , time_setrefs , RT_TIMING_LOAD_SETREFS);
- RT_TIMING_TIME_DIFF(time_setrefs , time_parsefds , RT_TIMING_LOAD_PARSEFDS);
- RT_TIMING_TIME_DIFF(time_parsefds , time_parsemds , RT_TIMING_LOAD_PARSEMDS);
- RT_TIMING_TIME_DIFF(time_parsemds , time_parsecpool, RT_TIMING_LOAD_PARSECP);
- RT_TIMING_TIME_DIFF(time_parsecpool, time_verify , RT_TIMING_LOAD_VERIFY);
- RT_TIMING_TIME_DIFF(time_verify , time_attrs , RT_TIMING_LOAD_ATTRS);
- RT_TIMING_TIME_DIFF(time_start , time_attrs , RT_TIMING_LOAD_TOTAL);
-
- return true;
-}
-
-
-/* load_class_from_classbuffer *************************************************
-
- Convenience wrapper for load_class_from_classbuffer.
-
- SYNCHRONIZATION:
- This function is NOT synchronized!
-
-*******************************************************************************/
-
-classinfo *load_class_from_classbuffer(classbuffer *cb)
-{
- classinfo *c;
- bool result;
- int32_t dumpmarker;
-
- /* Get the classbuffer's class. */
-
- c = cb->clazz;
-
- /* Check if the class is already loaded. */
-
- if (c->state & CLASS_LOADED)
- return c;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_class_loads++;
-#endif
-
-#if !defined(NDEBUG)
- if (loadverbose)
- log_message_class("Loading class: ", c);
-#endif
-
- /* Mark start of dump memory area. */
-
- DMARKER;
-
- /* Class is currently loading. */
-
- c->state |= CLASS_LOADING;
-
- /* Parse the classbuffer. */
-
- result = load_class_from_classbuffer_intern(cb);
-
- /* Release dump area. */
-
- DRELEASE;
-
- /* An error occurred. */
-
- if (result == false) {
- /* Revert loading state. */
-
- c->state = (c->state & ~CLASS_LOADING);
-
- return NULL;
- }
-
- /* Revert loading state and set loaded. */
-
- c->state = (c->state & ~CLASS_LOADING) | CLASS_LOADED;
-
-#if defined(ENABLE_JVMTI)
- /* fire Class Prepare JVMTI event */
-
- if (jvmti)
- jvmti_ClassLoadPrepare(true, c);
-#endif
-
-#if !defined(NDEBUG)
- if (loadverbose)
- log_message_class("Loading done class: ", c);
-#endif
-
- return c;
-}
-
-
-/* load_newly_created_array ****************************************************
-
- Load a newly created array class.
-
- RETURN VALUE:
- c....................the array class C has been loaded
- other classinfo......the array class was found in the class cache,
- C has been freed
- NULL.................an exception has been thrown
-
- Note:
- This is an internal function. Do not use it unless you know exactly
- what you are doing!
-
- Use one of the load_class_... functions for general array class loading.
-
-*******************************************************************************/
-
-classinfo *load_newly_created_array(classinfo *c, classloader_t *loader)
-{
- classinfo *comp = NULL;
- methodinfo *clone;
- methoddesc *clonedesc;
- constant_classref *classrefs;
- char *text;
- s4 namelen;
- utf *u;
-
- text = c->name->text;
- namelen = c->name->blength;
-
- /* Check array class name */
-
- if ((namelen < 2) || (text[0] != '[')) {
- exceptions_throw_classnotfoundexception(c->name);
- return NULL;
- }
-
- /* Check the element type */
-
- switch (text[1]) {
- case '[':
- /* c is an array of arrays. We have to create the component class. */
-
- u = utf_new(text + 1, namelen - 1);
-
- comp = load_class_from_classloader(u, loader);
-
- if (comp == NULL)
- return NULL;
-
- assert(comp->state & CLASS_LOADED);
-
- /* the array's flags are that of the component class */
- c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
- c->classloader = comp->classloader;
- break;
-
- case 'L':
- /* c is an array of objects. */
-
- /* check for cases like `[L;' or `[L[I;' or `[Ljava.lang.Object' */
- if ((namelen < 4) || (text[2] == '[') || (text[namelen - 1] != ';')) {
- exceptions_throw_classnotfoundexception(c->name);
- return NULL;
- }
-
- u = utf_new(text + 2, namelen - 3);
-
- if (!(comp = load_class_from_classloader(u, loader)))
- return NULL;
-
- assert(comp->state & CLASS_LOADED);
-
- /* the array's flags are that of the component class */
- c->flags = (comp->flags & ~ACC_INTERFACE) | ACC_FINAL | ACC_ABSTRACT;
- c->classloader = comp->classloader;
- break;
-
- default:
- /* c is an array of a primitive type */
-
- /* check for cases like `[II' and whether the character is a
- valid primitive type */
-
- if ((namelen > 2) || (Primitive_get_class_by_char(text[1]) == NULL)) {
- exceptions_throw_classnotfoundexception(c->name);
- return NULL;
- }
-
- /* the accessibility of the array class is public (VM Spec 5.3.3) */
- c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT;
- c->classloader = NULL;
- }
-
- assert(class_java_lang_Object);
-#if defined(ENABLE_JAVASE)
- assert(class_java_lang_Cloneable);
- assert(class_java_io_Serializable);
-#endif
-
- /* Setup the array class. */
-
- c->super = class_java_lang_Object;
-
-#if defined(ENABLE_JAVASE)
-
- c->interfacescount = 2;
- c->interfaces = MNEW(classinfo*, 2);
- c->interfaces[0] = class_java_lang_Cloneable;
- c->interfaces[1] = class_java_io_Serializable;
-
-#elif defined(ENABLE_JAVAME_CLDC1_1)
-
- c->interfacescount = 0;
- c->interfaces = NULL;
-
-#else
-# error unknow Java configuration
-#endif
-
- c->methodscount = 1;
- c->methods = MNEW(methodinfo, c->methodscount);
-
- MZERO(c->methods, methodinfo, c->methodscount);
-
- classrefs = MNEW(constant_classref, 2);
-
- CLASSREF_INIT(classrefs[0], c, c->name);
- CLASSREF_INIT(classrefs[1], c, utf_java_lang_Object);
-
- /* create descriptor for clone method */
- /* we need one paramslot which is reserved for the 'this' parameter */
- clonedesc = NEW(methoddesc);
- clonedesc->returntype.type = TYPE_ADR;
- clonedesc->returntype.classref = classrefs + 1;
- clonedesc->returntype.arraydim = 0;
- /* initialize params to "empty", add real params below in
- descriptor_params_from_paramtypes */
- clonedesc->paramcount = 0;
- clonedesc->paramslots = 0;
- clonedesc->paramtypes[0].classref = classrefs + 0;
- clonedesc->params = NULL;
-
- /* create methodinfo */
-
- clone = c->methods;
- MSET(clone, 0, methodinfo, 1);
-
-#if defined(ENABLE_THREADS)
- lock_init_object_lock(&clone->header);
-#endif
-
- /* ATTENTION: if you delete the ACC_NATIVE below, set
- clone->maxlocals=1 (interpreter related) */
-
- clone->flags = ACC_PUBLIC | ACC_NATIVE;
- clone->name = utf_clone;
- clone->descriptor = utf_void__java_lang_Object;
- clone->parseddesc = clonedesc;
- clone->clazz = c;
-
- /* parse the descriptor to get the register allocation */
-
- if (!descriptor_params_from_paramtypes(clonedesc, clone->flags))
- return false;
-
- clone->code = codegen_generate_stub_native(clone, BUILTIN_clone);
-
- /* XXX: field: length? */
-
- /* array classes are not loaded from class files */
-
- c->state |= CLASS_LOADED;
- c->parseddescs = (u1 *) clonedesc;
- c->parseddescsize = sizeof(methodinfo);
- c->classrefs = classrefs;
- c->classrefcount = 1;
-
- /* insert class into the loaded class cache */
- /* XXX free classinfo if NULL returned? */
-
- return classcache_store(loader, c, true);
-}
-
-
-/* loader_close ****************************************************************
-
- Frees all resources.
-
-*******************************************************************************/
-
-void loader_close(void)
-{
- /* empty */
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/loader.h - class loader header
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _LOADER_H
-#define _LOADER_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct classbuffer classbuffer;
-
-
-#include "config.h"
-
-#include <stdio.h>
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/references.h"
-#include "vmcore/utf8.h"
-
-
-/* constant pool entries *******************************************************
-
- All constant pool entries need a data structure which contain the entrys
- value. In some cases this structure exist already, in the remaining cases
- this structure must be generated:
-
- kind structure generated?
- ----------------------------------------------------------------------
- CONSTANT_Class constant_classref yes
- CONSTANT_Fieldref constant_FMIref yes
- CONSTANT_Methodref constant_FMIref yes
- CONSTANT_InterfaceMethodref constant_FMIref yes
- CONSTANT_String unicode no
- CONSTANT_Integer constant_integer yes
- CONSTANT_Float constant_float yes
- CONSTANT_Long constant_long yes
- CONSTANT_Double constant_double yes
- CONSTANT_NameAndType constant_nameandtype yes
- CONSTANT_Utf8 unicode no
- CONSTANT_UNUSED -
-
-*******************************************************************************/
-
-typedef struct { /* Integer */
- s4 value;
-} constant_integer;
-
-
-typedef struct { /* Float */
- float value;
-} constant_float;
-
-
-typedef struct { /* Long */
- s8 value;
-} constant_long;
-
-
-typedef struct { /* Double */
- double value;
-} constant_double;
-
-
-typedef struct { /* NameAndType (Field or Method) */
- utf *name; /* field/method name */
- utf *descriptor; /* field/method type descriptor string */
-} constant_nameandtype;
-
-
-/* classbuffer ****************************************************************/
-
-struct classbuffer {
- classinfo *clazz; /* pointer to classinfo structure */
- uint8_t *data; /* pointer to byte code */
- int32_t size; /* size of the byte code */
- uint8_t *pos; /* current read position */
- char *path; /* path to file (for debugging) */
-};
-
-
-/* hashtable_classloader_entry *************************************************
-
- ATTENTION: The pointer to the classloader object needs to be the
- first field of the entry, so that it can be used as an indirection
- cell. This is checked by gc_init() during startup.
-
-*******************************************************************************/
-
-typedef struct hashtable_classloader_entry hashtable_classloader_entry;
-
-struct hashtable_classloader_entry {
- java_object_t *object;
- hashtable_classloader_entry *hashlink;
-};
-
-
-/* classloader *****************************************************************
-
- [!ENABLE_HANDLES]: The classloader is a Java Object which cannot move.
- [ENABLE_HANDLES] : The classloader entry itself is a static handle for a
- given classloader (use loader_hashtable_classloader_foo).
-
-*******************************************************************************/
-
-#if defined(ENABLE_HANDLES)
-typedef hashtable_classloader_entry classloader_t;
-#else
-typedef java_object_t classloader_t;
-#endif
-
-
-/* function prototypes ********************************************************/
-
-void loader_preinit(void);
-void loader_init(void);
-
-/* classloader management functions */
-classloader_t *loader_hashtable_classloader_add(java_handle_t *cl);
-classloader_t *loader_hashtable_classloader_find(java_handle_t *cl);
-
-void loader_load_all_classes(void);
-
-bool loader_skip_attribute_body(classbuffer *cb);
-
-#if defined(ENABLE_JAVASE)
-bool loader_load_attribute_signature(classbuffer *cb, utf **signature);
-#endif
-
-/* free resources */
-void loader_close(void);
-
-/* class loading functions */
-classinfo *load_class_from_sysloader(utf *name);
-classinfo *load_class_from_classloader(utf *name, classloader_t *cl);
-classinfo *load_class_bootstrap(utf *name);
-
-/* (don't use the following directly) */
-classinfo *load_class_from_classbuffer(classbuffer *cb);
-classinfo *load_newly_created_array(classinfo *c, classloader_t *loader);
-
-#endif /* _LOADER_H */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/method.c - method functions
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "native/llni.h"
-
-#include "threads/lock-common.h"
-
-#include "vm/array.h"
-#include "vm/builtin.h"
-#include "vm/exceptions.hpp"
-#include "vm/global.h"
-#include "vm/resolve.h"
-#include "vm/vm.hpp"
-
-#include "vm/jit/code.h"
-#include "vm/jit/methodheader.h"
-
-#include "vm/jit_interface.h"
-
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-#if !defined(NDEBUG) && defined(ENABLE_INLINING)
-#define INLINELOG(code) do { if (opt_TraceInlining) { code } } while (0)
-#else
-#define INLINELOG(code)
-#endif
-
-
-/* global variables ***********************************************************/
-
-methodinfo *method_java_lang_reflect_Method_invoke;
-
-
-/* method_init *****************************************************************
-
- Initialize method subsystem.
-
-*******************************************************************************/
-
-void method_init(void)
-{
-#if defined(ENABLE_JAVASE)
- /* Sanity check. */
-
- if (class_java_lang_reflect_Method == NULL)
- vm_abort("method_init: class_java_lang_reflect_Method is NULL");
-
- /* Cache java.lang.reflect.Method.invoke() */
-
- method_java_lang_reflect_Method_invoke =
- class_findmethod(class_java_lang_reflect_Method, utf_invoke, NULL);
-
- if (method_java_lang_reflect_Method_invoke == NULL)
- vm_abort("method_init: Could not resolve method java.lang.reflect.Method.invoke().");
-#endif
-}
-
-
-/* method_load *****************************************************************
-
- Loads a method from the class file and fills an existing methodinfo
- structure.
-
- method_info {
- u2 access_flags;
- u2 name_index;
- u2 descriptor_index;
- u2 attributes_count;
- attribute_info attributes[attribute_count];
- }
-
- attribute_info {
- u2 attribute_name_index;
- u4 attribute_length;
- u1 info[attribute_length];
- }
-
- LineNumberTable_attribute {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 line_number_table_length;
- {
- u2 start_pc;
- u2 line_number;
- } line_number_table[line_number_table_length];
- }
-
-*******************************************************************************/
-
-bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool)
-{
- classinfo *c;
- int argcount;
- s4 i, j, k, l;
- utf *u;
- u2 name_index;
- u2 descriptor_index;
- u2 attributes_count;
- u2 attribute_name_index;
- utf *attribute_name;
- u2 code_attributes_count;
- u2 code_attribute_name_index;
- utf *code_attribute_name;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- LOCK_INIT_OBJECT_LOCK(&(m->header));
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_all_methods++;
-#endif
-
- /* all fields of m have been zeroed in load_class_from_classbuffer */
-
- m->clazz = c;
-
- if (!suck_check_classbuffer_size(cb, 2 + 2 + 2))
- return false;
-
- /* access flags */
-
- m->flags = suck_u2(cb);
-
- /* name */
-
- name_index = suck_u2(cb);
-
- if (!(u = class_getconstant(c, name_index, CONSTANT_Utf8)))
- return false;
-
- m->name = u;
-
- /* descriptor */
-
- descriptor_index = suck_u2(cb);
-
- if (!(u = class_getconstant(c, descriptor_index, CONSTANT_Utf8)))
- return false;
-
- m->descriptor = u;
-
- if (!descriptor_pool_add(descpool, u, &argcount))
- return false;
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (!is_valid_name_utf(m->name)) {
- exceptions_throw_classformaterror(c, "Method with invalid name");
- return false;
- }
-
- if (m->name->text[0] == '<' &&
- m->name != utf_init && m->name != utf_clinit) {
- exceptions_throw_classformaterror(c, "Method with invalid special name");
- return false;
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- if (!(m->flags & ACC_STATIC))
- argcount++; /* count the 'this' argument */
-
-#ifdef ENABLE_VERIFIER
- if (opt_verify) {
- if (argcount > 255) {
- exceptions_throw_classformaterror(c, "Too many arguments in signature");
- return false;
- }
-
- /* check flag consistency */
- if (m->name != utf_clinit) {
- i = (m->flags & (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED));
-
- if (i != 0 && i != ACC_PUBLIC && i != ACC_PRIVATE && i != ACC_PROTECTED) {
- exceptions_throw_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
- return false;
- }
-
- if (m->flags & ACC_ABSTRACT) {
- if ((m->flags & (ACC_FINAL | ACC_NATIVE | ACC_PRIVATE |
- ACC_STATIC | ACC_STRICT | ACC_SYNCHRONIZED))) {
- exceptions_throw_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
- return false;
- }
- }
-
- if (c->flags & ACC_INTERFACE) {
- if ((m->flags & (ACC_ABSTRACT | ACC_PUBLIC)) != (ACC_ABSTRACT | ACC_PUBLIC)) {
- exceptions_throw_classformaterror(c,
- "Illegal method modifiers: 0x%X",
- m->flags);
- return false;
- }
- }
-
- if (m->name == utf_init) {
- if (m->flags & (ACC_STATIC | ACC_FINAL | ACC_SYNCHRONIZED |
- ACC_NATIVE | ACC_ABSTRACT)) {
- exceptions_throw_classformaterror(c, "Instance initialization method has invalid flags set");
- return false;
- }
- }
- }
- }
-#endif /* ENABLE_VERIFIER */
-
- /* mark the method as monomorphic until further notice */
-
- m->flags |= ACC_METHOD_MONOMORPHIC;
-
- /* non-abstract methods have an implementation in this class */
-
- if (!(m->flags & ACC_ABSTRACT))
- m->flags |= ACC_METHOD_IMPLEMENTED;
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* attributes count */
-
- attributes_count = suck_u2(cb);
-
- for (i = 0; i < attributes_count; i++) {
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* attribute name index */
-
- attribute_name_index = suck_u2(cb);
-
- attribute_name =
- class_getconstant(c, attribute_name_index, CONSTANT_Utf8);
-
- if (attribute_name == NULL)
- return false;
-
- if (attribute_name == utf_Code) {
- /* Code */
-
- if (m->flags & (ACC_ABSTRACT | ACC_NATIVE)) {
- exceptions_throw_classformaterror(c, "Code attribute in native or abstract methods");
- return false;
- }
-
- if (m->jcode) {
- exceptions_throw_classformaterror(c, "Multiple Code attributes");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 4 + 2 + 2))
- return false;
-
- suck_u4(cb);
- m->maxstack = suck_u2(cb);
- m->maxlocals = suck_u2(cb);
-
- if (m->maxlocals < argcount) {
- exceptions_throw_classformaterror(c, "Arguments can't fit into locals");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 4))
- return false;
-
- m->jcodelength = suck_u4(cb);
-
- if (m->jcodelength == 0) {
- exceptions_throw_classformaterror(c, "Code of a method has length 0");
- return false;
- }
-
- if (m->jcodelength > 65535) {
- exceptions_throw_classformaterror(c, "Code of a method longer than 65535 bytes");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, m->jcodelength))
- return false;
-
- m->jcode = MNEW(u1, m->jcodelength);
- suck_nbytes(m->jcode, cb, m->jcodelength);
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- m->rawexceptiontablelength = suck_u2(cb);
- if (!suck_check_classbuffer_size(cb, (2 + 2 + 2 + 2) * m->rawexceptiontablelength))
- return false;
-
- m->rawexceptiontable = MNEW(raw_exception_entry, m->rawexceptiontablelength);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat) {
- count_vmcode_len += m->jcodelength + 18;
- count_extable_len +=
- m->rawexceptiontablelength * sizeof(raw_exception_entry);
- }
-#endif
-
- for (j = 0; j < m->rawexceptiontablelength; j++) {
- u4 idx;
- m->rawexceptiontable[j].startpc = suck_u2(cb);
- m->rawexceptiontable[j].endpc = suck_u2(cb);
- m->rawexceptiontable[j].handlerpc = suck_u2(cb);
-
- idx = suck_u2(cb);
-
- if (!idx) {
- m->rawexceptiontable[j].catchtype.any = NULL;
- }
- else {
- /* the classref is created later */
- if (!(m->rawexceptiontable[j].catchtype.any =
- (utf *) class_getconstant(c, idx, CONSTANT_Class)))
- return false;
- }
- }
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* code attributes count */
-
- code_attributes_count = suck_u2(cb);
-
- for (k = 0; k < code_attributes_count; k++) {
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* code attribute name index */
-
- code_attribute_name_index = suck_u2(cb);
-
- code_attribute_name =
- class_getconstant(c, code_attribute_name_index, CONSTANT_Utf8);
-
- if (code_attribute_name == NULL)
- return false;
-
- /* check which code attribute */
-
- if (code_attribute_name == utf_LineNumberTable) {
- /* LineNumberTable */
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* attribute length */
-
- (void) suck_u4(cb);
-
- /* line number table length */
-
- m->linenumbercount = suck_u2(cb);
-
- if (!suck_check_classbuffer_size(cb,
- (2 + 2) * m->linenumbercount))
- return false;
-
- m->linenumbers = MNEW(lineinfo, m->linenumbercount);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- size_lineinfo += sizeof(lineinfo) * m->linenumbercount;
-#endif
-
- for (l = 0; l < m->linenumbercount; l++) {
- m->linenumbers[l].start_pc = suck_u2(cb);
- m->linenumbers[l].line_number = suck_u2(cb);
- }
- }
-#if defined(ENABLE_JAVASE)
- else if (code_attribute_name == utf_StackMapTable) {
- /* StackTableMap */
-
- if (!stackmap_load_attribute_stackmaptable(cb, m))
- return false;
- }
-#endif
- else {
- /* unknown code attribute */
-
- if (!loader_skip_attribute_body(cb))
- return false;
- }
- }
- }
- else if (attribute_name == utf_Exceptions) {
- /* Exceptions */
-
- if (m->thrownexceptions != NULL) {
- exceptions_throw_classformaterror(c, "Multiple Exceptions attributes");
- return false;
- }
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* attribute length */
-
- (void) suck_u4(cb);
-
- m->thrownexceptionscount = suck_u2(cb);
-
- if (!suck_check_classbuffer_size(cb, 2 * m->thrownexceptionscount))
- return false;
-
- m->thrownexceptions = MNEW(classref_or_classinfo, m->thrownexceptionscount);
-
- for (j = 0; j < m->thrownexceptionscount; j++) {
- /* the classref is created later */
- if (!((m->thrownexceptions)[j].any =
- (utf*) class_getconstant(c, suck_u2(cb), CONSTANT_Class)))
- return false;
- }
- }
-#if defined(ENABLE_JAVASE)
- else if (attribute_name == utf_Signature) {
- /* Signature */
-
- if (!loader_load_attribute_signature(cb, &(m->signature)))
- return false;
- }
-
-#if defined(ENABLE_ANNOTATIONS)
- else if (attribute_name == utf_RuntimeVisibleAnnotations) {
- /* RuntimeVisibleAnnotations */
- if (!annotation_load_method_attribute_runtimevisibleannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_RuntimeInvisibleAnnotations) {
- /* RuntimeInvisibleAnnotations */
- if (!annotation_load_method_attribute_runtimeinvisibleannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_RuntimeVisibleParameterAnnotations) {
- /* RuntimeVisibleParameterAnnotations */
- if (!annotation_load_method_attribute_runtimevisibleparameterannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_RuntimeInvisibleParameterAnnotations) {
- /* RuntimeInvisibleParameterAnnotations */
- if (!annotation_load_method_attribute_runtimeinvisibleparameterannotations(cb, m))
- return false;
- }
- else if (attribute_name == utf_AnnotationDefault) {
- /* AnnotationDefault */
- if (!annotation_load_method_attribute_annotationdefault(cb, m))
- return false;
- }
-#endif
-#endif
- else {
- /* unknown attribute */
-
- if (!loader_skip_attribute_body(cb))
- return false;
- }
- }
-
- if ((m->jcode == NULL) && !(m->flags & (ACC_ABSTRACT | ACC_NATIVE))) {
- exceptions_throw_classformaterror(c, "Missing Code attribute");
- return false;
- }
-
-#if defined(ENABLE_REPLACEMENT)
- /* initialize the hit countdown field */
-
- m->hitcountdown = METHOD_INITIAL_HIT_COUNTDOWN;
-#endif
-
- /* everything was ok */
-
- return true;
-}
-
-
-/* method_free *****************************************************************
-
- Frees all memory that was allocated for this method.
-
-*******************************************************************************/
-
-void method_free(methodinfo *m)
-{
- if (m->jcode)
- MFREE(m->jcode, u1, m->jcodelength);
-
- if (m->rawexceptiontable)
- MFREE(m->rawexceptiontable, raw_exception_entry, m->rawexceptiontablelength);
-
- code_free_code_of_method(m);
-
- if (m->stubroutine) {
- if (m->flags & ACC_NATIVE) {
- removenativestub(m->stubroutine);
-
- } else {
- removecompilerstub(m->stubroutine);
- }
- }
-}
-
-
-/* method_canoverwrite *********************************************************
-
- Check if m and old are identical with respect to type and
- name. This means that old can be overwritten with m.
-
-*******************************************************************************/
-
-bool method_canoverwrite(methodinfo *m, methodinfo *old)
-{
- if (m->name != old->name)
- return false;
-
- if (m->descriptor != old->descriptor)
- return false;
-
- if (m->flags & ACC_STATIC)
- return false;
-
- return true;
-}
-
-
-/* method_new_builtin **********************************************************
-
- Creates a minimal methodinfo structure for builtins. This comes handy
- when dealing with builtin stubs or stacktraces.
-
-*******************************************************************************/
-
-methodinfo *method_new_builtin(builtintable_entry *bte)
-{
- methodinfo *m;
-
- /* allocate the methodinfo structure */
-
- m = NEW(methodinfo);
-
- /* initialize methodinfo structure */
-
- MZERO(m, methodinfo, 1);
- LOCK_INIT_OBJECT_LOCK(&(m->header));
-
- m->flags = ACC_METHOD_BUILTIN;
- m->parseddesc = bte->md;
- m->name = bte->name;
- m->descriptor = bte->descriptor;
-
- /* return the newly created methodinfo */
-
- return m;
-}
-
-
-/* method_vftbl_lookup *********************************************************
-
- Does a method lookup in the passed virtual function table. This
- function does exactly the same thing as JIT, but additionally
- relies on the fact, that the methodinfo pointer is at the first
- data segment slot (even for compiler stubs).
-
-*******************************************************************************/
-
-methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m)
-{
- methodptr mptr;
- methodptr *pmptr;
- methodinfo *resm; /* pointer to new resolved method */
-
- /* If the method is not an instance method, just return it. */
-
- if (m->flags & ACC_STATIC)
- return m;
-
- assert(vftbl);
-
- /* Get the method from the virtual function table. Is this an
- interface method? */
-
- if (m->clazz->flags & ACC_INTERFACE) {
- pmptr = vftbl->interfacetable[-(m->clazz->index)];
- mptr = pmptr[(m - m->clazz->methods)];
- }
- else {
- mptr = vftbl->table[m->vftblindex];
- }
-
- /* and now get the codeinfo pointer from the first data segment slot */
-
- resm = code_get_methodinfo_for_pv(mptr);
-
- return resm;
-}
-
-
-/* method_get_parametercount **************************************************
-
- Use the descriptor of a method to determine the number of parameters
- of the method. The this pointer of non-static methods is not counted.
-
- IN:
- m........the method of which the parameters should be counted
-
- RETURN VALUE:
- The parameter count or -1 on error.
-
-*******************************************************************************/
-
-int32_t method_get_parametercount(methodinfo *m)
-{
- methoddesc *md; /* method descriptor of m */
- int32_t paramcount = 0; /* the parameter count of m */
-
- md = m->parseddesc;
-
- /* is the descriptor fully parsed? */
-
- if (md->params == NULL) {
- if (!descriptor_params_from_paramtypes(md, m->flags)) {
- return -1;
- }
- }
-
- paramcount = md->paramcount;
-
- /* skip `this' pointer */
-
- if (!(m->flags & ACC_STATIC)) {
- --paramcount;
- }
-
- return paramcount;
-}
-
-
-/* method_get_parametertypearray ***********************************************
-
- Use the descriptor of a method to generate a java.lang.Class array
- which contains the classes of the parametertypes of the method.
-
- This function is called by java.lang.reflect.{Constructor,Method}.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m)
-{
- methoddesc *md;
- typedesc *paramtypes;
- int32_t paramcount;
- java_handle_objectarray_t *oa;
- int32_t i;
- classinfo *c;
-
- md = m->parseddesc;
-
- /* is the descriptor fully parsed? */
-
- if (m->parseddesc->params == NULL)
- if (!descriptor_params_from_paramtypes(md, m->flags))
- return NULL;
-
- paramtypes = md->paramtypes;
- paramcount = md->paramcount;
-
- /* skip `this' pointer */
-
- if (!(m->flags & ACC_STATIC)) {
- paramtypes++;
- paramcount--;
- }
-
- /* create class-array */
-
- oa = builtin_anewarray(paramcount, class_java_lang_Class);
-
- if (oa == NULL)
- return NULL;
-
- /* get classes */
-
- for (i = 0; i < paramcount; i++) {
- if (!resolve_class_from_typedesc(¶mtypes[i], true, false, &c))
- return NULL;
-
- LLNI_array_direct(oa, i) = (java_object_t *) c;
- }
-
- return oa;
-}
-
-
-/* method_get_exceptionarray ***************************************************
-
- Get the exceptions which can be thrown by a method.
-
-*******************************************************************************/
-
-java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m)
-{
- java_handle_objectarray_t *oa;
- classinfo *c;
- s4 i;
-
- /* create class-array */
-
- oa = builtin_anewarray(m->thrownexceptionscount, class_java_lang_Class);
-
- if (oa == NULL)
- return NULL;
-
- /* iterate over all exceptions and store the class in the array */
-
- for (i = 0; i < m->thrownexceptionscount; i++) {
- c = resolve_classref_or_classinfo_eager(m->thrownexceptions[i], true);
-
- if (c == NULL)
- return NULL;
-
- LLNI_array_direct(oa, i) = (java_object_t *) c;
- }
-
- return oa;
-}
-
-
-/* method_returntype_get *******************************************************
-
- Get the return type of the method.
-
-*******************************************************************************/
-
-classinfo *method_returntype_get(methodinfo *m)
-{
- typedesc *td;
- classinfo *c;
-
- td = &(m->parseddesc->returntype);
-
- if (!resolve_class_from_typedesc(td, true, false, &c))
- return NULL;
-
- return c;
-}
-
-
-/* method_count_implementations ************************************************
-
- Count the implementations of a method in a class cone (a class and all its
- subclasses.)
-
- IN:
- m................the method to count
- c................class at which to start the counting (this class and
- all its subclasses will be searched)
-
- OUT:
- *found...........if found != NULL, *found receives the method
- implementation that was found. This value is only
- meaningful if the return value is 1.
-
- RETURN VALUE:
- the number of implementations found
-
-*******************************************************************************/
-
-s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found)
-{
- s4 count;
- methodinfo *mp;
- methodinfo *mend;
- classinfo *child;
-
- count = 0;
-
- mp = c->methods;
- mend = mp + c->methodscount;
-
- for (; mp < mend; ++mp) {
- if (method_canoverwrite(mp, m)) {
- if (found)
- *found = mp;
- count++;
- break;
- }
- }
-
- for (child = c->sub; child != NULL; child = child->nextsub) {
- count += method_count_implementations(m, child, found);
- }
-
- return count;
-}
-
-
-/* method_get_annotations ******************************************************
-
- Get a methods' unparsed annotations in a byte array.
-
- IN:
- m........the method of which the annotations should be returned
-
- RETURN VALUE:
- The unparsed annotations in a byte array (or NULL if there aren't any).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *method_get_annotations(methodinfo *m)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* methods' declaring class */
- int slot; /* methods' slot */
- java_handle_t *annotations; /* methods' unparsed annotations */
- java_handle_t *method_annotations; /* all methods' unparsed annotations */
- /* of the declaring class */
-
- c = m->clazz;
- slot = m - c->methods;
- annotations = NULL;
-
- LLNI_classinfo_field_get(c, method_annotations, method_annotations);
-
- /* the method_annotations array might be shorter then the method
- * count if the methods above a certain index have no annotations.
- */
- if (method_annotations != NULL &&
- array_length_get(method_annotations) > slot) {
- annotations = array_objectarray_element_get(
- (java_handle_objectarray_t*)method_annotations, slot);
- }
-
- return (java_handle_bytearray_t*)annotations;
-#else
- return NULL;
-#endif
-}
-
-
-/* method_get_parameterannotations ********************************************
-
- Get a methods' unparsed parameter annotations in an array of byte
- arrays.
-
- IN:
- m........the method of which the parameter annotations should be
- returned
-
- RETURN VALUE:
- The unparsed parameter annotations in a byte array (or NULL if
- there aren't any).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* methods' declaring class */
- int slot; /* methods' slot */
- java_handle_t *parameterAnnotations; /* methods' unparsed */
- /* parameter annotations */
- java_handle_t *method_parameterannotations; /* all methods' unparsed */
- /* parameter annotations of */
- /* the declaring class */
-
- c = m->clazz;
- slot = m - c->methods;
- parameterAnnotations = NULL;
-
- LLNI_classinfo_field_get(
- c, method_parameterannotations, method_parameterannotations);
-
- /* the method_annotations array might be shorter then the method
- * count if the methods above a certain index have no annotations.
- */
- if (method_parameterannotations != NULL &&
- array_length_get(method_parameterannotations) > slot) {
- parameterAnnotations = array_objectarray_element_get(
- (java_handle_objectarray_t*)method_parameterannotations,
- slot);
- }
-
- return (java_handle_bytearray_t*)parameterAnnotations;
-#else
- return NULL;
-#endif
-}
-
-
-/* method_get_annotationdefault ***********************************************
-
- Get a methods' unparsed annotation default value in a byte array.
-
- IN:
- m........the method of which the annotation default value should be
- returned
-
- RETURN VALUE:
- The unparsed annotation default value in a byte array (or NULL if
- there isn't one).
-
-*******************************************************************************/
-
-java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m)
-{
-#if defined(ENABLE_ANNOTATIONS)
- classinfo *c; /* methods' declaring class */
- int slot; /* methods' slot */
- java_handle_t *annotationDefault; /* methods' unparsed */
- /* annotation default value */
- java_handle_t *method_annotationdefaults; /* all methods' unparsed */
- /* annotation default values of */
- /* the declaring class */
-
- c = m->clazz;
- slot = m - c->methods;
- annotationDefault = NULL;
-
- LLNI_classinfo_field_get(
- c, method_annotationdefaults, method_annotationdefaults);
-
- /* the method_annotations array might be shorter then the method
- * count if the methods above a certain index have no annotations.
- */
- if (method_annotationdefaults != NULL &&
- array_length_get(method_annotationdefaults) > slot) {
- annotationDefault = array_objectarray_element_get(
- (java_handle_objectarray_t*)method_annotationdefaults, slot);
- }
-
- return (java_handle_bytearray_t*)annotationDefault;
-#else
- return NULL;
-#endif
-}
-
-
-/* method_add_to_worklist ******************************************************
-
- Add the method to the given worklist. If the method already occurs in
- the worklist, the worklist remains unchanged.
-
-*******************************************************************************/
-
-static void method_add_to_worklist(methodinfo *m, method_worklist **wl)
-{
- method_worklist *wi;
-
- for (wi = *wl; wi != NULL; wi = wi->next)
- if (wi->m == m)
- return;
-
- wi = NEW(method_worklist);
- wi->next = *wl;
- wi->m = m;
-
- *wl = wi;
-}
-
-
-/* method_add_assumption_monomorphic *******************************************
-
- Record the assumption that the method is monomorphic.
-
- IN:
- m.................the method
- caller............the caller making the assumption
-
-*******************************************************************************/
-
-void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller)
-{
- method_assumption *as;
-
- /* XXX LOCKING FOR THIS FUNCTION? */
-
- /* check if we already have registered this assumption */
-
- for (as = m->assumptions; as != NULL; as = as->next) {
- if (as->context == caller)
- return;
- }
-
- /* register the assumption */
-
- as = NEW(method_assumption);
- as->next = m->assumptions;
- as->context = caller;
-
- m->assumptions = as;
-}
-
-/* method_break_assumption_monomorphic *****************************************
-
- Break the assumption that this method is monomorphic. All callers that
- have registered this assumption are added to the worklist.
-
- IN:
- m.................the method
- wl................worklist where to add invalidated callers
-
-*******************************************************************************/
-
-void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl)
-{
- method_assumption *as;
-
- /* XXX LOCKING FOR THIS FUNCTION? */
-
- for (as = m->assumptions; as != NULL; as = as->next) {
- INLINELOG(
- printf("ASSUMPTION BROKEN (monomorphism): ");
- method_print(m);
- printf(" in ");
- method_println(as->context);
- );
-
- method_add_to_worklist(as->context, wl);
-
-#if defined(ENABLE_TLH) && 0
- /* XXX hack */
- method_assumption *as2;
- as2 = m->assumptions;
- m->assumptions = NULL;
- method_break_assumption_monomorphic(as->context, wl);
- /*
- assert(m->assumptions == NULL);
- m->assumptions = as2;*/
-#endif
-
- }
-}
-
-/* method_printflags ***********************************************************
-
- Prints the flags of a method to stdout like.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_printflags(methodinfo *m)
-{
- if (m == NULL) {
- printf("NULL");
- return;
- }
-
- if (m->flags & ACC_PUBLIC) printf(" PUBLIC");
- if (m->flags & ACC_PRIVATE) printf(" PRIVATE");
- if (m->flags & ACC_PROTECTED) printf(" PROTECTED");
- if (m->flags & ACC_STATIC) printf(" STATIC");
- if (m->flags & ACC_FINAL) printf(" FINAL");
- if (m->flags & ACC_SYNCHRONIZED) printf(" SYNCHRONIZED");
- if (m->flags & ACC_VOLATILE) printf(" VOLATILE");
- if (m->flags & ACC_TRANSIENT) printf(" TRANSIENT");
- if (m->flags & ACC_NATIVE) printf(" NATIVE");
- if (m->flags & ACC_INTERFACE) printf(" INTERFACE");
- if (m->flags & ACC_ABSTRACT) printf(" ABSTRACT");
- if (m->flags & ACC_METHOD_BUILTIN) printf(" (builtin)");
- if (m->flags & ACC_METHOD_MONOMORPHIC) printf(" (mono)");
- if (m->flags & ACC_METHOD_IMPLEMENTED) printf(" (impl)");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_print ****************************************************************
-
- Prints a method to stdout like:
-
- java.lang.Object.<init>()V
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_print(methodinfo *m)
-{
- if (m == NULL) {
- printf("NULL");
- return;
- }
-
- if (m->clazz != NULL)
- utf_display_printable_ascii_classname(m->clazz->name);
- else
- printf("NULL");
- printf(".");
- utf_display_printable_ascii(m->name);
- utf_display_printable_ascii(m->descriptor);
-
- method_printflags(m);
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_println **************************************************************
-
- Prints a method plus new line to stdout like:
-
- java.lang.Object.<init>()V
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_println(methodinfo *m)
-{
- if (opt_debugcolor) printf("\033[31m"); /* red */
- method_print(m);
- if (opt_debugcolor) printf("\033[m");
- printf("\n");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_methodref_print ******************************************************
-
- Prints a method reference to stdout.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_methodref_print(constant_FMIref *mr)
-{
- if (!mr) {
- printf("(constant_FMIref *)NULL");
- return;
- }
-
- if (IS_FMIREF_RESOLVED(mr)) {
- printf("<method> ");
- method_print(mr->p.method);
- }
- else {
- printf("<methodref> ");
- utf_display_printable_ascii_classname(mr->p.classref->name);
- printf(".");
- utf_display_printable_ascii(mr->name);
- utf_display_printable_ascii(mr->descriptor);
- }
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* method_methodref_println ****************************************************
-
- Prints a method reference to stdout, followed by a newline.
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void method_methodref_println(constant_FMIref *mr)
-{
- method_methodref_print(mr);
- printf("\n");
-}
-#endif /* !defined(NDEBUG) */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/method.h - method functions header
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _METHOD_H
-#define _METHOD_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* forward typedefs ***********************************************************/
-
-typedef struct methodinfo methodinfo;
-typedef struct raw_exception_entry raw_exception_entry;
-typedef struct lineinfo lineinfo;
-typedef struct method_assumption method_assumption;
-typedef struct method_worklist method_worklist;
-typedef struct codeinfo codeinfo;
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/builtin.h"
-#include "vm/global.h"
-
-#include "vmcore/descriptor.h"
-#include "vmcore/references.h"
-#include "vmcore/linker.h"
-#include "vmcore/loader.h"
-
-#if defined(ENABLE_JAVASE)
-# include "vmcore/stackmap.h"
-#endif
-
-#include "vmcore/utf8.h"
-
-
-#if defined(ENABLE_REPLACEMENT)
-/* Initial value for the hit countdown field of each method. */
-#define METHOD_INITIAL_HIT_COUNTDOWN 1000
-#endif
-
-
-/* methodinfo *****************************************************************/
-
-struct methodinfo { /* method structure */
- java_object_t header; /* we need this in jit's monitorenter */
- s4 flags; /* ACC flags */
- utf *name; /* name of method */
- utf *descriptor; /* JavaVM descriptor string of method */
-#if defined(ENABLE_JAVASE)
- utf *signature; /* Signature attribute */
- stack_map_t *stack_map; /* StackMapTable attribute */
-#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) */
- s4 maxstack; /* maximum stack depth of method */
- s4 maxlocals; /* maximum number of local variables */
- s4 jcodelength; /* length of JavaVM code */
- u1 *jcode; /* pointer to JavaVM code */
-
- s4 rawexceptiontablelength; /* exceptiontable length */
- raw_exception_entry *rawexceptiontable; /* the exceptiontable */
-
- u2 thrownexceptionscount; /* number of exceptions attribute */
- classref_or_classinfo *thrownexceptions; /* except. a method may throw */
-
- u2 linenumbercount; /* number of linenumber attributes */
- lineinfo *linenumbers; /* array of lineinfo items */
-
- u1 *stubroutine; /* stub for compiling or calling natives */
- codeinfo *code; /* current code of this method */
-
-#if defined(ENABLE_LSRA)
- s4 maxlifetimes; /* helper for lsra */
-#endif
-
- methodinfo *overwrites; /* method that is directly overwritten */
- method_assumption *assumptions; /* list of assumptions about this method */
-
-#if defined(ENABLE_REPLACEMENT)
- s4 hitcountdown; /* decreased for each hit */
-#endif
-
-#if defined(ENABLE_DEBUG_FILTER)
- u1 filtermatches; /* flags indicating which filters the method matches */
-#endif
-
-#if defined(ENABLE_ESCAPE)
- u1 *paramescape;
-#endif
-};
-
-/* method_assumption ***********************************************************
-
- This struct is used for registering assumptions about methods.
-
-*******************************************************************************/
-
-struct method_assumption {
- method_assumption *next;
- methodinfo *context;
-};
-
-
-/* method_worklist *************************************************************
-
- List node used for method worklists.
-
-*******************************************************************************/
-
-struct method_worklist {
- method_worklist *next;
- methodinfo *m;
-};
-
-
-/* raw_exception_entry ********************************************************/
-
-/* exception table entry read by the loader */
-
-struct raw_exception_entry { /* exceptiontable entry in a method */
- classref_or_classinfo catchtype; /* catchtype of exc. (0 == catchall) */
- u2 startpc; /* start pc of guarded area (inclusive) */
- u2 endpc; /* end pc of guarded area (exklusive) */
- u2 handlerpc; /* pc of exception handler */
-};
-
-
-/* lineinfo *******************************************************************/
-
-struct lineinfo {
- u2 start_pc;
- u2 line_number;
-};
-
-
-/* global variables ***********************************************************/
-
-extern methodinfo *method_java_lang_reflect_Method_invoke;
-
-
-/* inline functions ***********************************************************/
-
-inline static bool method_is_builtin(methodinfo* m)
-{
- return m->flags & ACC_METHOD_BUILTIN;
-}
-
-
-/* function prototypes ********************************************************/
-
-void method_init(void);
-
-bool method_load(classbuffer *cb, methodinfo *m, descriptor_pool *descpool);
-void method_free(methodinfo *m);
-bool method_canoverwrite(methodinfo *m, methodinfo *old);
-
-methodinfo *method_new_builtin(builtintable_entry *bte);
-
-methodinfo *method_vftbl_lookup(vftbl_t *vftbl, methodinfo* m);
-
-int32_t method_get_parametercount(methodinfo *m);
-java_handle_objectarray_t *method_get_parametertypearray(methodinfo *m);
-java_handle_objectarray_t *method_get_exceptionarray(methodinfo *m);
-classinfo *method_returntype_get(methodinfo *m);
-
-void method_add_assumption_monomorphic(methodinfo *m, methodinfo *caller);
-void method_break_assumption_monomorphic(methodinfo *m, method_worklist **wl);
-
-s4 method_count_implementations(methodinfo *m, classinfo *c, methodinfo **found);
-
-java_handle_bytearray_t *method_get_annotations(methodinfo *m);
-java_handle_bytearray_t *method_get_parameterannotations(methodinfo *m);
-java_handle_bytearray_t *method_get_annotationdefault(methodinfo *m);
-
-#if !defined(NDEBUG)
-void method_printflags(methodinfo *m);
-void method_print(methodinfo *m);
-void method_println(methodinfo *m);
-void method_methodref_print(constant_FMIref *mr);
-void method_methodref_println(constant_FMIref *mr);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _METHOD_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/options.c - contains global options
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <limits.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "mm/memory.h"
-
-#include "native/jni.h"
-
-#include "vm/vm.hpp"
-
-#include "vmcore/options.h"
-#include "vmcore/os.hpp"
-
-
-/* command line option ********************************************************/
-
-s4 opt_index = 0; /* index of processed arguments */
-char *opt_arg; /* this one exports the option argument */
-
-bool opt_foo = false; /* option for development */
-
-bool opt_jar = false;
-
-#if defined(ENABLE_JIT)
-bool opt_jit = true; /* JIT mode execution (default) */
-bool opt_intrp = false; /* interpreter mode execution */
-#else
-bool opt_jit = false; /* JIT mode execution */
-bool opt_intrp = true; /* interpreter mode execution (default) */
-#endif
-
-bool opt_run = true;
-
-s4 opt_heapmaxsize = 0; /* maximum heap size */
-s4 opt_heapstartsize = 0; /* initial heap size */
-s4 opt_stacksize = 0; /* thread stack size */
-
-bool opt_verbose = false;
-bool opt_debugcolor = false; /* use ANSI terminal sequences */
-bool compileall = false;
-
-bool loadverbose = false;
-bool initverbose = false;
-
-bool opt_verboseclass = false;
-bool opt_verbosegc = false;
-bool opt_verbosejni = false;
-bool opt_verbosecall = false; /* trace all method invocation */
-
-bool showmethods = false;
-bool showconstantpool = false;
-bool showutf = false;
-
-char *opt_method = NULL;
-char *opt_signature = NULL;
-
-bool compileverbose = false; /* trace compiler actions */
-bool showstack = false;
-
-bool opt_showdisassemble = false; /* generate disassembler listing */
-bool opt_shownops = false;
-bool opt_showddatasegment = false; /* generate data segment listing */
-bool opt_showintermediate = false; /* generate intermediate code listing */
-
-bool checkbounds = true; /* check array bounds */
-bool opt_noieee = false; /* don't implement ieee compliant floats */
-bool checksync = true; /* do synchronization */
-#if defined(ENABLE_LOOP)
-bool opt_loops = false; /* optimize array accesses in loops */
-#endif
-
-bool makeinitializations = true;
-
-#if defined(ENABLE_STATISTICS)
-bool opt_stat = false;
-bool opt_getloadingtime = false; /* to measure the runtime */
-bool opt_getcompilingtime = false; /* compute compile time */
-#endif
-#if defined(ENABLE_VERIFIER)
-bool opt_verify = true; /* true if classfiles should be verified */
-#endif
-
-#if defined(ENABLE_PROFILING)
-bool opt_prof = false;
-bool opt_prof_bb = false;
-#endif
-
-#if defined(ENABLE_OPAGENT)
-bool opt_opagent = false;
-#endif
-
-/* optimization options *******************************************************/
-
-#if defined(ENABLE_IFCONV)
-bool opt_ifconv = false;
-#endif
-
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
-bool opt_lsra = false;
-#endif
-#if defined(ENABLE_SSA)
-bool opt_ssa_dce = false; /* enable dead code elemination */
-bool opt_ssa_cp = false; /* enable copy propagation */
-#endif
-
-
-/* interpreter options ********************************************************/
-
-#if defined(ENABLE_INTRP)
-bool opt_no_dynamic = false; /* suppress dynamic superinstructions */
-bool opt_no_replication = false; /* don't use replication in intrp */
-bool opt_no_quicksuper = false; /* instructions for quickening cannot be
- part of dynamic superinstructions */
-
-s4 opt_static_supers = 0x7fffffff;
-bool vm_debug = false; /* XXX this should be called `opt_trace' */
-#endif
-
-#if defined(ENABLE_DEBUG_FILTER)
-const char *opt_filter_verbosecall_include = 0;
-const char *opt_filter_verbosecall_exclude = 0;
-const char *opt_filter_show_method = 0;
-#endif
-
-
-/* -XX options ****************************************************************/
-
-/* NOTE: For better readability keep these alpha-sorted. */
-
-/* Options which must always be available (production options in
- HotSpot). */
-
-int64_t opt_MaxDirectMemorySize = -1;
-int opt_MaxPermSize = 0;
-int opt_PermSize = 0;
-int opt_ThreadStackSize = 0;
-
-/* Debugging options which can be turned off. */
-
-int opt_DebugExceptions = 0;
-int opt_DebugFinalizer = 0;
-int opt_DebugLocalReferences = 0;
-int opt_DebugLocks = 0;
-int opt_DebugPackage = 0;
-int opt_DebugPatcher = 0;
-int opt_DebugProperties = 0;
-int opt_DebugStackFrameInfo = 0;
-int opt_DebugStackTrace = 0;
-int opt_DebugThreads = 0;
-#if defined(ENABLE_DISASSEMBLER)
-int opt_DisassembleStubs = 0;
-#endif
-#if defined(ENABLE_OPAGENT)
-int opt_EnableOpagent = 0;
-#endif
-#if defined(ENABLE_GC_CACAO)
-int opt_GCDebugRootSet = 0;
-int opt_GCStress = 0;
-#endif
-#if defined(ENABLE_INLINING)
-int opt_Inline = 0;
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
-int opt_InlineAll = 0;
-int opt_InlineCount = INT_MAX;
-int opt_InlineMaxSize = INT_MAX;
-int opt_InlineMinSize = 0;
-#endif
-#endif
-int opt_PrintConfig = 0;
-int opt_ProfileGCMemoryUsage = 0;
-int opt_ProfileMemoryUsage = 0;
-FILE *opt_ProfileMemoryUsageGNUPlot = NULL;
-#if defined(ENABLE_REPLACEMENT)
-int opt_TestReplacement = 0;
-#endif
-int opt_TraceCompilerCalls = 0;
-int opt_TraceExceptions = 0;
-int opt_TraceHPI = 0;
-#if defined(ENABLE_INLINING) && !defined(NDEBUG)
-int opt_TraceInlining = 0;
-#endif
-int opt_TraceJavaCalls = 0;
-int opt_TraceJNICalls = 0;
-int opt_TraceJVMCalls = 0;
-int opt_TraceJVMCallsVerbose = 0;
-int opt_TraceLinkClass = 0;
-#if defined(ENABLE_REPLACEMENT)
-int opt_TraceReplacement = 0;
-#endif
-int opt_TraceSubsystemInitialization = 0;
-int opt_TraceTraps = 0;
-
-
-enum {
- OPT_TYPE_BOOLEAN,
- OPT_TYPE_VALUE
-};
-
-enum {
- /* Options which must always be available (production options in
- HotSpot). */
-
- OPT_MaxDirectMemorySize,
- OPT_MaxPermSize,
- OPT_PermSize,
- OPT_ThreadStackSize,
-
- /* Debugging options which can be turned off. */
-
- OPT_DebugExceptions,
- OPT_DebugFinalizer,
- OPT_DebugLocalReferences,
- OPT_DebugLocks,
- OPT_DebugPackage,
- OPT_DebugPatcher,
- OPT_DebugProperties,
- OPT_DebugStackFrameInfo,
- OPT_DebugStackTrace,
- OPT_DebugThreads,
- OPT_DisassembleStubs,
- OPT_EnableOpagent,
- OPT_GCDebugRootSet,
- OPT_GCStress,
- OPT_Inline,
- OPT_InlineAll,
- OPT_InlineCount,
- OPT_InlineMaxSize,
- OPT_InlineMinSize,
- OPT_PrintConfig,
- OPT_ProfileGCMemoryUsage,
- OPT_ProfileMemoryUsage,
- OPT_ProfileMemoryUsageGNUPlot,
- OPT_TestReplacement,
- OPT_TraceCompilerCalls,
- OPT_TraceExceptions,
- OPT_TraceHPI,
- OPT_TraceInlining,
- OPT_TraceJavaCalls,
- OPT_TraceJNICalls,
- OPT_TraceJVMCalls,
- OPT_TraceJVMCallsVerbose,
- OPT_TraceLinkClass,
- OPT_TraceReplacement,
- OPT_TraceSubsystemInitialization,
- OPT_TraceTraps,
- OPT_Vmlog,
- OPT_VmlogStrings,
- OPT_VmlogIgnore
-};
-
-
-option_t options_XX[] = {
- /* Options which must always be available (production options in
- HotSpot). */
-
- { "MaxDirectMemorySize", OPT_MaxDirectMemorySize, OPT_TYPE_VALUE, "Maximum total size of NIO direct-buffer allocations" },
- { "MaxPermSize", OPT_MaxPermSize, OPT_TYPE_VALUE, "not implemented" },
- { "PermSize", OPT_PermSize, OPT_TYPE_VALUE, "not implemented" },
- { "ThreadStackSize", OPT_ThreadStackSize, OPT_TYPE_VALUE, "TODO" },
-
- /* Debugging options which can be turned off. */
-
- { "DebugExceptions", OPT_DebugExceptions, OPT_TYPE_BOOLEAN, "debug exceptions" },
- { "DebugFinalizer", OPT_DebugFinalizer, OPT_TYPE_BOOLEAN, "debug finalizer thread" },
- { "DebugLocalReferences", OPT_DebugLocalReferences, OPT_TYPE_BOOLEAN, "print debug information for local reference tables" },
- { "DebugLocks", OPT_DebugLocks, OPT_TYPE_BOOLEAN, "print debug information for locks" },
- { "DebugPackage", OPT_DebugPackage, OPT_TYPE_BOOLEAN, "debug Java boot-packages" },
- { "DebugPatcher", OPT_DebugPatcher, OPT_TYPE_BOOLEAN, "debug JIT code patching" },
- { "DebugProperties", OPT_DebugProperties, OPT_TYPE_BOOLEAN, "print debug information for properties" },
- { "DebugStackFrameInfo", OPT_DebugStackFrameInfo, OPT_TYPE_BOOLEAN, "TODO" },
- { "DebugStackTrace", OPT_DebugStackTrace, OPT_TYPE_BOOLEAN, "debug stacktrace creation" },
- { "DebugThreads", OPT_DebugThreads, OPT_TYPE_BOOLEAN, "print debug information for threads" },
-#if defined(ENABLE_DISASSEMBLER)
- { "DisassembleStubs", OPT_DisassembleStubs, OPT_TYPE_BOOLEAN, "disassemble builtin and native stubs when generated" },
-#endif
-#if defined(ENABLE_OPAGENT)
- { "EnableOpagent", OPT_EnableOpagent, OPT_TYPE_BOOLEAN, "enable providing JIT output to Oprofile" },
-#endif
-#if defined(ENABLE_GC_CACAO)
- { "GCDebugRootSet", OPT_GCDebugRootSet, OPT_TYPE_BOOLEAN, "GC: print root-set at collection" },
- { "GCStress", OPT_GCStress, OPT_TYPE_BOOLEAN, "GC: forced collection at every allocation" },
-#endif
-#if defined(ENABLE_INLINING)
- { "Inline", OPT_Inline, OPT_TYPE_BOOLEAN, "enable method inlining" },
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
- { "InlineAll", OPT_InlineAll, OPT_TYPE_BOOLEAN, "use inlining in all compilations" },
- { "InlineCount", OPT_InlineCount, OPT_TYPE_VALUE, "stop inlining after the given number of roots" },
- { "InlineMaxSize", OPT_InlineMaxSize, OPT_TYPE_VALUE, "maximum size for inlined result" },
- { "InlineMinSize", OPT_InlineMinSize, OPT_TYPE_VALUE, "minimum size for inlined result" },
-#endif
-#endif
- { "PrintConfig", OPT_PrintConfig, OPT_TYPE_BOOLEAN, "print VM configuration" },
- { "ProfileGCMemoryUsage", OPT_ProfileGCMemoryUsage, OPT_TYPE_VALUE, "profiles GC memory usage in the given interval, <value> is in seconds (default: 5)" },
- { "ProfileMemoryUsage", OPT_ProfileMemoryUsage, OPT_TYPE_VALUE, "TODO" },
- { "ProfileMemoryUsageGNUPlot", OPT_ProfileMemoryUsageGNUPlot, OPT_TYPE_VALUE, "TODO" },
-#if defined(ENABLE_REPLACEMENT)
- { "TestReplacement", OPT_TestReplacement, OPT_TYPE_BOOLEAN, "activate all replacement points during code generation" },
-#endif
- { "TraceCompilerCalls", OPT_TraceCompilerCalls, OPT_TYPE_BOOLEAN, "trace JIT compiler calls" },
- { "TraceExceptions", OPT_TraceExceptions, OPT_TYPE_BOOLEAN, "trace Exception throwing" },
- { "TraceHPI", OPT_TraceHPI, OPT_TYPE_BOOLEAN, "Trace Host Porting Interface (HPI)" },
-#if defined(ENABLE_INLINING) && !defined(NDEBUG)
- { "TraceInlining", OPT_TraceInlining, OPT_TYPE_VALUE, "trace method inlining with the given verbosity level (default: 1)" },
-#endif
-#if !defined(ENABLE_VMLOG)
- { "TraceJavaCalls", OPT_TraceJavaCalls, OPT_TYPE_BOOLEAN, "trace Java method calls" },
-#endif
- { "TraceJNICalls", OPT_TraceJNICalls, OPT_TYPE_BOOLEAN, "trace JNI method calls" },
- { "TraceJVMCalls", OPT_TraceJVMCalls, OPT_TYPE_BOOLEAN, "trace JVM method calls but omit very frequent ones" },
- { "TraceJVMCallsVerbose", OPT_TraceJVMCallsVerbose, OPT_TYPE_BOOLEAN, "trace all JVM method calls" },
- { "TraceLinkClass", OPT_TraceLinkClass, OPT_TYPE_BOOLEAN, "trace class linking" },
-#if defined(ENABLE_REPLACEMENT)
- { "TraceReplacement", OPT_TraceReplacement, OPT_TYPE_VALUE, "trace on-stack replacement with the given verbosity level (default: 1)" },
-#endif
- { "TraceSubsystemInitialization", OPT_TraceSubsystemInitialization, OPT_TYPE_BOOLEAN, "trace initialization of subsystems" },
- { "TraceTraps", OPT_TraceTraps, OPT_TYPE_BOOLEAN, "trace traps generated by JIT code" },
-#if defined(ENABLE_VMLOG)
- { "Vmlog", OPT_Vmlog, OPT_TYPE_VALUE, "prefix for vmlog trace files (enables vmlog)" },
- { "VmlogStrings", OPT_VmlogStrings, OPT_TYPE_VALUE, "prefix of vmlog string file to load" },
- { "VmlogIgnore", OPT_VmlogIgnore, OPT_TYPE_VALUE, "prefix of vmlog ignore file to load" },
-#endif
-
- /* end marker */
-
- { NULL, -1, -1, NULL }
-};
-
-
-/* options_get *****************************************************************
-
- DOCUMENT ME!!!
-
-*******************************************************************************/
-
-int options_get(opt_struct *opts, JavaVMInitArgs *vm_args)
-{
- char *option;
- int i;
-
- if (opt_index >= vm_args->nOptions)
- return OPT_DONE;
-
- /* get the current option */
-
- option = vm_args->options[opt_index].optionString;
-
- if ((option == NULL) || (option[0] != '-'))
- return OPT_DONE;
-
- for (i = 0; opts[i].name; i++) {
- if (!opts[i].arg) {
- /* boolean option found */
-
- if (strcmp(option + 1, opts[i].name) == 0) {
- opt_index++;
- return opts[i].value;
- }
-
- } else {
- /* parameter option found */
-
- /* with a space between */
-
- if (strcmp(option + 1, opts[i].name) == 0) {
- opt_index++;
-
- if (opt_index < vm_args->nOptions) {
- opt_arg = os_strdup(vm_args->options[opt_index].optionString);
- opt_index++;
- return opts[i].value;
- }
-
- return OPT_ERROR;
-
- } else {
- /* parameter and option have no space between */
-
- /* FIXME: this assumption is plain wrong, hits you if there is a
- * parameter with no argument starting with same letter as param with argument
- * but named after that one, ouch! */
-
- size_t l = os_strlen(opts[i].name);
-
- if (os_strlen(option + 1) > l) {
- if (memcmp(option + 1, opts[i].name, l) == 0) {
- opt_index++;
- opt_arg = os_strdup(option + 1 + l);
- return opts[i].value;
- }
- }
- }
- }
- }
-
- return OPT_ERROR;
-}
-
-
-/* options_xxusage *************************************************************
-
- Print usage message for debugging options.
-
-*******************************************************************************/
-
-static void options_xxusage(void)
-{
- option_t *opt;
- int length;
- int i;
- const char *c;
-
- /* Prevent compiler warning. */
-
- length = 0;
-
- for (opt = options_XX; opt->name != NULL; opt++) {
- printf(" -XX:");
-
- switch (opt->type) {
- case OPT_TYPE_BOOLEAN:
- printf("+%s", opt->name);
- length = os_strlen(" -XX:+") + os_strlen(opt->name);
- break;
-
- case OPT_TYPE_VALUE:
- printf("%s=<value>", opt->name);
- length = os_strlen(" -XX:") + os_strlen(opt->name) +
- os_strlen("=<value>");
- break;
-
- default:
- vm_abort("options_xxusage: unkown option type %d", opt->type);
- }
-
- /* Check if the help fits into one 80-column line.
- Documentation starts at column 29. */
-
- if (length < (29 - 1)) {
- /* Print missing spaces up to column 29. */
-
- for (i = length; i < 29; i++)
- printf(" ");
- }
- else {
- printf("\n");
- printf(" "); /* 29 spaces */
- }
-
- /* Check documentation length. */
-
- length = os_strlen(opt->doc);
-
- if (length < (80 - 29)) {
- printf("%s", opt->doc);
- }
- else {
- for (c = opt->doc, i = 29; *c != 0; c++, i++) {
- /* If we are at the end of the line, break it. */
-
- if (i == 80) {
- printf("\n");
- printf(" "); /* 29 spaces */
- i = 29;
- }
-
- printf("%c", *c);
- }
- }
-
- printf("\n");
- }
-
- /* exit with error code */
-
- exit(1);
-}
-
-
-/* options_xx ******************************************************************
-
- Handle -XX: options.
-
-*******************************************************************************/
-
-void options_xx(JavaVMInitArgs *vm_args)
-{
- const char *name;
- const char *start;
- char *end;
- int length;
- int enable;
- char *value;
- option_t *opt;
- char *filename;
- FILE *file;
- int i;
-
- /* Iterate over all passed options. */
-
- for (i = 0; i < vm_args->nOptions; i++) {
- /* Get the current option. */
-
- name = vm_args->options[i].optionString;
-
- /* Check for help (-XX). */
-
- if (strcmp(name, "-XX") == 0)
- options_xxusage();
-
- /* Check if the option start with -XX. */
-
- start = strstr(name, "-XX:");
-
- if ((start == NULL) || (start != name))
- continue;
-
- /* Check if the option is a boolean option. */
-
- if (name[4] == '+') {
- start = name + 4 + 1;
- enable = 1;
- }
- else if (name[4] == '-') {
- start = name + 4 + 1;
- enable = 0;
- }
- else {
- start = name + 4;
- enable = -1;
- }
-
- /* Search for a '=' in the option name and get the option name
- length and the value of the option. */
-
- end = strchr(start, '=');
-
- if (end == NULL) {
- length = os_strlen(start);
- value = NULL;
- }
- else {
- length = end - start;
- value = end + 1;
- }
-
- /* Search the option in the option array. */
-
- for (opt = options_XX; opt->name != NULL; opt++) {
- if (strncmp(opt->name, start, length) == 0) {
- /* Check if the options passed fits to the type. */
-
- switch (opt->type) {
- case OPT_TYPE_BOOLEAN:
- if ((enable == -1) || (value != NULL))
- options_xxusage();
- break;
- case OPT_TYPE_VALUE:
- if ((enable != -1) || (value == NULL))
- options_xxusage();
- break;
- default:
- vm_abort("options_xx: unknown option type %d for option %s",
- opt->type, opt->name);
- }
-
- break;
- }
- }
-
- /* Process the option. */
-
- switch (opt->value) {
-
- /* Options which must always be available (production options
- in HotSpot). */
-
- case OPT_MaxDirectMemorySize:
- opt_MaxDirectMemorySize = os_atoi(value);
- break;
-
- case OPT_MaxPermSize:
- /* Currently ignored. */
- break;
-
- case OPT_PermSize:
- /* Currently ignored. */
- break;
-
- case OPT_ThreadStackSize:
- /* currently ignored */
- break;
-
- /* Debugging options which can be turned off. */
-
- case OPT_DebugExceptions:
- opt_DebugExceptions = enable;
- break;
-
- case OPT_DebugFinalizer:
- opt_DebugFinalizer = enable;
- break;
-
- case OPT_DebugLocalReferences:
- opt_DebugLocalReferences = enable;
- break;
-
- case OPT_DebugLocks:
- opt_DebugLocks = enable;
- break;
-
- case OPT_DebugPackage:
- opt_DebugPackage = enable;
- break;
-
- case OPT_DebugPatcher:
- opt_DebugPatcher = enable;
- break;
-
- case OPT_DebugProperties:
- opt_DebugProperties = enable;
- break;
-
- case OPT_DebugStackFrameInfo:
- opt_DebugStackFrameInfo = enable;
- break;
-
- case OPT_DebugStackTrace:
- opt_DebugStackTrace = enable;
- break;
-
- case OPT_DebugThreads:
- opt_DebugThreads = enable;
- break;
-
-#if defined(ENABLE_DISASSEMBLER)
- case OPT_DisassembleStubs:
- opt_DisassembleStubs = enable;
- break;
-#endif
-
-#if defined(ENABLE_OPAGENT)
- case OPT_EnableOpagent:
- opt_EnableOpagent = enable;
- break;
-#endif
-
-#if defined(ENABLE_GC_CACAO)
- case OPT_GCDebugRootSet:
- opt_GCDebugRootSet = enable;
- break;
-
- case OPT_GCStress:
- opt_GCStress = enable;
- break;
-#endif
-
-#if defined(ENABLE_INLINING)
- case OPT_Inline:
- opt_Inline = enable;
- break;
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
- case OPT_InlineAll:
- opt_InlineAll = enable;
- break;
-
- case OPT_InlineCount:
- if (value != NULL)
- opt_InlineCount = os_atoi(value);
- break;
-
- case OPT_InlineMaxSize:
- if (value != NULL)
- opt_InlineMaxSize = os_atoi(value);
- break;
-
- case OPT_InlineMinSize:
- if (value != NULL)
- opt_InlineMinSize = os_atoi(value);
- break;
-#endif
-#endif
-
- case OPT_PrintConfig:
- opt_PrintConfig = enable;
- break;
-
- case OPT_ProfileGCMemoryUsage:
- if (value == NULL)
- opt_ProfileGCMemoryUsage = 5;
- else
- opt_ProfileGCMemoryUsage = os_atoi(value);
- break;
-
- case OPT_ProfileMemoryUsage:
- if (value == NULL)
- opt_ProfileMemoryUsage = 5;
- else
- opt_ProfileMemoryUsage = os_atoi(value);
-
-# if defined(ENABLE_STATISTICS)
- /* we also need statistics */
-
- opt_stat = true;
-# endif
- break;
-
- case OPT_ProfileMemoryUsageGNUPlot:
- if (value == NULL)
- filename = "profile.dat";
- else
- filename = value;
-
- file = fopen(filename, "w");
-
- if (file == NULL)
- vm_abort_errno("options_xx: fopen failed");
-
- opt_ProfileMemoryUsageGNUPlot = file;
- break;
-
-#if defined(ENABLE_REPLACEMENT)
- case OPT_TestReplacement:
- opt_TestReplacement = enable;
- break;
-#endif
-
- case OPT_TraceCompilerCalls:
- opt_TraceCompilerCalls = enable;
- break;
-
- case OPT_TraceExceptions:
- opt_TraceExceptions = enable;
- break;
-
- case OPT_TraceHPI:
- opt_TraceHPI = enable;
- break;
-
-#if defined(ENABLE_INLINING) && !defined(NDEBUG)
- case OPT_TraceInlining:
- if (value == NULL)
- opt_TraceInlining = 1;
- else
- opt_TraceInlining = os_atoi(value);
- break;
-#endif
-
- case OPT_TraceJavaCalls:
- opt_verbosecall = enable;
- opt_TraceJavaCalls = enable;
- break;
-
- case OPT_TraceJNICalls:
- opt_TraceJNICalls = enable;
- break;
-
- case OPT_TraceJVMCalls:
- opt_TraceJVMCalls = enable;
- break;
-
- case OPT_TraceJVMCallsVerbose:
- opt_TraceJVMCallsVerbose = enable;
- break;
-
- case OPT_TraceLinkClass:
- opt_TraceLinkClass = enable;
- break;
-
-#if defined(ENABLE_REPLACEMENT)
- case OPT_TraceReplacement:
- if (value == NULL)
- opt_TraceReplacement = 1;
- else
- opt_TraceReplacement = os_atoi(value);
- break;
-#endif
-
- case OPT_TraceSubsystemInitialization:
- opt_TraceSubsystemInitialization = enable;
- break;
-
- case OPT_TraceTraps:
- opt_TraceTraps = enable;
- break;
-
-#if defined(ENABLE_VMLOG)
- case OPT_Vmlog:
- if (value == NULL)
- vmlog_cacao_set_prefix("vmlog");
- else
- vmlog_cacao_set_prefix(value);
- opt_verbosecall = 1;
- opt_TraceJavaCalls = 1;
- break;
-
- case OPT_VmlogStrings:
- if (value != NULL)
- vmlog_cacao_set_stringprefix(value);
- break;
-
- case OPT_VmlogIgnore:
- if (value != NULL)
- vmlog_cacao_set_ignoreprefix(value);
- break;
-#endif
-
- default:
- printf("Unknown -XX option: %s\n", name);
- break;
- }
- }
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/options.h - define global options extern
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _OPTIONS_H
-#define _OPTIONS_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "native/jni.h"
-
-#include "vm/global.h"
-
-
-/* reserved option numbers ****************************************************/
-
-/* define these negative since the other options are an enum */
-
-#define OPT_DONE -1
-#define OPT_ERROR -2
-#define OPT_IGNORE -3
-
-
-typedef struct opt_struct opt_struct;
-
-struct opt_struct {
- const char *name;
- bool arg;
- int value;
-};
-
-
-typedef struct option_t option_t;
-
-struct option_t {
- const char *name;
- int value;
- int type;
- const char *doc;
-};
-
-
-/* global variables ***********************************************************/
-
-extern s4 opt_index;
-extern char *opt_arg;
-
-extern bool opt_foo;
-
-extern bool opt_jit;
-extern bool opt_intrp;
-
-extern bool opt_jar;
-extern bool opt_run;
-
-extern s4 opt_heapmaxsize;
-extern s4 opt_heapstartsize;
-extern s4 opt_stacksize;
-
-extern bool opt_verbose;
-extern bool opt_debugcolor;
-extern bool compileall;
-
-extern bool loadverbose; /* Print debug messages during loading */
-extern bool initverbose; /* Log class initialization */
-
-extern bool opt_verboseclass;
-extern bool opt_verbosegc;
-extern bool opt_verbosejni;
-extern bool opt_verbosecall;
-
-extern bool showmethods;
-extern bool showconstantpool;
-extern bool showutf;
-
-extern char *opt_method;
-extern char *opt_signature;
-
-extern bool compileverbose;
-extern bool showstack;
-
-extern bool opt_showdisassemble;
-extern bool opt_shownops;
-extern bool opt_showddatasegment;
-extern bool opt_showintermediate;
-
-extern bool checkbounds;
-extern bool opt_noieee;
-extern bool checksync;
-#if defined(ENABLE_LOOP)
-extern bool opt_loops;
-#endif
-
-extern bool makeinitializations;
-
-#if defined(ENABLE_STATISTICS)
-extern bool opt_stat;
-extern bool opt_getloadingtime;
-extern bool opt_getcompilingtime;
-#endif
-#if defined(ENABLE_VERIFIER)
-extern bool opt_verify;
-#endif
-
-#if defined(ENABLE_PROFILING)
-extern bool opt_prof;
-extern bool opt_prof_bb;
-#endif
-
-/* optimization options *******************************************************/
-
-#if defined(ENABLE_IFCONV)
-extern bool opt_ifconv;
-#endif
-
-#if defined(ENABLE_LSRA) || defined(ENABLE_SSA)
-extern bool opt_lsra;
-#endif
-#if defined(ENABLE_SSA)
-extern bool opt_ssa_dce; /* enable dead code elemination */
-extern bool opt_ssa_cp; /* enable copy propagation */
-#endif
-
-/* interpreter options ********************************************************/
-
-#if defined(ENABLE_INTRP)
-extern bool opt_no_dynamic;
-extern bool opt_no_replication;
-extern bool opt_no_quicksuper;
-
-extern s4 opt_static_supers;
-extern bool vm_debug;
-#endif
-
-/* debug output filtering options *********************************************/
-
-#if defined(ENABLE_DEBUG_FILTER)
-extern const char *opt_filter_verbosecall_include;
-extern const char *opt_filter_verbosecall_exclude;
-extern const char *opt_filter_show_method;
-#endif
-
-
-/* -XX options ****************************************************************/
-
-/* NOTE: For better readability keep these alpha-sorted. */
-
-/* Options which must always be available (production options in
- HotSpot). */
-
-extern int64_t opt_MaxDirectMemorySize;
-extern int opt_MaxPermSize;
-extern int opt_PermSize;
-extern int opt_ThreadStackSize;
-
-/* Debugging options which can be turned off. */
-
-extern int opt_DebugExceptions;
-extern int opt_DebugFinalizer;
-extern int opt_DebugLocalReferences;
-extern int opt_DebugLocks;
-extern int opt_DebugPatcher;
-extern int opt_DebugPackage;
-extern int opt_DebugProperties;
-extern int opt_DebugStackFrameInfo;
-extern int opt_DebugStackTrace;
-extern int opt_DebugThreads;
-#if defined(ENABLE_DISASSEMBLER)
-extern int opt_DisassembleStubs;
-#endif
-#if defined(ENABLE_OPAGENT)
-extern int opt_EnableOpagent;
-#endif
-#if defined(ENABLE_GC_CACAO)
-extern int opt_GCDebugRootSet;
-extern int opt_GCStress;
-#endif
-#if defined(ENABLE_INLINING)
-extern int opt_Inline;
-#if defined(ENABLE_INLINING_DEBUG) || !defined(NDEBUG)
-extern int opt_InlineAll;
-extern int opt_InlineCount;
-extern int opt_InlineMaxSize;
-extern int opt_InlineMinSize;
-#endif
-#endif
-extern int opt_PrintConfig;
-extern int opt_ProfileGCMemoryUsage;
-extern int opt_ProfileMemoryUsage;
-extern FILE *opt_ProfileMemoryUsageGNUPlot;
-#if defined(ENABLE_REPLACEMENT)
-extern int opt_TestReplacement;
-#endif
-extern int opt_TraceCompilerCalls;
-extern int opt_TraceExceptions;
-extern int opt_TraceHPI;
-#if defined(ENABLE_INLINING) && !defined(NDEBUG)
-extern int opt_TraceInlining;
-#endif
-extern int opt_TraceJavaCalls;
-extern int opt_TraceJNICalls;
-extern int opt_TraceJVMCalls;
-extern int opt_TraceJVMCallsVerbose;
-extern int opt_TraceLinkClass;
-#if defined(ENABLE_REPLACEMENT)
-extern int opt_TraceReplacement;
-#endif
-extern int opt_TraceSubsystemInitialization;
-extern int opt_TraceTraps;
-
-
-/* function prototypes ********************************************************/
-
-int options_get(opt_struct *opts, JavaVMInitArgs *vm_args);
-void options_xx(JavaVMInitArgs *vm_args);
-
-
-/* debug **********************************************************************/
-
-#if !defined(NDEBUG)
-# define TRACESUBSYSTEMINITIALIZATION(text) \
- do { \
- if (opt_TraceSubsystemInitialization) { \
- log_println("[Initializing subsystem: %s]", text); \
- } \
- } while (0)
-#else
-# define TRACESUBSYSTEMINITIALIZATION(text)
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _OPTIONS_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/os.cpp - system (OS) functions
-
- Copyright (C) 2007
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-/* 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>
-# include <mach/host_info.h>
-#endif
-
-/* this should work on BSD */
-/* #include <sys/sysctl.h> */
-
-#include "vm/vm.hpp"
-
-
-/**
- * Maps anonymous memory, even on systems not defining
- * MAP_ANON(YMOUS).
- *
- * @param ...
- */
-void* os::mmap_anonymous(void *addr, size_t len, int prot, int flags)
-{
- void* p;
-
-#if defined(MAP_ANON) || defined(MAP_ANONYMOUS)
- p = mmap(addr, len, prot,
-# if defined(MAP_ANON)
- MAP_ANON | flags,
-# else
- MAP_ANONYMOUS | flags,
-# endif
- -1, 0);
-#else
- int fd;
-
- fd = open("/dev/zero", O_RDONLY, 0);
-
- if (fd == -1)
- vm_abort("os::mmap_anonymous: open failed: %s", os::strerror(errno));
-
- p = mmap(addr, len, prot, flags, fd, 0);
-#endif
-
-#if defined(MAP_FAILED)
- if (p == MAP_FAILED)
-#else
- if (p == (void *) -1)
-#endif
- vm_abort("os::mmap_anonymous: mmap failed: %s", os::strerror(errno));
-
- return p;
-}
-
-
-/**
- * Returns the number of online processors in the system.
- *
- * @return Number of online processors.
- */
-int os::processors_online(void)
-{
-#if defined(_SC_NPROC_ONLN)
-
- return (int) sysconf(_SC_NPROC_ONLN);
-
-#elif defined(_SC_NPROCESSORS_ONLN)
-
- return (int) sysconf(_SC_NPROCESSORS_ONLN);
-
-#elif defined(__DARWIN__)
-
- host_basic_info_data_t hinfo;
- mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
- kern_return_t rc;
-
- rc = host_info(mach_host_self(), HOST_BASIC_INFO,
- (host_info_t) &hinfo, &hinfo_count);
-
- if (rc != KERN_SUCCESS) {
- return -1;
- }
-
- /* XXX michi: according to my infos this should be
- hinfo.max_cpus, can someone please confirm or deny that? */
- return (int) hinfo.avail_cpus;
-
-#elif defined(__FREEBSD__)
-# error IMPLEMENT ME!
-
- /* this should work in BSD */
- /*
- int ncpu, mib[2], rc;
- size_t len;
-
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- len = sizeof(ncpu);
- rc = sysctl(mib, 2, &ncpu, &len, NULL, 0);
-
- return (int32_t) ncpu;
- */
-
-#else
-
- return 1;
-
-#endif
-}
-
-
-// Legacy C interface.
-
-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
- int os_dlclose(void* handle) { return os::dlclose(handle); }
- char* os_dlerror(void) { return os::dlerror(); }
- void* os_dlopen(const char* filename, int flag) { return os::dlopen(filename, flag); }
- void* os_dlsym(void* handle, const char* symbol) { return os::dlsym(handle, symbol); }
- int os_fclose(FILE* fp) { return os::fclose(fp); }
- FILE* os_fopen(const char* path, const char* mode) { return os::fopen(path, mode); }
- 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); }
-
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c++
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/os.hpp - system (OS) functions
-
- Copyright (C) 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _OS_HPP
-#define _OS_HPP
-
-#include "config.h"
-
-/* NOTE: In this file we check for all system headers, because we wrap
- all system calls into inline functions for better portability. */
-
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-#endif
-
-#if defined(HAVE_DLFCN_H)
-# include <dlfcn.h>
-#endif
-
-#if defined(HAVE_ERRNO_H)
-# include <errno.h>
-#endif
-
-#if defined(HAVE_FCNTL_H)
-# include <fcntl.h>
-#endif
-
-#if defined(ENABLE_JRE_LAYOUT)
-# if defined(HAVE_LIBGEN_H)
-# include <libgen.h>
-# endif
-#endif
-
-#if defined(HAVE_STDINT_H)
-# include <stdint.h>
-#endif
-
-#if defined(HAVE_STDIO_H)
-# include <stdio.h>
-#endif
-
-#if defined(HAVE_STDLIB_H)
-# include <stdlib.h>
-#endif
-
-#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(HAVE_SYS_SOCKET_H)
-# include <sys/socket.h>
-#endif
-
-#if defined(HAVE_SYS_STAT_H)
-# include <sys/stat.h>
-#endif
-
-#if defined(HAVE_SYS_TYPES_H)
-# include <sys/types.h>
-#endif
-
-
-#ifdef __cplusplus
-
-// Class wrapping system (OS) functions.
-class os {
-public:
- // Inline functions.
- static inline void abort();
- static inline int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
- static inline int access(const char *pathname, int mode);
- static inline int atoi(const char* nptr);
- static inline void* calloc(size_t nmemb, size_t size);
- static inline int close(int fd);
- static inline int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
-#if defined(ENABLE_JRE_LAYOUT)
- static inline char* dirname(char* path);
-#endif
- static inline int dlclose(void* handle);
- static inline char* dlerror(void);
- static inline void* dlopen(const char* filename, int flag);
- static inline void* dlsym(void* handle, const char* symbol);
- static inline int fclose(FILE* fp);
- static inline FILE* fopen(const char* path, const char* mode);
- static inline size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
- static inline void free(void* ptr);
- static inline int gethostname(char* name, size_t len);
- static inline int getpagesize(void);
- static inline int getsockname(int s, struct sockaddr* name, socklen_t* namelen);
- static inline int getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen);
- static inline int listen(int sockfd, int backlog);
- static inline void* malloc(size_t size);
- static inline void* memcpy(void* dest, const void* src, size_t n);
- static inline void* memset(void* s, int c, size_t n);
- static inline int mprotect(void* addr, size_t len, int prot);
- static inline int scandir(const char* dir, struct dirent*** namelist, int(*filter)(const struct dirent*), int(*compar)(const void*, const void*));
- static inline int setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen);
- static inline int shutdown(int s, int how);
- static inline int socket(int domain, int type, int protocol);
- static inline int stat(const char* path, struct stat* buf);
- static inline char* strcat(char* dest, const char* src);
- static inline char* strcpy(char* dest, const char* src);
- static inline char* strdup(const char* s);
- static inline size_t strlen(const char* s);
- static inline char* strerror(int errnum);
-
- static void* mmap_anonymous(void *addr, size_t len, int prot, int flags);
- static int processors_online(void);
-};
-
-
-inline void os::abort(void)
-{
-#if defined(HAVE_ABORT)
- ::abort();
-#else
-# error abort not available
-#endif
-}
-
-inline int os::accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
-{
-#if defined(HAVE_ACCEPT)
- return ::accept(sockfd, addr, addrlen);
-#else
-# error accept not available
-#endif
-}
-
-inline int os::access(const char* pathname, int mode)
-{
-#if defined(HAVE_ACCESS)
- return ::access(pathname, mode);
-#else
-# error access not available
-#endif
-}
-
-inline int os::atoi(const char* nptr)
-{
-#if defined(HAVE_ATOI)
- return ::atoi(nptr);
-#else
-# error atoi not available
-#endif
-}
-
-inline void* os::calloc(size_t nmemb, size_t size)
-{
-#if defined(HAVE_CALLOC)
- return ::calloc(nmemb, size);
-#else
-# error calloc not available
-#endif
-}
-
-inline int os::close(int fd)
-{
-#if defined(HAVE_CLOSE)
- return ::close(fd);
-#else
-# error close not available
-#endif
-}
-
-inline int os::connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen)
-{
-#if defined(HAVE_CONNECT)
- return ::connect(sockfd, serv_addr, addrlen);
-#else
-# error connect not available
-#endif
-}
-
-#if defined(ENABLE_JRE_LAYOUT)
-inline char* os::dirname(char* path)
-{
-#if defined(HAVE_DIRNAME)
- return ::dirname(path);
-#else
-# error dirname not available
-#endif
-}
-#endif
-
-inline int os::dlclose(void* handle)
-{
-#if defined(HAVE_DLCLOSE)
- return ::dlclose(handle);
-#else
-# error dlclose not available
-#endif
-}
-
-inline char* os::dlerror(void)
-{
-#if defined(HAVE_DLERROR)
- return ::dlerror();
-#else
-# error dlerror not available
-#endif
-}
-
-inline void* os::dlopen(const char* filename, int flag)
-{
-#if defined(HAVE_DLOPEN)
- return ::dlopen(filename, flag);
-#else
-# error dlopen not available
-#endif
-}
-
-inline void* os::dlsym(void* handle, const char* symbol)
-{
-#if defined(HAVE_DLSYM)
- return ::dlsym(handle, symbol);
-#else
-# error dlsym not available
-#endif
-}
-
-inline int os::fclose(FILE* fp)
-{
-#if defined(HAVE_FCLOSE)
- return ::fclose(fp);
-#else
-# error fclose not available
-#endif
-}
-
-inline FILE* os::fopen(const char* path, const char* mode)
-{
-#if defined(HAVE_FOPEN)
- return ::fopen(path, mode);
-#else
-# error fopen not available
-#endif
-}
-
-inline size_t os::fread(void* ptr, size_t size, size_t nmemb, FILE* stream)
-{
-#if defined(HAVE_FREAD)
- return ::fread(ptr, size, nmemb, stream);
-#else
-# error fread not available
-#endif
-}
-
-inline void os::free(void* ptr)
-{
-#if defined(HAVE_FREE)
- ::free(ptr);
-#else
-# error free not available
-#endif
-}
-
-inline static int system_fsync(int fd)
-{
-#if defined(HAVE_FSYNC)
- return fsync(fd);
-#else
-# error fsync not available
-#endif
-}
-
-inline static int system_ftruncate(int fd, off_t length)
-{
-#if defined(HAVE_FTRUNCATE)
- return ftruncate(fd, length);
-#else
-# error ftruncate not available
-#endif
-}
-
-inline int os::gethostname(char* name, size_t len)
-{
-#if defined(HAVE_GETHOSTNAME)
- return ::gethostname(name, len);
-#else
-# error gethostname not available
-#endif
-}
-
-inline int os::getpagesize(void)
-{
-#if defined(HAVE_GETPAGESIZE)
- return ::getpagesize();
-#else
-# error getpagesize not available
-#endif
-}
-
-inline int os::getsockname(int s, struct sockaddr* name, socklen_t* namelen)
-{
-#if defined(HAVE_GETSOCKNAME)
- return ::getsockname(s, name, namelen);
-#else
-# error getsockname not available
-#endif
-}
-
-inline int os::getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen)
-{
-#if defined(HAVE_GETSOCKOPT)
- return ::getsockopt(s, level, optname, optval, optlen);
-#else
-# error getsockopt not available
-#endif
-}
-
-inline int os::listen(int sockfd, int backlog)
-{
-#if defined(HAVE_LISTEN)
- return ::listen(sockfd, backlog);
-#else
-# error listen not available
-#endif
-}
-
-inline static off_t system_lseek(int fildes, off_t offset, int whence)
-{
-#if defined(HAVE_LSEEK)
- return lseek(fildes, offset, whence);
-#else
-# error lseek not available
-#endif
-}
-
-inline void* os::malloc(size_t size)
-{
-#if defined(HAVE_MALLOC)
- return ::malloc(size);
-#else
-# error malloc not available
-#endif
-}
-
-inline void* os::memcpy(void* dest, const void* src, size_t n)
-{
-#if defined(HAVE_MEMCPY)
- return ::memcpy(dest, src, n);
-#else
-# error memcpy not available
-#endif
-}
-
-inline void* os::memset(void* s, int c, size_t n)
-{
-#if defined(HAVE_MEMSET)
- return ::memset(s, c, n);
-#else
-# error memset not available
-#endif
-}
-
-inline int os::mprotect(void* addr, size_t len, int prot)
-{
-#if defined(HAVE_MPROTECT)
- return ::mprotect(addr, len, prot);
-#else
-# error mprotect not available
-#endif
-}
-
-inline static int system_open(const char *pathname, int flags, mode_t mode)
-{
-#if defined(HAVE_OPEN)
- return open(pathname, flags, mode);
-#else
-# error open not available
-#endif
-}
-
-inline static ssize_t system_read(int fd, void *buf, size_t count)
-{
-#if defined(HAVE_READ)
- return read(fd, buf, count);
-#else
-# error read not available
-#endif
-}
-
-inline static void *system_realloc(void *ptr, size_t size)
-{
-#if defined(HAVE_REALLOC)
- return realloc(ptr, size);
-#else
-# error realloc not available
-#endif
-}
-
-inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
-/*
-#elif defined(__SOLARIS__)
-inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **))
-#elif defined(__IRIX__)
-inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(dirent_t *), int(*compar)(dirent_t **, dirent_t **))
-#else
-inline int os::scandir(const char *dir, struct dirent ***namelist, int(*filter)(struct dirent *), int(*compar)(const void *, const void *))
-#endif
-*/
-{
-#if defined(HAVE_SCANDIR)
-# if defined(__LINUX__)
- return ::scandir(dir, namelist, filter, compar);
-# else
- return ::scandir(dir, namelist, (int (*)(struct dirent*)) filter, compar);
-# endif
-#else
-# error scandir not available
-#endif
-}
-
-inline int os::setsockopt(int s, int level, int optname, const void* optval, socklen_t optlen)
-{
-#if defined(HAVE_SETSOCKOPT)
- return ::setsockopt(s, level, optname, optval, optlen);
-#else
-# error setsockopt not available
-#endif
-}
-
-inline int os::shutdown(int s, int how)
-{
-#if defined(HAVE_SHUTDOWN)
- return ::shutdown(s, how);
-#else
-# error shutdown not available
-#endif
-}
-
-inline int os::socket(int domain, int type, int protocol)
-{
-#if defined(HAVE_SOCKET)
- return ::socket(domain, type, protocol);
-#else
-# error socket not available
-#endif
-}
-
-inline int os::stat(const char* path, struct stat* buf)
-{
-#if defined(HAVE_STAT)
- return ::stat(path, buf);
-#else
-# error stat not available
-#endif
-}
-
-inline char* os::strcat(char* dest, const char* src)
-{
-#if defined(HAVE_STRCAT)
- return ::strcat(dest, src);
-#else
-# error strcat not available
-#endif
-}
-
-inline char* os::strcpy(char* dest, const char* src)
-{
-#if defined(HAVE_STRCPY)
- return ::strcpy(dest, src);
-#else
-# error strcpy not available
-#endif
-}
-
-inline char* os::strdup(const char* s)
-{
-#if defined(HAVE_STRDUP)
- return ::strdup(s);
-#else
-# error strdup not available
-#endif
-}
-
-inline char* os::strerror(int errnum)
-{
-#if defined(HAVE_STRERROR)
- return ::strerror(errnum);
-#else
-# error strerror not available
-#endif
-}
-
-inline size_t os::strlen(const char* s)
-{
-#if defined(HAVE_STRLEN)
- return ::strlen(s);
-#else
-# error strlen not available
-#endif
-}
-
-inline static ssize_t system_write(int fd, const void *buf, size_t count)
-{
-#if defined(HAVE_WRITE)
- return write(fd, buf, count);
-#else
-# error write not available
-#endif
-}
-
-#else
-
-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);
-int os_dlclose(void* handle);
-char* os_dlerror(void);
-void* os_dlopen(const char* filename, int flag);
-void* os_dlsym(void* handle, const char* symbol);
-int os_fclose(FILE* fp);
-FILE* os_fopen(const char* path, const char* mode);
-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);
-
-#endif
-
-#endif // _OS_HPP
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c++
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/primitivecore.c - core functions for primitive types
-
- Copyright (C) 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdint.h>
-
-#include "vm/global.h"
-#include "vm/primitive.hpp"
-#include "vm/vm.hpp"
-
-#include "vmcore/class.h"
-#include "vmcore/globals.hpp"
-#include "vmcore/options.h"
-#include "vmcore/utf8.h"
-
-
-/* primitivetype_table *********************************************************
-
- Structure for primitive classes: contains the class for wrapping
- the primitive type, the primitive class, the name of the class for
- wrapping, the one character type signature and the name of the
- primitive class.
-
- CAUTION: Don't change the order of the types. This table is indexed
- by the ARRAYTYPE_ constants (except ARRAYTYPE_OBJECT).
-
-*******************************************************************************/
-
-primitivetypeinfo primitivetype_table[PRIMITIVETYPE_COUNT] = {
- { "int" , NULL, NULL, NULL, "java/lang/Integer", 'I', "[I", NULL },
- { "long" , NULL, NULL, NULL, "java/lang/Long", 'J', "[J", NULL },
- { "float" , NULL, NULL, NULL, "java/lang/Float", 'F', "[F", NULL },
- { "double" , NULL, NULL, NULL, "java/lang/Double", 'D', "[D", NULL },
- { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
- { "byte" , NULL, NULL, NULL, "java/lang/Byte", 'B', "[B", NULL },
- { "char" , NULL, NULL, NULL, "java/lang/Character", 'C', "[C", NULL },
- { "short" , NULL, NULL, NULL, "java/lang/Short", 'S', "[S", NULL },
- { "boolean" , NULL, NULL, NULL, "java/lang/Boolean", 'Z', "[Z", NULL },
- { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
-#if defined(ENABLE_JAVASE)
- { "void" , NULL, NULL, NULL, "java/lang/Void", 'V', NULL, NULL }
-#else
- { NULL , NULL, NULL, NULL, NULL, 0 , NULL, NULL },
-#endif
-};
-
-
-/* primitive_init **************************************************************
-
- Fill the primitive type table with the primitive-type classes,
- array-classes and wrapper classes. This is important in the VM
- startup.
-
- We split this primitive-type table initialization because of
- annotations in the bootstrap classes.
-
- But we may get a problem if we have annotations in:
-
- java/lang/Object
- java/lang/Cloneable
- java/io/Serializable
-
- Also see: loader_preinit and linker_preinit.
-
-*******************************************************************************/
-
-void primitive_init(void)
-{
- utf *name;
- classinfo *c;
- utf *u;
- classinfo *ac;
- int i;
-
- TRACESUBSYSTEMINITIALIZATION("primitive_init");
-
- /* Load and link primitive-type classes and array-classes. */
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
- /* Skip dummy entries. */
-
- if (primitivetype_table[i].cname == NULL)
- continue;
-
- /* create UTF-8 name */
-
- name = utf_new_char(primitivetype_table[i].cname);
-
- primitivetype_table[i].name = name;
-
- /* create primitive class */
-
- c = class_create_classinfo(name);
-
- /* Primitive type classes don't have a super class. */
-
- c->super = NULL;
-
- /* set flags and mark it as primitive class */
-
- c->flags = ACC_PUBLIC | ACC_FINAL | ACC_ABSTRACT | ACC_CLASS_PRIMITIVE;
-
- /* prevent loader from loading primitive class */
-
- c->state |= CLASS_LOADED;
-
- /* INFO: don't put primitive classes into the classcache */
-
- if (!link_class(c))
- vm_abort("linker_init: linking failed");
-
- /* Just to be sure. */
-
- assert(c->state & CLASS_LOADED);
- assert(c->state & CLASS_LINKED);
-
- primitivetype_table[i].class_primitive = c;
-
- /* Create primitive array class. */
-
- if (primitivetype_table[i].arrayname != NULL) {
- u = utf_new_char(primitivetype_table[i].arrayname);
- ac = class_create_classinfo(u);
- ac = load_newly_created_array(ac, NULL);
-
- if (ac == NULL)
- vm_abort("primitive_init: loading failed");
-
- assert(ac->state & CLASS_LOADED);
-
- if (!link_class(ac))
- vm_abort("primitive_init: linking failed");
-
- /* Just to be sure. */
-
- assert(ac->state & CLASS_LOADED);
- assert(ac->state & CLASS_LINKED);
-
- primitivetype_table[i].arrayclass = ac;
- }
- }
-
- /* We use two for-loops to have the array-classes already in the
- primitive-type table (hint: annotations in wrapper-classes). */
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
- /* Skip dummy entries. */
-
- if (primitivetype_table[i].cname == NULL)
- continue;
-
- /* Create class for wrapping the primitive type. */
-
- u = utf_new_char(primitivetype_table[i].wrapname);
- c = load_class_bootstrap(u);
-
- if (c == NULL)
- vm_abort("primitive_init: loading failed");
-
- if (!link_class(c))
- vm_abort("primitive_init: linking failed");
-
- /* Just to be sure. */
-
- assert(c->state & CLASS_LOADED);
- assert(c->state & CLASS_LINKED);
-
- primitivetype_table[i].class_wrap = c;
- }
-}
-
-
-/* primitive_postinit **********************************************************
-
- Finish the primitive-type table initialization. In this step we
- set the vftbl of the primitive-type classes.
-
- This is necessary because java/lang/Class is loaded and linked
- after the primitive types have been linked.
-
- We have to do that in an extra function, as the primitive types are
- not stored in the classcache.
-
-*******************************************************************************/
-
-void primitive_postinit(void)
-{
- classinfo *c;
- int i;
-
- TRACESUBSYSTEMINITIALIZATION("primitive_postinit");
-
- assert(class_java_lang_Class);
- assert(class_java_lang_Class->vftbl);
-
- for (i = 0; i < PRIMITIVETYPE_COUNT; i++) {
- /* Skip dummy entries. */
-
- if (primitivetype_table[i].cname == NULL)
- continue;
-
- c = primitivetype_table[i].class_primitive;
-
- c->object.header.vftbl = class_java_lang_Class->vftbl;
- }
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/references.h - references to classes/fields/methods
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-#ifndef _REFERENCES_H_
-#define _REFERENCES_H_
-
-/* forward typedefs ***********************************************************/
-
-typedef struct constant_classref constant_classref;
-typedef struct constant_FMIref constant_FMIref;
-
-
-/* constant_classref **********************************************************/
-
-struct constant_classref {
- void *pseudo_vftbl; /* for distinguishing it from classinfo */
- struct classinfo *referer; /* class containing the reference */
- struct utf *name; /* name of the class refered to */
-};
-
-
-/* classref_or_classinfo ******************************************************/
-
-typedef union classref_or_classinfo {
- constant_classref *ref; /* a symbolic class reference */
- struct classinfo *cls; /* an already loaded class */
- void *any; /* used for general access (x != NULL,...) */
-} classref_or_classinfo;
-
-
-/* parseddesc_t ***************************************************************/
-
-typedef union parseddesc {
- struct typedesc *fd; /* parsed field descriptor */
- struct methoddesc *md; /* parsed method descriptor */
- void *any; /* used for simple test against NULL */
-} parseddesc_t;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/descriptor.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
-#include "vmcore/utf8.h"
-
-
-/*----------------------------------------------------------------------------*/
-/* References */
-/* */
-/* This header files defines the following types used for references to */
-/* classes/methods/fields and descriptors: */
-/* */
-/* classinfo * a loaded class */
-/* constant_classref a symbolic reference */
-/* classref_or_classinfo a loaded class or a symbolic reference */
-/* */
-/* constant_FMIref a symb. ref. to a field/method/intf.method */
-/* */
-/* typedesc * describes a field type */
-/* methoddesc * descrives a method type */
-/* parseddesc describes a field type or a method type */
-/*----------------------------------------------------------------------------*/
-
-/* structs ********************************************************************/
-
-/* constant_FMIref ************************************************************/
-
-struct constant_FMIref{ /* Fieldref, Methodref and InterfaceMethodref */
- union {
- s4 index; /* used only within the loader */
- constant_classref *classref; /* class having this field/meth./intfm. */
- fieldinfo *field; /* resolved field */
- methodinfo *method; /* resolved method */
- } p;
- utf *name; /* field/method/interfacemethod name */
- utf *descriptor; /* field/method/intfmeth. type descriptor string */
- parseddesc_t parseddesc; /* parsed descriptor */
-};
-
-
-/* macros *********************************************************************/
-
-/* a value that never occurrs in classinfo.header.vftbl */
-#define CLASSREF_PSEUDO_VFTBL ((void *) 1)
-
-/* macro for testing if a classref_or_classinfo is a classref */
-/* `reforinfo` is only evaluated once */
-#define IS_CLASSREF(reforinfo) \
- ((reforinfo).ref->pseudo_vftbl == CLASSREF_PSEUDO_VFTBL)
-
-/* macro for testing if a constant_FMIref has been resolved */
-/* `fmiref` is only evaluated once */
-#define IS_FMIREF_RESOLVED(fmiref) \
- ((fmiref)->p.classref->pseudo_vftbl != CLASSREF_PSEUDO_VFTBL)
-
-/* the same as IS_CLASSREF, but also check against NULL */
-#define IS_XCLASSREF(reforinfo) \
- ((reforinfo).any && IS_CLASSREF(reforinfo))
-
-/* macro for casting a classref/classinfo * to a classref_or_classinfo */
-#define CLASSREF_OR_CLASSINFO(value) \
- (*((classref_or_classinfo *)(&(value))))
-
-/* macro for accessing the name of a classref/classinfo */
-#define CLASSREF_OR_CLASSINFO_NAME(value) \
- (IS_CLASSREF(value) ? (value).ref->name : (value).cls->name)
-
-/* macro for accessing the class name of a method reference */
-#define METHODREF_CLASSNAME(fmiref) \
- (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.method->clazz->name \
- : (fmiref)->p.classref->name)
-
-/* macro for accessing the class name of a method reference */
-#define FIELDREF_CLASSNAME(fmiref) \
- (IS_FMIREF_RESOLVED(fmiref) ? (fmiref)->p.field->clazz->name \
- : (fmiref)->p.classref->name)
-
-/* initialize a constant_classref with referer `ref` and name `classname` */
-
-#define CLASSREF_INIT(c,ref,classname) \
- do { \
- (c).pseudo_vftbl = CLASSREF_PSEUDO_VFTBL; \
- (c).referer = (ref); \
- (c).name = (classname); \
- } while (0)
-
-#endif /* _REFERENCES_H_ */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
-
+++ /dev/null
-/* src/vmcore/rt-timing.c - POSIX real-time timing utilities
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <time.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "vm/global.h"
-
-#include "vmcore/rt-timing.h"
-
-
-struct rt_timing_stat {
- int index;
- int totalindex;
- const char *name;
-};
-
-static struct rt_timing_stat rt_timing_stat_defs[] = {
- { RT_TIMING_JIT_CHECKS ,RT_TIMING_JIT_TOTAL , "checks at beginning" },
- { RT_TIMING_JIT_PARSE ,RT_TIMING_JIT_TOTAL , "parse" },
- { RT_TIMING_JIT_STACK ,RT_TIMING_JIT_TOTAL , "analyse_stack" },
- { RT_TIMING_JIT_TYPECHECK ,RT_TIMING_JIT_TOTAL , "typecheck" },
- { RT_TIMING_JIT_LOOP ,RT_TIMING_JIT_TOTAL , "loop" },
- { RT_TIMING_JIT_IFCONV ,RT_TIMING_JIT_TOTAL , "if conversion" },
- { RT_TIMING_JIT_ALLOC ,RT_TIMING_JIT_TOTAL , "register allocation" },
- { RT_TIMING_JIT_RPLPOINTS ,RT_TIMING_JIT_TOTAL , "replacement point generation" },
- { RT_TIMING_JIT_CODEGEN ,RT_TIMING_JIT_TOTAL , "codegen" },
- { RT_TIMING_JIT_TOTAL ,-1 , "total compile time" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_LINK_RESOLVE ,RT_TIMING_LINK_TOTAL, "link: resolve superclass/superinterfaces"},
- { RT_TIMING_LINK_C_VFTBL ,RT_TIMING_LINK_TOTAL, "link: compute vftbl length"},
- { RT_TIMING_LINK_ABSTRACT ,RT_TIMING_LINK_TOTAL, "link: handle abstract methods"},
- { RT_TIMING_LINK_C_IFTBL ,RT_TIMING_LINK_TOTAL, "link: compute interface table"},
- { RT_TIMING_LINK_F_VFTBL ,RT_TIMING_LINK_TOTAL, "link: fill vftbl"},
- { RT_TIMING_LINK_OFFSETS ,RT_TIMING_LINK_TOTAL, "link: set offsets"},
- { RT_TIMING_LINK_F_IFTBL ,RT_TIMING_LINK_TOTAL, "link: fill interface table"},
- { RT_TIMING_LINK_FINALIZER ,RT_TIMING_LINK_TOTAL, "link: set finalizer"},
- { RT_TIMING_LINK_EXCEPTS ,RT_TIMING_LINK_TOTAL, "link: resolve exception classes"},
- { RT_TIMING_LINK_SUBCLASS ,RT_TIMING_LINK_TOTAL, "link: re-calculate subclass indices"},
- { RT_TIMING_LINK_TOTAL ,-1 , "total link time" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_LOAD_CHECKS ,RT_TIMING_LOAD_TOTAL, "load: initial checks"},
- { RT_TIMING_LOAD_NDPOOL ,RT_TIMING_LOAD_TOTAL, "load: new descriptor pool"},
- { RT_TIMING_LOAD_CPOOL ,RT_TIMING_LOAD_TOTAL, "load: load constant pool"},
- { RT_TIMING_LOAD_SETUP ,RT_TIMING_LOAD_TOTAL, "load: class setup"},
- { RT_TIMING_LOAD_FIELDS ,RT_TIMING_LOAD_TOTAL, "load: load fields"},
- { RT_TIMING_LOAD_METHODS ,RT_TIMING_LOAD_TOTAL, "load: load methods"},
- { RT_TIMING_LOAD_CLASSREFS ,RT_TIMING_LOAD_TOTAL, "load: create classrefs"},
- { RT_TIMING_LOAD_DESCS ,RT_TIMING_LOAD_TOTAL, "load: allocate descriptors"},
- { RT_TIMING_LOAD_SETREFS ,RT_TIMING_LOAD_TOTAL, "load: set classrefs"},
- { RT_TIMING_LOAD_PARSEFDS ,RT_TIMING_LOAD_TOTAL, "load: parse field descriptors"},
- { RT_TIMING_LOAD_PARSEMDS ,RT_TIMING_LOAD_TOTAL, "load: parse method descriptors"},
- { RT_TIMING_LOAD_PARSECP ,RT_TIMING_LOAD_TOTAL, "load: parse descriptors in constant pool"},
- { RT_TIMING_LOAD_VERIFY ,RT_TIMING_LOAD_TOTAL, "load: verifier checks"},
- { RT_TIMING_LOAD_ATTRS ,RT_TIMING_LOAD_TOTAL, "load: load attributes"},
- { RT_TIMING_LOAD_TOTAL ,-1 , "total load time (from classbuffer)"},
- { -1 ,-1 , "" },
-
- { RT_TIMING_LOAD_BOOT_LOOKUP,-1 , "boot: lookup in classcache"},
- { RT_TIMING_LOAD_BOOT_ARRAY ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load array classes"},
- { RT_TIMING_LOAD_BOOT_SUCK ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: suck class files"},
- { RT_TIMING_LOAD_BOOT_LOAD ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: load from class buffer"},
- { RT_TIMING_LOAD_BOOT_CACHE ,RT_TIMING_LOAD_BOOT_TOTAL, "boot: store in classcache"},
- { RT_TIMING_LOAD_BOOT_TOTAL ,-1 , "total bootstrap loader time"},
- { -1 ,-1 , "" },
-
- { RT_TIMING_LOAD_CL_LOOKUP ,-1 , "classloader: lookup in classcache" },
- { RT_TIMING_LOAD_CL_PREPARE ,-1 , "classloader: prepare loader call" },
- { RT_TIMING_LOAD_CL_JAVA ,-1 , "classloader: loader Java code" },
- { RT_TIMING_LOAD_CL_CACHE ,-1 , "classloader: store in classcache" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_NEW_OBJECT ,-1 , "builtin_new time" },
- { RT_TIMING_NEW_ARRAY ,-1 , "builtin_newarray time" },
- { -1 ,-1 , "" },
-
- { RT_TIMING_GC_ALLOC ,-1 , "heap allocation time" },
-#if defined(ENABLE_GC_CACAO)
- { RT_TIMING_GC_SUSPEND ,RT_TIMING_GC_TOTAL , "gc: suspending threads" },
- { RT_TIMING_GC_ROOTSET1 ,RT_TIMING_GC_TOTAL , "gc: rootset finding" },
- { RT_TIMING_GC_MARK ,RT_TIMING_GC_TOTAL , "gc: marking phase" },
- { RT_TIMING_GC_COMPACT ,RT_TIMING_GC_TOTAL , "gc: compaction phase" },
- { RT_TIMING_GC_ROOTSET2 ,RT_TIMING_GC_TOTAL , "gc: rootset writeback" },
- { RT_TIMING_GC_TOTAL ,-1 , "total garbage collection time" },
-#endif
- { -1 ,-1 , "" },
-
-#if defined(ENABLE_REPLACEMENT)
- { RT_TIMING_REPLACE ,-1 , "replacement" },
- { -1 ,-1 , "" },
-#endif
-
- { RT_TIMING_1 ,-1 , "temporary timer 1" },
- { RT_TIMING_2 ,-1 , "temporary timer 2" },
- { RT_TIMING_3 ,-1 , "temporary timer 3" },
- { RT_TIMING_4 ,-1 , "temporary timer 4" },
- { -1 ,-1 , "" },
-
- { 0 ,-1 , NULL }
-};
-
-static long long rt_timing_sum[RT_TIMING_N] = { 0 };
-
-void rt_timing_gettime(struct timespec *ts)
-{
- if (clock_gettime(CLOCK_THREAD_CPUTIME_ID,ts) != 0) {
- fprintf(stderr,"could not get time by clock_gettime: %s\n",strerror(errno));
- abort();
- }
-}
-
-long rt_timing_diff_usec(struct timespec *a,struct timespec *b)
-{
- long diff;
- time_t atime;
-
- diff = (b->tv_nsec - a->tv_nsec) / 1000;
- atime = a->tv_sec;
- while (atime < b->tv_sec) {
- atime++;
- diff += 1000000;
- }
- return diff;
-}
-
-void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index)
-{
- long diff;
-
- diff = rt_timing_diff_usec(a,b);
- rt_timing_sum[index] += diff;
-}
-
-void rt_timing_print_time_stats(FILE *file)
-{
- struct rt_timing_stat *stats;
- double total;
-
- for (stats = rt_timing_stat_defs; stats->name; ++stats) {
- if (stats->index < 0) {
- fprintf(file,"%s\n",stats->name);
- continue;
- }
-
- if (stats->totalindex >= 0) {
- total = rt_timing_sum[stats->totalindex];
- fprintf(file,"%12lld usec %3.0f%% %s\n",
- rt_timing_sum[stats->index],
- (total != 0.0) ? rt_timing_sum[stats->index] / total * 100.0 : 0.0,
- stats->name);
- }
- else {
- fprintf(file,"%12lld usec %s\n",
- rt_timing_sum[stats->index],
- stats->name);
- }
- }
-}
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/rt-timing.h - POSIX real-time timing utilities
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _RT_TIMING_H
-#define _RT_TIMING_H
-
-#include "config.h"
-
-#if defined(ENABLE_RT_TIMING)
-
-#include <time.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "vm/global.h"
-
-
-#define RT_TIMING_GET_TIME(ts) \
- rt_timing_gettime(&(ts));
-
-#define RT_TIMING_TIME_DIFF(a,b,index) \
- rt_timing_time_diff(&(a),&(b),(index));
-
-#define RT_TIMING_JIT_CHECKS 0
-#define RT_TIMING_JIT_PARSE 1
-#define RT_TIMING_JIT_STACK 2
-#define RT_TIMING_JIT_TYPECHECK 3
-#define RT_TIMING_JIT_LOOP 4
-#define RT_TIMING_JIT_IFCONV 5
-#define RT_TIMING_JIT_ALLOC 6
-#define RT_TIMING_JIT_RPLPOINTS 7
-#define RT_TIMING_JIT_CODEGEN 8
-#define RT_TIMING_JIT_TOTAL 9
-
-#define RT_TIMING_LINK_RESOLVE 10
-#define RT_TIMING_LINK_C_VFTBL 11
-#define RT_TIMING_LINK_ABSTRACT 12
-#define RT_TIMING_LINK_C_IFTBL 13
-#define RT_TIMING_LINK_F_VFTBL 14
-#define RT_TIMING_LINK_OFFSETS 15
-#define RT_TIMING_LINK_F_IFTBL 16
-#define RT_TIMING_LINK_FINALIZER 17
-#define RT_TIMING_LINK_EXCEPTS 18
-#define RT_TIMING_LINK_SUBCLASS 19
-#define RT_TIMING_LINK_TOTAL 20
-
-#define RT_TIMING_LOAD_CHECKS 21
-#define RT_TIMING_LOAD_NDPOOL 22
-#define RT_TIMING_LOAD_CPOOL 23
-#define RT_TIMING_LOAD_SETUP 24
-#define RT_TIMING_LOAD_FIELDS 25
-#define RT_TIMING_LOAD_METHODS 26
-#define RT_TIMING_LOAD_CLASSREFS 27
-#define RT_TIMING_LOAD_DESCS 28
-#define RT_TIMING_LOAD_SETREFS 29
-#define RT_TIMING_LOAD_PARSEFDS 30
-#define RT_TIMING_LOAD_PARSEMDS 31
-#define RT_TIMING_LOAD_PARSECP 32
-#define RT_TIMING_LOAD_VERIFY 33
-#define RT_TIMING_LOAD_ATTRS 34
-#define RT_TIMING_LOAD_TOTAL 35
-
-#define RT_TIMING_LOAD_BOOT_LOOKUP 36
-#define RT_TIMING_LOAD_BOOT_ARRAY 37
-#define RT_TIMING_LOAD_BOOT_SUCK 38
-#define RT_TIMING_LOAD_BOOT_LOAD 39
-#define RT_TIMING_LOAD_BOOT_CACHE 40
-#define RT_TIMING_LOAD_BOOT_TOTAL 41
-
-#define RT_TIMING_LOAD_CL_LOOKUP 42
-#define RT_TIMING_LOAD_CL_PREPARE 43
-#define RT_TIMING_LOAD_CL_JAVA 44
-#define RT_TIMING_LOAD_CL_CACHE 45
-
-#define RT_TIMING_NEW_OBJECT 46
-#define RT_TIMING_NEW_ARRAY 47
-
-#define RT_TIMING_GC_ALLOC 48
-#define RT_TIMING_GC_SUSPEND 49
-#define RT_TIMING_GC_ROOTSET1 50
-#define RT_TIMING_GC_MARK 51
-#define RT_TIMING_GC_COMPACT 52
-#define RT_TIMING_GC_ROOTSET2 53
-#define RT_TIMING_GC_TOTAL 54
-
-#define RT_TIMING_REPLACE 55
-
-#define RT_TIMING_1 56
-#define RT_TIMING_2 57
-#define RT_TIMING_3 58
-#define RT_TIMING_4 59
-
-#define RT_TIMING_N 60
-
-void rt_timing_gettime(struct timespec *ts);
-
-void rt_timing_time_diff(struct timespec *a,struct timespec *b,int index);
-
-long rt_timing_diff_usec(struct timespec *a,struct timespec *b);
-
-void rt_timing_print_time_stats(FILE *file);
-
-#else /* !defined(ENABLE_RT_TIMING) */
-
-#define RT_TIMING_GET_TIME(ts)
-#define RT_TIMING_TIME_DIFF(a,b,index)
-
-#endif /* defined(ENABLE_RT_TIMING) */
-
-#endif /* _RT_TIMING_H */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/stackmap.c - class attribute StackMapTable
-
- Copyright (C) 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "vm/exceptions.hpp"
-
-#include "vmcore/class.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/stackmap.h"
-#include "vmcore/statistics.h"
-#include "vmcore/suck.h"
-
-
-/* stackmap_get_verification_type_info *****************************************
-
- union verification_type_info {
- Top_variable_info;
- Integer_variable_info;
- Float_variable_info;
- Long_variable_info;
- Double_variable_info;
- Null_variable_info;
- UninitializedThis_variable_info;
- Object_variable_info;
- Uninitialized_variable_info;
- }
-
- Top_variable_info {
- u1 tag = ITEM_Top; // 0
- }
-
- Integer_variable_info {
- u1 tag = ITEM_Integer; // 1
- }
-
- Float_variable_info {
- u1 tag = ITEM_Float; // 2
- }
-
- Long_variable_info {
- u1 tag = ITEM_Long; // 4
- }
-
- Double_variable_info {
- u1 tag = ITEM_Double; // 3
- }
-
- Null_variable_info {
- u1 tag = ITEM_Null; // 5
- }
-
- UninitializedThis_variable_info {
- u1 tag = ITEM_UninitializedThis; // 6
- }
-
- Object_variable_info {
- u1 tag = ITEM_Object; // 7
- u2 cpool_index;
- }
-
- Uninitialized_variable_info {
- u1 tag = ITEM_Uninitialized; // 8
- u2 offset;
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_verification_type_info(classbuffer *cb, verification_type_info_t *verification_type_info)
-{
- /* get verification type */
-
- if (!suck_check_classbuffer_size(cb, 1))
- return false;
-
- verification_type_info->tag = suck_u1(cb);
-
- /* process the tag */
-
- switch (verification_type_info->tag) {
- case ITEM_Top:
- case ITEM_Integer:
- case ITEM_Float:
- case ITEM_Long:
- case ITEM_Double:
- case ITEM_Null:
- case ITEM_UninitializedThis:
- break;
-
- case ITEM_Object:
- /* get constant pool index */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- verification_type_info->Object_variable_info.cpool_index = suck_u2(cb);
- break;
-
- case ITEM_Uninitialized:
- /* get offset */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- verification_type_info->Uninitialized_variable_info.offset = suck_u2(cb);
- break;
- }
-
- return true;
-}
-
-
-/* stackmap_get_same_locals_1_stack_item_frame *********************************
-
- same_locals_1_stack_item_frame {
- u1 frame_type = SAME_LOCALS_1_STACK_ITEM; // 64-127
- verification_type_info stack[1];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_same_locals_1_stack_item_frame(classbuffer *cb, stack_map_frame_t *stack_map_frame)
-{
- same_locals_1_stack_item_frame_t *same_locals_1_stack_item_frame;
-
- /* for convenience */
-
- same_locals_1_stack_item_frame =
- &(stack_map_frame->same_locals_1_stack_item_frame);
-
- if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame->stack[0])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_get_same_locals_1_stack_item_frame_extended ************************
-
- same_locals_1_stack_item_frame_extended {
- u1 frame_type = SAME_LOCALS_1_STACK_ITEM_EXTENDED; // 247
- u2 offset_delta;
- verification_type_info stack[1];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_same_locals_1_stack_item_frame_extended(classbuffer *cb, stack_map_frame_t *stack_map_frame)
-{
- same_locals_1_stack_item_frame_extended_t *same_locals_1_stack_item_frame_extended;
-
- /* for convenience */
-
- same_locals_1_stack_item_frame_extended =
- &(stack_map_frame->same_locals_1_stack_item_frame_extended);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- same_locals_1_stack_item_frame_extended->offset_delta = suck_u2(cb);
-
- /* process stack */
-
- if (!stackmap_get_verification_type_info(cb, &(same_locals_1_stack_item_frame_extended->stack[0])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_get_chop_frame *****************************************************
-
- chop_frame {
- u1 frame_type = CHOP_FRAME; // 248-250
- u2 offset_delta;
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_chop_frame(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- chop_frame_t *chop_frame;
-
- /* for convenience */
-
- chop_frame = &(stack_map_frame->chop_frame);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- chop_frame->offset_delta = suck_u2(cb);
-
- return true;
-}
-
-
-/* stackmap_get_same_frame_extended ********************************************
-
- same_frame_extended {
- u1 frame_type = SAME_FRAME_EXTENDED; // 251
- u2 offset_delta;
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_same_frame_extended(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- same_frame_extended_t *same_frame_extended;
-
- /* for convenience */
-
- same_frame_extended = &(stack_map_frame->same_frame_extended);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- same_frame_extended->offset_delta = suck_u2(cb);
-
- return true;
-}
-
-
-/* stackmap_get_append_frame ***************************************************
-
- append_frame {
- u1 frame_type = APPEND_FRAME; // 252-254
- u2 offset_delta;
- verification_type_info locals[frame_Type - 251];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_append_frame(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- append_frame_t *append_frame;
- s4 number_of_locals;
- s4 i;
-
- /* for convenience */
-
- append_frame = &(stack_map_frame->append_frame);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- /* get offset delta */
-
- append_frame->offset_delta = suck_u2(cb);
-
- /* allocate locals array */
-
- number_of_locals = append_frame->frame_type - 251;
-
- append_frame->locals = DMNEW(verification_type_info_t, number_of_locals);
-
- /* process all locals */
-
- for (i = 0; i < number_of_locals; i++)
- if (!stackmap_get_verification_type_info(cb, &(append_frame->locals[i])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_get_full_frame *****************************************************
-
- full_frame {
- u1 frame_type = FULL_FRAME;
- u2 offset_delta;
- u2 number_of_locals;
- verification_type_info locals[number_of_locals];
- u2 number_of_stack_items;
- verification_type_info stack[number_of_stack_items];
- }
-
-*******************************************************************************/
-
-static bool stackmap_get_full_frame(classbuffer *cb,
- stack_map_frame_t *stack_map_frame)
-{
- full_frame_t *full_frame;
- s4 i;
-
- /* for convenience */
-
- full_frame = &(stack_map_frame->full_frame);
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 2 + 2))
- return false;
-
- /* get offset delta */
-
- stack_map_frame->full_frame.offset_delta = suck_u2(cb);
-
- /* get number of locals */
-
- full_frame->number_of_locals = suck_u2(cb);
-
- /* allocate locals array */
-
- full_frame->locals =
- DMNEW(verification_type_info_t, full_frame->number_of_locals);
-
- /* process all locals */
-
- for (i = 0; i < full_frame->number_of_locals; i++)
- if (!stackmap_get_verification_type_info(cb, &(full_frame->locals[i])))
- return false;
-
- /* get number of stack items */
-
- if (!suck_check_classbuffer_size(cb, 2))
- return false;
-
- full_frame->number_of_stack_items = suck_u2(cb);
-
- /* allocate stack array */
-
- full_frame->stack =
- DMNEW(verification_type_info_t, full_frame->number_of_stack_items);
-
- /* process all stack items */
-
- for (i = 0; i < full_frame->number_of_stack_items; i++)
- if (!stackmap_get_verification_type_info(cb, &(full_frame->stack[i])))
- return false;
-
- return true;
-}
-
-
-/* stackmap_load_attribute_stackmaptable ***************************************
-
- stack_map {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 number_of_entries;
- stack_map_frame entries[number_of_entries];
- }
-
- union stack_map_frame {
- same_frame;
- same_locals_1_stack_item_frame;
- same_locals_1_stack_item_frame_extended;
- chop_frame;
- same_frame_extended;
- append_frame;
- full_frame;
- }
-
- same_frame {
- u1 frame_type = SAME; // 0-63
- }
-
-*******************************************************************************/
-
-bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m)
-{
- classinfo *c;
- stack_map_t *stack_map;
- s4 i;
- u1 frame_type;
-
- /* get classinfo */
-
- c = cb->clazz;
-
- /* allocate stack map structure */
-
- stack_map = DNEW(stack_map_t);
-
- STATISTICS(size_stack_map += sizeof(stack_map_t));
-
- /* check buffer size */
-
- if (!suck_check_classbuffer_size(cb, 4 + 2))
- return false;
-
- /* attribute_length */
-
- stack_map->attribute_length = suck_u4(cb);
-
- if (!suck_check_classbuffer_size(cb, stack_map->attribute_length))
- return false;
-
- /* get number of entries */
-
- stack_map->number_of_entries = suck_u2(cb);
-
- /* process all entries */
-
- stack_map->entries = DMNEW(stack_map_frame_t, stack_map->number_of_entries);
-
- for (i = 0; i < stack_map->number_of_entries; i++) {
- /* get the frame type */
-
- frame_type = suck_u1(cb);
-
- stack_map->entries[i].frame_type = frame_type;
-
- /* process frame */
-
- if (frame_type <= FRAME_TYPE_SAME) {
- /* same_frame */
- }
- else if (frame_type <= FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM) {
- /* same_locals_1_stack_item_frame */
-
- if (!stackmap_get_same_locals_1_stack_item_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type <= FRAME_TYPE_RESERVED) {
- /* reserved */
-
- exceptions_throw_classformaterror(c, "reserved frame type");
- return false;
- }
- else if (frame_type == FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
- /* same_locals_1_stack_item_frame_extended */
-
- if (!stackmap_get_same_locals_1_stack_item_frame_extended(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type <= FRAME_TYPE_CHOP) {
- /* chop_frame */
-
- if (!stackmap_get_chop_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type == FRAME_TYPE_SAME_FRAME_EXTENDED) {
- /* same_frame_extended */
-
- if (!stackmap_get_same_frame_extended(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type <= FRAME_TYPE_APPEND) {
- /* append_frame */
-
- if (!stackmap_get_append_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- else if (frame_type == FRAME_TYPE_FULL_FRAME) {
- /* full_frame */
-
- if (!stackmap_get_full_frame(cb, &(stack_map->entries[i])))
- return false;
- }
- }
-
- /* store stack map in method structure */
-
-#if 0
- /* currently not used */
-
- m->stack_map = stack_map;
-#endif
-
- return true;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/stackmap.h - class attribute StackMapTable
-
- Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
- R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
- C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
- Institut f. Computersprachen - TU Wien
-
- 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 _STACKMAP_H
-#define _STACKMAP_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct stack_map_t stack_map_t;
-typedef union stack_map_frame_t stack_map_frame_t;
-typedef struct same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame_t;
-typedef struct same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended_t;
-typedef struct chop_frame_t chop_frame_t;
-typedef struct same_frame_extended_t same_frame_extended_t;
-typedef struct append_frame_t append_frame_t;
-typedef struct full_frame_t full_frame_t;
-
-typedef union verification_type_info_t verification_type_info_t;
-typedef struct Top_variable_info_t Top_variable_info_t;
-typedef struct Integer_variable_info_t Integer_variable_info_t;
-typedef struct Float_variable_info_t Float_variable_info_t;
-typedef struct Long_variable_info_t Long_variable_info_t;
-typedef struct Double_variable_info_t Double_variable_info_t;
-typedef struct Null_variable_info_t Null_variable_info_t;
-typedef struct UninitializedThis_variable_info_t UninitializedThis_variable_info_t;
-typedef struct Object_variable_info_t Object_variable_info_t;
-typedef struct Uninitialized_variable_info_t Uninitialized_variable_info_t;
-
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-#include "vmcore/loader.h"
-#include "vmcore/method.h"
-
-
-/* verification_type_info *****************************************************/
-
-#define ITEM_Top 0
-#define ITEM_Integer 1
-#define ITEM_Float 2
-#define ITEM_Double 3
-#define ITEM_Long 4
-#define ITEM_Null 5
-#define ITEM_UninitializedThis 6
-#define ITEM_Object 7
-#define ITEM_Uninitialized 8
-
-struct Top_variable_info_t {
- u1 tag;
-};
-
-struct Integer_variable_info_t {
- u1 tag;
-};
-
-struct Float_variable_info_t {
- u1 tag;
-};
-
-struct Long_variable_info_t {
- u1 tag;
-};
-
-struct Double_variable_info_t {
- u1 tag;
-};
-
-struct Null_variable_info_t {
- u1 tag;
-};
-
-struct UninitializedThis_variable_info_t {
- u1 tag;
-};
-
-struct Object_variable_info_t {
- u1 tag;
- u2 cpool_index;
-};
-
-struct Uninitialized_variable_info_t {
- u1 tag;
- u2 offset;
-};
-
-union verification_type_info_t {
- u1 tag;
- Top_variable_info_t Top_variable_info;
- Integer_variable_info_t Integer_variable_info;
- Float_variable_info_t Float_variable_info;
- Long_variable_info_t Long_variable_info;
- Double_variable_info_t Double_variable_info;
- Null_variable_info_t Null_variable_info;
- UninitializedThis_variable_info_t UninitializedThis_variable_info;
- Object_variable_info_t Object_variable_info;
- Uninitialized_variable_info_t Uninitialized_variable_info;
-};
-
-
-/* stack_map_t ****************************************************************/
-
-struct stack_map_t {
- u2 attribute_name_index;
- u4 attribute_length;
- u2 number_of_entries;
- stack_map_frame_t *entries;
-};
-
-
-/* same_locals_1_stack_item_frame_t *******************************************/
-
-struct same_locals_1_stack_item_frame_t {
- u1 frame_type;
- verification_type_info_t stack[1];
-};
-
-
-/* same_locals_1_stack_item_frame_extended_t **********************************/
-
-struct same_locals_1_stack_item_frame_extended_t {
- u1 frame_type;
- u2 offset_delta;
- verification_type_info_t stack[1];
-};
-
-
-/* chop_frame_t ***************************************************************/
-
-struct chop_frame_t {
- u1 frame_type;
- u2 offset_delta;
-};
-
-
-/* same_frame_extended_t ******************************************************/
-
-struct same_frame_extended_t {
- u1 frame_type;
- u2 offset_delta;
-};
-
-
-/* append_frame_t *************************************************************/
-
-struct append_frame_t {
- u1 frame_type;
- u2 offset_delta;
- verification_type_info_t *locals;
-};
-
-
-/* full_frame_t ***************************************************************/
-
-struct full_frame_t {
- u1 frame_type;
- u2 offset_delta;
- u2 number_of_locals;
- verification_type_info_t *locals;
- u2 number_of_stack_items;
- verification_type_info_t *stack;
-};
-
-
-/* stack_map_frame_t **********************************************************/
-
-#define FRAME_TYPE_SAME 63 /* 0-63 */
-#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM 127 /* 0-127 */
-#define FRAME_TYPE_RESERVED 246 /* 128-246 */
-#define FRAME_TYPE_SAME_LOCALS_1_STACK_ITEM_EXTENDED 247 /* 247 */
-#define FRAME_TYPE_CHOP 250 /* 248-250 */
-#define FRAME_TYPE_SAME_FRAME_EXTENDED 251 /* 251 */
-#define FRAME_TYPE_APPEND 254 /* 252-254 */
-#define FRAME_TYPE_FULL_FRAME 255 /* 255 */
-
-union stack_map_frame_t {
- u1 frame_type;
- same_locals_1_stack_item_frame_t same_locals_1_stack_item_frame;
- same_locals_1_stack_item_frame_extended_t same_locals_1_stack_item_frame_extended;
- chop_frame_t chop_frame;
- same_frame_extended_t same_frame_extended;
- append_frame_t append_frame;
- full_frame_t full_frame;
-};
-
-
-/* function prototypes ********************************************************/
-
-bool stackmap_load_attribute_stackmaptable(classbuffer *cb, methodinfo *m);
-
-#endif /* _STACKMAP_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/statistics.c - global varables for statistics
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#if defined(HAVE_TIME_H)
-# include <time.h>
-#endif
-
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#endif
-
-#if defined(HAVE_SYS_RESOURCE_H)
-# include <sys/resource.h>
-#endif
-
-#include "vm/types.h"
-
-#include "mm/gc.hpp"
-
-#include "toolbox/logging.h"
-
-#include "vm/global.h"
-
-#include "vm/jit/code.h"
-
-#include "vmcore/class.h"
-#include "vmcore/field.h"
-#include "vmcore/method.h"
-#include "vmcore/options.h"
-#include "vmcore/statistics.h"
-
-
-/* global variables ***********************************************************/
-
-static s8 loadingtime = 0; /* accumulated loading time */
-static s8 loadingstarttime = 0;
-static s8 loadingstoptime = 0;
-static s4 loadingtime_recursion = 0;
-
-static s8 compilingtime = 0; /* accumulated compile time */
-static s8 compilingstarttime = 0;
-static s8 compilingstoptime = 0;
-static s4 compilingtime_recursion = 0;
-
-s4 codememusage = 0;
-s4 maxcodememusage = 0;
-
-s4 memoryusage = 0;
-s4 maxmemusage = 0;
-
-s4 maxdumpsize = 0;
-
-s4 globalallocateddumpsize = 0;
-s4 globaluseddumpsize = 0;
-
-
-/* variables for measurements *************************************************/
-
-s4 size_classinfo = 0;
-s4 size_fieldinfo = 0;
-s4 size_methodinfo = 0;
-s4 size_lineinfo = 0;
-s4 size_codeinfo = 0;
-
-s4 size_stub_native = 0;
-
-s4 size_stack_map = 0;
-s4 size_string = 0;
-
-s4 size_threadobject = 0;
-int32_t size_thread_index_t = 0;
-int32_t size_stacksize = 0;
-
-s4 size_lock_record = 0;
-s4 size_lock_hashtable = 0;
-s4 size_lock_waiter = 0;
-
-int32_t count_linenumbertable = 0;
-int32_t size_linenumbertable = 0;
-
-s4 size_patchref = 0;
-
-u8 count_calls_java_to_native = 0;
-u8 count_calls_native_to_java = 0;
-
-int count_const_pool_len = 0;
-int count_classref_len = 0;
-int count_parsed_desc_len = 0;
-int count_vftbl_len = 0;
-int count_all_methods = 0;
-int count_methods_marked_used = 0; /* RTA */
-
-int count_vmcode_len = 0;
-int count_extable_len = 0;
-int count_class_loads = 0;
-int count_class_inits = 0;
-
-int count_utf_len = 0; /* size of utf hash */
-int count_utf_new = 0; /* calls of utf_new */
-int count_utf_new_found = 0; /* calls of utf_new with fast return */
-
-int count_locals_conflicts = 0; /* register allocator statistics */
-int count_locals_spilled = 0;
-int count_locals_register = 0;
-int count_ss_spilled = 0;
-int count_ss_register = 0;
-int count_methods_allocated_by_lsra = 0;
-int count_mem_move_bb = 0;
-int count_interface_size = 0;
-int count_argument_mem_ss = 0;
-int count_argument_reg_ss = 0;
-int count_method_in_register = 0;
-int count_mov_reg_reg = 0;
-int count_mov_mem_reg = 0;
-int count_mov_reg_mem = 0;
-int count_mov_mem_mem = 0;
-
-int count_jit_calls = 0;
-int count_methods = 0;
-int count_spills_read_ila = 0;
-int count_spills_read_flt = 0;
-int count_spills_read_dbl = 0;
-int count_spills_write_ila = 0;
-int count_spills_write_flt = 0;
-int count_spills_write_dbl = 0;
-int count_pcmd_activ = 0;
-int count_pcmd_drop = 0;
-int count_pcmd_zero = 0;
-int count_pcmd_const_store = 0;
-int count_pcmd_const_alu = 0;
-int count_pcmd_const_bra = 0;
-int count_pcmd_load = 0;
-int count_pcmd_move = 0;
-int count_load_instruction = 0;
-int count_pcmd_store = 0;
-int count_pcmd_store_comb = 0;
-int count_dup_instruction = 0;
-int count_pcmd_op = 0;
-int count_pcmd_mem = 0;
-int count_pcmd_met = 0;
-int count_pcmd_bra = 0;
-int count_pcmd_table = 0;
-int count_pcmd_return = 0;
-int count_pcmd_returnx = 0;
-int count_check_null = 0;
-int count_check_bound = 0;
-int count_max_basic_blocks = 0;
-int count_basic_blocks = 0;
-int count_javainstr = 0;
-int count_max_javainstr = 0;
-int count_javacodesize = 0;
-int count_javaexcsize = 0;
-int count_calls = 0;
-int count_tryblocks = 0;
-int count_code_len = 0;
-int count_data_len = 0;
-int count_cstub_len = 0;
-int count_max_new_stack = 0;
-int count_upper_bound_new_stack = 0;
-
-int count_emit_branch = 0;
-int count_emit_branch_8bit = 0;
-int count_emit_branch_16bit = 0;
-int count_emit_branch_32bit = 0;
-int count_emit_branch_64bit = 0;
-
-s4 count_branches_resolved = 0;
-s4 count_branches_unresolved = 0;
-
-u8 count_jni_callXmethod_calls=0;
-u8 count_jni_calls=0;
-
-
-static int count_block_stack_init[11] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0
-};
-int *count_block_stack = count_block_stack_init;
-static int count_analyse_iterations_init[5] = {
- 0, 0, 0, 0, 0
-};
-int *count_analyse_iterations = count_analyse_iterations_init;
-static int count_method_bb_distribution_init[9] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0
-};
-int *count_method_bb_distribution = count_method_bb_distribution_init;
-static int count_block_size_distribution_init[18] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0
-};
-int *count_block_size_distribution = count_block_size_distribution_init;
-static int count_store_length_init[21] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0
-};
-int *count_store_length = count_store_length_init;
-static int count_store_depth_init[11] = {
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,
- 0
-};
-int *count_store_depth = count_store_depth_init;
-
-
-/* instruction scheduler statistics *******************************************/
-
-s4 count_schedule_basic_blocks = 0;
-s4 count_schedule_nodes = 0;
-s4 count_schedule_leaders = 0;
-s4 count_schedule_max_leaders = 0;
-s4 count_schedule_critical_path = 0;
-
-
-/* jnicallXmethodinvokation ***************************************************
-
- increments the jni CallXMethod invokation count by one
-
-*******************************************************************************/
-
-void jnicallXmethodnvokation(void)
-{
- /* XXX do locking here */
- count_jni_callXmethod_calls++;
-}
-
-
-/* jniinvokation *************************************************************
-
- increments the jni overall invokation count by one
-
-*******************************************************************************/
-
-void jniinvokation(void)
-{
- /* XXX do locking here */
- count_jni_calls++;
-}
-
-
-/* getcputime *********************************** ******************************
-
- Returns the used CPU time in microseconds
-
-*******************************************************************************/
-
-s8 getcputime(void)
-{
-#if defined(HAVE_GETRUSAGE)
- struct rusage ru;
- int sec, usec;
-
- getrusage(RUSAGE_SELF, &ru);
-
- sec = ru.ru_utime.tv_sec + ru.ru_stime.tv_sec;
- usec = ru.ru_utime.tv_usec + ru.ru_stime.tv_usec;
-
- return sec * 1000000 + usec;
-#else
- /* If we don't have getrusage, simply return 0. */
-
- return 0;
-#endif
-}
-
-
-/* loadingtime_stop ************************************************************
-
- XXX
-
-*******************************************************************************/
-
-void loadingtime_start(void)
-{
- loadingtime_recursion++;
-
- if (loadingtime_recursion == 1)
- loadingstarttime = getcputime();
-}
-
-
-/* loadingtime_stop ************************************************************
-
- XXX
-
-*******************************************************************************/
-
-void loadingtime_stop(void)
-{
- if (loadingtime_recursion == 1) {
- loadingstoptime = getcputime();
- loadingtime += (loadingstoptime - loadingstarttime);
- }
-
- loadingtime_recursion--;
-}
-
-
-/* compilingtime_stop **********************************************************
-
- XXX
-
-*******************************************************************************/
-
-void compilingtime_start(void)
-{
- compilingtime_recursion++;
-
- if (compilingtime_recursion == 1)
- compilingstarttime = getcputime();
-}
-
-
-/* compilingtime_stop **********************************************************
-
- XXX
-
-*******************************************************************************/
-
-void compilingtime_stop(void)
-{
- if (compilingtime_recursion == 1) {
- compilingstoptime = getcputime();
- compilingtime += (compilingstoptime - compilingstarttime);
- }
-
- compilingtime_recursion--;
-}
-
-
-/* print_times *****************************************************************
-
- Prints a summary of CPU time usage.
-
-*******************************************************************************/
-
-void print_times(void)
-{
- s8 totaltime;
- s8 runtime;
-
- totaltime = getcputime();
- runtime = totaltime - loadingtime - compilingtime;
-
-#if SIZEOF_VOID_P == 8
- dolog("Time for loading classes: %6ld ms", loadingtime / 1000);
- dolog("Time for compiling code: %6ld ms", compilingtime / 1000);
- dolog("Time for running program: %6ld ms", runtime / 1000);
- dolog("Total time: %6ld ms", totaltime / 1000);
-#else
- dolog("Time for loading classes: %6lld ms", loadingtime / 1000);
- dolog("Time for compiling code: %6lld ms", compilingtime / 1000);
- dolog("Time for running program: %6lld ms", runtime / 1000);
- dolog("Total time: %6lld ms", totaltime / 1000);
-#endif
-}
-
-
-/* print_stats *****************************************************************
-
- outputs detailed compiler statistics
-
-*******************************************************************************/
-
-void print_stats(void)
-{
- s4 i;
- float f;
- s4 sum;
-
-
- dolog("Number of JIT compiler calls: %6d", count_jit_calls);
- dolog("Number of compiled methods: %6d", count_methods);
-
- dolog("Number of compiled basic blocks: %6d",
- count_basic_blocks);
- dolog("Number of max. basic blocks per method: %6d",
- count_max_basic_blocks);
-
- dolog("Number of compiled JavaVM instructions: %6d",
- count_javainstr);
- dolog("Number of max. JavaVM instructions per method: %6d",
- count_max_javainstr);
- dolog("Size of compiled JavaVM instructions: %6d(%d)",
- count_javacodesize, count_javacodesize - count_methods * 18);
-
- dolog("Size of compiled Exception Tables: %d", count_javaexcsize);
- dolog("Number of Machine-Instructions: %d", count_code_len >> 2);
- dolog("Number of Spills (write to memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
- count_spills_write_ila + count_spills_write_flt + count_spills_write_dbl,
- count_spills_write_ila, count_spills_write_flt, count_spills_write_dbl);
- dolog("Number of Spills (read from memory) <all [i/l/a|flt|dbl]>: %d [%d|%d|%d]",
- count_spills_read_ila + count_spills_read_flt + count_spills_read_dbl,
- count_spills_read_ila, count_spills_read_flt, count_spills_read_dbl);
- dolog("Number of Activ Pseudocommands: %6d", count_pcmd_activ);
- dolog("Number of Drop Pseudocommands: %6d", count_pcmd_drop);
- dolog("Number of Const Pseudocommands: %6d (zero:%5d)",
- count_pcmd_load, count_pcmd_zero);
- dolog("Number of ConstAlu Pseudocommands: %6d (cmp: %5d, store:%5d)",
- count_pcmd_const_alu, count_pcmd_const_bra, count_pcmd_const_store);
- dolog("Number of Move Pseudocommands: %6d", count_pcmd_move);
- dolog("Number of Load Pseudocommands: %6d", count_load_instruction);
- dolog("Number of Store Pseudocommands: %6d (combined: %5d)",
- count_pcmd_store, count_pcmd_store - count_pcmd_store_comb);
- dolog("Number of OP Pseudocommands: %6d", count_pcmd_op);
- dolog("Number of DUP Pseudocommands: %6d", count_dup_instruction);
- dolog("Number of Mem Pseudocommands: %6d", count_pcmd_mem);
- dolog("Number of Method Pseudocommands: %6d", count_pcmd_met);
- dolog("Number of Branch Pseudocommands: %6d (rets:%5d, Xrets: %5d)",
- count_pcmd_bra, count_pcmd_return, count_pcmd_returnx);
- log_println(" resolved branches: %6d", count_branches_resolved);
- log_println(" unresolved branches: %6d", count_branches_unresolved);
- dolog("Number of Table Pseudocommands: %6d", count_pcmd_table);
- dolog("Number of Useful Pseudocommands: %6d", count_pcmd_table +
- count_pcmd_bra + count_pcmd_load + count_pcmd_mem + count_pcmd_op);
- dolog("Number of Null Pointer Checks: %6d", count_check_null);
- dolog("Number of Array Bound Checks: %6d", count_check_bound);
- dolog("Number of Try-Blocks: %d", count_tryblocks);
-
- dolog("Number of branch_emit (total, 8bit/16bit/32bit/64bit offset): %d, %d/%d/%d/%d",
- count_emit_branch, count_emit_branch_8bit, count_emit_branch_16bit,
- count_emit_branch_32bit, count_emit_branch_64bit);
-
- dolog("Maximal count of stack elements: %d", count_max_new_stack);
- dolog("Upper bound of max stack elements: %d", count_upper_bound_new_stack);
- dolog("Distribution of stack sizes at block boundary");
- dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
- dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
- count_block_stack[0], count_block_stack[1], count_block_stack[2],
- count_block_stack[3], count_block_stack[4], count_block_stack[5],
- count_block_stack[6], count_block_stack[7], count_block_stack[8],
- count_block_stack[9], count_block_stack[10]);
- dolog("Distribution of store stack depth");
- dolog(" 0 1 2 3 4 5 6 7 8 9 >=10");
- dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
- count_store_depth[0], count_store_depth[1], count_store_depth[2],
- count_store_depth[3], count_store_depth[4], count_store_depth[5],
- count_store_depth[6], count_store_depth[7], count_store_depth[8],
- count_store_depth[9], count_store_depth[10]);
- dolog("Distribution of store creator chains first part");
- dolog(" 0 1 2 3 4 5 6 7 8 9");
- dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
- count_store_length[0], count_store_length[1], count_store_length[2],
- count_store_length[3], count_store_length[4], count_store_length[5],
- count_store_length[6], count_store_length[7], count_store_length[8],
- count_store_length[9]);
- dolog("Distribution of store creator chains second part");
- dolog(" 10 11 12 13 14 15 16 17 18 19 >=20");
- dolog("%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d%6d",
- count_store_length[10], count_store_length[11],
- count_store_length[12], count_store_length[13],
- count_store_length[14], count_store_length[15],
- count_store_length[16], count_store_length[17],
- count_store_length[18], count_store_length[19],
- count_store_length[20]);
- dolog("Distribution of analysis iterations");
- dolog(" 1 2 3 4 >=5");
- dolog("%6d%6d%6d%6d%6d",
- count_analyse_iterations[0], count_analyse_iterations[1],
- count_analyse_iterations[2], count_analyse_iterations[3],
- count_analyse_iterations[4]);
-
-
- /* Distribution of basic blocks per method ********************************/
-
- log_println("Distribution of basic blocks per method:");
- log_println(" <=5 <=10 <=15 <=20 <=30 <=40 <=50 <=75 >75");
-
- log_start();
- for (i = 0; i <= 8; i++)
- log_print("%6d", count_method_bb_distribution[i]);
- log_finish();
-
- /* print ratio */
-
- f = (float) count_methods;
-
- log_start();
- for (i = 0; i <= 8; i++)
- log_print("%6.2f", (float) count_method_bb_distribution[i] / f);
- log_finish();
-
- /* print cumulated ratio */
-
- log_start();
- for (i = 0, sum = 0; i <= 8; i++) {
- sum += count_method_bb_distribution[i];
- log_print("%6.2f", (float) sum / f);
- }
- log_finish();
-
-
- /* Distribution of basic block sizes **************************************/
-
- log_println("Distribution of basic block sizes:");
- log_println(" 0 1 2 3 4 5 6 7 8 9 <13 <15 <17 <19 <21 <26 <31 >30");
-
- /* print block sizes */
-
- log_start();
- for (i = 0; i <= 17; i++)
- log_print("%6d", count_block_size_distribution[i]);
- log_finish();
-
- /* print ratio */
-
- f = (float) count_basic_blocks;
-
- log_start();
- for (i = 0; i <= 17; i++)
- log_print("%6.2f", (float) count_block_size_distribution[i] / f);
- log_finish();
-
- /* print cumulated ratio */
-
- log_start();
- for (i = 0, sum = 0; i <= 17; i++) {
- sum += count_block_size_distribution[i];
- log_print("%6.2f", (float) sum / f);
- }
- log_finish();
-
- statistics_print_memory_usage();
-
- dolog("Number of class loads: %6d", count_class_loads);
- dolog("Number of class inits: %6d", count_class_inits);
- dolog("Number of loaded Methods: %6d\n", count_all_methods);
-
- dolog("Calls of utf_new: %6d", count_utf_new);
- dolog("Calls of utf_new (element found): %6d\n", count_utf_new_found);
-
-
- /* LSRA statistics ********************************************************/
-
- dolog("Moves reg -> reg: %6d", count_mov_reg_reg);
- dolog("Moves mem -> reg: %6d", count_mov_mem_reg);
- dolog("Moves reg -> mem: %6d", count_mov_reg_mem);
- dolog("Moves mem -> mem: %6d", count_mov_mem_mem);
-
- dolog("Methods allocated by LSRA: %6d",
- count_methods_allocated_by_lsra);
- dolog("Conflicts between local Variables: %6d", count_locals_conflicts);
- dolog("Local Variables held in Memory: %6d", count_locals_spilled);
- dolog("Local Variables held in Registers: %6d", count_locals_register);
- dolog("Stackslots held in Memory: %6d", count_ss_spilled);
- dolog("Stackslots held in Registers: %6d", count_ss_register);
- dolog("Memory moves at BB Boundaries: %6d", count_mem_move_bb);
- dolog("Number of interface slots: %6d\n", count_interface_size);
- dolog("Number of Argument stack slots in register: %6d",
- count_argument_reg_ss);
- dolog("Number of Argument stack slots in memory: %6d\n",
- count_argument_mem_ss);
- dolog("Number of Methods kept in registers: %6d\n",
- count_method_in_register);
-
-
- /* instruction scheduler statistics ***************************************/
-
-#if defined(USE_SCHEDULER)
- dolog("Instruction scheduler statistics:");
- dolog("Number of basic blocks: %7d", count_schedule_basic_blocks);
- dolog("Number of nodes: %7d", count_schedule_nodes);
- dolog("Number of leaders nodes: %7d", count_schedule_leaders);
- dolog("Number of max. leaders nodes: %7d", count_schedule_max_leaders);
- dolog("Length of critical path: %7d\n", count_schedule_critical_path);
-#endif
-
-
- /* call statistics ********************************************************/
-
- dolog("Function call statistics:");
- dolog("Number of jni->CallXMethod function invokations: %ld",
- count_jni_callXmethod_calls);
- dolog("Overall number of jni invokations: %ld",
- count_jni_calls);
-
- log_println("java-to-native calls: %10ld", count_calls_java_to_native);
- log_println("native-to-java calls: %10ld", count_calls_native_to_java);
-
-
- /* now print other statistics ********************************************/
-
-#if defined(ENABLE_INTRP)
- print_dynamic_super_statistics();
-#endif
-}
-
-
-/* statistics_print_date *******************************************************
-
- Print current date and time.
-
-*******************************************************************************/
-
-void statistics_print_date(void)
-{
- time_t t;
- struct tm tm;
-
-#if defined(HAVE_TIME)
- time(&t);
-#else
-# error !HAVE_TIME
-#endif
-
-#if defined(HAVE_LOCALTIME_R)
- localtime_r(&t, &tm);
-#else
-# error !HAVE_LOCALTIME_R
-#endif
-
- log_println("%d-%02d-%02d %02d:%02d:%02d",
- 1900 + tm.tm_year, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
-}
-
-
-/* statistics_print_memory_usage ***********************************************
-
- Print current memory usage.
-
-*******************************************************************************/
-
-void statistics_print_memory_usage(void)
-{
- s4 sum;
-
- log_println("memory usage ----------------------");
- log_println("");
- log_println("code: %10d", count_code_len);
- log_println("data: %10d", count_data_len);
- log_println(" ----------");
-
- sum =
- count_code_len +
- count_data_len;
-
- log_println(" %10d", sum);
-
- log_println("");
-
- log_println("classinfo (%3d B): %10d", (int) sizeof(classinfo), size_classinfo);
- log_println("fieldinfo (%3d B): %10d", (int) sizeof(fieldinfo), size_fieldinfo);
- log_println("methodinfo (%3d B): %10d", (int) sizeof(methodinfo), size_methodinfo);
- log_println("lineinfo (%3d B): %10d", (int) sizeof(lineinfo), size_lineinfo);
- log_println("codeinfo (%3d B): %10d", (int) sizeof(codeinfo), size_codeinfo);
- log_println(" ----------");
-
- sum =
- size_classinfo +
- size_fieldinfo +
- size_methodinfo +
- size_lineinfo +
- size_codeinfo;
-
- log_println(" %10d", sum);
-
- log_println("");
-
- log_println("linenumber tables (%5d): %10d", count_linenumbertable, size_linenumbertable);
- log_println("exception tables: %10d", count_extable_len);
- log_println("patcher references: %10d", size_patchref);
- log_println(" ----------");
-
- sum =
- size_linenumbertable +
- count_extable_len +
- size_patchref;
-
- log_println(" %10d", sum);
-
- log_println("");
-
- log_println("constant pool: %10d", count_const_pool_len);
- log_println("classref: %10d", count_classref_len);
- log_println("parsed descriptors: %10d", count_parsed_desc_len);
- log_println("vftbl: %10d", count_vftbl_len);
- log_println("compiler stubs: %10d", count_cstub_len);
- log_println("native stubs: %10d", size_stub_native);
- log_println("utf: %10d", count_utf_len);
- log_println("vmcode: %10d", count_vmcode_len);
- log_println("stack map: %10d", size_stack_map);
- log_println("string: %10d", size_string);
- log_println("threadobject: %10d", size_threadobject);
- log_println("thread index: %10d", size_thread_index_t);
- log_println("stack size: %10d", size_stacksize);
- log_println("lock record: %10d", size_lock_record);
- log_println("lock hashtable: %10d", size_lock_hashtable);
- log_println("lock waiter: %10d", size_lock_waiter);
- log_println(" ----------");
-
- sum =
- count_const_pool_len +
- count_classref_len +
- count_parsed_desc_len +
- count_vftbl_len +
- count_cstub_len +
- size_stub_native +
- count_utf_len +
- count_vmcode_len +
- size_stack_map +
- size_string +
- size_threadobject +
- size_thread_index_t +
- size_stacksize +
- size_lock_record +
- size_lock_hashtable +
- size_lock_waiter;
-
- log_println(" %10d", sum);
-
- log_println("");
-
- log_println("max. code memory: %10d", maxcodememusage);
- log_println("max. heap memory: %10d", maxmemusage);
- log_println("max. dump memory: %10d", maxdumpsize);
- log_println("");
- log_println("heap memory not freed: %10d", (int32_t) memoryusage);
- log_println("dump memory not freed: %10d", (int32_t) globalallocateddumpsize);
-
- log_println("");
-}
-
-
-/* statistics_print_gc_memory_usage ********************************************
-
- Print current GC memory usage.
-
-*******************************************************************************/
-
-void statistics_print_gc_memory_usage(void)
-{
- static int64_t count = 0;
- int64_t max;
- int64_t size;
- int64_t free;
- int64_t used;
- int64_t total;
-
- count++;
-
- max = gc_get_max_heap_size();
- size = gc_get_heap_size();
- free = gc_get_free_bytes();
- used = size - free;
- total = gc_get_total_bytes();
-
- if (opt_ProfileMemoryUsageGNUPlot) {
- if (count == 1)
- fprintf(opt_ProfileMemoryUsageGNUPlot, "plot \"profile.dat\" using 1:2 with lines title \"max. Java heap size\", \"profile.dat\" using 1:3 with lines title \"Java heap size\", \"profile.dat\" using 1:4 with lines title \"used\", \"profile.dat\" using 1:5 with lines title \"free\"\n");
-
-#if SIZEOF_VOID_P == 8
- fprintf(opt_ProfileMemoryUsageGNUPlot, "%ld %ld %ld %ld %ld\n", count, max, size, used, free);
-#else
- fprintf(opt_ProfileMemoryUsageGNUPlot, "%lld %lld %lld %lld %lld\n", count, max, size, used, free);
-#endif
-
- fflush(opt_ProfileMemoryUsageGNUPlot);
- }
- else {
- log_println("GC memory usage -------------------");
- log_println("");
- log_println("max. Java heap size: %10lld", max);
- log_println("");
- log_println("Java heap size: %10lld", size);
- log_println("used: %10lld", used);
- log_println("free: %10lld", free);
- log_println("totally used: %10lld", total);
- log_println("");
- }
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/statistics.h - exports global varables for statistics
-
- Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
- C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
- E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
- J. Wenninger, Institut f. Computersprachen - TU Wien
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _STATISTICS_H
-#define _STATISTICS_H
-
-#include "config.h"
-
-#include <stdint.h>
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* statistic macros ***********************************************************/
-
-#if defined(ENABLE_STATISTICS)
-#define STATISTICS(x) \
- do { \
- if (opt_stat) { \
- x; \
- } \
- } while (0)
-#else
-#define STATISTICS(x) /* nothing */
-#endif
-
-/* in_ inline statistics */
-
-#define IN_MAX 9
-#define IN_UNIQUEVIRT 0x0000
-#define IN_UNIQUE_INTERFACE 0x0001
-#define IN_OUTSIDERS 0x0004
-#define IN_MAXDEPTH 0x0008
-#define IN_MAXCODE 0x0010
-#define IN_JCODELENGTH 0x0020
-#define IN_EXCEPTION 0x0040
-#define IN_NOT_UNIQUE_VIRT 0x0080
-#define IN_NOT_UNIQUE_INTERFACE 0x0100
-
-#define N_UNIQUEVIRT 0
-#define N_UNIQUE_INTERFACE 1
-#define N_OUTSIDERS 2
-#define N_MAXDEPTH 3
-#define N_MAXCODE 4
-#define N_JCODELENGTH 5
-#define N_EXCEPTION 6
-#define N_NOT_UNIQUE_VIRT 7
-#define N_NOT_UNIQUE_INTERFACE 8
-
-
-/* global variables ***********************************************************/
-
-extern s4 codememusage;
-extern s4 maxcodememusage;
-
-extern s4 memoryusage;
-extern s4 maxmemusage;
-
-extern s4 maxdumpsize;
-
-extern s4 globalallocateddumpsize;
-extern s4 globaluseddumpsize;
-
-
-/* variables for measurements *************************************************/
-
-extern s4 size_classinfo;
-extern s4 size_fieldinfo;
-extern s4 size_methodinfo;
-extern s4 size_lineinfo;
-extern s4 size_codeinfo;
-
-extern s4 size_stub_native;
-
-extern s4 size_stack_map;
-extern s4 size_string;
-
-extern s4 size_threadobject;
-extern int32_t size_thread_index_t;
-extern int32_t size_stacksize;
-
-extern s4 size_lock_record;
-extern s4 size_lock_hashtable;
-extern s4 size_lock_waiter;
-
-extern int32_t count_linenumbertable;
-extern int32_t size_linenumbertable;
-
-extern s4 size_patchref;
-
-extern u8 count_calls_java_to_native;
-extern u8 count_calls_native_to_java;
-
-extern int count_const_pool_len;
-extern int count_classref_len;
-extern int count_parsed_desc_len;
-extern int count_vftbl_len;
-extern int count_all_methods;
-extern int count_methods_marked_used; /*RTA*/
-extern int count_vmcode_len;
-extern int count_extable_len;
-extern int count_class_loads;
-extern int count_class_inits;
-
-extern int count_utf_len; /* size of utf hash */
-extern int count_utf_new;
-extern int count_utf_new_found;
-
-extern int count_locals_conflicts;
-extern int count_locals_spilled;
-extern int count_locals_register;
-extern int count_ss_spilled;
-extern int count_ss_register;
-extern int count_methods_allocated_by_lsra;
-extern int count_mem_move_bb;
-extern int count_interface_size;
-extern int count_argument_mem_ss;
-extern int count_argument_reg_ss;
-extern int count_method_in_register;
-extern int count_mov_reg_reg;
-extern int count_mov_mem_reg;
-extern int count_mov_reg_mem;
-extern int count_mov_mem_mem;
-
-extern int count_jit_calls;
-extern int count_methods;
-extern int count_spills_read_ila;
-extern int count_spills_read_flt;
-extern int count_spills_read_dbl;
-extern int count_spills_write_ila;
-extern int count_spills_write_flt;
-extern int count_spills_write_dbl;
-extern int count_pcmd_activ;
-extern int count_pcmd_drop;
-extern int count_pcmd_zero;
-extern int count_pcmd_const_store;
-extern int count_pcmd_const_alu;
-extern int count_pcmd_const_bra;
-extern int count_pcmd_load;
-extern int count_pcmd_move;
-extern int count_load_instruction;
-extern int count_pcmd_store;
-extern int count_pcmd_store_comb;
-extern int count_dup_instruction;
-extern int count_pcmd_op;
-extern int count_pcmd_mem;
-extern int count_pcmd_met;
-extern int count_pcmd_bra;
-extern int count_pcmd_table;
-extern int count_pcmd_return;
-extern int count_pcmd_returnx;
-extern int count_check_null;
-extern int count_check_bound;
-extern int count_max_basic_blocks;
-extern int count_basic_blocks;
-extern int count_max_javainstr;
-extern int count_javainstr;
-extern int count_javacodesize;
-extern int count_javaexcsize;
-extern int count_calls;
-extern int count_tryblocks;
-extern int count_code_len;
-extern int count_data_len;
-extern int count_cstub_len;
-extern int count_max_new_stack;
-extern int count_upper_bound_new_stack;
-
-extern int count_emit_branch;
-extern int count_emit_branch_8bit;
-extern int count_emit_branch_16bit;
-extern int count_emit_branch_32bit;
-extern int count_emit_branch_64bit;
-
-extern s4 count_branches_resolved;
-extern s4 count_branches_unresolved;
-
-extern int *count_block_stack;
-extern int *count_analyse_iterations;
-extern int *count_method_bb_distribution;
-extern int *count_block_size_distribution;
-extern int *count_store_length;
-extern int *count_store_depth;
- /* in_ inline statistics */
-extern int count_in;
-extern int count_in_uniqVirt;
-extern int count_in_uniqIntf;
-extern int count_in_rejected;
-extern int count_in_rejected_mult;
-extern int count_in_outsiders;
-extern int count_in_uniqueVirt_not_inlined;
-extern int count_in_uniqueInterface_not_inlined;
-extern int count_in_maxDepth;
-extern int count_in_maxMethods;
-
-extern u2 count_in_not [512];
-
-/* instruction scheduler statistics *******************************************/
-
-extern s4 count_schedule_basic_blocks;
-extern s4 count_schedule_nodes;
-extern s4 count_schedule_leaders;
-extern s4 count_schedule_max_leaders;
-extern s4 count_schedule_critical_path;
-
-
-/* function prototypes ********************************************************/
-
-s8 getcputime(void);
-
-void loadingtime_start(void);
-void loadingtime_stop(void);
-void compilingtime_start(void);
-void compilingtime_stop(void);
-
-void print_times(void);
-void print_stats(void);
-
-void statistics_print_date(void);
-void statistics_print_memory_usage(void);
-void statistics_print_gc_memory_usage(void);
-
-void mem_usagelog(bool givewarnings);
-
-void compiledinvokation(void);
-void jnicallXmethodnvokation(void);
-void jniinvokation(void);
-
-#endif /* _STATISTICS_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/suck.c - functions to read LE ordered types from a buffer
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <stdlib.h>
-
-#include "vm/types.h"
-
-#include "arch.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/list.h"
-#include "toolbox/logging.h"
-#include "toolbox/util.h"
-
-#include "vm/exceptions.hpp"
-#include "vm/properties.h"
-#include "vm/vm.hpp"
-
-#include "vmcore/loader.h"
-#include "vmcore/options.h"
-#include "vmcore/suck.h"
-#include "vmcore/os.hpp"
-#include "vmcore/zip.h"
-
-
-/* global variables ***********************************************************/
-
-list_t *list_classpath_entries;
-
-
-/* suck_init *******************************************************************
-
- Initializes the suck subsystem like initializing the classpath
- entries list.
-
-*******************************************************************************/
-
-bool suck_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("suck_init");
-
- list_classpath_entries = list_create(OFFSET(list_classpath_entry, linkage));
-
- /* everything's ok */
-
- return true;
-}
-
-
-/* scandir_filter **************************************************************
-
- Filters for zip/jar files.
-
-*******************************************************************************/
-
-static int scandir_filter(const struct dirent *a)
-{
- s4 namlen;
-
-#if defined(_DIRENT_HAVE_D_NAMLEN)
- namlen = a->d_namlen;
-#else
- namlen = strlen(a->d_name);
-#endif
-
- if ((strncasecmp(a->d_name + namlen - 4, ".zip", 4) == 0) ||
- (strncasecmp(a->d_name + namlen - 4, ".jar", 4) == 0))
- return 1;
-
- return 0;
-}
-
-
-/* suck_add ********************************************************************
-
- Adds a classpath to the global classpath entries list.
-
-*******************************************************************************/
-
-void suck_add(char *classpath)
-{
- list_classpath_entry *lce;
- char *start;
- char *end;
- char *filename;
- s4 filenamelen;
- bool is_zip;
- char *cwd;
- s4 cwdlen;
-#if defined(ENABLE_ZLIB)
- hashtable *ht;
-#endif
-
- /* parse the classpath string */
-
- for (start = classpath; (*start) != '\0'; ) {
-
- /* search for ':' delimiter to get the end of the current entry */
- for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
-
- if (start != end) {
- is_zip = false;
- filenamelen = end - start;
-
- if (filenamelen > 4) {
- if ((strncasecmp(end - 4, ".zip", 4) == 0) ||
- (strncasecmp(end - 4, ".jar", 4) == 0)) {
- is_zip = true;
- }
- }
-
- /* save classpath entries as absolute pathnames */
-
- cwd = NULL;
- cwdlen = 0;
-
- if (*start != '/') { /* XXX fix me for win32 */
- cwd = _Jv_getcwd();
- cwdlen = strlen(cwd) + strlen("/");
- }
-
- /* allocate memory for filename and fill it */
-
- filename = MNEW(char, filenamelen + cwdlen + strlen("/") +
- strlen("0"));
-
- if (cwd) {
- strcpy(filename, cwd);
- strcat(filename, "/");
- strncat(filename, start, filenamelen);
-
- /* add cwd length to file length */
- filenamelen += cwdlen;
-
- } else {
- strncpy(filename, start, filenamelen);
- filename[filenamelen] = '\0';
- }
-
- lce = NULL;
-
- if (is_zip) {
-#if defined(ENABLE_ZLIB)
- ht = zip_open(filename);
-
- if (ht != NULL) {
- lce = NEW(list_classpath_entry);
-
- lce->type = CLASSPATH_ARCHIVE;
- lce->htclasses = ht;
- lce->path = filename;
- lce->pathlen = filenamelen;
-
- /* SUN compatible -verbose:class output */
-
- if (opt_verboseclass)
- printf("[Opened %s]\n", filename);
- }
-
-#else
- vm_abort("suck_add: zip/jar files not supported");
-#endif
- }
- else {
- if (filename[filenamelen - 1] != '/') {/* XXX fixme for win32 */
- filename[filenamelen] = '/';
- filename[filenamelen + 1] = '\0';
- filenamelen++;
- }
-
- lce = NEW(list_classpath_entry);
-
- lce->type = CLASSPATH_PATH;
- lce->path = filename;
- lce->pathlen = filenamelen;
- }
-
- /* add current classpath entry, if no error */
-
- if (lce != NULL)
- list_add_last(list_classpath_entries, lce);
- }
-
- /* goto next classpath entry, skip ':' delimiter */
-
- if ((*end) == ':')
- start = end + 1;
- else
- start = end;
- }
-}
-
-
-/* suck_add_from_property ******************************************************
-
- Adds a classpath form a property entry to the global classpath
- entries list.
-
-*******************************************************************************/
-
-void suck_add_from_property(const char *key)
-{
- const char *value;
- const char *start;
- const char *end;
- char *path;
- s4 pathlen;
- struct dirent **namelist;
- s4 n;
- s4 i;
- s4 namlen;
- char *boot_class_path;
- char *p;
-
- /* get the property value */
-
- value = properties_get(key);
-
- if (value == NULL)
- return;
-
- /* get the directory entries of the property */
-
- for (start = value; (*start) != '\0'; ) {
-
- /* search for ':' delimiter to get the end of the current entry */
-
- for (end = start; ((*end) != '\0') && ((*end) != ':'); end++);
-
- /* found an entry */
-
- if (start != end) {
- /* allocate memory for the path entry */
-
- pathlen = end - start;
- path = MNEW(char, pathlen + strlen("0"));
-
- /* copy and terminate the string */
-
- strncpy(path, start, pathlen);
- path[pathlen] = '\0';
-
- /* Reset namelist to NULL for the freeing in an error case
- (see below). */
-
- namelist = NULL;
-
- /* scan the directory found for zip/jar files */
-
- n = os_scandir(path, &namelist, scandir_filter, alphasort);
-
- /* On error, just continue, this should be ok. */
-
- if (n > 0) {
- for (i = 0; i < n; i++) {
-#if defined(_DIRENT_HAVE_D_NAMLEN)
- namlen = namelist[i]->d_namlen;
-#else
- namlen = strlen(namelist[i]->d_name);
-#endif
-
- /* Allocate memory for bootclasspath. */
-
- // FIXME Make boot_class_path const char*.
- boot_class_path = (char*) properties_get("sun.boot.class.path");
-
- p = MNEW(char,
- pathlen + strlen("/") + namlen +
- strlen(":") +
- strlen(boot_class_path) +
- strlen("0"));
-
- /* Prepend the file found to the bootclasspath. */
-
- strcpy(p, path);
- strcat(p, "/");
- strcat(p, namelist[i]->d_name);
- strcat(p, ":");
- strcat(p, boot_class_path);
-
- properties_add("sun.boot.class.path", p);
- properties_add("java.boot.class.path", p);
-
- MFREE(boot_class_path, char, strlen(boot_class_path));
-
- /* free the memory allocated by scandir */
- /* (We use `free` as the memory came from the C library.) */
-
- free(namelist[i]);
- }
- }
-
- /* On some systems (like Linux) when n == 0, then namelist
- returned from scnadir is NULL, thus we don't have to
- free it.
- (Use `free` as the memory came from the C library.) */
-
- if (namelist != NULL)
- free(namelist);
-
- MFREE(path, char, pathlen + strlen("0"));
- }
-
- /* goto next entry, skip ':' delimiter */
-
- if ((*end) == ':')
- start = end + 1;
- else
- start = end;
- }
-}
-
-
-/* suck_check_classbuffer_size *************************************************
-
- Assert that at least <len> bytes are left to read <len> is limited
- to the range of non-negative s4 values.
-
-*******************************************************************************/
-
-bool suck_check_classbuffer_size(classbuffer *cb, s4 len)
-{
-#ifdef ENABLE_VERIFIER
- if (len < 0 || ((cb->data + cb->size) - cb->pos) < len) {
- exceptions_throw_classformaterror(cb->clazz, "Truncated class file");
- return false;
- }
-#endif /* ENABLE_VERIFIER */
-
- return true;
-}
-
-
-u1 suck_u1(classbuffer *cb)
-{
- u1 a;
-
- a = SUCK_BE_U1(cb->pos);
- cb->pos++;
-
- return a;
-}
-
-
-u2 suck_u2(classbuffer *cb)
-{
- u2 a;
-
- a = SUCK_BE_U2(cb->pos);
- cb->pos += 2;
-
- return a;
-}
-
-
-u4 suck_u4(classbuffer *cb)
-{
- u4 a;
-
- a = SUCK_BE_U4(cb->pos);
- cb->pos += 4;
-
- return a;
-}
-
-
-u8 suck_u8(classbuffer *cb)
-{
-#if U8_AVAILABLE == 1
- u8 a;
-
- a = SUCK_BE_U8(cb->pos);
- cb->pos += 8;
-
- return a;
-#else
- u8 v;
-
- v.high = suck_u4(cb);
- v.low = suck_u4(cb);
-
- return v;
-#endif
-}
-
-
-float suck_float(classbuffer *cb)
-{
- float f;
-
-#if WORDS_BIGENDIAN == 0
- u1 buffer[4];
- u2 i;
-
- for (i = 0; i < 4; i++)
- buffer[3 - i] = suck_u1(cb);
-
- MCOPY((u1 *) (&f), buffer, u1, 4);
-#else
- suck_nbytes((u1*) (&f), cb, 4);
-#endif
-
- assert(sizeof(float) == 4);
-
- return f;
-}
-
-
-double suck_double(classbuffer *cb)
-{
- double d;
-
-#if WORDS_BIGENDIAN == 0
- u1 buffer[8];
- u2 i;
-
-# if defined(__ARM__) && defined(__ARMEL__) && !defined(__VFP_FP__)
- /*
- * On little endian ARM processors when using FPA, word order
- * of doubles is still big endian. So take that into account
- * here. When using VFP, word order of doubles follows byte
- * order. (michi 2005/07/24)
- */
- for (i = 0; i < 4; i++)
- buffer[3 - i] = suck_u1(cb);
- for (i = 0; i < 4; i++)
- buffer[7 - i] = suck_u1(cb);
-# else
- for (i = 0; i < 8; i++)
- buffer[7 - i] = suck_u1(cb);
-# endif /* defined(__ARM__) && ... */
-
- MCOPY((u1 *) (&d), buffer, u1, 8);
-#else
- suck_nbytes((u1*) (&d), cb, 8);
-#endif
-
- assert(sizeof(double) == 8);
-
- return d;
-}
-
-
-/* suck_nbytes *****************************************************************
-
- Transfer block of classfile data into a buffer.
-
-*******************************************************************************/
-
-void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len)
-{
- MCOPY(buffer, cb->pos, u1, len);
- cb->pos += len;
-}
-
-
-/* suck_skip_nbytes ************************************************************
-
- Skip block of classfile data.
-
-*******************************************************************************/
-
-void suck_skip_nbytes(classbuffer *cb, s4 len)
-{
- cb->pos += len;
-}
-
-
-/* suck_start ******************************************************************
-
- Returns true if classbuffer is already loaded or a file for the
- specified class has succussfully been read in. All directories of
- the searchpath are used to find the classfile (<classname>.class).
- Returns NULL if no classfile is found and writes an error message.
-
-*******************************************************************************/
-
-classbuffer *suck_start(classinfo *c)
-{
- list_classpath_entry *lce;
- char *filename;
- s4 filenamelen;
- char *path;
- FILE *classfile;
- s4 len;
- struct stat buffer;
- classbuffer *cb;
-
- /* initialize return value */
-
- cb = NULL;
-
- /* get the classname as char string (do it here for the warning at
- the end of the function) */
-
- filenamelen = utf_bytes(c->name) + strlen(".class") + strlen("0");
- filename = MNEW(char, filenamelen);
-
- utf_copy(filename, c->name);
- strcat(filename, ".class");
-
- /* walk through all classpath entries */
-
- for (lce = list_first(list_classpath_entries); lce != NULL && cb == NULL;
- lce = list_next(list_classpath_entries, lce)) {
-#if defined(ENABLE_ZLIB)
- if (lce->type == CLASSPATH_ARCHIVE) {
-
- /* enter a monitor on zip/jar archives */
-
- LOCK_MONITOR_ENTER(lce);
-
- /* try to get the file in current archive */
-
- cb = zip_get(lce, c);
-
- /* leave the monitor */
-
- LOCK_MONITOR_EXIT(lce);
-
- } else {
-#endif /* defined(ENABLE_ZLIB) */
- path = MNEW(char, lce->pathlen + filenamelen);
- strcpy(path, lce->path);
- strcat(path, filename);
-
- classfile = os_fopen(path, "r");
-
- if (classfile) { /* file exists */
- if (!os_stat(path, &buffer)) { /* read classfile data */
- cb = NEW(classbuffer);
- cb->clazz = c;
- cb->size = buffer.st_size;
- cb->data = MNEW(u1, cb->size);
- cb->pos = cb->data;
- cb->path = lce->path;
-
- /* read class data */
-
- len = os_fread((void *) cb->data, 1, cb->size,
- classfile);
-
- if (len != buffer.st_size) {
- suck_stop(cb);
-/* if (ferror(classfile)) { */
-/* } */
- }
-
- /* close the class file */
-
- os_fclose(classfile);
- }
- }
-
- MFREE(path, char, lce->pathlen + filenamelen);
-#if defined(ENABLE_ZLIB)
- }
-#endif
- }
-
- if (opt_verbose)
- if (cb == NULL)
- dolog("Warning: Can not open class file '%s'", filename);
-
- MFREE(filename, char, filenamelen);
-
- return cb;
-}
-
-
-/* suck_stop *******************************************************************
-
- Frees memory for buffer with classfile data.
-
- CAUTION: This function may only be called if buffer has been
- allocated by suck_start with reading a file.
-
-*******************************************************************************/
-
-void suck_stop(classbuffer *cb)
-{
- /* free memory */
-
- MFREE(cb->data, u1, cb->size);
- FREE(cb, classbuffer);
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/suck.h - functions to read LE ordered types from a buffer
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _SUCK_H
-#define _SUCK_H
-
-#include "config.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-#include "toolbox/list.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-
-
-/* list_classpath_entry *******************************************************/
-
-enum {
- CLASSPATH_PATH,
- CLASSPATH_ARCHIVE
-};
-
-typedef struct list_classpath_entry list_classpath_entry;
-
-struct list_classpath_entry {
-#if defined(ENABLE_THREADS)
- java_object_t header; /* monitor locking on zip/jar files */
-#endif
- s4 type;
- char *path;
- s4 pathlen;
-#if defined(ENABLE_ZLIB)
- hashtable *htclasses;
-#endif
- listnode_t linkage;
-};
-
-
-/* macros to read LE and BE types from a buffer ********************************
-
- BE macros are for Java class file loading.
- LE macros are for ZIP file loading.
-
-*******************************************************************************/
-
-/* LE macros (for ZIP files ) *************************************************/
-
-#if defined(__I386__) || defined(__X86_64__)
-
-/* we can optimize the LE access on little endian machines without alignment */
-
-#define SUCK_LE_U1(p) *((u1 *) (p))
-#define SUCK_LE_U2(p) *((u2 *) (p))
-#define SUCK_LE_U4(p) *((u4 *) (p))
-
-#if U8_AVAILABLE == 1
-#define SUCK_LE_U8(p) *((u8 *) (p))
-#endif
-
-#else /* defined(__I386__) || defined(__X86_64__) */
-
-#define SUCK_LE_U1(p) \
- ((u1) (p)[0])
-
-#define SUCK_LE_U2(p) \
- ((((u2) (p)[1]) << 8) + \
- ((u2) (p)[0]))
-
-#define SUCK_LE_U4(p) \
- ((((u4) (p)[3]) << 24) + \
- (((u4) (p)[2]) << 16) + \
- (((u4) (p)[1]) << 8) + \
- ((u4) (p)[0]))
-
-#if U8_AVAILABLE == 1
-#define SUCK_LE_U8(p) \
- ((((u8) (p)[7]) << 56) + \
- (((u8) (p)[6]) << 48) + \
- (((u8) (p)[5]) << 40) + \
- (((u8) (p)[4]) << 32) + \
- (((u8) (p)[3]) << 24) + \
- (((u8) (p)[2]) << 16) + \
- (((u8) (p)[1]) << 8) + \
- ((u8) (p)[0]))
-#endif
-
-#endif /* defined(__I386__) || defined(__X86_64__) */
-
-
-/* BE macros (for Java class files ) ******************************************/
-
-#define SUCK_BE_U1(p) \
- ((u1) (p)[0])
-
-#define SUCK_BE_U2(p) \
- ((((u2) (p)[0]) << 8) + \
- ((u2) (p)[1]))
-
-#define SUCK_BE_U4(p) \
- ((((u4) (p)[0]) << 24) + \
- (((u4) (p)[1]) << 16) + \
- (((u4) (p)[2]) << 8) + \
- ((u4) (p)[3]))
-
-#if U8_AVAILABLE == 1
-#define SUCK_BE_U8(p) \
- ((((u8) (p)[0]) << 56) + \
- (((u8) (p)[1]) << 48) + \
- (((u8) (p)[2]) << 40) + \
- (((u8) (p)[3]) << 32) + \
- (((u8) (p)[4]) << 24) + \
- (((u8) (p)[5]) << 16) + \
- (((u8) (p)[6]) << 8) + \
- ((u8) (p)[7]))
-#endif
-
-
-#define SUCK_BE_S1(p) (s1) SUCK_BE_U1(p)
-#define SUCK_BE_S2(p) (s2) SUCK_BE_U2(p)
-#define SUCK_BE_S4(p) (s4) SUCK_BE_U4(p)
-#define SUCK_BE_S8(p) (s8) SUCK_BE_U8(p)
-
-
-/* signed suck defines ********************************************************/
-
-#define suck_s1(a) (s1) suck_u1((a))
-#define suck_s2(a) (s2) suck_u2((a))
-#define suck_s4(a) (s4) suck_u4((a))
-#define suck_s8(a) (s8) suck_u8((a))
-
-
-/* export variables ***********************************************************/
-
-extern list_t *list_classpath_entries;
-
-
-/* function prototypes ********************************************************/
-
-bool suck_init(void);
-
-void suck_add(char *classpath);
-void suck_add_from_property(const char *key);
-
-bool suck_check_classbuffer_size(classbuffer *cb, s4 len);
-
-u1 suck_u1(classbuffer *cb);
-u2 suck_u2(classbuffer *cb);
-u4 suck_u4(classbuffer *cb);
-u8 suck_u8(classbuffer *cb);
-
-float suck_float(classbuffer *cb);
-double suck_double(classbuffer *cb);
-
-void suck_nbytes(u1 *buffer, classbuffer *cb, s4 len);
-void suck_skip_nbytes(classbuffer *cb, s4 len);
-
-classbuffer *suck_start(classinfo *c);
-
-void suck_stop(classbuffer *cb);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SUCK_H */
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
+++ /dev/null
-/* src/vmcore/utf8.c - utf8 string functions
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <string.h>
-#include <assert.h>
-
-#include "vm/types.h"
-
-#include "mm/memory.h"
-
-#include "threads/lock-common.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/exceptions.hpp"
-
-#include "vmcore/options.h"
-
-#if defined(ENABLE_STATISTICS)
-# include "vmcore/statistics.h"
-#endif
-
-#include "vmcore/utf8.h"
-
-
-/* global variables ***********************************************************/
-
-/* hashsize must be power of 2 */
-
-#define HASHTABLE_UTF_SIZE 16384 /* initial size of utf-hash */
-
-hashtable *hashtable_utf; /* hashtable for utf8-symbols */
-
-
-/* utf-symbols for pointer comparison of frequently used strings **************/
-
-utf *utf_java_lang_Object;
-
-utf *utf_java_lang_Class;
-utf *utf_java_lang_ClassLoader;
-utf *utf_java_lang_Cloneable;
-utf *utf_java_lang_SecurityManager;
-utf *utf_java_lang_String;
-utf *utf_java_lang_ThreadGroup;
-utf *utf_java_lang_ref_SoftReference;
-utf *utf_java_lang_ref_WeakReference;
-utf *utf_java_lang_ref_PhantomReference;
-utf *utf_java_io_Serializable;
-
-utf *utf_java_lang_Throwable;
-utf *utf_java_lang_Error;
-
-utf *utf_java_lang_AbstractMethodError;
-utf *utf_java_lang_ClassCircularityError;
-utf *utf_java_lang_ClassFormatError;
-utf *utf_java_lang_ExceptionInInitializerError;
-utf *utf_java_lang_IncompatibleClassChangeError;
-utf *utf_java_lang_InstantiationError;
-utf *utf_java_lang_InternalError;
-utf *utf_java_lang_LinkageError;
-utf *utf_java_lang_NoClassDefFoundError;
-utf *utf_java_lang_NoSuchFieldError;
-utf *utf_java_lang_NoSuchMethodError;
-utf *utf_java_lang_OutOfMemoryError;
-utf *utf_java_lang_UnsatisfiedLinkError;
-utf *utf_java_lang_UnsupportedClassVersionError;
-utf *utf_java_lang_VerifyError;
-utf *utf_java_lang_VirtualMachineError;
-
-utf *utf_java_lang_Exception;
-
-utf *utf_java_lang_ArithmeticException;
-utf *utf_java_lang_ArrayIndexOutOfBoundsException;
-utf *utf_java_lang_ArrayStoreException;
-utf *utf_java_lang_ClassCastException;
-utf *utf_java_lang_ClassNotFoundException;
-utf *utf_java_lang_CloneNotSupportedException;
-utf *utf_java_lang_IllegalAccessException;
-utf *utf_java_lang_IllegalArgumentException;
-utf *utf_java_lang_IllegalMonitorStateException;
-utf *utf_java_lang_InstantiationException;
-utf *utf_java_lang_InterruptedException;
-utf *utf_java_lang_NegativeArraySizeException;
-utf *utf_java_lang_NullPointerException;
-utf *utf_java_lang_RuntimeException;
-utf *utf_java_lang_StringIndexOutOfBoundsException;
-
-utf *utf_java_lang_reflect_InvocationTargetException;
-
-utf *utf_java_security_PrivilegedActionException;
-
-#if defined(ENABLE_JAVASE)
-utf* utf_java_lang_Void;
-#endif
-
-utf* utf_java_lang_Boolean;
-utf* utf_java_lang_Byte;
-utf* utf_java_lang_Character;
-utf* utf_java_lang_Short;
-utf* utf_java_lang_Integer;
-utf* utf_java_lang_Long;
-utf* utf_java_lang_Float;
-utf* utf_java_lang_Double;
-
-#if defined(ENABLE_JAVASE)
-utf *utf_java_lang_StackTraceElement;
-utf *utf_java_lang_reflect_Constructor;
-utf *utf_java_lang_reflect_Field;
-utf *utf_java_lang_reflect_Method;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-utf *utf_java_lang_reflect_VMConstructor;
-utf *utf_java_lang_reflect_VMField;
-utf *utf_java_lang_reflect_VMMethod;
-# endif
-
-utf *utf_java_util_Vector;
-#endif
-
-utf *utf_InnerClasses; /* InnerClasses */
-utf *utf_ConstantValue; /* ConstantValue */
-utf *utf_Code; /* Code */
-utf *utf_Exceptions; /* Exceptions */
-utf *utf_LineNumberTable; /* LineNumberTable */
-utf *utf_SourceFile; /* SourceFile */
-
-#if defined(ENABLE_JAVASE)
-utf *utf_EnclosingMethod;
-utf *utf_Signature;
-utf *utf_StackMapTable;
-
-#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
-
-utf *utf_init; /* <init> */
-utf *utf_clinit; /* <clinit> */
-utf *utf_clone; /* clone */
-utf *utf_finalize; /* finalize */
-utf *utf_invoke;
-utf *utf_main;
-utf *utf_run; /* run */
-
-utf *utf_add;
-utf *utf_dispatch;
-utf *utf_remove;
-utf *utf_addThread;
-utf *utf_removeThread;
-utf *utf_put;
-utf *utf_get;
-utf *utf_uncaughtException;
-utf *utf_value;
-
-utf *utf_fillInStackTrace;
-utf *utf_findNative;
-utf *utf_getSystemClassLoader;
-utf *utf_initCause;
-utf *utf_loadClass;
-utf *utf_loadClassInternal;
-utf *utf_printStackTrace;
-
-utf *utf_division_by_zero;
-
-utf *utf_Z; /* Z */
-utf *utf_B; /* B */
-utf *utf_C; /* C */
-utf *utf_S; /* S */
-utf *utf_I; /* I */
-utf *utf_J; /* J */
-utf *utf_F; /* F */
-utf *utf_D; /* D */
-
-utf *utf_void__void; /* ()V */
-utf *utf_boolean__void; /* (Z)V */
-utf *utf_byte__void; /* (B)V */
-utf *utf_char__void; /* (C)V */
-utf *utf_short__void; /* (S)V */
-utf *utf_int__void; /* (I)V */
-utf *utf_long__void; /* (J)V */
-utf *utf_float__void; /* (F)V */
-utf *utf_double__void; /* (D)V */
-
-utf *utf_void__java_lang_ClassLoader; /* ()Ljava/lang/ClassLoader; */
-utf *utf_void__java_lang_Object; /* ()Ljava/lang/Object; */
-utf *utf_void__java_lang_Throwable; /* ()Ljava/lang/Throwable; */
-utf *utf_java_lang_ClassLoader_java_lang_String__J;
-utf *utf_java_lang_Exception__V; /* (Ljava/lang/Exception;)V */
-utf *utf_java_lang_Object__java_lang_Object;
-utf *utf_java_lang_String__void; /* (Ljava/lang/String;)V */
-utf *utf_java_lang_String__java_lang_Class;
-utf *utf_java_lang_Thread__V; /* (Ljava/lang/Thread;)V */
-utf *utf_java_lang_Thread_java_lang_Throwable__V;
-utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
-utf *utf_java_lang_Throwable__void; /* (Ljava/lang/Throwable;)V */
-utf *utf_java_lang_Throwable__java_lang_Throwable;
-
-utf *utf_not_named_yet; /* special name for unnamed classes */
-utf *utf_null;
-utf *array_packagename;
-
-
-/* utf_init ********************************************************************
-
- Initializes the utf8 subsystem.
-
-*******************************************************************************/
-
-void utf8_init(void)
-{
- TRACESUBSYSTEMINITIALIZATION("utf8_init");
-
- /* create utf8 hashtable */
-
- hashtable_utf = NEW(hashtable);
-
- hashtable_create(hashtable_utf, HASHTABLE_UTF_SIZE);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_len += sizeof(utf*) * hashtable_utf->size;
-#endif
-
- /* create utf-symbols for pointer comparison of frequently used strings */
-
- utf_java_lang_Object = utf_new_char("java/lang/Object");
-
- utf_java_lang_Class = utf_new_char("java/lang/Class");
- utf_java_lang_ClassLoader = utf_new_char("java/lang/ClassLoader");
- utf_java_lang_Cloneable = utf_new_char("java/lang/Cloneable");
- utf_java_lang_SecurityManager = utf_new_char("java/lang/SecurityManager");
- utf_java_lang_String = utf_new_char("java/lang/String");
- utf_java_lang_ThreadGroup = utf_new_char("java/lang/ThreadGroup");
-
- utf_java_lang_ref_SoftReference =
- utf_new_char("java/lang/ref/SoftReference");
-
- utf_java_lang_ref_WeakReference =
- utf_new_char("java/lang/ref/WeakReference");
-
- utf_java_lang_ref_PhantomReference =
- utf_new_char("java/lang/ref/PhantomReference");
-
- utf_java_io_Serializable = utf_new_char("java/io/Serializable");
-
- utf_java_lang_Throwable = utf_new_char("java/lang/Throwable");
- utf_java_lang_Error = utf_new_char("java/lang/Error");
-
- utf_java_lang_ClassCircularityError =
- utf_new_char("java/lang/ClassCircularityError");
-
- utf_java_lang_ClassFormatError = utf_new_char("java/lang/ClassFormatError");
-
- utf_java_lang_ExceptionInInitializerError =
- utf_new_char("java/lang/ExceptionInInitializerError");
-
- utf_java_lang_IncompatibleClassChangeError =
- utf_new_char("java/lang/IncompatibleClassChangeError");
-
- utf_java_lang_InstantiationError =
- utf_new_char("java/lang/InstantiationError");
-
- utf_java_lang_InternalError = utf_new_char("java/lang/InternalError");
- utf_java_lang_LinkageError = utf_new_char("java/lang/LinkageError");
-
- utf_java_lang_NoClassDefFoundError =
- utf_new_char("java/lang/NoClassDefFoundError");
-
- utf_java_lang_OutOfMemoryError = utf_new_char("java/lang/OutOfMemoryError");
-
- utf_java_lang_UnsatisfiedLinkError =
- utf_new_char("java/lang/UnsatisfiedLinkError");
-
- utf_java_lang_UnsupportedClassVersionError =
- utf_new_char("java/lang/UnsupportedClassVersionError");
-
- utf_java_lang_VerifyError = utf_new_char("java/lang/VerifyError");
-
- utf_java_lang_VirtualMachineError =
- utf_new_char("java/lang/VirtualMachineError");
-
-#if defined(ENABLE_JAVASE)
- utf_java_lang_AbstractMethodError =
- utf_new_char("java/lang/AbstractMethodError");
-
- utf_java_lang_NoSuchFieldError =
- utf_new_char("java/lang/NoSuchFieldError");
-
- utf_java_lang_NoSuchMethodError =
- utf_new_char("java/lang/NoSuchMethodError");
-#endif
-
- utf_java_lang_Exception = utf_new_char("java/lang/Exception");
-
- utf_java_lang_ArithmeticException =
- utf_new_char("java/lang/ArithmeticException");
-
- utf_java_lang_ArrayIndexOutOfBoundsException =
- utf_new_char("java/lang/ArrayIndexOutOfBoundsException");
-
- utf_java_lang_ArrayStoreException =
- utf_new_char("java/lang/ArrayStoreException");
-
- utf_java_lang_ClassCastException =
- utf_new_char("java/lang/ClassCastException");
-
- utf_java_lang_ClassNotFoundException =
- utf_new_char("java/lang/ClassNotFoundException");
-
- utf_java_lang_CloneNotSupportedException =
- utf_new_char("java/lang/CloneNotSupportedException");
-
- utf_java_lang_IllegalAccessException =
- utf_new_char("java/lang/IllegalAccessException");
-
- utf_java_lang_IllegalArgumentException =
- utf_new_char("java/lang/IllegalArgumentException");
-
- utf_java_lang_IllegalMonitorStateException =
- utf_new_char("java/lang/IllegalMonitorStateException");
-
- utf_java_lang_InstantiationException =
- utf_new_char("java/lang/InstantiationException");
-
- utf_java_lang_InterruptedException =
- utf_new_char("java/lang/InterruptedException");
-
- utf_java_lang_NegativeArraySizeException =
- utf_new_char("java/lang/NegativeArraySizeException");
-
- utf_java_lang_NullPointerException =
- utf_new_char("java/lang/NullPointerException");
-
- utf_java_lang_RuntimeException =
- utf_new_char("java/lang/RuntimeException");
-
- utf_java_lang_StringIndexOutOfBoundsException =
- utf_new_char("java/lang/StringIndexOutOfBoundsException");
-
- utf_java_lang_reflect_InvocationTargetException =
- utf_new_char("java/lang/reflect/InvocationTargetException");
-
- utf_java_security_PrivilegedActionException =
- utf_new_char("java/security/PrivilegedActionException");
-
-#if defined(ENABLE_JAVASE)
- utf_java_lang_Void = utf_new_char("java/lang/Void");
-#endif
-
- utf_java_lang_Boolean = utf_new_char("java/lang/Boolean");
- utf_java_lang_Byte = utf_new_char("java/lang/Byte");
- utf_java_lang_Character = utf_new_char("java/lang/Character");
- utf_java_lang_Short = utf_new_char("java/lang/Short");
- utf_java_lang_Integer = utf_new_char("java/lang/Integer");
- utf_java_lang_Long = utf_new_char("java/lang/Long");
- utf_java_lang_Float = utf_new_char("java/lang/Float");
- utf_java_lang_Double = utf_new_char("java/lang/Double");
-
-#if defined(ENABLE_JAVASE)
- utf_java_lang_StackTraceElement =
- utf_new_char("java/lang/StackTraceElement");
-
- utf_java_lang_reflect_Constructor =
- utf_new_char("java/lang/reflect/Constructor");
-
- utf_java_lang_reflect_Field = utf_new_char("java/lang/reflect/Field");
- utf_java_lang_reflect_Method = utf_new_char("java/lang/reflect/Method");
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
- utf_java_lang_reflect_VMConstructor = utf_new_char("java/lang/reflect/VMConstructor");
- utf_java_lang_reflect_VMField = utf_new_char("java/lang/reflect/VMField");
- utf_java_lang_reflect_VMMethod = utf_new_char("java/lang/reflect/VMMethod");
-# endif
-
- utf_java_util_Vector = utf_new_char("java/util/Vector");
-#endif
-
- utf_InnerClasses = utf_new_char("InnerClasses");
- utf_ConstantValue = utf_new_char("ConstantValue");
- utf_Code = utf_new_char("Code");
- utf_Exceptions = utf_new_char("Exceptions");
- utf_LineNumberTable = utf_new_char("LineNumberTable");
- utf_SourceFile = utf_new_char("SourceFile");
-
-#if defined(ENABLE_JAVASE)
- utf_EnclosingMethod = utf_new_char("EnclosingMethod");
- utf_Signature = utf_new_char("Signature");
- utf_StackMapTable = utf_new_char("StackMapTable");
-
-# if defined(ENABLE_ANNOTATIONS)
- utf_RuntimeVisibleAnnotations = utf_new_char("RuntimeVisibleAnnotations");
- utf_RuntimeInvisibleAnnotations = utf_new_char("RuntimeInvisibleAnnotations");
- utf_RuntimeVisibleParameterAnnotations = utf_new_char("RuntimeVisibleParameterAnnotations");
- utf_RuntimeInvisibleParameterAnnotations = utf_new_char("RuntimeInvisibleParameterAnnotations");
- utf_AnnotationDefault = utf_new_char("AnnotationDefault");
-# endif
-#endif
-
- utf_init = utf_new_char("<init>");
- utf_clinit = utf_new_char("<clinit>");
- utf_clone = utf_new_char("clone");
- utf_finalize = utf_new_char("finalize");
- utf_invoke = utf_new_char("invoke");
- utf_main = utf_new_char("main");
- utf_run = utf_new_char("run");
-
- utf_add = utf_new_char("add");
- utf_dispatch = utf_new_char("dispatch");
- utf_remove = utf_new_char("remove");
- utf_addThread = utf_new_char("addThread");
- utf_removeThread = utf_new_char("removeThread");
- utf_put = utf_new_char("put");
- utf_get = utf_new_char("get");
- utf_uncaughtException = utf_new_char("uncaughtException");
- utf_value = utf_new_char("value");
-
- utf_fillInStackTrace = utf_new_char("fillInStackTrace");
- utf_findNative = utf_new_char("findNative");
- utf_getSystemClassLoader = utf_new_char("getSystemClassLoader");
- utf_initCause = utf_new_char("initCause");
- utf_loadClass = utf_new_char("loadClass");
- utf_loadClassInternal = utf_new_char("loadClassInternal");
- utf_printStackTrace = utf_new_char("printStackTrace");
-
- utf_division_by_zero = utf_new_char("/ by zero");
-
- utf_Z = utf_new_char("Z");
- utf_B = utf_new_char("B");
- utf_C = utf_new_char("C");
- utf_S = utf_new_char("S");
- utf_I = utf_new_char("I");
- utf_J = utf_new_char("J");
- utf_F = utf_new_char("F");
- utf_D = utf_new_char("D");
-
- utf_void__void = utf_new_char("()V");
- utf_boolean__void = utf_new_char("(Z)V");
- utf_byte__void = utf_new_char("(B)V");
- utf_char__void = utf_new_char("(C)V");
- utf_short__void = utf_new_char("(S)V");
- utf_int__void = utf_new_char("(I)V");
- utf_long__void = utf_new_char("(J)V");
- utf_float__void = utf_new_char("(F)V");
- utf_double__void = utf_new_char("(D)V");
- utf_void__java_lang_Object = utf_new_char("()Ljava/lang/Object;");
- utf_void__java_lang_Throwable = utf_new_char("()Ljava/lang/Throwable;");
-
- utf_void__java_lang_ClassLoader =
- utf_new_char("()Ljava/lang/ClassLoader;");
-
- utf_java_lang_ClassLoader_java_lang_String__J =
- utf_new_char("(Ljava/lang/ClassLoader;Ljava/lang/String;)J");
-
- utf_java_lang_Exception__V = utf_new_char("(Ljava/lang/Exception;)V");
-
- utf_java_lang_Object__java_lang_Object =
- utf_new_char("(Ljava/lang/Object;)Ljava/lang/Object;");
-
- utf_java_lang_String__void = utf_new_char("(Ljava/lang/String;)V");
-
- utf_java_lang_String__java_lang_Class =
- utf_new_char("(Ljava/lang/String;)Ljava/lang/Class;");
-
- utf_java_lang_Thread__V = utf_new_char("(Ljava/lang/Thread;)V");
-
- utf_java_lang_Thread_java_lang_Throwable__V =
- utf_new_char("(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
-
- utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V =
- utf_new_char("(Ljava/lang/ThreadGroup;Ljava/lang/String;)V");
-
- utf_java_lang_Throwable__void = utf_new_char("(Ljava/lang/Throwable;)V");
-
- utf_java_lang_Throwable__java_lang_Throwable =
- utf_new_char("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
-
- utf_null = utf_new_char("null");
- utf_not_named_yet = utf_new_char("\t<not_named_yet>");
- array_packagename = utf_new_char("\t<the array package>");
-}
-
-
-/* utf_hashkey *****************************************************************
-
- The hashkey is computed from the utf-text by using up to 8
- characters. For utf-symbols longer than 15 characters 3 characters
- are taken from the beginning and the end, 2 characters are taken
- from the middle.
-
-*******************************************************************************/
-
-#define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
-#define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
-
-u4 utf_hashkey(const char *text, u4 length)
-{
- const char *start_pos = text; /* pointer to utf text */
- u4 a;
-
- switch (length) {
- case 0: /* empty string */
- return 0;
-
- case 1: return fbs(0);
- case 2: return fbs(0) ^ nbs(3);
- case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
- case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
- case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
- case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
- case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
- case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
-
- case 9:
- a = fbs(0);
- a ^= nbs(1);
- a ^= nbs(2);
- text++;
- return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
-
- case 10:
- a = fbs(0);
- text++;
- a ^= nbs(2);
- a ^= nbs(3);
- a ^= nbs(4);
- text++;
- return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
-
- case 11:
- a = fbs(0);
- text++;
- a ^= nbs(2);
- a ^= nbs(3);
- a ^= nbs(4);
- text++;
- return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
-
- case 12:
- a = fbs(0);
- text += 2;
- a ^= nbs(2);
- a ^= nbs(3);
- text++;
- a ^= nbs(5);
- a ^= nbs(6);
- a ^= nbs(7);
- text++;
- return a ^ nbs(9) ^ nbs(10);
-
- case 13:
- a = fbs(0);
- a ^= nbs(1);
- text++;
- a ^= nbs(3);
- a ^= nbs(4);
- text += 2;
- a ^= nbs(7);
- a ^= nbs(8);
- text += 2;
- return a ^ nbs(9) ^ nbs(10);
-
- case 14:
- a = fbs(0);
- text += 2;
- a ^= nbs(3);
- a ^= nbs(4);
- text += 2;
- a ^= nbs(7);
- a ^= nbs(8);
- text += 2;
- return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
-
- case 15:
- a = fbs(0);
- text += 2;
- a ^= nbs(3);
- a ^= nbs(4);
- text += 2;
- a ^= nbs(7);
- a ^= nbs(8);
- text += 2;
- return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
-
- default: /* 3 characters from beginning */
- a = fbs(0);
- text += 2;
- a ^= nbs(3);
- a ^= nbs(4);
-
- /* 2 characters from middle */
- text = start_pos + (length / 2);
- a ^= fbs(5);
- text += 2;
- a ^= nbs(6);
-
- /* 3 characters from end */
- text = start_pos + length - 4;
-
- a ^= fbs(7);
- text++;
-
- return a ^ nbs(10) ^ nbs(11);
- }
-}
-
-/* utf_full_hashkey ************************************************************
-
- This function computes a hash value using all bytes in the string.
-
- The algorithm is the "One-at-a-time" algorithm as published
- by Bob Jenkins on http://burtleburtle.net/bob/hash/doobs.html.
-
-*******************************************************************************/
-
-u4 utf_full_hashkey(const char *text, u4 length)
-{
- register const unsigned char *p = (const unsigned char *) text;
- register u4 hash;
- register u4 i;
-
- hash = 0;
- for (i=length; i--;)
- {
- hash += *p++;
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
- hash += (hash << 3);
- hash ^= (hash >> 11);
- hash += (hash << 15);
-
- return hash;
-}
-
-/* unicode_hashkey *************************************************************
-
- Compute the hashkey of a unicode string.
-
-*******************************************************************************/
-
-u4 unicode_hashkey(u2 *text, u2 len)
-{
- return utf_hashkey((char *) text, len);
-}
-
-
-/* utf_new *********************************************************************
-
- Creates a new utf-symbol, the text of the symbol is passed as a
- u1-array. The function searches the utf-hashtable for a utf-symbol
- with this text. On success the element returned, otherwise a new
- hashtable element is created.
-
- If the number of entries in the hashtable exceeds twice the size of
- the hashtable slots a reorganization of the hashtable is done and
- the utf symbols are copied to a new hashtable with doubled size.
-
-*******************************************************************************/
-
-utf *utf_new(const char *text, u2 length)
-{
- u4 key; /* hashkey computed from utf-text */
- u4 slot; /* slot in hashtable */
- utf *u; /* hashtable element */
- u2 i;
-
- LOCK_MONITOR_ENTER(hashtable_utf->header);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_new++;
-#endif
-
- key = utf_hashkey(text, length);
- slot = key & (hashtable_utf->size - 1);
- u = hashtable_utf->ptr[slot];
-
- /* search external hash chain for utf-symbol */
-
- while (u) {
- if (u->blength == length) {
- /* compare text of hashtable elements */
-
- for (i = 0; i < length; i++)
- if (text[i] != u->text[i])
- goto nomatch;
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_new_found++;
-#endif
-
- /* symbol found in hashtable */
-
- LOCK_MONITOR_EXIT(hashtable_utf->header);
-
- return u;
- }
-
- nomatch:
- u = u->hashlink; /* next element in external chain */
- }
-
- /* location in hashtable found, create new utf element */
-
- u = NEW(utf);
-
- u->blength = length; /* length in bytes of utfstring */
- u->hashlink = hashtable_utf->ptr[slot]; /* link in external hashchain */
- u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
-
- memcpy(u->text, text, length); /* copy utf-text */
- u->text[length] = '\0';
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_len += sizeof(utf) + length + 1;
-#endif
-
- hashtable_utf->ptr[slot] = u; /* insert symbol into table */
- hashtable_utf->entries++; /* update number of entries */
-
- if (hashtable_utf->entries > (hashtable_utf->size * 2)) {
-
- /* reorganization of hashtable, average length of the external
- chains is approx. 2 */
-
- hashtable *newhash; /* the new hashtable */
- u4 i;
- utf *u;
- utf *nextu;
- u4 slot;
-
- /* create new hashtable, double the size */
-
- newhash = hashtable_resize(hashtable_utf, hashtable_utf->size * 2);
-
-#if defined(ENABLE_STATISTICS)
- if (opt_stat)
- count_utf_len += sizeof(utf*) * hashtable_utf->size;
-#endif
-
- /* transfer elements to new hashtable */
-
- for (i = 0; i < hashtable_utf->size; i++) {
- u = hashtable_utf->ptr[i];
-
- while (u) {
- nextu = u->hashlink;
- slot = utf_hashkey(u->text, u->blength) & (newhash->size - 1);
-
- u->hashlink = (utf *) newhash->ptr[slot];
- newhash->ptr[slot] = u;
-
- /* follow link in external hash chain */
-
- u = nextu;
- }
- }
-
- /* dispose old table */
-
- hashtable_free(hashtable_utf);
-
- hashtable_utf = newhash;
- }
-
- LOCK_MONITOR_EXIT(hashtable_utf->header);
-
- return u;
-}
-
-
-/* utf_new_u2 ******************************************************************
-
- Make utf symbol from u2 array, if isclassname is true '.' is
- replaced by '/'.
-
-*******************************************************************************/
-
-utf *utf_new_u2(u2 *unicode_pos, u4 unicode_length, bool isclassname)
-{
- char *buffer; /* memory buffer for unicode characters */
- char *pos; /* pointer to current position in buffer */
- u4 left; /* unicode characters left */
- u4 buflength; /* utf length in bytes of the u2 array */
- utf *result; /* resulting utf-string */
- int i;
-
- /* determine utf length in bytes and allocate memory */
-
- buflength = u2_utflength(unicode_pos, unicode_length);
- buffer = MNEW(char, buflength);
-
- left = buflength;
- pos = buffer;
-
- for (i = 0; i++ < unicode_length; unicode_pos++) {
- /* next unicode character */
- u2 c = *unicode_pos;
-
- if ((c != 0) && (c < 0x80)) {
- /* 1 character */
- left--;
- if ((int) left < 0) break;
- /* convert classname */
- if (isclassname && c == '.')
- *pos++ = '/';
- else
- *pos++ = (char) c;
-
- } else if (c < 0x800) {
- /* 2 characters */
- unsigned char high = c >> 6;
- unsigned char low = c & 0x3F;
- left = left - 2;
- if ((int) left < 0) break;
- *pos++ = high | 0xC0;
- *pos++ = low | 0x80;
-
- } else {
- /* 3 characters */
- char low = c & 0x3f;
- char mid = (c >> 6) & 0x3F;
- char high = c >> 12;
- left = left - 3;
- if ((int) left < 0) break;
- *pos++ = high | 0xE0;
- *pos++ = mid | 0x80;
- *pos++ = low | 0x80;
- }
- }
-
- /* insert utf-string into symbol-table */
- result = utf_new(buffer,buflength);
-
- MFREE(buffer, char, buflength);
-
- return result;
-}
-
-
-/* utf_new_char ****************************************************************
-
- Creates a new utf symbol, the text for this symbol is passed as a
- c-string ( = char* ).
-
-*******************************************************************************/
-
-utf *utf_new_char(const char *text)
-{
- return utf_new(text, strlen(text));
-}
-
-
-/* utf_new_char_classname ******************************************************
-
- Creates a new utf symbol, the text for this symbol is passed as a
- c-string ( = char* ) "." characters are going to be replaced by
- "/". Since the above function is used often, this is a separte
- function, instead of an if.
-
-*******************************************************************************/
-
-utf *utf_new_char_classname(const char *text)
-{
- if (strchr(text, '.')) {
- char *txt = strdup(text);
- char *end = txt + strlen(txt);
- char *c;
- utf *tmpRes;
-
- for (c = txt; c < end; c++)
- if (*c == '.') *c = '/';
-
- tmpRes = utf_new(txt, strlen(txt));
- FREE(txt, 0);
-
- return tmpRes;
-
- } else
- return utf_new(text, strlen(text));
-}
-
-
-/* utf_nextu2 ******************************************************************
-
- Read the next unicode character from the utf string and increment
- the utf-string pointer accordingly.
-
- CAUTION: This function is unsafe for input that was not checked
- by is_valid_utf!
-
-*******************************************************************************/
-
-u2 utf_nextu2(char **utf_ptr)
-{
- /* uncompressed unicode character */
- u2 unicode_char = 0;
- /* current position in utf text */
- unsigned char *utf = (unsigned char *) (*utf_ptr);
- /* bytes representing the unicode character */
- unsigned char ch1, ch2, ch3;
- /* number of bytes used to represent the unicode character */
- int len = 0;
-
- switch ((ch1 = utf[0]) >> 4) {
- default: /* 1 byte */
- (*utf_ptr)++;
- return (u2) ch1;
- case 0xC:
- case 0xD: /* 2 bytes */
- if (((ch2 = utf[1]) & 0xC0) == 0x80) {
- unsigned char high = ch1 & 0x1F;
- unsigned char low = ch2 & 0x3F;
- unicode_char = (high << 6) + low;
- len = 2;
- }
- break;
-
- case 0xE: /* 2 or 3 bytes */
- if (((ch2 = utf[1]) & 0xC0) == 0x80) {
- if (((ch3 = utf[2]) & 0xC0) == 0x80) {
- unsigned char low = ch3 & 0x3f;
- unsigned char mid = ch2 & 0x3f;
- unsigned char high = ch1 & 0x0f;
- unicode_char = (((high << 6) + mid) << 6) + low;
- len = 3;
- } else
- len = 2;
- }
- break;
- }
-
- /* update position in utf-text */
- *utf_ptr = (char *) (utf + len);
-
- return unicode_char;
-}
-
-
-/* utf_bytes *******************************************************************
-
- Determine number of bytes (aka. octets) in the utf string.
-
- IN:
- u............utf string
-
- OUT:
- The number of octets of this utf string.
- There is _no_ terminating zero included in this count.
-
-*******************************************************************************/
-
-u4 utf_bytes(utf *u)
-{
- return u->blength;
-}
-
-
-/* utf_get_number_of_u2s_for_buffer ********************************************
-
- Determine number of UTF-16 u2s in the given UTF-8 buffer
-
- CAUTION: This function is unsafe for input that was not checked
- by is_valid_utf!
-
- CAUTION: Use this function *only* when you want to convert an UTF-8 buffer
- to an array of u2s (UTF-16) and want to know how many of them you will get.
- All other uses of this function are probably wrong.
-
- IN:
- buffer........points to first char in buffer
- blength.......number of _bytes_ in the buffer
-
- OUT:
- the number of u2s needed to hold this string in UTF-16 encoding.
- There is _no_ terminating zero included in this count.
-
- NOTE: Unlike utf_get_number_of_u2s, this function never throws an
- exception.
-
-*******************************************************************************/
-
-u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength)
-{
- const char *endpos; /* points behind utf string */
- const char *utf_ptr; /* current position in utf text */
- u4 len = 0; /* number of unicode characters */
-
- utf_ptr = buffer;
- endpos = utf_ptr + blength;
-
- while (utf_ptr < endpos) {
- len++;
- /* next unicode character */
- utf_nextu2((char **)&utf_ptr);
- }
-
- assert(utf_ptr == endpos);
-
- return len;
-}
-
-
-/* utf_get_number_of_u2s *******************************************************
-
- Determine number of UTF-16 u2s in the utf string.
-
- CAUTION: This function is unsafe for input that was not checked
- by is_valid_utf!
-
- CAUTION: Use this function *only* when you want to convert a utf string
- to an array of u2s and want to know how many of them you will get.
- All other uses of this function are probably wrong.
-
- IN:
- u............utf string
-
- OUT:
- the number of u2s needed to hold this string in UTF-16 encoding.
- There is _no_ terminating zero included in this count.
- XXX 0 if a NullPointerException has been thrown (see below)
-
-*******************************************************************************/
-
-u4 utf_get_number_of_u2s(utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
- u4 len = 0; /* number of unicode characters */
-
- /* XXX this is probably not checked by most callers! Review this after */
- /* the invalid uses of this function have been eliminated */
- if (u == NULL) {
- exceptions_throw_nullpointerexception();
- return 0;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- len++;
- /* next unicode character */
- utf_nextu2(&utf_ptr);
- }
-
- if (utf_ptr != endpos) {
- /* string ended abruptly */
- exceptions_throw_internalerror("Illegal utf8 string");
- return 0;
- }
-
- return len;
-}
-
-
-/* utf8_safe_number_of_u2s *****************************************************
-
- Determine number of UTF-16 u2s needed for decoding the given UTF-8 string.
- (For invalid UTF-8 the U+fffd replacement character will be counted.)
-
- This function is safe even for invalid UTF-8 strings.
-
- IN:
- text..........zero-terminated(!) UTF-8 string (may be invalid)
- must NOT be NULL
- nbytes........strlen(text). (This is needed to completely emulate
- the RI).
-
- OUT:
- the number of u2s needed to hold this string in UTF-16 encoding.
- There is _no_ terminating zero included in this count.
-
-*******************************************************************************/
-
-s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes) {
- register const unsigned char *t;
- register s4 byte;
- register s4 len;
- register const unsigned char *tlimit;
- s4 byte1;
- s4 byte2;
- s4 byte3;
- s4 value;
- s4 skip;
-
- assert(text);
- assert(nbytes >= 0);
-
- len = 0;
- t = (const unsigned char *) text;
- tlimit = t + nbytes;
-
- /* CAUTION: Keep this code in sync with utf8_safe_convert_to_u2s! */
-
- while (1) {
- byte = *t++;
-
- if (byte & 0x80) {
- /* highest bit set, non-ASCII character */
-
- if ((byte & 0xe0) == 0xc0) {
- /* 2-byte: should be 110..... 10...... ? */
-
- if ((*t++ & 0xc0) == 0x80)
- ; /* valid 2-byte */
- else
- t--; /* invalid */
- }
- else if ((byte & 0xf0) == 0xe0) {
- /* 3-byte: should be 1110.... 10...... 10...... */
- /* ^t */
-
- if (t + 2 > tlimit)
- return len + 1; /* invalid, stop here */
-
- if ((*t++ & 0xc0) == 0x80) {
- if ((*t++ & 0xc0) == 0x80)
- ; /* valid 3-byte */
- else
- t--; /* invalid */
- }
- else
- t--; /* invalid */
- }
- else if ((byte & 0xf8) == 0xf0) {
- /* 4-byte: should be 11110... 10...... 10...... 10...... */
- /* ^t */
-
- if (t + 3 > tlimit)
- return len + 1; /* invalid, stop here */
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- if (((byte2 = *t++) & 0xc0) == 0x80) {
- if (((byte3 = *t++) & 0xc0) == 0x80) {
- /* valid 4-byte UTF-8? */
- value = ((byte & 0x07) << 18)
- | ((byte1 & 0x3f) << 12)
- | ((byte2 & 0x3f) << 6)
- | ((byte3 & 0x3f) );
-
- if (value > 0x10FFFF)
- ; /* invalid */
- else if (value > 0xFFFF)
- len += 1; /* we need surrogates */
- else
- ; /* 16bit suffice */
- }
- else
- t--; /* invalid */
- }
- else
- t--; /* invalid */
- }
- else
- t--; /* invalid */
- }
- else if ((byte & 0xfc) == 0xf8) {
- /* invalid 5-byte */
- if (t + 4 > tlimit)
- return len + 1; /* invalid, stop here */
-
- skip = 4;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- }
- else if ((byte & 0xfe) == 0xfc) {
- /* invalid 6-byte */
- if (t + 5 > tlimit)
- return len + 1; /* invalid, stop here */
-
- skip = 5;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- }
- else
- ; /* invalid */
- }
- else {
- /* NUL */
-
- if (byte == 0)
- break;
-
- /* ASCII character, common case */
- }
-
- len++;
- }
-
- return len;
-}
-
-
-/* utf8_safe_convert_to_u2s ****************************************************
-
- Convert the given UTF-8 string to UTF-16 into a pre-allocated buffer.
- (Invalid UTF-8 will be replaced with the U+fffd replacement character.)
- Use utf8_safe_number_of_u2s to determine the number of u2s to allocate.
-
- This function is safe even for invalid UTF-8 strings.
-
- IN:
- text..........zero-terminated(!) UTF-8 string (may be invalid)
- must NOT be NULL
- nbytes........strlen(text). (This is needed to completely emulate
- the RI).
- buffer........a preallocated array of u2s to receive the decoded
- string. Use utf8_safe_number_of_u2s to get the
- required number of u2s for allocating this.
-
-*******************************************************************************/
-
-#define UNICODE_REPLACEMENT 0xfffd
-
-void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer) {
- register const unsigned char *t;
- register s4 byte;
- register const unsigned char *tlimit;
- s4 byte1;
- s4 byte2;
- s4 byte3;
- s4 value;
- s4 skip;
-
- assert(text);
- assert(nbytes >= 0);
-
- t = (const unsigned char *) text;
- tlimit = t + nbytes;
-
- /* CAUTION: Keep this code in sync with utf8_safe_number_of_u2s! */
-
- while (1) {
- byte = *t++;
-
- if (byte & 0x80) {
- /* highest bit set, non-ASCII character */
-
- if ((byte & 0xe0) == 0xc0) {
- /* 2-byte: should be 110..... 10...... */
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- /* valid 2-byte UTF-8 */
- *buffer++ = ((byte & 0x1f) << 6)
- | ((byte1 & 0x3f) );
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else if ((byte & 0xf0) == 0xe0) {
- /* 3-byte: should be 1110.... 10...... 10...... */
-
- if (t + 2 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- if (((byte2 = *t++) & 0xc0) == 0x80) {
- /* valid 3-byte UTF-8 */
- *buffer++ = ((byte & 0x0f) << 12)
- | ((byte1 & 0x3f) << 6)
- | ((byte2 & 0x3f) );
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else if ((byte & 0xf8) == 0xf0) {
- /* 4-byte: should be 11110... 10...... 10...... 10...... */
-
- if (t + 3 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- if (((byte1 = *t++) & 0xc0) == 0x80) {
- if (((byte2 = *t++) & 0xc0) == 0x80) {
- if (((byte3 = *t++) & 0xc0) == 0x80) {
- /* valid 4-byte UTF-8? */
- value = ((byte & 0x07) << 18)
- | ((byte1 & 0x3f) << 12)
- | ((byte2 & 0x3f) << 6)
- | ((byte3 & 0x3f) );
-
- if (value > 0x10FFFF) {
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else if (value > 0xFFFF) {
- /* we need surrogates */
- *buffer++ = 0xd800 | ((value >> 10) - 0x40);
- *buffer++ = 0xdc00 | (value & 0x03ff);
- }
- else
- *buffer++ = value; /* 16bit suffice */
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else {
- *buffer++ = UNICODE_REPLACEMENT;
- t--;
- }
- }
- else if ((byte & 0xfc) == 0xf8) {
- if (t + 4 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- skip = 4;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else if ((byte & 0xfe) == 0xfc) {
- if (t + 5 > tlimit) {
- *buffer++ = UNICODE_REPLACEMENT;
- return;
- }
-
- skip = 5;
- for (; skip && ((*t & 0xc0) == 0x80); --skip)
- t++;
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else
- *buffer++ = UNICODE_REPLACEMENT;
- }
- else {
- /* NUL */
-
- if (byte == 0)
- break;
-
- /* ASCII character, common case */
-
- *buffer++ = byte;
- }
- }
-}
-
-
-/* u2_utflength ****************************************************************
-
- Returns the utf length in bytes of a u2 array.
-
-*******************************************************************************/
-
-u4 u2_utflength(u2 *text, u4 u2_length)
-{
- u4 result_len = 0; /* utf length in bytes */
- u2 ch; /* current unicode character */
- u4 len;
-
- for (len = 0; len < u2_length; len++) {
- /* next unicode character */
- ch = *text++;
-
- /* determine bytes required to store unicode character as utf */
- if (ch && (ch < 0x80))
- result_len++;
- else if (ch < 0x800)
- result_len += 2;
- else
- result_len += 3;
- }
-
- return result_len;
-}
-
-
-/* utf_copy ********************************************************************
-
- Copy the given utf string byte-for-byte to a buffer.
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_copy(char *buffer, utf *u)
-{
- /* our utf strings are zero-terminated (done by utf_new) */
- MCOPY(buffer, u->text, char, u->blength + 1);
-}
-
-
-/* utf_cat *********************************************************************
-
- Append the given utf string byte-for-byte to a buffer.
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_cat(char *buffer, utf *u)
-{
- /* our utf strings are zero-terminated (done by utf_new) */
- MCOPY(buffer + strlen(buffer), u->text, char, u->blength + 1);
-}
-
-
-/* utf_copy_classname **********************************************************
-
- Copy the given utf classname byte-for-byte to a buffer.
- '/' is replaced by '.'
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_copy_classname(char *buffer, utf *u)
-{
- char *bufptr;
- char *srcptr;
- char *endptr;
- char ch;
-
- bufptr = buffer;
- srcptr = u->text;
- endptr = UTF_END(u) + 1; /* utfs are zero-terminared by utf_new */
-
- while (srcptr != endptr) {
- ch = *srcptr++;
- if (ch == '/')
- ch = '.';
- *bufptr++ = ch;
- }
-}
-
-
-/* utf_cat *********************************************************************
-
- Append the given utf classname byte-for-byte to a buffer.
- '/' is replaced by '.'
-
- IN:
- buffer.......the buffer
- u............the utf string
-
-*******************************************************************************/
-
-void utf_cat_classname(char *buffer, utf *u)
-{
- utf_copy_classname(buffer + strlen(buffer), u);
-}
-
-/* utf_display_printable_ascii *************************************************
-
- Write utf symbol to stdout (for debugging purposes).
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_display_printable_ascii(utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (u == NULL) {
- printf("NULL");
- fflush(stdout);
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
-
- u2 c = utf_nextu2(&utf_ptr);
-
- if ((c >= 32) && (c <= 127))
- printf("%c", c);
- else
- printf("?");
- }
-
- fflush(stdout);
-}
-
-
-/* utf_display_printable_ascii_classname ***************************************
-
- Write utf symbol to stdout with `/' converted to `.' (for debugging
- purposes).
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_display_printable_ascii_classname(utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (u == NULL) {
- printf("NULL");
- fflush(stdout);
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
-
- u2 c = utf_nextu2(&utf_ptr);
-
- if (c == '/')
- c = '.';
-
- if ((c >= 32) && (c <= 127))
- printf("%c", c);
- else
- printf("?");
- }
-
- fflush(stdout);
-}
-
-
-/* utf_sprint_convert_to_latin1 ************************************************
-
- Write utf symbol into c-string (for debugging purposes).
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_sprint_convert_to_latin1(char *buffer, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
- u2 pos = 0; /* position in c-string */
-
- if (!u) {
- strcpy(buffer, "NULL");
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos)
- /* copy next unicode character */
- buffer[pos++] = utf_nextu2(&utf_ptr);
-
- /* terminate string */
- buffer[pos] = '\0';
-}
-
-
-/* utf_sprint_convert_to_latin1_classname **************************************
-
- Write utf symbol into c-string with `/' converted to `.' (for debugging
- purposes).
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
- u2 pos = 0; /* position in c-string */
-
- if (!u) {
- strcpy(buffer, "NULL");
- return;
- }
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* copy next unicode character */
- u2 c = utf_nextu2(&utf_ptr);
- if (c == '/') c = '.';
- buffer[pos++] = c;
- }
-
- /* terminate string */
- buffer[pos] = '\0';
-}
-
-
-/* utf_strcat_convert_to_latin1 ************************************************
-
- Like libc strcat, but uses an utf8 string.
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_strcat_convert_to_latin1(char *buffer, utf *u)
-{
- utf_sprint_convert_to_latin1(buffer + strlen(buffer), u);
-}
-
-
-/* utf_strcat_convert_to_latin1_classname **************************************
-
- Like libc strcat, but uses an utf8 string.
- Characters are converted to 8-bit Latin-1, non-Latin-1 characters yield
- invalid results.
-
-*******************************************************************************/
-
-void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u)
-{
- utf_sprint_convert_to_latin1_classname(buffer + strlen(buffer), u);
-}
-
-
-/* utf_fprint_printable_ascii **************************************************
-
- Write utf symbol into file.
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_fprint_printable_ascii(FILE *file, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (!u)
- return;
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
- u2 c = utf_nextu2(&utf_ptr);
-
- if (c >= 32 && c <= 127) fprintf(file, "%c", c);
- else fprintf(file, "?");
- }
-}
-
-
-/* utf_fprint_printable_ascii_classname ****************************************
-
- Write utf symbol into file with `/' converted to `.'.
- Non-printable and non-ASCII characters are printed as '?'.
-
-*******************************************************************************/
-
-void utf_fprint_printable_ascii_classname(FILE *file, utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
-
- if (!u)
- return;
-
- endpos = UTF_END(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- /* read next unicode character */
- u2 c = utf_nextu2(&utf_ptr);
- if (c == '/') c = '.';
-
- if (c >= 32 && c <= 127) fprintf(file, "%c", c);
- else fprintf(file, "?");
- }
-}
-
-
-/* is_valid_utf ****************************************************************
-
- Return true if the given string is a valid UTF-8 string.
-
- utf_ptr...points to first character
- end_pos...points after last character
-
-*******************************************************************************/
-
-/* static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26}; */
-
-bool is_valid_utf(char *utf_ptr, char *end_pos)
-{
- int bytes;
- int len,i;
- char c;
- unsigned long v;
-
- if (end_pos < utf_ptr) return false;
- bytes = end_pos - utf_ptr;
- while (bytes--) {
- c = *utf_ptr++;
-
- if (!c) return false; /* 0x00 is not allowed */
- if ((c & 0x80) == 0) continue; /* ASCII */
-
- if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
- else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
- else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
- else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
- else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
- else return false; /* invalid leading byte */
-
- if (len > 2) return false; /* Java limitation */
-
- v = (unsigned long)c & (0x3f >> len);
-
- if ((bytes -= len) < 0) return false; /* missing bytes */
-
- for (i = len; i--; ) {
- c = *utf_ptr++;
- if ((c & 0xc0) != 0x80) /* 10xx xxxx */
- return false;
- v = (v << 6) | (c & 0x3f);
- }
-
- if (v == 0) {
- if (len != 1) return false; /* Java special */
-
- } else {
- /* Sun Java seems to allow overlong UTF-8 encodings */
-
- /* if (v < min_codepoint[len]) */
- /* XXX throw exception? */
- }
-
- /* surrogates in UTF-8 seem to be allowed in Java classfiles */
- /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
-
- /* even these seem to be allowed */
- /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
- }
-
- return true;
-}
-
-
-/* is_valid_name ***************************************************************
-
- Return true if the given string may be used as a class/field/method
- name. (Currently this only disallows empty strings and control
- characters.)
-
- NOTE: The string is assumed to have passed is_valid_utf!
-
- utf_ptr...points to first character
- end_pos...points after last character
-
-*******************************************************************************/
-
-bool is_valid_name(char *utf_ptr, char *end_pos)
-{
- if (end_pos <= utf_ptr) return false; /* disallow empty names */
-
- while (utf_ptr < end_pos) {
- unsigned char c = *utf_ptr++;
-
- if (c < 0x20) return false; /* disallow control characters */
- if (c == 0xc0 && (unsigned char) *utf_ptr == 0x80) /* disallow zero */
- return false;
- }
-
- return true;
-}
-
-bool is_valid_name_utf(utf *u)
-{
- return is_valid_name(u->text, UTF_END(u));
-}
-
-
-/* utf_show ********************************************************************
-
- Writes the utf symbols in the utfhash to stdout and displays the
- number of external hash chains grouped according to the chainlength
- (for debugging purposes).
-
-*******************************************************************************/
-
-#if !defined(NDEBUG)
-void utf_show(void)
-{
-
-#define CHAIN_LIMIT 20 /* limit for seperated enumeration */
-
- u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
- u4 max_chainlength = 0; /* maximum length of the chains */
- u4 sum_chainlength = 0; /* sum of the chainlengths */
- u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
- u4 i;
-
- printf("UTF-HASH:\n");
-
- /* show element of utf-hashtable */
-
- for (i = 0; i < hashtable_utf->size; i++) {
- utf *u = hashtable_utf->ptr[i];
-
- if (u) {
- printf("SLOT %d: ", (int) i);
-
- while (u) {
- printf("'");
- utf_display_printable_ascii(u);
- printf("' ");
- u = u->hashlink;
- }
- printf("\n");
- }
- }
-
- printf("UTF-HASH: %d slots for %d entries\n",
- (int) hashtable_utf->size, (int) hashtable_utf->entries );
-
- if (hashtable_utf->entries == 0)
- return;
-
- printf("chains:\n chainlength number of chains %% of utfstrings\n");
-
- for (i=0;i<CHAIN_LIMIT;i++)
- chain_count[i]=0;
-
- /* count numbers of hashchains according to their length */
- for (i=0; i<hashtable_utf->size; i++) {
-
- utf *u = (utf*) hashtable_utf->ptr[i];
- u4 chain_length = 0;
-
- /* determine chainlength */
- while (u) {
- u = u->hashlink;
- chain_length++;
- }
-
- /* update sum of all chainlengths */
- sum_chainlength+=chain_length;
-
- /* determine the maximum length of the chains */
- if (chain_length>max_chainlength)
- max_chainlength = chain_length;
-
- /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
- if (chain_length>=CHAIN_LIMIT) {
- beyond_limit+=chain_length;
- chain_length=CHAIN_LIMIT-1;
- }
-
- /* update number of hashchains of current length */
- chain_count[chain_length]++;
- }
-
- /* display results */
- for (i=1;i<CHAIN_LIMIT-1;i++)
- printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/hashtable_utf->entries));
-
- printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/hashtable_utf->entries);
-
-
- printf("max. chainlength:%5d\n",max_chainlength);
-
- /* avg. chainlength = sum of chainlengths / number of chains */
- printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (hashtable_utf->size-chain_count[0]));
-}
-#endif /* !defined(NDEBUG) */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/utf8.h - utf8 string functions
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _UTF_H
-#define _UTF_H
-
-/* forward typedefs ***********************************************************/
-
-typedef struct utf utf;
-
-#include "config.h"
-
-#include <stdio.h>
-
-#include "vm/types.h"
-
-#include "vm/global.h"
-
-
-/* data structure for utf8 symbols ********************************************/
-
-struct utf {
- utf *hashlink; /* link for external hash chain */
- s4 blength; /* text length in bytes */
- char *text; /* pointer to text */
-};
-
-/* to determine the end of utf strings */
-
-#define UTF_END(u) ((char *) u->text + u->blength)
-
-
-/* utf-symbols for pointer comparison of frequently used strings **************/
-
-extern utf *utf_java_lang_Object;
-
-extern utf *utf_java_lang_Class;
-extern utf *utf_java_lang_ClassLoader;
-extern utf *utf_java_lang_Cloneable;
-extern utf *utf_java_lang_SecurityManager;
-extern utf *utf_java_lang_String;
-extern utf *utf_java_lang_ThreadGroup;
-extern utf *utf_java_lang_ref_SoftReference;
-extern utf *utf_java_lang_ref_WeakReference;
-extern utf *utf_java_lang_ref_PhantomReference;
-extern utf *utf_java_io_Serializable;
-
-extern utf *utf_java_lang_Throwable;
-extern utf *utf_java_lang_Error;
-
-extern utf *utf_java_lang_AbstractMethodError;
-extern utf *utf_java_lang_ClassCircularityError;
-extern utf *utf_java_lang_ClassFormatError;
-extern utf *utf_java_lang_ExceptionInInitializerError;
-extern utf *utf_java_lang_IncompatibleClassChangeError;
-extern utf *utf_java_lang_InstantiationError;
-extern utf *utf_java_lang_InternalError;
-extern utf *utf_java_lang_LinkageError;
-extern utf *utf_java_lang_NoClassDefFoundError;
-extern utf *utf_java_lang_NoSuchFieldError;
-extern utf *utf_java_lang_NoSuchMethodError;
-extern utf *utf_java_lang_OutOfMemoryError;
-extern utf *utf_java_lang_UnsatisfiedLinkError;
-extern utf *utf_java_lang_UnsupportedClassVersionError;
-extern utf *utf_java_lang_VerifyError;
-extern utf *utf_java_lang_VirtualMachineError;
-
-extern utf *utf_java_lang_Exception;
-
-extern utf *utf_java_lang_ArithmeticException;
-extern utf *utf_java_lang_ArrayIndexOutOfBoundsException;
-extern utf *utf_java_lang_ArrayStoreException;
-extern utf *utf_java_lang_ClassCastException;
-extern utf *utf_java_lang_ClassNotFoundException;
-extern utf *utf_java_lang_CloneNotSupportedException;
-extern utf *utf_java_lang_IllegalAccessException;
-extern utf *utf_java_lang_IllegalArgumentException;
-extern utf *utf_java_lang_IllegalMonitorStateException;
-extern utf *utf_java_lang_InstantiationException;
-extern utf *utf_java_lang_InterruptedException;
-extern utf *utf_java_lang_NegativeArraySizeException;
-extern utf *utf_java_lang_NullPointerException;
-extern utf *utf_java_lang_RuntimeException;
-extern utf *utf_java_lang_StringIndexOutOfBoundsException;
-
-extern utf *utf_java_lang_reflect_InvocationTargetException;
-
-extern utf *utf_java_security_PrivilegedActionException;
-
-#if defined(ENABLE_JAVASE)
-extern utf* utf_java_lang_Void;
-#endif
-
-extern utf* utf_java_lang_Boolean;
-extern utf* utf_java_lang_Byte;
-extern utf* utf_java_lang_Character;
-extern utf* utf_java_lang_Short;
-extern utf* utf_java_lang_Integer;
-extern utf* utf_java_lang_Long;
-extern utf* utf_java_lang_Float;
-extern utf* utf_java_lang_Double;
-
-#if defined(ENABLE_JAVASE)
-extern utf *utf_java_lang_StackTraceElement;
-extern utf *utf_java_lang_reflect_Constructor;
-extern utf *utf_java_lang_reflect_Field;
-extern utf *utf_java_lang_reflect_Method;
-
-# if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
-extern utf *utf_java_lang_reflect_VMConstructor;
-extern utf *utf_java_lang_reflect_VMField;
-extern utf *utf_java_lang_reflect_VMMethod;
-# endif
-
-extern utf *utf_java_util_Vector;
-#endif
-
-extern utf *utf_InnerClasses;
-extern utf *utf_ConstantValue;
-extern utf *utf_Code;
-extern utf *utf_Exceptions;
-extern utf *utf_LineNumberTable;
-extern utf *utf_SourceFile;
-
-#if defined(ENABLE_JAVASE)
-extern utf *utf_EnclosingMethod;
-extern utf *utf_Signature;
-extern utf *utf_StackMapTable;
-
-#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
-
-extern utf *utf_init;
-extern utf *utf_clinit;
-extern utf *utf_clone;
-extern utf *utf_finalize;
-extern utf *utf_invoke;
-extern utf *utf_main;
-extern utf *utf_run;
-
-extern utf *utf_add;
-extern utf *utf_dispatch;
-extern utf *utf_remove;
-extern utf *utf_addThread;
-extern utf *utf_removeThread;
-extern utf *utf_put;
-extern utf *utf_get;
-extern utf *utf_uncaughtException;
-extern utf *utf_value;
-
-extern utf *utf_fillInStackTrace;
-extern utf *utf_findNative;
-extern utf *utf_getSystemClassLoader;
-extern utf *utf_initCause;
-extern utf *utf_loadClass;
-extern utf *utf_loadClassInternal;
-extern utf *utf_printStackTrace;
-
-extern utf *utf_division_by_zero;
-
-extern utf *utf_Z;
-extern utf *utf_B;
-extern utf *utf_C;
-extern utf *utf_S;
-extern utf *utf_I;
-extern utf *utf_J;
-extern utf *utf_F;
-extern utf *utf_D;
-
-extern utf *utf_void__void;
-extern utf *utf_boolean__void;
-extern utf *utf_byte__void;
-extern utf *utf_char__void;
-extern utf *utf_short__void;
-extern utf *utf_int__void;
-extern utf *utf_long__void;
-extern utf *utf_float__void;
-extern utf *utf_double__void;
-
-extern utf *utf_void__java_lang_ClassLoader;
-extern utf *utf_void__java_lang_Object;
-extern utf *utf_void__java_lang_Throwable;
-extern utf *utf_java_lang_ClassLoader_java_lang_String__J;
-extern utf *utf_java_lang_Exception__V;
-extern utf *utf_java_lang_Object__java_lang_Object;
-extern utf *utf_java_lang_String__void;
-extern utf *utf_java_lang_String__java_lang_Class;
-extern utf *utf_java_lang_Thread__V;
-extern utf *utf_java_lang_Thread_java_lang_Throwable__V;
-extern utf *utf_Ljava_lang_ThreadGroup_Ljava_lang_String__V;
-extern utf *utf_java_lang_Throwable__void;
-extern utf *utf_java_lang_Throwable__java_lang_Throwable;
-
-extern utf *utf_not_named_yet;
-extern utf *utf_null;
-extern utf *array_packagename;
-
-
-/* function prototypes ********************************************************/
-
-/* initialize the utf8 subsystem */
-void utf8_init(void);
-
-u4 utf_hashkey(const char *text, u4 length);
-u4 utf_full_hashkey(const char *text, u4 length);
-
-/* determine hashkey of a unicode-symbol */
-u4 unicode_hashkey(u2 *text, u2 length);
-
-/* create new utf-symbol */
-utf *utf_new(const char *text, u2 length);
-
-/* make utf symbol from u2 array */
-utf *utf_new_u2(u2 *unicodedata, u4 unicodelength, bool isclassname);
-
-utf *utf_new_char(const char *text);
-utf *utf_new_char_classname(const char *text);
-
-/* get number of bytes */
-u4 utf_bytes(utf *u);
-
-/* get next unicode character of a utf-string */
-u2 utf_nextu2(char **utf);
-
-/* get (number of) unicode characters of a utf string (safe) */
-s4 utf8_safe_number_of_u2s(const char *text, s4 nbytes);
-void utf8_safe_convert_to_u2s(const char *text, s4 nbytes, u2 *buffer);
-
-/* get (number of) unicode characters of a utf string (UNSAFE!) */
-u4 utf_get_number_of_u2s(utf *u);
-u4 utf_get_number_of_u2s_for_buffer(const char *buffer, u4 blength);
-
-/* determine utf length in bytes of a u2 array */
-u4 u2_utflength(u2 *text, u4 u2_length);
-
-void utf_copy(char *buffer, utf *u);
-void utf_cat(char *buffer, utf *u);
-void utf_copy_classname(char *buffer, utf *u);
-void utf_cat_classname(char *buffer, utf *u);
-
-/* write utf symbol to file/buffer */
-void utf_display_printable_ascii(utf *u);
-void utf_display_printable_ascii_classname(utf *u);
-
-void utf_sprint_convert_to_latin1(char *buffer, utf *u);
-void utf_sprint_convert_to_latin1_classname(char *buffer, utf *u);
-
-void utf_strcat_convert_to_latin1(char *buffer, utf *u);
-void utf_strcat_convert_to_latin1_classname(char *buffer, utf *u);
-
-void utf_fprint_printable_ascii(FILE *file, utf *u);
-void utf_fprint_printable_ascii_classname(FILE *file, utf *u);
-
-/* check if a UTF-8 string is valid */
-bool is_valid_utf(char *utf_ptr, char *end_pos);
-
-/* check if a UTF-8 string may be used as a class/field/method name */
-bool is_valid_name(char *utf_ptr, char *end_pos);
-bool is_valid_name_utf(utf *u);
-
-/* show utf-table */
-void utf_show(void);
-
-#endif /* _UTF_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/zip.c - ZIP file handling for bootstrap classloader
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#include "config.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <zlib.h>
-#include <sys/mman.h>
-
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "mm/memory.h"
-
-#include "vm/global.h"
-#include "vm/vm.hpp"
-
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-#include "vmcore/zip.h"
-
-
-/* start size for classes hashtable *******************************************/
-
-#define HASHTABLE_CLASSES_SIZE (1 << 10)
-
-
-/* info taken from:
- http://www.pkware.com/business_and_developers/developer/popups/appnote.txt
-*/
-
-/* all signatures in the ZIP file have a length of 4 bytes ********************/
-
-#define SIGNATURE_LENGTH 4
-
-/* Central directory structure *************************************************
-
- [file header 1]
- .
- .
- .
- [file header n]
- [digital signature]
-
- File header:
-
- central file header signature 4 bytes (0x02014b50)
- version made by 2 bytes
- version needed to extract 2 bytes
- general purpose bit flag 2 bytes
- compression method 2 bytes
- last mod file time 2 bytes
- last mod file date 2 bytes
- crc-32 4 bytes
- compressed size 4 bytes
- uncompressed size 4 bytes
- file name length 2 bytes
- extra field length 2 bytes
- file comment length 2 bytes
- disk number start 2 bytes
- internal file attributes 2 bytes
- external file attributes 4 bytes
- relative offset of local header 4 bytes
-
- file name (variable size)
- extra field (variable size)
- file comment (variable size)
-
- Digital signature:
-
- header signature 4 bytes (0x05054b50)
- size of data 2 bytes
- signature data (variable size)
-
-*******************************************************************************/
-
-#define CDSFH_HEADER_SIZE 46
-
-#define CDSFH_SIGNATURE 0x02014b50
-#define CDSFH_COMPRESSION_METHOD 10
-#define CDSFH_COMPRESSED_SIZE 20
-#define CDSFH_UNCOMPRESSED_SIZE 24
-#define CDSFH_FILE_NAME_LENGTH 28
-#define CDSFH_EXTRA_FIELD_LENGTH 30
-#define CDSFH_FILE_COMMENT_LENGTH 32
-#define CDSFH_RELATIVE_OFFSET 42
-#define CDSFH_FILENAME 46
-
-typedef struct cdsfh cdsfh;
-
-struct cdsfh {
- u2 compressionmethod;
- u4 compressedsize;
- u4 uncompressedsize;
- u2 filenamelength;
- u2 extrafieldlength;
- u2 filecommentlength;
- u4 relativeoffset;
-};
-
-
-/* End of central directory record *********************************************
-
- end of central dir signature 4 bytes (0x06054b50)
- number of this disk 2 bytes
- number of the disk with the
- start of the central directory 2 bytes
- total number of entries in the
- central directory on this disk 2 bytes
- total number of entries in
- the central directory 2 bytes
- size of the central directory 4 bytes
- offset of start of central
- directory with respect to
- the starting disk number 4 bytes
- .ZIP file comment length 2 bytes
- .ZIP file comment (variable size)
-
-*******************************************************************************/
-
-#define EOCDR_SIGNATURE 0x06054b50
-#define EOCDR_ENTRIES 10
-#define EOCDR_OFFSET 16
-
-typedef struct eocdr eocdr;
-
-struct eocdr {
- u2 entries;
- u4 offset;
-};
-
-
-/* zip_open ********************************************************************
-
- XXX
-
-*******************************************************************************/
-
-hashtable *zip_open(char *path)
-{
- hashtable *ht;
- hashtable_zipfile_entry *htzfe;
- int fd;
- u1 lfh_signature[SIGNATURE_LENGTH];
- off_t len;
- u1 *filep;
- s4 i;
- u1 *p;
- eocdr eocdr;
- cdsfh cdsfh;
- const char *filename;
- const char *classext;
- utf *u;
- u4 key; /* hashkey computed from utf-text */
- u4 slot; /* slot in hashtable */
-
- /* first of all, open the file */
-
- if ((fd = open(path, O_RDONLY)) == -1)
- return NULL;
-
- /* check for signature in first local file header */
-
- if (read(fd, lfh_signature, SIGNATURE_LENGTH) != SIGNATURE_LENGTH)
- return NULL;
-
- if (SUCK_LE_U4(lfh_signature) != LFH_SIGNATURE)
- return NULL;
-
- /* get the file length */
-
- if ((len = lseek(fd, 0, SEEK_END)) == -1)
- return NULL;
-
- /* we better mmap the file */
-
- filep = mmap(0, len, PROT_READ, MAP_PRIVATE, fd, 0);
-
- /* some older compilers, like DEC OSF cc, don't like comparisons
- on void* types */
-
- if ((ptrint) filep == (ptrint) MAP_FAILED)
- return NULL;
-
- /* find end of central directory record */
-
- for (p = filep + len; p >= filep; p--)
- if (SUCK_LE_U4(p) == EOCDR_SIGNATURE)
- break;
-
- /* get number of entries in central directory */
-
- eocdr.entries = SUCK_LE_U2(p + EOCDR_ENTRIES);
- eocdr.offset = SUCK_LE_U4(p + EOCDR_OFFSET);
-
- /* create hashtable for filenames */
-
- ht = NEW(hashtable);
-
- hashtable_create(ht, HASHTABLE_CLASSES_SIZE);
-
- /* add all file entries into the hashtable */
-
- for (i = 0, p = filep + eocdr.offset; i < eocdr.entries; i++) {
- /* check file header signature */
-
- if (SUCK_LE_U4(p) != CDSFH_SIGNATURE)
- return NULL;
-
- /* we found an entry */
-
- cdsfh.compressionmethod = SUCK_LE_U2(p + CDSFH_COMPRESSION_METHOD);
- cdsfh.compressedsize = SUCK_LE_U4(p + CDSFH_COMPRESSED_SIZE);
- cdsfh.uncompressedsize = SUCK_LE_U4(p + CDSFH_UNCOMPRESSED_SIZE);
- cdsfh.filenamelength = SUCK_LE_U2(p + CDSFH_FILE_NAME_LENGTH);
- cdsfh.extrafieldlength = SUCK_LE_U2(p + CDSFH_EXTRA_FIELD_LENGTH);
- cdsfh.filecommentlength = SUCK_LE_U2(p + CDSFH_FILE_COMMENT_LENGTH);
- cdsfh.relativeoffset = SUCK_LE_U4(p + CDSFH_RELATIVE_OFFSET);
-
- /* create utf8 string of filename, strip .class from classes */
-
- filename = (const char *) (p + CDSFH_FILENAME);
- classext = filename + cdsfh.filenamelength - strlen(".class");
-
- /* skip directory entries */
-
- if (filename[cdsfh.filenamelength - 1] != '/') {
- if (strncmp(classext, ".class", strlen(".class")) == 0)
- u = utf_new(filename, cdsfh.filenamelength - strlen(".class"));
- else
- u = utf_new(filename, cdsfh.filenamelength);
-
- /* insert class into hashtable */
-
- htzfe = NEW(hashtable_zipfile_entry);
-
- htzfe->filename = u;
- htzfe->compressionmethod = cdsfh.compressionmethod;
- htzfe->compressedsize = cdsfh.compressedsize;
- htzfe->uncompressedsize = cdsfh.uncompressedsize;
- htzfe->data = filep + cdsfh.relativeoffset;
-
- /* get hashtable slot */
-
- key = utf_hashkey(u->text, u->blength);
- slot = key & (ht->size - 1);
-
- /* insert into external chain */
-
- htzfe->hashlink = ht->ptr[slot];
-
- /* insert hashtable zipfile entry */
-
- ht->ptr[slot] = htzfe;
- ht->entries++;
- }
-
- /* move to next central directory structure file header */
-
- p = p +
- CDSFH_HEADER_SIZE +
- cdsfh.filenamelength +
- cdsfh.extrafieldlength +
- cdsfh.filecommentlength;
- }
-
- /* return pointer to hashtable */
-
- return ht;
-}
-
-
-/* zip_find ********************************************************************
-
- Search for the given filename in the classpath entries of a zip file.
-
- NOTE: The '.class' extension is stripped when reading a zip file, so if
- you want to find a .class file, you must search for its name _without_
- the '.class' extension.
- XXX I dont like that, it makes foo and foo.class ambiguous. -Edwin
-
- IN:
- lce..........the classpath entries for the zip file
- u............the filename to look for
-
- RETURN VALUE:
- hashtable_zipfile_entry * of the entry if found, or
- NULL if not found
-
-*******************************************************************************/
-
-hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u)
-{
- hashtable *ht;
- u4 key; /* hashkey computed from utf-text */
- u4 slot; /* slot in hashtable */
- hashtable_zipfile_entry *htzfe; /* hashtable element */
-
- /* get classes hashtable from the classpath entry */
-
- ht = lce->htclasses;
-
- /* get the hashtable slot of the name searched */
-
- key = utf_hashkey(u->text, u->blength);
- slot = key & (ht->size - 1);
- htzfe = ht->ptr[slot];
-
- /* search external hash chain for utf-symbol */
-
- while (htzfe) {
- if (htzfe->filename == u)
- return htzfe;
-
- /* next element in external chain */
-
- htzfe = htzfe->hashlink;
- }
-
- /* file not found in this archive */
-
- return NULL;
-}
-
-
-/* zip_get ********************************************************************
-
- XXX
-
-*******************************************************************************/
-
-classbuffer *zip_get(list_classpath_entry *lce, classinfo *c)
-{
- hashtable_zipfile_entry *htzfe;
- lfh lfh;
- u1 *indata;
- u1 *outdata;
- z_stream zs;
- int err;
- classbuffer *cb;
-
- /* try to find the class in the current archive */
-
- htzfe = zip_find(lce, c->name);
-
- if (htzfe == NULL)
- return NULL;
-
- /* read stuff from local file header */
-
- lfh.filenamelength = SUCK_LE_U2(htzfe->data + LFH_FILE_NAME_LENGTH);
- lfh.extrafieldlength = SUCK_LE_U2(htzfe->data + LFH_EXTRA_FIELD_LENGTH);
-
- indata = htzfe->data +
- LFH_HEADER_SIZE +
- lfh.filenamelength +
- lfh.extrafieldlength;
-
- /* allocate buffer for uncompressed data */
-
- outdata = MNEW(u1, htzfe->uncompressedsize);
-
- /* how is the file stored? */
-
- switch (htzfe->compressionmethod) {
- case Z_DEFLATED:
- /* fill z_stream structure */
-
- zs.next_in = indata;
- zs.avail_in = htzfe->compressedsize;
- zs.next_out = outdata;
- zs.avail_out = htzfe->uncompressedsize;
-
- zs.zalloc = Z_NULL;
- zs.zfree = Z_NULL;
- zs.opaque = Z_NULL;
-
- /* initialize this inflate run */
-
- if (inflateInit2(&zs, -MAX_WBITS) != Z_OK)
- vm_abort("zip_get: inflateInit2 failed: %s", strerror(errno));
-
- /* decompress the file into buffer */
-
- err = inflate(&zs, Z_SYNC_FLUSH);
-
- if ((err != Z_STREAM_END) && (err != Z_OK))
- vm_abort("zip_get: inflate failed: %s", strerror(errno));
-
- /* finish this inflate run */
-
- if (inflateEnd(&zs) != Z_OK)
- vm_abort("zip_get: inflateEnd failed: %s", strerror(errno));
- break;
-
- case 0:
- /* uncompressed file, just copy the data */
- MCOPY(outdata, indata, u1, htzfe->compressedsize);
- break;
-
- default:
- vm_abort("zip_get: unknown compression method %d",
- htzfe->compressionmethod);
- }
-
- /* allocate classbuffer */
-
- cb = NEW(classbuffer);
-
- cb->clazz = c;
- cb->size = htzfe->uncompressedsize;
- cb->data = outdata;
- cb->pos = outdata;
- cb->path = lce->path;
-
- /* return the filled classbuffer structure */
-
- return cb;
-}
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- * vim:noexpandtab:sw=4:ts=4:
- */
+++ /dev/null
-/* src/vmcore/zip.c - ZIP file handling for bootstrap classloader
-
- Copyright (C) 1996-2005, 2006, 2007, 2008
- CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
-
- This file is part of CACAO.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2, or (at
- your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
-*/
-
-
-#ifndef _ZIP_H
-#define _ZIP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "config.h"
-#include "vm/types.h"
-
-#include "toolbox/hashtable.h"
-
-#include "vm/global.h"
-
-#include "vmcore/class.h"
-#include "vmcore/loader.h"
-#include "vmcore/suck.h"
-#include "vmcore/utf8.h"
-
-
-/* Local file header ***********************************************************
-
- local file header signature 4 bytes (0x04034b50)
- version needed to extract 2 bytes
- general purpose bit flag 2 bytes
- compression method 2 bytes
- last mod file time 2 bytes
- last mod file date 2 bytes
- crc-32 4 bytes
- compressed size 4 bytes
- uncompressed size 4 bytes
- file name length 2 bytes
- extra field length 2 bytes
-
- file name (variable size)
- extra field (variable size)
-
-*******************************************************************************/
-
-#define LFH_HEADER_SIZE 30
-
-#define LFH_SIGNATURE 0x04034b50
-#define LFH_FILE_NAME_LENGTH 26
-#define LFH_EXTRA_FIELD_LENGTH 28
-
-typedef struct lfh lfh;
-
-struct lfh {
- u2 compressionmethod;
- u4 compressedsize;
- u4 uncompressedsize;
- u2 filenamelength;
- u2 extrafieldlength;
-};
-
-/* hashtable_zipfile_entry ****************************************************/
-
-typedef struct hashtable_zipfile_entry hashtable_zipfile_entry;
-
-struct hashtable_zipfile_entry {
- utf *filename;
- u2 compressionmethod;
- u4 compressedsize;
- u4 uncompressedsize;
- u1 *data;
- hashtable_zipfile_entry *hashlink;
-};
-
-
-/* function prototypes ********************************************************/
-
-hashtable *zip_open(char *path);
-hashtable_zipfile_entry *zip_find(list_classpath_entry *lce, utf *u);
-classbuffer *zip_get(list_classpath_entry *lce, classinfo *c);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _ZIP_H */
-
-
-/*
- * These are local overrides for various environment variables in Emacs.
- * Please do not remove this and leave it at the end of the file, where
- * Emacs will automagically detect them.
- * ---------------------------------------------------------------------
- * Local variables:
- * mode: c
- * indent-tabs-mode: t
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */